00001
00009 #define _GNU_SOURCE
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <errno.h>
00014 #include <time.h>
00015 #include <assert.h>
00016 #include <string.h>
00017 #include <fcntl.h>
00018 #include <stdarg.h>
00019
00020 #define BUILD_DLL_MIHL
00021 #include "mihl.h"
00022
00023 #define __MAIN__
00024 #include "glovars.h"
00025
00026 #include "tcp_utils.h"
00027 #include "b64.h"
00028
00041 static int add_new_connexion( mihl_ctx_t *ctx, SOCKET sockfd, struct sockaddr_in *client_addr ) {
00042
00043
00044 if ( ctx->nb_connexions == ctx->maxnb_cnx ) {
00045 oops:;
00046 mihl_log( ctx, MIHL_LOG_INFO, "Too many connexions (%d): connexion refused\015\012",
00047 ctx->nb_connexions );
00048 return -1;
00049 }
00050 mihl_cnx_t *cnx = NULL;
00051 for ( int ncnx = 0; ncnx < ctx->maxnb_cnx; ncnx++ ) {
00052 cnx = &ctx->connexions[ncnx];
00053 if ( !cnx->active )
00054 break;
00055 }
00056 if ( cnx == NULL )
00057 goto oops;
00058 ctx->nb_connexions++;
00059
00060 cnx->active = 1;
00061 cnx->sockfd = sockfd;
00062 memmove( &cnx->info.client_addr, client_addr, sizeof(struct sockaddr_in) );
00063 cnx->info.time_started = time( NULL );
00064 cnx->info.time_last_data = cnx->info.time_started;
00065 cnx->info.last_request = NULL;
00066 cnx->info.host = NULL;
00067 cnx->info.user_agent = NULL;
00068 cnx->keep_alive = 300;
00069 cnx->authorization = NULL;
00070 cnx->html_buffer_len = 0;
00071 cnx->html_buffer_sz = 8192;
00072 cnx->html_buffer = (char*)malloc(cnx->html_buffer_sz);
00073 strcpy( cnx->html_buffer, "" );
00074
00075 mihl_log( ctx, MIHL_LOG_INFO_VERBOSE, "\015\012Accepted a connexion from %s, socket=%d\015\012",
00076 inet_ntoa( cnx->info.client_addr.sin_addr ), sockfd );
00077
00078 return ctx->nb_connexions-1;
00079 }
00080
00087 static void delete_connexion( mihl_cnx_t *cnx ) {
00088 mihl_ctx_t *ctx = cnx->ctx;
00089 mihl_log( ctx, MIHL_LOG_INFO_VERBOSE, "Delete connexion for socket %d\015\012", cnx->sockfd );
00090 shutdown( cnx->sockfd, SHUT_RDWR );
00091 closesocket( cnx->sockfd );
00092 cnx->active = 0;
00093 mihl_cnxinfo_t *info = &cnx->info;
00094 if ( info->last_request )
00095 FREE( info->last_request );
00096 if ( info->host )
00097 FREE( info->host );
00098 if ( info->user_agent )
00099 FREE( info->user_agent );
00100 if ( cnx->html_buffer )
00101 FREE( cnx->html_buffer );
00102 ctx->nb_connexions--;
00103 }
00104
00113 static int bind_and_listen( mihl_ctx_t *ctx ) {
00114
00115
00116 ctx->sockfd = socket( AF_INET, SOCK_STREAM, 0 );
00117 if ( ctx->sockfd < 0 ) {
00118 mihl_log( ctx, MIHL_LOG_ERROR, "Unable to open a socket!\015\012" );
00119 exit( -1 );
00120 }
00121
00122
00123 const int flag = 1;
00124 if ( setsockopt( ctx->sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&flag, sizeof( flag ) ) < 0 ) {
00125 mihl_log( ctx, MIHL_LOG_ERROR, "Unable to setsockopt a socket!\015\012" );
00126 exit( -1 );
00127 }
00128
00129
00130 fcntl( ctx->sockfd, F_SETFL, fcntl( ctx->sockfd, F_GETFL, 0 ) | O_NONBLOCK );
00131
00132
00133 struct sockaddr_in server_addr;
00134 memset( &server_addr, 0, sizeof( server_addr ) );
00135 server_addr.sin_family = AF_INET;
00136 if ( !strcmp( ctx->bind_addr, "" ) )
00137 server_addr.sin_addr.s_addr = htonl( INADDR_ANY );
00138 else
00139 server_addr.sin_addr.s_addr = inet_addr(ctx->bind_addr);
00140 server_addr.sin_port = htons( ctx->port );
00141 int status = bind( ctx->sockfd, ( struct sockaddr * ) &server_addr, sizeof( struct sockaddr_in ) );
00142 if ( (status == SOCKET_ERROR) && (ERRNO == EADDRINUSE) ) {
00143 mihl_log( ctx, MIHL_LOG_ERROR, "%s %d\015\012\tUnable to bind, port %d is already in use\015\012",
00144 __FILE__, __LINE__,
00145 ctx->port );
00146 if ( closesocket( ctx->sockfd ) == -1 )
00147 mihl_log( ctx, MIHL_LOG_ERROR, "Error %d while closing socket %d\015\012",
00148 errno, ctx->sockfd );
00149 return -1;
00150 }
00151 if ( status < 0 ) {
00152 mihl_log( ctx, MIHL_LOG_ERROR, "%s %d\015\012Unable to bind - port %d - status=%d errno=%s\015\012",
00153 __FILE__, __LINE__,
00154 ctx->port,
00155 status, strerror( errno ) );
00156 if ( closesocket( ctx->sockfd ) == -1 )
00157 mihl_log( ctx, MIHL_LOG_ERROR, "Error %d while closing socket %d\015\012",
00158 errno, ctx->sockfd );
00159 return -1;
00160 }
00161
00162 return listen( ctx->sockfd, 8 );
00163
00164 }
00165
00175 static int page_not_found( mihl_cnx_t *cnx, char const *tag, char const *host, void *param ) {
00176 mihl_add( cnx, "<html>" );
00177 mihl_add( cnx, "<head>" );
00178 mihl_add( cnx, "</head>" );
00179 mihl_add( cnx, "<br>" );
00180 mihl_add( cnx, " THIS PAGE IS NOT FOUND " );
00181 mihl_add( cnx, "<br>" );
00182 mihl_add( cnx, "[%s]", tag );
00183 mihl_add( cnx, "<br>" );
00184 mihl_add( cnx, "</body>" );
00185 mihl_add( cnx, "</html>" );
00186 return mihl_send( cnx, NULL,
00187 "Content-type: text/html\r\n" );
00188 }
00189
00210 mihl_ctx_t *mihl_init( char const *bind_addr, int port, int maxnb_cnx, unsigned log_level ) {
00211
00212 mihl_ctx_t *ctx = (mihl_ctx_t *)malloc( sizeof(mihl_ctx_t) );
00213 if ( ctx == NULL )
00214 return NULL;
00215 if ( !bind_addr )
00216 strcpy( ctx->bind_addr, "" );
00217 else
00218 strncpy( ctx->bind_addr, bind_addr, sizeof(ctx->bind_addr)-1 );
00219 ctx->port = port;
00220 ctx->maxnb_cnx = maxnb_cnx;
00221 ctx->log_level = log_level;
00222
00223 ctx->nb_connexions = 0;
00224 ctx->connexions = (mihl_cnx_t *) malloc( sizeof(mihl_cnx_t) * ctx->maxnb_cnx );
00225 if ( ctx->connexions == NULL ) {
00226 free( ctx );
00227 return NULL;
00228 }
00229 for ( int ncnx = 0; ncnx < ctx->maxnb_cnx; ncnx++ ) {
00230 mihl_cnx_t *cnx = &ctx->connexions[ncnx];
00231 cnx->ctx = ctx;
00232 cnx->active = 0;
00233 }
00234
00235 ctx->read_buffer_maxlen = 8*1024*1024;
00236 ctx->read_buffer = (char *)malloc( ctx->read_buffer_maxlen );
00237
00238
00239 ctx->nb_handles = 0;
00240 ctx->handles = NULL;
00241 mihl_handle_get( ctx, NULL, page_not_found, NULL );
00242
00243 bind_and_listen( ctx );
00244
00245 return ctx;
00246 }
00247
00255 mihl_ctx_t *mihl_get_ctx( mihl_cnx_t *cnx ) {
00256 return cnx->ctx;
00257 }
00258
00268 int mihl_end( mihl_ctx_t *ctx ) {
00269 FREE( ctx->read_buffer );
00270 return 0;
00271 }
00272
00283 int send_file( mihl_cnx_t *cnx, char const *tag, char const *filename, char *content_type, int close_connection ) {
00284 char *file;
00285 int length;
00286 if ( read_file( filename, &file, &length ) == -1 ) {
00287 return -1;
00288 }
00289
00290
00291 time_t now = time( NULL );
00292 struct tm *tm = gmtime( &now );
00293 char date[80];
00294 strftime( date, sizeof(date)-1, "%c", tm );
00295 char msg1[1024];
00296 int len = sprintf( msg1,
00297 "HTTP/1.1 200 OK\r\n"
00298 "Accept-Ranges: bytes\r\n"
00299 "Content-Length: %d\r\n"
00300 "Date: %s\r\n"
00301 "Content-Type: %s\r\n"
00302 "Connection: %s\r\n"
00303 "\r\n",
00304 length, date, content_type,
00305 (close_connection) ? "close" : "keep-alive" );
00306 int dcount = tcp_write( cnx->sockfd, msg1, len );
00307 if ( dcount == -1 ) {
00308 mihl_log( cnx->ctx, MIHL_LOG_ERROR, "\015\012*** %s %d: OOPS - %m!!!!!\015\012", __FILE__, __LINE__ );
00309 return -1;
00310 }
00311
00312 char *p = file;
00313 int rem = length;
00314 for (;;) {
00315 int count = MIN( rem, 16384 );
00316 dcount = tcp_write( cnx->sockfd, (const char *)p, count );
00317 if ( dcount == -1 ) {
00318 mihl_log( cnx->ctx, MIHL_LOG_ERROR, "\015\012*** %s %d: - %m!!!!!\015\012", __FILE__, __LINE__ );
00319 return -1;
00320 }
00321 rem -= count;
00322 if ( rem == 0 )
00323 break;
00324 p += count;
00325 }
00326
00327 free( file );
00328 return 0;
00329 }
00330
00344 static int search_for_handle( mihl_cnx_t *cnx, char const *tag, char *host, int nb_variables, char **vars_names, char **vars_values ) {
00345 mihl_ctx_t *ctx = cnx->ctx;
00346 mihl_handle_t *handle_nfound = NULL;
00347 for ( int n = 0; n < ctx->nb_handles; n++ ) {
00348 mihl_handle_t *handle = &ctx->handles[n];
00349 if ( !handle->tag ) {
00350 handle_nfound = handle;
00351 }
00352 if ( handle->tag &&
00353 ((!handle->partial && !strcmp(tag, handle->tag)) || (handle->partial && !strncmp(tag, handle->tag, handle->partial))) ) {
00354 if ( handle->pf_get )
00355 return handle->pf_get( cnx, tag, host, handle->param );
00356 if ( handle->pf_post )
00357 return handle->pf_post( cnx, tag, host, nb_variables, vars_names, vars_values, handle->param );
00358 return send_file( cnx, tag, handle->filename, handle->content_type, handle->close_connection );
00359 }
00360 }
00361 if ( handle_nfound )
00362 return handle_nfound->pf_get( cnx, tag, host, handle_nfound->param );
00363 return 0;
00364 }
00365
00375 static int manage_new_connexions( mihl_ctx_t *ctx, time_t now ) {
00376 for (;;) {
00377 socklen_t client_addr_len = sizeof( struct sockaddr_in );
00378 struct sockaddr_in client_addr;
00379 SOCKET sockfd_accept = accept( ctx->sockfd,
00380 (struct sockaddr *)&client_addr, &client_addr_len );
00381
00382 if ( sockfd_accept == -1 ) {
00383 if ( (ERRNO == EAGAIN) || (ERRNO == EWOULDBLOCK) )
00384 return 0;
00385 if ( errno == EINTR ) {
00386 mihl_log( ctx, MIHL_LOG_ERROR, "!!! %d !!!\015\012", __LINE__ );
00387
00388 continue;
00389 }
00390 mihl_log( ctx, MIHL_LOG_ERROR, "Socket non accepted - errno=%d\015\012", ERRNO );
00391 if ( closesocket( ctx->sockfd ) == -1 ) {
00392 mihl_log( ctx, MIHL_LOG_ERROR, "Error %d while closing socket %d\015\012", errno, ctx->sockfd );
00393 }
00394 exit( -1 );
00395 }
00396
00397 return add_new_connexion( ctx, sockfd_accept, &client_addr );
00398 }
00399 }
00400
00407 static int got_data_for_active_connexion( mihl_cnx_t *cnx ) {
00408
00409 mihl_ctx_t *ctx = cnx->ctx;
00410 int len = 0;
00411 for (;;) {
00412 int l = tcp_read( cnx->sockfd, &ctx->read_buffer[len], ctx->read_buffer_maxlen-len );
00413 if ( l == 0 )
00414 break;
00415 len += l;
00416 char *p = strstr( ctx->read_buffer, "\r\n\r\n" );
00417 if ( p )
00418 break;
00419 }
00420
00421 if ( len == ctx->read_buffer_maxlen-1 )
00422 return 0;
00423 if ( ctx->log_level & MIHL_LOG_DEBUG ) {
00424 mihl_log( cnx->ctx, MIHL_LOG_DEBUG, "\015\012%d:[%s]\015\012", cnx->sockfd, ctx->read_buffer );
00425 }
00426 else {
00427 char *p = strchr( ctx->read_buffer, '\015' );
00428 if ( p )
00429 *p = 0;
00430 mihl_log( cnx->ctx, MIHL_LOG_INFO_VERBOSE, "[%s]\015\012", ctx->read_buffer );
00431 if ( p )
00432 *p = '\015';
00433 }
00434
00435 if ( len == 0 ) {
00436 cnx->info.time_last_data = 0;
00437 return -1;
00438 }
00439 cnx->info.time_last_data = time( NULL );
00440
00441
00442
00443 int version, subversion;
00444 char tag[1024];
00445 strcpy( tag, "" );
00446 if ( (len >= 14) && (!strncmp( ctx->read_buffer, "GET", 3 )) ) {
00447 char _tag[1024];
00448 int status = sscanf( ctx->read_buffer, "GET %s HTTP/%d.%d",
00449 _tag, &version, &subversion );
00450 if ( status == 3 ) {
00451 strncpy( tag, _tag, sizeof(tag)-1 );
00452 cnx->info.last_request = strdup(tag);
00453 }
00454 }
00455 else if ( (len >= 14) && (!strncmp( ctx->read_buffer, "POST", 4 )) ) {
00456 char _tag[1024];
00457 int status = sscanf( ctx->read_buffer, "POST %s HTTP/%d.%d",
00458 _tag, &version, &subversion );
00459 if ( status == 3 ) {
00460 strncpy( tag, _tag, sizeof(tag)-1 );
00461 cnx->info.last_request = strdup(tag);
00462 }
00463 }
00464
00465
00466
00467
00468 int nb_options;
00469 char *options_names[80], *options_values[80];
00470 int nb_variables;
00471 char *vars_names[80], *vars_values[80];
00472 decode_keys_values( cnx, ctx->read_buffer,
00473 &nb_options, options_names, options_values, 80,
00474 &nb_variables, vars_names, vars_values, 80 );
00475 #if 0
00476 {
00477 static int cpt = 0;
00478 printf( "%3d: len=%d / %d nbopt=%d nbvars=%d\015\12", cpt, len, ctx->read_buffer_maxlen, nb_options, nb_variables );
00479 fflush( stdout);
00480 char fname[100];
00481 sprintf( fname, "a%03d", cpt );
00482 FILE *fp = fopen( fname, "w" );
00483 fwrite( ctx->read_buffer, len, 1, fp );
00484 fclose( fp );
00485 sprintf( fname, "b%03d", cpt++ );
00486 fp = fopen( fname, "w" );
00487 fprintf( fp, "%3d: len=%d / %d nbopt=%d nbvars=%d\015\12",
00488 cpt, len, ctx->read_buffer_maxlen, nb_options, nb_variables );
00489 fprintf( fp, "\015\012" );
00490 for ( int n = 0; n < nb_options; n++ )
00491 fprintf( fp, " %2d: %s = [%s]\015\012", n, options_names[n], options_values[n] );
00492 fprintf( fp, "\015\012" );
00493 for ( int n = 0; n < nb_variables; n++ )
00494 fprintf( fp, " %2d: %s = [%s]\015\012", n, vars_names[n], vars_values[n] );
00495 fclose( fp );
00496 }
00497 #endif
00498
00499
00500
00501
00502 search_for_handle( cnx, tag, cnx->info.host,
00503 nb_variables, vars_names, vars_values );
00504
00505
00506 for ( int n = 0; n < nb_options; n++ ) {
00507 free( options_names[n] );
00508 free( options_values[n] );
00509 }
00510
00511 return 1;
00512 }
00513
00521 static int manage_existent_connexions( mihl_ctx_t *ctx, time_t now ) {
00522
00523
00524 if ( ctx->nb_connexions == 0 )
00525 return 0;
00526
00527 SOCKET last_sockfd = -1;
00528 fd_set ready;
00529 FD_ZERO( &ready );
00530 for ( int ncnx = 0; ncnx < ctx->maxnb_cnx; ncnx++ ) {
00531 mihl_cnx_t *cnx = &ctx->connexions[ncnx];
00532 if ( !cnx->active )
00533 continue;
00534 FD_SET( cnx->sockfd, &ready );
00535 if ( cnx->sockfd > last_sockfd )
00536 last_sockfd = cnx->sockfd;
00537 }
00538
00539 struct timeval tv;
00540 tv.tv_sec = 0;
00541 tv.tv_usec = 0;
00542 int status = select( (int)last_sockfd+1, &ready, NULL, NULL, &tv );
00543 if ( status == 0 )
00544 return 0;
00545 assert( status != -1 );
00546
00547 for ( int ncnx = 0; ncnx < ctx->maxnb_cnx; ncnx++ ) {
00548 mihl_cnx_t *cnx = &ctx->connexions[ncnx];
00549 if ( !cnx->active )
00550 continue;
00551 if ( FD_ISSET( cnx->sockfd, &ready ) ) {
00552 got_data_for_active_connexion( cnx );
00553 }
00554 }
00555
00556 return 1;
00557 }
00558
00566 static int manage_timedout_connexions( mihl_ctx_t *ctx, time_t now ) {
00567 for ( int ncnx = 0; ncnx < ctx->maxnb_cnx; ncnx++ ) {
00568 mihl_cnx_t *cnx = &ctx->connexions[ncnx];
00569 if ( !cnx->active )
00570 continue;
00571 int t = (int)difftime( now, cnx->info.time_last_data );
00572 if ( t >= cnx->keep_alive )
00573 delete_connexion( cnx );
00574 }
00575 return 0;
00576 }
00577
00592 static int mihl_handle_get_add( mihl_ctx_t *ctx, char const *tag, mihl_pf_handle_get_t *pf, void *param ) {
00593 if ( ctx->handles == NULL )
00594 ctx->handles = (mihl_handle_t *)malloc( sizeof(mihl_handle_t) );
00595 else
00596 ctx->handles = (mihl_handle_t *)realloc( ctx->handles, sizeof(mihl_handle_t) * (ctx->nb_handles+1) );
00597 if ( !ctx->handles )
00598 return -1;
00599 mihl_handle_t *handle = &ctx->handles[ctx->nb_handles++];
00600 if ( tag ) {
00601 handle->tag = strdup( tag );
00602 if ( !strchr( tag, '*') )
00603 handle->partial = 0;
00604 else
00605 handle->partial = strlen(tag)-1;
00606 }
00607 else {
00608 handle->tag = NULL;
00609 }
00610 handle->pf_get = pf;
00611 handle->pf_post = NULL;
00612 handle->param = param;
00613 handle->filename = NULL;
00614 handle->content_type = NULL;
00615 handle->close_connection = 0;
00616 return ctx->nb_handles;
00617 }
00618
00634 int mihl_handle_get( mihl_ctx_t *ctx, char const *tag, mihl_pf_handle_get_t *pf, void *param ) {
00635
00636
00637 mihl_handle_t *handle_found = NULL;
00638 for ( int n = 0; n < ctx->nb_handles; n++ ) {
00639 mihl_handle_t *handle = &ctx->handles[n];
00640 if ( handle->pf_post || handle->filename || !handle->pf_get )
00641 continue;
00642 if ( !handle->tag && !tag ) {
00643 handle_found = handle;
00644 break;
00645 }
00646 if ( handle->tag &&
00647 ((!handle->partial && !strcmp(tag, handle->tag)) || (handle->partial && !strncmp(tag, handle->tag, handle->partial))) ) {
00648 handle_found = handle;
00649 break;
00650 }
00651 }
00652
00653
00654 if ( !handle_found )
00655 return mihl_handle_get_add( ctx, tag, pf, param );
00656
00657
00658 if ( handle_found->tag )
00659 FREE( handle_found->tag );
00660 if ( pf ) {
00661 handle_found->pf_get = pf;
00662 if ( tag )
00663 handle_found->tag = strdup( tag );
00664 }
00665
00666 return -1;
00667 }
00668
00683 int mihl_handle_post( mihl_ctx_t *ctx, char const *tag, mihl_pf_handle_post_t *pf, void *param ) {
00684 if ( tag == NULL )
00685 return -1;
00686 if ( ctx->handles == NULL ) {
00687 ctx->handles = (mihl_handle_t *)malloc( sizeof(mihl_handle_t) );
00688 }
00689 else {
00690 ctx->handles = (mihl_handle_t *)realloc( ctx->handles, sizeof(mihl_handle_t) * (ctx->nb_handles+1) );
00691 }
00692 mihl_handle_t *handle = &ctx->handles[ctx->nb_handles++];
00693 handle->tag = strdup( tag );
00694 if ( strchr( tag, '*') )
00695 handle->partial = 0;
00696 else
00697 handle->partial = strlen(tag)-1;
00698 handle->pf_get = NULL;
00699 handle->pf_post = pf;
00700 handle->param = param;
00701 handle->filename = NULL;
00702 handle->content_type = NULL;
00703 handle->close_connection = 0;
00704 return ctx->nb_handles;
00705 }
00706
00719 int mihl_handle_file( mihl_ctx_t *ctx, char const *tag, char const *filename, char const *content_type, int close_connection ) {
00720 if ( tag == NULL )
00721 return -1;
00722 if ( !filename || !content_type )
00723 return -1;
00724 if ( ctx->handles == NULL )
00725 ctx->handles = (mihl_handle_t *)malloc( sizeof(mihl_handle_t) );
00726 else
00727 ctx->handles = (mihl_handle_t *)realloc( ctx->handles, sizeof(mihl_handle_t) * (ctx->nb_handles+1) );
00728 if ( !ctx->handles )
00729 return -1;
00730 mihl_handle_t *handle = &ctx->handles[ctx->nb_handles++];
00731 handle->tag = strdup( tag );
00732 if ( strchr( tag, '*') )
00733 handle->partial = 0;
00734 else
00735 handle->partial = strlen(tag)-1;
00736 handle->pf_get = NULL;
00737 handle->pf_post = NULL;
00738 handle->filename = strdup( filename );
00739 handle->content_type = strdup( content_type );
00740 handle->close_connection = close_connection;
00741 return ctx->nb_handles;
00742 }
00743
00763 int mihl_server( mihl_ctx_t *ctx ) {
00764 time_t now = time( NULL );
00765 manage_new_connexions( ctx, now );
00766 manage_existent_connexions( ctx, now );
00767 manage_timedout_connexions( ctx, now );
00768 return ctx->nb_connexions;
00769 }
00770
00777 void mihl_set_log_level( mihl_ctx_t *ctx, mihl_log_level_t level ) {
00778 ctx->log_level = level;
00779 }
00780
00787 mihl_log_level_t mihl_get_log_level( mihl_ctx_t *ctx ) {
00788 return ctx->log_level;
00789 }
00790
00800 int mihl_log( mihl_ctx_t *ctx, unsigned level, const char *fmt, ... ) {
00801 if ( !(level & ctx->log_level) )
00802 return 0;
00803 va_list ap;
00804 va_start( ap, fmt );
00805 int len = vprintf( fmt, ap );
00806 va_end( ap );
00807 fflush( stdout );
00808 return len;
00809 }
00810
00817 int mihl_dump_info( mihl_ctx_t *ctx ) {
00818 unsigned level = ctx->log_level;
00819 ctx->log_level = MIHL_LOG_ERROR | MIHL_LOG_WARNING | MIHL_LOG_INFO |
00820 MIHL_LOG_INFO_VERBOSE | MIHL_LOG_DEBUG;
00821 mihl_log( ctx, MIHL_LOG_DEBUG, "%d active connexions\015\012", ctx->nb_connexions );
00822 if ( ctx->nb_connexions == 0 )
00823 return 0;
00824 printf( "Sockfd Client Start Inact Last Request\015\012" );
00825 time_t now = time( NULL );
00826 for ( int ncnx = 0; ncnx < ctx->maxnb_cnx; ncnx++ ) {
00827 mihl_cnx_t *cnx = &ctx->connexions[ncnx];
00828 if ( cnx->active ) {
00829 char client[20+1];
00830 strncpy( client, inet_ntoa( cnx->info.client_addr.sin_addr ), 20 );
00831 client[20] = 0;
00832 printf( "%6d %-20s %4d\" %4d\" %s\015\012",
00833 cnx->sockfd,
00834 client,
00835 (int)(now - cnx->info.time_started),
00836 (int)(now - cnx->info.time_last_data),
00837 cnx->info.last_request );
00838 }
00839 }
00840 fflush( stdout );
00841 ctx->log_level = level;
00842 return ctx->nb_connexions;
00843 }
00844
00855 int mihl_info( mihl_ctx_t *ctx, int maxnb_cnxinfos, mihl_cnxinfo_t *infos ) {
00856 if ( maxnb_cnxinfos <= 0 )
00857 return 0;
00858 int nb_cnxinfos = 0;
00859 for ( int ncnx = 0; ncnx < ctx->maxnb_cnx; ncnx++ ) {
00860 mihl_cnx_t *cnx = &ctx->connexions[ncnx];
00861 if ( !cnx->active )
00862 continue;
00863 memmove( &infos[nb_cnxinfos++], &cnx->info, sizeof(mihl_cnxinfo_t) );
00864 if ( nb_cnxinfos == maxnb_cnxinfos )
00865 break;
00866 }
00867 return nb_cnxinfos;
00868 }
00869
00876 int mihl_dump_info_handlers( mihl_ctx_t *ctx ) {
00877 unsigned level = ctx->log_level;
00878 ctx->log_level = MIHL_LOG_ERROR | MIHL_LOG_WARNING | MIHL_LOG_INFO |
00879 MIHL_LOG_INFO_VERBOSE | MIHL_LOG_DEBUG;
00880 mihl_log( ctx, MIHL_LOG_DEBUG, "%d handles\015\012", ctx->nb_handles );
00881 printf( " %-32s %-32s\r\n", "Tag", "Type" );
00882 for ( int n = 0; n < ctx->nb_handles; n++ ) {
00883 mihl_handle_t *handle = &ctx->handles[n];
00884 char tag[32];
00885 memset( tag, 0, sizeof(tag) );
00886 if ( !handle->tag )
00887 strcpy( tag, "" );
00888 else
00889 strncpy( tag, handle->tag, sizeof(tag)-1 );
00890 char type[32];
00891 memset( type, 0, sizeof(type) );
00892 if ( handle->pf_get )
00893 strcpy( type, "*GET*" );
00894 else if ( handle->pf_post )
00895 strcpy( type, "*POST*" );
00896 else if ( handle->filename != NULL )
00897 strncpy( type, handle->filename, sizeof(type)-1 );
00898 printf( "%2d: %-32s %-32s", n, tag, type );
00899 printf( "\015\012" );
00900 }
00901 fflush( stdout );
00902 ctx->log_level = level;
00903 return ctx->nb_connexions;
00904 }
00905
00912 char *mihl_authorization( mihl_cnx_t *cnx ) {
00913 return cnx->authorization;
00914 }