📄 relay.c
字号:
cp = ""; len = 0; cldata->proxycldata.proxystate = PROXYCLSTATE_SEND_PICTURE; cldata->proxycldata.management_data = NULL; } else { camserv_log( MODNAME, "Unknown client state: \"%d\"", cldata->clienttype ); cp = ""; len = 0; } databuf_buf_set( cldata->writebuf, cp, len );}/* * relay_client_read: Called by the sockfield loop when a socket has become * readable -- On a client of which we have not identified * prior, we determine their type by their initial msg. * Otherwise on known sockets we attempt to read all the * data we are currently trying to get from them, then * dispatch them to the correct handling procedures * (camserv, vs. client). * * Arguments: Standard sockfield callback arguments * * Return Values: Returns one of SOCKFIELD_* */staticint relay_client_read( SockField_Data *sfdata, Socket *sock, void *cldata ){ ClientData *clientdata = cldata; int readres; char sparebuf[ 1024 ]; if( clientdata->clienttype == CLIENT_T_UNK ){ read( socket_query_fd( sock ), sparebuf, sizeof( sparebuf ) ); sparebuf[ sizeof( sparebuf ) - 1 ] = '\0'; /* Client initializing itself */ if( !strncmp( sparebuf, "GET", 3 ) ){ if( strstr( sparebuf, "/singleframe" )) clientdata->clienttype = CLIENT_T_SINGLE; else clientdata->clienttype = CLIENT_T_BROWSER; } else if( !strncmp( sparebuf, "PROXY", 5 )) { clientdata->clienttype = CLIENT_T_PROXY; } else { clientdata->clienttype = CLIENT_T_BROWSER; } databuf_buf_set( clientdata->readbuf, &clientdata->junkbuf[ 0 ], sizeof( clientdata->junkbuf )); set_client_writebuf( clientdata ); sock_field_unhold_write( sfdata ); return SOCKFIELD_OK; } readres = databuf_read( clientdata->readbuf, socket_query_fd( sock )); if( readres == -1 ) return SOCKFIELD_CLOSE; if( readres == 1 ) return SOCKFIELD_OK; if( clientdata->clienttype == CLIENT_T_CAMSERV ) return read_camera( sfdata, sock, clientdata ); else return read_client( sfdata, sock, clientdata ); return SOCKFIELD_OK;}/* * write_camera: Called when our camserv socket is set to writeable. For * most of the time we will just put ourselves on hold, however * the initial connection with the camserv requires us to * send the PROXY message. * * Return values: Returns one of SOCKFIELD_* */staticint write_camera( SockField_Data *sfdata, Socket *sock, ClientData *cldata ){ if( cldata->camdata.camstate != CAMSTATE_SEND_PROXY ){ sock_field_hold_write( sfdata, sock ); return SOCKFIELD_OK; } /* Here we have just initialized our proxy with the connected camera. So we put ourselves in a 'read' mode for the rest of the period */ cldata->camdata.camstate = CAMSTATE_RECV_SIZE; databuf_buf_set( cldata->readbuf, &cldata->camdata.picsize, sizeof( cldata->camdata.picsize ) ); return SOCKFIELD_OK;}/* * write_client_proxy: Called when a client (who has previously identified * itself as a proxy) has become writeable. Depending * on the current state of the proxy, a picture will * either be snagged from the management bins, or * the picture will be sent. * * Return values: Returns one of SOCKFIELD_* */staticint write_client_proxy( SockField_Data *sfdata, Socket *sock, ClientData *cldata ){ if( cldata->proxycldata.proxystate == PROXYCLSTATE_SEND_PICTURE ) { char *pic_data; size_t pic_size; int pic_id; /* Just finished sending a picture */ if( cldata->proxycldata.management_data && manager_dest_client( cldata->proxycldata.management_data ) == -1 ) camserv_log( MODNAME, "Error destroying client proxy management!"); /* Get a new picture to send */ cldata->proxycldata.management_data = manager_new_client( &pic_data, &pic_size, &pic_id ); if( cldata->proxycldata.management_data == NULL ){ camserv_log( MODNAME, "Error managing client proxy! " "(no pictures may be available yet)" ); sock_field_hold_write( sfdata, sock ); return SOCKFIELD_OK; } if( pic_id == cldata->proxycldata.last_pic_id ) { /* Proxy read too fast */ manager_dest_client( cldata->proxycldata.management_data ); cldata->proxycldata.management_data = NULL; sock_field_hold_write( sfdata, sock ); return SOCKFIELD_OK; } cldata->proxycldata.proxystate = PROXYCLSTATE_SEND_PICSIZE; cldata->proxycldata.picsize = htonl( pic_size ); cldata->proxycldata.pic_data = pic_data; cldata->proxycldata.last_pic_id = pic_id; databuf_buf_set( cldata->writebuf, &cldata->proxycldata.picsize, sizeof( cldata->proxycldata.picsize )); } else { /* Else just finished sending the picture size */ cldata->proxycldata.proxystate = PROXYCLSTATE_SEND_PICTURE; databuf_buf_set( cldata->writebuf, cldata->proxycldata.pic_data, ntohl( cldata->proxycldata.picsize )); } return SOCKFIELD_OK;}/* * write_client_regular: Called when a regular client has been set writeable. * in such a case we switch between all of the different * states of a client and send the appropriate thing. * * Return values: Returns one of SOCKFIELD_* */staticint write_client_regular( SockField_Data *sfdata, Socket *sock, ClientData *cldata ){ if( cldata->browserdata.browserstate == BROWSERSTATE_SEND_PREAMBLE || cldata->browserdata.browserstate == BROWSERSTATE_SEND_SEPERATOR ) { char *pic_data; size_t pic_size; int pic_id; cldata->browserdata.management_data = manager_new_client( &pic_data, &pic_size, &pic_id ); if( cldata->browserdata.management_data == NULL ){ camserv_log( MODNAME, "Error managing client! " "(no pictures may be available yet)"); sock_field_hold_write( sfdata, sock ); return SOCKFIELD_OK; } if( pic_id == cldata->browserdata.last_pic_id ) { /* Client reads fast */ manager_dest_client( cldata->browserdata.management_data ); cldata->browserdata.management_data = NULL; sock_field_hold_write( sfdata, sock ); return SOCKFIELD_OK; } databuf_buf_set( cldata->writebuf, pic_data, pic_size ); cldata->browserdata.last_pic_id = pic_id; cldata->browserdata.browserstate = BROWSERSTATE_SEND_PICTURE; } else { char *sep_data; size_t sep_size; if( manager_dest_client( cldata->browserdata.management_data ) == -1 ){ camserv_log( MODNAME, "Error destroying client management!"); } cldata->browserdata.management_data = NULL; cldata->browserdata.browserstate = BROWSERSTATE_SEND_SEPERATOR; sep_data = get_seperator_text( &sep_size ); databuf_buf_set( cldata->writebuf, sep_data, sep_size ); } return SOCKFIELD_OK;}staticint write_client( SockField_Data *sfdata, Socket *sock, ClientData *cldata ){ /* If client hasn't initialized itself with us yet, put him on hold */ if( cldata->clienttype == CLIENT_T_UNK ){ sock_field_hold_write( sfdata, sock ); return SOCKFIELD_OK; } if( cldata->clienttype == CLIENT_T_PROXY ) return write_client_proxy( sfdata, sock, cldata ); else return write_client_regular( sfdata, sock, cldata ); return SOCKFIELD_OK;}staticint relay_client_write( SockField_Data *sfdata, Socket *sock, void *cldata ){ ClientData *clientdata = cldata; int writeres; writeres = databuf_write( clientdata->writebuf, socket_query_fd( sock )); if( writeres == -1 ) return SOCKFIELD_CLOSE; if( writeres == 1 ) return SOCKFIELD_OK; /* Still data left to write */ /* Else we have written all the data we were supposed to */ if( clientdata->clienttype == CLIENT_T_CAMSERV ) return write_camera( sfdata, sock, clientdata ); else return write_client( sfdata, sock, clientdata ); return SOCKFIELD_OK;}staticvoid relay_accept( SockField_Data *sfdata, Socket *listen_sock, void *sys_cldata ){ ClientData *cldata; Socket *new_socket; if( (new_socket = socket_accept( listen_sock )) == NULL ){ camserv_log( MODNAME, "Error accepting new socket!"); return; } if( (cldata = client_data_new()) == NULL ){ camserv_log( MODNAME, "Error allocating clientdata!"); socket_dest( new_socket ); return; } cldata->clienttype = CLIENT_T_UNK; if( sock_field_manage_socket( sfdata, new_socket, cldata ) == -1 ){ camserv_log( MODNAME, "Error managing new socket" ); socket_dest( new_socket ); client_data_dest( cldata ); return; } camserv_log( MODNAME, "Accepted client: \"%s\"", socket_query_remote_name( new_socket ));}staticvoid relay_timeout( SockField_Data *sfdata, void *sys_cldata ){ RelayData *rdata = sys_cldata; if( rdata->camera_sock == NULL ) { camserv_log( MODNAME, "Attempting connect to camserver"); if( relay_connect_camserv( sfdata, rdata ) == -1 ){ camserv_log( MODNAME, "Error connecting to camserv: %s %d", rdata->camera_ip, rdata->camera_port ); } }}int main( int argc, char *argv[] ){ Socket *listen_sock; int localport, remoteport; RelayData rdata; struct timeval retry_time; if( argc < 3 ) { fprintf( stderr, "camserv relay v%s - by Jon Travis (jtravis@p00p.org)\n", VERSION ); fprintf( stderr, "Syntax: %s <port> <camserv IP> <ccamserv port>\n", argv[ 0 ]); fprintf( stderr, "\tThe relay will bind port <port> on the localhost\n"); fprintf( stderr, "\tand connect to the camserv port to do the relay.\n"); return -1; } signal( SIGPIPE, SIG_IGN ); if( sscanf( argv[1], "%d", &localport ) != 1 ) { camserv_log( MODNAME, "Error: port \"%s\" invalid!", argv[ 1 ] ); return -1; } if( localport < 1024 ) camserv_log( MODNAME, "Warning: Port numbers < 1024 shouldn't be used"); if( sscanf( argv[3], "%d", &remoteport ) != 1 ) { camserv_log( MODNAME, "Error: camserv port \"%s\" invalid!", argv[3] ); return -1; } strncpy( rdata.camera_ip, argv[2], sizeof( rdata.camera_ip ) - 1); rdata.camera_ip[ sizeof( rdata.camera_ip ) - 1 ] = '\0'; rdata.camera_port = remoteport; rdata.camera_sock = NULL; if( (listen_sock = socket_serve_tcp( NULL, localport, BACKLOG )) == NULL ){ camserv_log( MODNAME, "Could not bind local port: %s", strerror( errno )); return -1; } retry_time.tv_sec = 10; retry_time.tv_usec = 0; if( sock_field( listen_sock, &rdata, relay_init, relay_accept, relay_client_read, relay_client_write, relay_preclose, relay_timeout, &retry_time ) == -1 ) { socket_dest( listen_sock ); camserv_log( MODNAME, "Camserv relay abnormally terminated"); return -1; } socket_dest( listen_sock ); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -