aboutsummaryrefslogtreecommitdiff
path: root/websocksy.c
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2019-05-19 17:53:23 +0200
committercbdev <cb@cbcdn.com>2019-05-19 17:53:23 +0200
commitde23df891940464080297cd9b17324d8ee4601d7 (patch)
treef181b1620f1dfc073a32a65a55f089c3b3d1cd05 /websocksy.c
parent92638847a3b7f51fb795c7986b793536ece6beee (diff)
downloadwebsocksy-de23df891940464080297cd9b17324d8ee4601d7.tar.gz
websocksy-de23df891940464080297cd9b17324d8ee4601d7.tar.bz2
websocksy-de23df891940464080297cd9b17324d8ee4601d7.zip
Implement basic peer connection handling
Diffstat (limited to 'websocksy.c')
-rw-r--r--websocksy.c95
1 files changed, 92 insertions, 3 deletions
diff --git a/websocksy.c b/websocksy.c
index 714c3f5..e4f7886 100644
--- a/websocksy.c
+++ b/websocksy.c
@@ -16,6 +16,7 @@
* - backend config
* - framing config / per peer?
* - per-connection framing state
+ * - framing function discovery / registry
*/
/*
@@ -53,8 +54,46 @@ static struct {
};
int connect_peer(websocket* ws){
+ int rv = 1;
+
ws->peer = config.backend.query(ws->request_path, ws->protocols, ws->protocol, ws->headers, ws->header, ws);
- return 0;
+ if(!ws->peer.host || !ws->peer.port){
+ //no peer provided
+ return 1;
+ }
+
+ //assign default framing function if none provided
+ if(!ws->peer.framing){
+ ws->peer.framing = framing_auto;
+ }
+
+ switch(ws->peer.transport){
+ case peer_tcp_client:
+ ws->peer_fd = network_socket(ws->peer.host, ws->peer.port, SOCK_STREAM, 0);
+ break;
+ case peer_udp_client:
+ ws->peer_fd = network_socket(ws->peer.host, ws->peer.port, SOCK_DGRAM, 0);
+ break;
+ case peer_tcp_server:
+ //TODO implement tcp server mode
+ fprintf(stderr, "TCP Server mode not yet implemented\n");
+ rv = 1;
+ break;
+ case peer_udp_server:
+ ws->peer_fd = network_socket(ws->peer.host, ws->peer.port, SOCK_DGRAM, 1);
+ break;
+ case peer_fifo_tx:
+ case peer_fifo_rx:
+ case peer_unix:
+ default:
+ //TODO implement other peer modes
+ fprintf(stderr, "Peer connection mode not yet implemented\n");
+ rv = 1;
+ break;
+ }
+
+ rv = (ws->peer_fd == -1) ? 1 : 0;
+ return rv;
}
#include "ws_proto.c"
@@ -82,8 +121,58 @@ int args_parse(int argc, char** argv){
}
int ws_peer_data(websocket* ws){
- //TODO
- return -1;
+ ssize_t bytes_read, bytes_left = sizeof(ws->peer_buffer) - ws->peer_buffer_offset;
+ int64_t bytes_framed;
+ //default to a binary frame
+ ws_operation opcode = ws_frame_binary;
+
+ bytes_read = recv(ws->peer_fd, ws->peer_buffer + ws->peer_buffer_offset, bytes_left - 1, 0);
+ if(bytes_read < 0){
+ fprintf(stderr, "Failed to receive from peer: %s\n", strerror(errno));
+ ws_close(ws, ws_close_unexpected, "Peer connection failed");
+ return 0;
+ }
+ else if(bytes_read == 0){
+ //peer closed connection
+ ws_close(ws, ws_close_normal, "Peer closed connection");
+ return 0;
+ }
+
+ ws->peer_buffer[ws->peer_buffer_offset + bytes_read] = 0;
+
+ do{
+ //call the framing function
+ bytes_framed = ws->peer.framing(ws->peer_buffer, ws->peer_buffer_offset + bytes_read, bytes_read, &opcode, &(ws->peer_framing_data), ws->peer.framing_config);
+ if(bytes_framed > 0){
+ if(bytes_framed > ws->peer_buffer_offset + bytes_read){
+ ws_close(ws, ws_close_unexpected, "Internal error");
+ fprintf(stderr, "Overrun by framing function, have %lu + %lu bytes, framed %lu\n", ws->peer_buffer_offset, bytes_read, bytes_framed);
+ return 0;
+ }
+ //send the indicated n bytes to the websocket peer
+ if(ws_send_frame(ws, opcode, ws->peer_buffer, bytes_framed)){
+ return 1;
+ }
+ //copy back
+ memmove(ws->peer_buffer, ws->peer_buffer + bytes_framed, (ws->peer_buffer_offset + bytes_read) - bytes_framed);
+ //this should not actually happen, but it might with some weird framing functions/protocols
+ if(bytes_framed < ws->peer_buffer_offset){
+ ws->peer_buffer_offset -= bytes_framed;
+ }
+ else{
+ bytes_framed -= ws->peer_buffer_offset;
+ bytes_read -= bytes_framed;
+ ws->peer_buffer_offset = 0;
+ }
+ }
+ else if(bytes_framed < 0){
+ //TODO handle framing errors
+ }
+ }
+ while(bytes_framed && (ws->peer_buffer_offset + bytes_read) > 0);
+
+ ws->peer_buffer_offset += bytes_read;
+ return 0;
}
int main(int argc, char** argv){