?? main_loop.c
字號:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <signal.h>#include "camserv.h"#include "camconfig.h"#include "socket.h"#include "mainloop.h"#include "sockset.h"#include "manager.h"#include "databuf.h"#include "list.h"#include "log.h"extern int errno;static int Abort = 0;#define CINFO_STATE_PREAMBLE 0#define CINFO_STATE_PICTURE 1#define CINFO_STATE_SEPERATOR 2#define CINFO_STATE_SENDSIZE 3#define CINFO_STATE_UNINIT 4#define CLIENT_T_PROXY 0#define CLIENT_T_BROWSER 1#define CLIENT_T_UNINIT 2#define CLIENT_T_SINGLE 3#define RANDOMSTRING "ThisRandomString"#define CONTENTTYPE "image/jpeg"#define MODNAME "mainloop"#define MAX(x,y) (((x)>(y)) ? (x) : (y))typedef struct client_info_st { Socket *socket; DataBuf *writebuf; void *management_data; int state; /* One of CINFO_STATE_* */ time_t create_time; /* Resource management */ unsigned int bytes; unsigned int frames; unsigned int max_seconds; /* Max resource info */ unsigned int max_bytes; unsigned int max_frames; /********** Proxy only *********/ unsigned long proxypic_size; /* network order size of picture to send */ char *proxypic_data; /*******************************/ int last_picture_id; int client_type; /* One of CLIENT_T_* */} ClientInfo;staticchar *get_multi_preamble_text( size_t *len){#define MPREAMBLE_STR "HTTP/1.0 200 OK\n" \ "Content-type: multipart/x-mixed-replace;boundary=" RANDOMSTRING "\n" \ "Cache-Control: no-cache\n" \ "Cache-Control: private\n" \ "Pragma: no-cache\n\n" \ "--" RANDOMSTRING "\n" \ "Content-type: " CONTENTTYPE "\n\n" if( len != NULL ) *len = sizeof( MPREAMBLE_STR ) - 1; return MPREAMBLE_STR;}staticchar *get_single_preamble_text( size_t *len){#define SPREAMBLE_STR "HTTP/1.0 200 OK\n" \ "Content-type: " CONTENTTYPE "\n" \ "Cache-Control: no-cache\n" \ "Cache-Control: private\n" \ "Pragma: no-cache\n\n" if( len != NULL ) *len = sizeof( SPREAMBLE_STR ) - 1; return SPREAMBLE_STR;}staticchar *get_seperator_text( size_t *len ){#define SEPERATOR_TEXT "\n--" RANDOMSTRING "\n" \ "Content-type: " CONTENTTYPE "\n\n" /* XXX */ if( len != NULL ) *len = sizeof( SEPERATOR_TEXT ) - 1; return SEPERATOR_TEXT;}static ClientInfo *clientinfo_new( Socket *sock ){ ClientInfo *res; if( (res = malloc( sizeof( *res ))) == NULL ) return NULL; if( (res->writebuf = databuf_new()) == NULL ){ free( res ); return NULL; } res->management_data = NULL; res->socket = sock; res->state = CINFO_STATE_PREAMBLE; res->last_picture_id = -1; res->client_type = CLIENT_T_UNINIT; return res;}staticvoid clientinfo_dest( ClientInfo *cinfo ){ databuf_dest( cinfo->writebuf ); socket_dest( cinfo->socket ); if( cinfo->management_data ){ manager_dest_client( cinfo->management_data ); } free( cinfo );}/* * accept_client: Accept a client from the listen_socket, and return * a clientinfo structure containing it. The new socket * will be set to non-blocking IO mode. * * Arguments: listen_socket = Socket requiring an accept() operation. * * Return values: Returns NULL on failure, else a valid pointer to a freshly * allocated ClientInfo structure. */staticClientInfo *accept_client( const Socket *listen_socket ){ Socket *new_sock; ClientInfo *res; if( (new_sock = socket_accept( listen_socket )) == NULL ){ camserv_log( MODNAME, "Could not accept new client socket: %s", strerror( errno )); return NULL; } camserv_log( MODNAME, "Accepted new socket: %s", socket_query_remote_name( new_sock )); if( fcntl( socket_query_fd( new_sock ), F_SETFL, O_NONBLOCK ) == -1){ camserv_log( MODNAME, "Unable to set socket to nonblocking mode!"); socket_dest( new_sock ); return NULL; } if( (res = clientinfo_new( new_sock )) == NULL ){ camserv_log( MODNAME, "Error creating clientinfo structure!"); socket_dest( new_sock ); return NULL; } return res;} staticint dispatch_pictaker( const char *cmdbuf, const char *picture_mem ){ int command; if( sscanf( cmdbuf, "%d", &command ) != 1 ){ camserv_log( MODNAME, "Parse error reading data from pictaker!"); return -1; } if( command == 0 ) { char *new_picture_data; int nbytes; sscanf( cmdbuf, "%*d %d", &nbytes ); if( (new_picture_data = malloc( nbytes )) == NULL ){ camserv_log( MODNAME, "Error allocating memory to manage picture!"); return -1; } memcpy( new_picture_data, picture_mem, nbytes ); if( manager_new_picture( new_picture_data, nbytes, 100 ) == -1 ){ camserv_log( MODNAME, "Unable to manage picture!"); free( new_picture_data ); return -1; } } else { camserv_log( MODNAME, "Unknown pictaker dispatch command: %d", command ); return -1; } return 0;}staticint write_proxy_client( ClientInfo *cinfo, SockSet *writeset ){ int bufwrite; bufwrite = databuf_write( cinfo->writebuf, socket_query_fd( cinfo->socket )); if( bufwrite == -1 ) return -1; if( bufwrite == 1 ) return 0; /* In this case, we are done sending whatever it was that 'state' referred to */ if( cinfo->state == CINFO_STATE_SENDSIZE ) { databuf_buf_set( cinfo->writebuf, cinfo->proxypic_data, ntohl( cinfo->proxypic_size )); cinfo->state = CINFO_STATE_PICTURE; } else { /* Just finished sending a picture */ char *pic_data; size_t pic_size; int pic_id; /* Remove old info */ if( cinfo->management_data != NULL ) { if( manager_dest_client( cinfo->management_data ) == -1 ){ camserv_log( MODNAME, "Error destroying client management!"); } } cinfo->management_data = manager_new_client(&pic_data, &pic_size, &pic_id); if( cinfo->management_data == NULL ){ camserv_log( MODNAME, "Error managing proxy! (Picture may not be " "taken yet)"); sockset_hold( writeset, cinfo->socket ); return 0; } if( pic_id == cinfo->last_picture_id ) { manager_dest_client( cinfo->management_data ); cinfo->management_data = NULL; /* Proxy sucking too fast */ sockset_hold( writeset, cinfo->socket ); return 0; } camserv_log( MODNAME, "Writing picsize %d to client", (int) pic_size ); cinfo->proxypic_data = pic_data; cinfo->proxypic_size = htonl( pic_size ); cinfo->last_picture_id = pic_id; databuf_buf_set( cinfo->writebuf, &cinfo->proxypic_size, sizeof( cinfo->proxypic_size )); cinfo->state = CINFO_STATE_SENDSIZE; } return 0;}staticint write_regular_client( ClientInfo *cinfo, SockSet *writeset ){ switch(databuf_write( cinfo->writebuf, socket_query_fd( cinfo->socket ))) { case -1 : /* Error */ return -1; break; case 0: /* All done feeding client the current data */ if( cinfo->state == CINFO_STATE_PREAMBLE || cinfo->state == CINFO_STATE_SEPERATOR ) { char *pic_data; size_t pic_size; int pic_id; cinfo->management_data = manager_new_client( &pic_data, &pic_size, &pic_id ); if( cinfo->management_data == NULL ){ camserv_log( MODNAME, "Error managing client! (Picture may not" " be taken yet)"); /* Wait for the next successful picture to come around */ sockset_hold( writeset, cinfo->socket ); return 0; } if( pic_id == cinfo->last_picture_id ) { manager_dest_client( cinfo->management_data ); cinfo->management_data = NULL; /* Whoa boy! Hold on a second! */ sockset_hold( writeset, cinfo->socket ); return 0; } databuf_buf_set( cinfo->writebuf, pic_data, pic_size ); cinfo->last_picture_id = pic_id; cinfo->state = CINFO_STATE_PICTURE; /* Accounting stuff */ cinfo->frames++; cinfo->bytes += pic_size; } else { /* Just finished sending a picture */ char *sep_data; size_t sep_size; if( manager_dest_client( cinfo->management_data ) == -1 ){ camserv_log( MODNAME, "Error destroying client management!"); } cinfo->management_data = NULL; cinfo->state = CINFO_STATE_SEPERATOR; /* For single-frame clients we are done now, and drop them */ if( cinfo->client_type == CLIENT_T_SINGLE ) return 1; /* Check resource limits */ if( cinfo->max_seconds && (time( NULL ) - cinfo->create_time) > cinfo->max_seconds ) { camserv_log( MODNAME, "Dropping client \"%s\", time limit exceeded", socket_query_remote_name( cinfo->socket )); return 1; } if( cinfo->max_bytes && cinfo->bytes > cinfo->max_bytes ) { camserv_log( MODNAME, "Dropping client \"%s\", byte limit exceeded", socket_query_remote_name( cinfo->socket )); return 1; } if( cinfo->max_frames && cinfo->frames > cinfo->max_frames ) { camserv_log( MODNAME, "Dropping client \"%s\", frame limit exceeded", socket_query_remote_name( cinfo->socket ));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -