wac_network_http_server.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. ** JNetLib
  3. ** Copyright (C) 2001 Nullsoft, Inc.
  4. ** Author: Justin Frankel
  5. ** File: wac_network_http_server.cpp - JNL HTTP GET/POST serving implementation
  6. ** License: see jnetlib.h
  7. **
  8. ** This class just manages the http reply/sending, not where the data
  9. ** comes from, etc.
  10. */
  11. #include "netinc.h"
  12. #include "util.h"
  13. #include "wac_network_http_server.h"
  14. /*
  15. States for m_state:
  16. -1 error (connection closed, etc)
  17. 0 not read request yet.
  18. 1 reading headers
  19. 2 headers read, have not sent reply
  20. 3 sent reply
  21. 4 closed
  22. */
  23. wa::Components::WAC_Network_HTTP_Server::WAC_Network_HTTP_Server( WAC_Network_Connection *con )
  24. {
  25. m_con = con;
  26. m_state = 0;
  27. m_reply_headers = 0;
  28. m_reply_string = 0;
  29. m_recv_request = 0;
  30. m_errstr = 0;
  31. m_reply_ready = 0;
  32. m_method = 0;
  33. http_ver = 0;
  34. keep_alive = 0;
  35. }
  36. wa::Components::WAC_Network_HTTP_Server::~WAC_Network_HTTP_Server()
  37. {
  38. free( m_recv_request );
  39. free( m_reply_string );
  40. free( m_reply_headers );
  41. free( m_errstr );
  42. free( m_method );
  43. m_con->Release();
  44. }
  45. static size_t strlen_whitespace( const char *str )
  46. {
  47. size_t size = 0;
  48. while ( str && *str && *str != ' ' && *str != '\r' && *str != '\n' )
  49. {
  50. str++;
  51. size++;
  52. }
  53. return size;
  54. }
  55. int wa::Components::WAC_Network_HTTP_Server::run()
  56. { // returns: < 0 on error, 0 on connection close, 1 if reading request, 2 if reply not sent, 3 if reply sent, sending data.
  57. int cnt = 0;
  58. run_again:
  59. m_con->run();
  60. if ( m_con->get_state() == WAC_Network_Connection::STATE_ERROR )
  61. {
  62. seterrstr( m_con->get_errstr() );
  63. return -1;
  64. }
  65. if ( m_con->get_state() == WAC_Network_Connection::STATE_CLOSED )
  66. return 4;
  67. if ( m_state == 0 )
  68. {
  69. if ( m_con->recv_lines_available() > 0 )
  70. {
  71. char *buf = (char *)malloc( m_con->recv_bytes_available() - 1 );
  72. m_con->recv_line( buf, m_con->recv_bytes_available() - 1 );
  73. free( m_recv_request );
  74. m_recv_request = (char *)malloc( strlen( buf ) + 2 );
  75. strcpy( m_recv_request, buf );
  76. m_recv_request[ strlen( m_recv_request ) + 1 ] = 0;
  77. free( buf );
  78. buf = m_recv_request;
  79. while ( buf && *buf )
  80. buf++;
  81. while ( buf >= m_recv_request && *buf != ' ' )
  82. buf--;
  83. if ( strncmp( buf + 1, "HTTP", 4 ) )// || strncmp(m_recv_request,"GET ",3))
  84. {
  85. seterrstr( "malformed HTTP request" );
  86. m_state = -1;
  87. }
  88. else
  89. {
  90. http_ver = atoi( buf + 8 );
  91. size_t method_len = strlen_whitespace( m_recv_request );
  92. m_method = (char *)malloc( method_len + 1 );
  93. memcpy( m_method, m_recv_request, method_len );
  94. m_method[ method_len ] = 0;
  95. m_state = 1;
  96. cnt = 0;
  97. if ( buf >= m_recv_request )
  98. buf[ 0 ] = buf[ 1 ] = 0;
  99. buf = strstr( m_recv_request, "?" );
  100. if ( buf )
  101. {
  102. *buf++ = 0; // change &'s into 0s now.
  103. char *t = buf;
  104. int stat = 1;
  105. while ( t && *t )
  106. {
  107. if ( *t == '&' && !stat )
  108. {
  109. stat = 1;
  110. *t = 0;
  111. }
  112. else
  113. stat = 0;
  114. t++;
  115. }
  116. }
  117. }
  118. }
  119. else if ( !cnt++ )
  120. goto run_again;
  121. }
  122. if ( m_state == 1 )
  123. {
  124. if ( !cnt++ && m_con->recv_lines_available() < 1 )
  125. goto run_again;
  126. while ( m_con->recv_lines_available() > 0 )
  127. {
  128. char buf[ 4096 ] = { 0 };
  129. m_con->recv_line( buf, 4096 );
  130. if ( !buf[ 0 ] )
  131. {
  132. m_state = 2;
  133. break;
  134. }
  135. recvheaders.Add( buf );
  136. }
  137. }
  138. if ( m_state == 2 )
  139. {
  140. if ( m_reply_ready )
  141. {
  142. // send reply
  143. m_con->send_string( (char *)( m_reply_string ? m_reply_string : "HTTP/1.1 200 OK" ) );
  144. m_con->send_string( "\r\n" );
  145. if ( m_reply_headers )
  146. m_con->send_string( m_reply_headers );
  147. m_con->send_string( "\r\n" );
  148. m_state = 3;
  149. }
  150. }
  151. if ( m_state == 3 )
  152. {
  153. // nothing.
  154. }
  155. return m_state;
  156. }
  157. const char *wa::Components::WAC_Network_HTTP_Server::get_request_file()
  158. {
  159. // file portion of http request
  160. if ( !m_recv_request )
  161. return NULL;
  162. char *t = m_recv_request;
  163. while ( t && *t && *t != ' ' )
  164. t++;
  165. if ( !t || !*t )
  166. return NULL;
  167. while ( t && *t && *t == ' ' )
  168. t++;
  169. return t;
  170. }
  171. const char *wa::Components::WAC_Network_HTTP_Server::get_request_parm( const char *parmname ) // parameter portion (after ?)
  172. {
  173. const char *t = m_recv_request;
  174. while ( t && *t ) t++;
  175. if ( t ) t++;
  176. while ( t && *t )
  177. {
  178. while ( t && *t && *t == '&' ) t++;
  179. if ( !_strnicmp( t, parmname, strlen( parmname ) ) && t[ strlen( parmname ) ] == '=' )
  180. {
  181. return t + strlen( parmname ) + 1;
  182. }
  183. t += strlen( t ) + 1;
  184. }
  185. return NULL;
  186. }
  187. const char *wa::Components::WAC_Network_HTTP_Server::getheader( const char *headername )
  188. {
  189. return recvheaders.GetHeader( headername );
  190. }
  191. void wa::Components::WAC_Network_HTTP_Server::set_reply_string( const char *reply_string ) // should be HTTP/1.1 OK or the like
  192. {
  193. free( m_reply_string );
  194. m_reply_string = (char *)malloc( strlen( reply_string ) + 1 );
  195. strcpy( m_reply_string, reply_string );
  196. }
  197. void wa::Components::WAC_Network_HTTP_Server::add_reply_header( const char *header ) // "Connection: close" for example
  198. {
  199. // if they've specified a content-length, then we can keep alive an HTTP/1.1 connection
  200. if ( !keep_alive && http_ver == 1 && !_strnicmp( header, "Content-Length", 14 ) )
  201. keep_alive = 1;
  202. if ( m_reply_headers )
  203. {
  204. char *tmp = (char *)malloc( strlen( m_reply_headers ) + strlen( header ) + 3 );
  205. strcpy( tmp, m_reply_headers );
  206. strcat( tmp, header );
  207. strcat( tmp, "\r\n" );
  208. free( m_reply_headers );
  209. m_reply_headers = tmp;
  210. }
  211. else
  212. {
  213. m_reply_headers = (char *)malloc( strlen( header ) + 3 );
  214. strcpy( m_reply_headers, header );
  215. strcat( m_reply_headers, "\r\n" );
  216. }
  217. }
  218. void wa::Components::WAC_Network_HTTP_Server::reset()
  219. {
  220. free( m_recv_request ); m_recv_request = 0;
  221. free( m_reply_string ); m_reply_string = 0;
  222. free( m_reply_headers ); m_reply_headers = 0;
  223. free( m_errstr ); m_errstr = 0;
  224. free( m_method ); m_method = 0;
  225. m_reply_ready = 0;
  226. m_state = 0;
  227. keep_alive = 0;
  228. }
  229. #ifdef CBCLASS
  230. #undef CBCLASS
  231. #endif
  232. #define CBCLASS wa::Components::WAC_Network_HTTP_Server
  233. START_DISPATCH;
  234. CB( API_HTTPSERV_RUN, run );
  235. CB( API_HTTPSERV_GETERRSTR, geterrorstr );
  236. CB( API_HTTPSERV_GETREQUESTFILE, get_request_file );
  237. CB( API_HTTPSERV_GETREQUESTPARM, get_request_parm );
  238. CB( API_HTTPSERV_GETALLHEADERS, getallheaders );
  239. CB( API_HTTPSERV_GETHEADER, getheader );
  240. VCB( API_HTTPSERV_SETREPLYSTR, set_reply_string );
  241. VCB( API_HTTPSERV_SETREPLYHEADER, set_reply_header );
  242. VCB( API_HTTPSERV_SENDREPLY, send_reply );
  243. CB( API_HTTPSERV_BYTESINQUEUE, bytes_inqueue );
  244. CB( API_HTTPSERV_BYTESCANSEND, bytes_cansend );
  245. VCB( API_HTTPSERV_WRITEBYTES, write_bytes );
  246. VCB( API_HTTPSERV_CLOSE, close );
  247. CB( API_HTTPSERV_GETCON, get_con );
  248. CB( API_HTTPSERV_GETMETHOD, get_method );
  249. END_DISPATCH;