klhttp.c
上传用户:jnmzc84
上传日期:2022-08-08
资源大小:35k
文件大小:5k
源码类别:

网络编程

开发平台:

Visual C++

  1. /**
  2.   @file klhttp.c
  3.   @author Kevin Lynx
  4.   @date 7.29.2008
  5.   @brief the interface of klhttpd ( an simple embeded http server )
  6. */
  7. #include "klhttp-config.h"
  8. #include "klhttp.h"
  9. #include "evbuffer.h"
  10. #include "klhttp-netbase.h"
  11. #include "klhttp-internal.h"
  12. #include <malloc.h>
  13. #ifdef WIN32
  14. #include <winsock2.h>
  15. #endif
  16. /**
  17.   info log
  18. */
  19. static info_log_cb s_log;
  20. /**
  21.   helper function to support fmt.
  22. */
  23. static void _log( const char *fmt, ... )
  24. {
  25. if( s_log )
  26. {
  27. static char info[512];
  28. va_list list;
  29. va_start( list, fmt );
  30. vsprintf( info, fmt, list );
  31. va_end( list );
  32. s_log( info );
  33. }
  34. }
  35. /**
  36.   get the connection object.
  37. */
  38. static struct http_connection *_get_conn( struct http_connection_head *head, int fd )
  39. {
  40. struct http_connection *conn;
  41. LIST_FOREACH( conn, head, next )
  42. {
  43. if( fd == conn->fd )
  44. {
  45. return conn;
  46. }
  47. }
  48. return 0;
  49. }
  50. /**
  51.   accept new client.
  52. */
  53. static void _accept_conn( struct tcp_server *server, struct http_connection_head *head, int fd )
  54. {
  55. struct sockaddr_in addr;
  56. int len = sizeof( addr );
  57. int conn_fd = (int)accept( fd, (struct sockaddr*)&addr, &len );
  58. if( conn_fd < 0 )
  59. {
  60. return ;
  61. }
  62. _log( "accept a new connection : %s-%d", inet_ntoa( addr.sin_addr ), ntohs( addr.sin_port ) );
  63. {
  64. struct http_connection *conn = (struct http_connection*) malloc( sizeof( struct http_connection ) );
  65. conn->fd = conn_fd;
  66. conn->inbuf = evbuffer_new();
  67. conn->outbuf = evbuffer_new();
  68. /* add the fd into the server */
  69. ts_server_add( server, conn_fd );
  70. /* insert into the list */
  71. LIST_INSERT_HEAD( head, conn, next );
  72. }
  73. }
  74. /** 
  75.   disconnect a connection.
  76. */
  77. static void _disconnect_conn( struct http_connection *conn )
  78. {
  79. closesocket( conn->fd );
  80. evbuffer_free( conn->inbuf );
  81. evbuffer_free( conn->outbuf );
  82. }
  83. /**
  84.   retrieve the socket name 
  85. */
  86. static const char *_get_fd_name( int fd )
  87. {
  88. static char buf[64];
  89. struct sockaddr_in addr;
  90. int len = sizeof( addr );
  91. int ret = getpeername( fd, (struct sockaddr*)&addr, &len );
  92. if( ret < 0 )
  93. {
  94. return "0.0.0.0:0";
  95. }
  96. sprintf( buf, "%s:%d", inet_ntoa( addr.sin_addr ), ntohs( addr.sin_port ) );
  97. return buf;
  98. }
  99. /**
  100.   handle read.
  101. */
  102. static void _read_cb( int fd, void *arg )
  103. {
  104. struct http_server *server = (struct http_server*)arg;
  105. if( fd == server->server->fd )
  106. {
  107. /* accept new client */
  108. _accept_conn( server->server, &server->conns, fd );
  109. }
  110. else
  111. {
  112. struct http_request *request;
  113. struct http_connection *conn = _get_conn( &server->conns, fd );
  114. /* i suppose conn will not be invalid */
  115. int ret = evbuffer_read( conn->inbuf, fd, 4096 );
  116. if( ret <= 0 )
  117. {
  118. _log( "disconnect a connection : %s", _get_fd_name( fd ) );
  119. /* disconnect the connection */
  120. ts_server_remove( server->server, fd );
  121. _disconnect_conn( conn );
  122. /* remove from the list */
  123. LIST_REMOVE( conn, next );
  124. }
  125. else
  126. {
  127. /* parse the request */
  128. request = http_request_parse( conn->inbuf );
  129. /* call the user-level function */
  130. server->r_cb( conn, request, server->arg );
  131. /* free the request */
  132. http_request_free( request );
  133. }
  134. }
  135. }
  136. /**
  137.   handle write.
  138. */
  139. static void _write_cb( int fd, void *arg )
  140. {
  141. struct http_server *server = (struct http_server*)arg;
  142. struct http_connection *conn = _get_conn( &server->conns, fd );
  143. if( EVBUFFER_LENGTH( conn->outbuf ) > 0 )
  144. {
  145. evbuffer_write( conn->outbuf, fd );
  146. }
  147. }
  148. void http_set_info_log( info_log_cb log )
  149. {
  150. s_log = log;
  151. }
  152. struct http_server *http_start( const char *ip, unsigned short port, int max_conn )
  153. {
  154. int ret;
  155. struct http_server *server = (struct http_server*) malloc( sizeof( struct http_server ) );
  156. server->server = (struct tcp_server*) malloc( sizeof( struct tcp_server ) );
  157. LIST_INIT( &server->conns );
  158. server->r_cb = 0;
  159. server->arg = 0;
  160. ret = ts_server_startup( server->server, ip, port, max_conn, _read_cb, _write_cb, server );
  161. if( ret < 0 )
  162. {
  163. free( server->server );
  164. free( server );
  165. return 0;
  166. }
  167. return server;
  168. }
  169. void http_set_rcb( struct http_server *server, request_cb cb, void *arg )
  170. {
  171. server->r_cb = cb;
  172. server->arg = arg;
  173. }
  174. void http_free( struct http_server *server )
  175. {
  176. struct http_connection *conn, *prev = 0;
  177. ts_server_cleanup( server->server );
  178. LIST_FOREACH( conn, &server->conns, next )
  179. {
  180. if( prev != 0 )
  181. {
  182. free( prev );
  183. }
  184. _disconnect_conn( conn );
  185. prev = conn;
  186. }
  187. }
  188. int http_poll( struct http_server *server, struct timeval *timeout )
  189. {
  190. return ts_server_poll( server->server, timeout );
  191. }