diff options
author | cbdev <cb@cbcdn.com> | 2019-05-19 17:53:23 +0200 |
---|---|---|
committer | cbdev <cb@cbcdn.com> | 2019-05-19 17:53:23 +0200 |
commit | de23df891940464080297cd9b17324d8ee4601d7 (patch) | |
tree | f181b1620f1dfc073a32a65a55f089c3b3d1cd05 /websocksy.c | |
parent | 92638847a3b7f51fb795c7986b793536ece6beee (diff) | |
download | websocksy-de23df891940464080297cd9b17324d8ee4601d7.tar.gz websocksy-de23df891940464080297cd9b17324d8ee4601d7.tar.bz2 websocksy-de23df891940464080297cd9b17324d8ee4601d7.zip |
Implement basic peer connection handling
Diffstat (limited to 'websocksy.c')
-rw-r--r-- | websocksy.c | 95 |
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){ |