HttpSession.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. #include "HttpSession.h"
  2. #include "http_parser.h"
  3. static int on_url(http_parser* parser, const char *at, size_t length);
  4. static int on_status(http_parser* parser, const char *at, size_t length);
  5. static int on_header_field(http_parser* parser, const char *at, size_t length);
  6. static int on_header_value(http_parser* parser, const char *at, size_t length);
  7. static int on_body(http_parser* parser, const char *at, size_t length);
  8. static int on_message_begin(http_parser* parser);
  9. static int on_headers_complete(http_parser* parser);
  10. static int on_message_complete(http_parser* parser);
  11. enum http_parser_state {
  12. HP_START_REQ_OR_RES,
  13. HP_MESSAGE_BEGIN, HP_URL,
  14. HP_STATUS,
  15. HP_HEADER_FIELD,
  16. HP_HEADER_VALUE,
  17. HP_HEADERS_COMPLETE,
  18. HP_BODY,
  19. HP_MESSAGE_COMPLETE
  20. };
  21. class Http1Session : public HttpSession {
  22. public:
  23. static http_parser_settings* cbs;
  24. http_parser parser;
  25. http_parser_state state;
  26. HttpPayload* submited;
  27. HttpPayload* parsed;
  28. // tmp
  29. std::string url; // for on_url
  30. std::string header_field; // for on_header_field
  31. std::string header_value; // for on_header_value
  32. std::string sendbuf; // for GetSendData
  33. void handle_header() {
  34. if (header_field.size() != 0 && header_value.size() != 0) {
  35. parsed->headers[header_field] = header_value;
  36. header_field.clear();
  37. header_value.clear();
  38. }
  39. }
  40. Http1Session() {
  41. if (cbs == NULL) {
  42. cbs = (http_parser_settings*)malloc(sizeof(http_parser_settings));
  43. http_parser_settings_init(cbs);
  44. cbs->on_message_begin = on_message_begin;
  45. cbs->on_url = on_url;
  46. cbs->on_status = on_status;
  47. cbs->on_header_field = on_header_field;
  48. cbs->on_header_value = on_header_value;
  49. cbs->on_headers_complete = on_headers_complete;
  50. cbs->on_body = on_body;
  51. cbs->on_message_complete = on_message_complete;
  52. }
  53. http_parser_init(&parser, HTTP_BOTH);
  54. parser.data = this;
  55. state = HP_START_REQ_OR_RES;
  56. submited = NULL;
  57. parsed = NULL;
  58. }
  59. virtual ~Http1Session() {
  60. }
  61. virtual int GetSendData(char** data, size_t* len) {
  62. if (!submited) {
  63. *data = NULL;
  64. *len = 0;
  65. return 0;
  66. }
  67. sendbuf = submited->Dump(true, true);
  68. submited = NULL;
  69. *data = (char*)sendbuf.data();
  70. *len = sendbuf.size();
  71. return sendbuf.size();
  72. }
  73. virtual int FeedRecvData(const char* data, size_t len) {
  74. return http_parser_execute(&parser, cbs, data, len);
  75. }
  76. virtual bool WantRecv() {
  77. return state != HP_MESSAGE_COMPLETE;
  78. }
  79. virtual int SubmitRequest(HttpRequest* req) {
  80. submited = req;
  81. return 0;
  82. }
  83. virtual int SubmitResponse(HttpResponse* res) {
  84. submited = res;
  85. return 0;
  86. }
  87. virtual int InitRequest(HttpRequest* req) {
  88. req->Reset();
  89. parsed = req;
  90. http_parser_init(&parser, HTTP_REQUEST);
  91. return 0;
  92. }
  93. virtual int InitResponse(HttpResponse* res) {
  94. res->Reset();
  95. parsed = res;
  96. http_parser_init(&parser, HTTP_RESPONSE);
  97. return 0;
  98. }
  99. virtual int GetError() {
  100. return parser.http_errno;
  101. }
  102. virtual const char* StrError(int error) {
  103. return http_errno_description((enum http_errno)error);
  104. }
  105. };
  106. http_parser_settings* Http1Session::cbs = NULL;
  107. int on_url(http_parser* parser, const char *at, size_t length) {
  108. printd("on_url:%.*s\n", (int)length, at);
  109. Http1Session* hss = (Http1Session*)parser->data;
  110. hss->state = HP_URL;
  111. hss->url.insert(hss->url.size(), at, length);
  112. return 0;
  113. }
  114. int on_status(http_parser* parser, const char *at, size_t length) {
  115. printd("on_status:%.*s\n", (int)length, at);
  116. Http1Session* hss = (Http1Session*)parser->data;
  117. hss->state = HP_STATUS;
  118. return 0;
  119. }
  120. int on_header_field(http_parser* parser, const char *at, size_t length) {
  121. printd("on_header_field:%.*s\n", (int)length, at);
  122. Http1Session* hss = (Http1Session*)parser->data;
  123. hss->handle_header();
  124. hss->state = HP_HEADER_FIELD;
  125. hss->header_field.insert(hss->header_field.size(), at, length);
  126. return 0;
  127. }
  128. int on_header_value(http_parser* parser, const char *at, size_t length) {
  129. printd("on_header_value:%.*s""\n", (int)length, at);
  130. Http1Session* hss = (Http1Session*)parser->data;
  131. hss->state = HP_HEADER_VALUE;
  132. hss->header_value.insert(hss->header_value.size(), at, length);
  133. return 0;
  134. }
  135. int on_body(http_parser* parser, const char *at, size_t length) {
  136. //printd("on_body:%.*s""\n", (int)length, at);
  137. Http1Session* hss = (Http1Session*)parser->data;
  138. hss->state = HP_BODY;
  139. hss->parsed->body.insert(hss->parsed->body.size(), at, length);
  140. return 0;
  141. }
  142. int on_message_begin(http_parser* parser) {
  143. printd("on_message_begin\n");
  144. Http1Session* hss = (Http1Session*)parser->data;
  145. hss->state = HP_MESSAGE_BEGIN;
  146. return 0;
  147. }
  148. int on_headers_complete(http_parser* parser) {
  149. printd("on_headers_complete\n");
  150. Http1Session* hss = (Http1Session*)parser->data;
  151. hss->handle_header();
  152. auto iter = hss->parsed->headers.find("content-type");
  153. if (iter != hss->parsed->headers.end()) {
  154. hss->parsed->content_type = http_content_type_enum(iter->second.c_str());
  155. }
  156. hss->parsed->http_major = parser->http_major;
  157. hss->parsed->http_minor = parser->http_minor;
  158. if (hss->parsed->type == HTTP_REQUEST) {
  159. HttpRequest* req = (HttpRequest*)hss->parsed;
  160. req->method = (http_method)parser->method;
  161. req->url = hss->url;
  162. }
  163. else if (hss->parsed->type == HTTP_RESPONSE) {
  164. HttpResponse* res = (HttpResponse*)hss->parsed;
  165. res->status_code = (http_status)parser->status_code;
  166. }
  167. hss->state = HP_HEADERS_COMPLETE;
  168. return 0;
  169. }
  170. int on_message_complete(http_parser* parser) {
  171. printd("on_message_complete\n");
  172. Http1Session* hss = (Http1Session*)parser->data;
  173. hss->state = HP_MESSAGE_COMPLETE;
  174. return 0;
  175. }
  176. #ifdef WITH_NGHTTP2
  177. #include "nghttp2/nghttp2.h"
  178. #include "http2def.h"
  179. static nghttp2_nv make_nv(const char* name, const char* value) {
  180. nghttp2_nv nv;
  181. nv.name = (uint8_t*)name;
  182. nv.value = (uint8_t*)value;
  183. nv.namelen = strlen(name);
  184. nv.valuelen = strlen(value);
  185. nv.flags = NGHTTP2_NV_FLAG_NONE;
  186. return nv;
  187. }
  188. static nghttp2_nv make_nv2(const char* name, const char* value,
  189. int namelen, int valuelen) {
  190. nghttp2_nv nv;
  191. nv.name = (uint8_t*)name;
  192. nv.value = (uint8_t*)value;
  193. nv.namelen = namelen;
  194. nv.valuelen = valuelen;
  195. nv.flags = NGHTTP2_NV_FLAG_NONE;
  196. return nv;
  197. }
  198. static void print_frame_hd(const nghttp2_frame_hd* hd) {
  199. printd("[frame] length=%d type=%x flags=%x stream_id=%d\n",
  200. (int)hd->length, (int)hd->type, (int)hd->flags, hd->stream_id);
  201. }
  202. static int on_header_callback(nghttp2_session *session,
  203. const nghttp2_frame *frame,
  204. const uint8_t *name, size_t namelen,
  205. const uint8_t *value, size_t valuelen,
  206. uint8_t flags, void *userdata);
  207. static int on_data_chunk_recv_callback(nghttp2_session *session,
  208. uint8_t flags, int32_t stream_id, const uint8_t *data,
  209. size_t len, void *userdata);
  210. static int on_frame_recv_callback(nghttp2_session *session,
  211. const nghttp2_frame *frame, void *userdata);
  212. /*
  213. static ssize_t data_source_read_callback(nghttp2_session *session,
  214. int32_t stream_id, uint8_t *buf, size_t length,
  215. uint32_t *data_flags, nghttp2_data_source *source, void *userdata);
  216. */
  217. enum http2_session_state {
  218. HSS_SEND_MAGIC,
  219. HSS_SEND_SETTINGS,
  220. HSS_SEND_HEADERS,
  221. HSS_SEND_DATA_FRAME_HD,
  222. HSS_SEND_DATA
  223. };
  224. class Http2Session : public HttpSession {
  225. public:
  226. static nghttp2_session_callbacks* cbs;
  227. nghttp2_session* session;
  228. http2_session_state state;
  229. HttpPayload* submited;
  230. HttpPayload* parsed;
  231. int error;
  232. int stream_id;
  233. int stream_closed;
  234. unsigned char frame_hdbuf[HTTP2_FRAME_HDLEN];
  235. Http2Session(http_session_type type) {
  236. if (cbs == NULL) {
  237. nghttp2_session_callbacks_new(&cbs);
  238. nghttp2_session_callbacks_set_on_header_callback(cbs, on_header_callback);
  239. nghttp2_session_callbacks_set_on_data_chunk_recv_callback(cbs, on_data_chunk_recv_callback);
  240. nghttp2_session_callbacks_set_on_frame_recv_callback(cbs, on_frame_recv_callback);
  241. }
  242. if (type == HTTP_CLIENT) {
  243. nghttp2_session_client_new(&session, cbs, NULL);
  244. state = HSS_SEND_MAGIC;
  245. }
  246. else if (type == HTTP_SERVER) {
  247. nghttp2_session_server_new(&session, cbs, NULL);
  248. state = HSS_SEND_SETTINGS;
  249. }
  250. nghttp2_session_set_user_data(session, this);
  251. submited = NULL;
  252. parsed = NULL;
  253. stream_id = -1;
  254. stream_closed = 0;
  255. nghttp2_settings_entry settings[] = {
  256. {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}
  257. };
  258. nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, settings, ARRAY_SIZE(settings));
  259. state = HSS_SEND_SETTINGS;
  260. }
  261. virtual ~Http2Session() {
  262. if (session) {
  263. nghttp2_session_del(session);
  264. session = NULL;
  265. }
  266. }
  267. virtual int GetSendData(char** data, size_t* len) {
  268. // HTTP2_MAGIC,HTTP2_SETTINGS,HTTP2_HEADERS
  269. *len = nghttp2_session_mem_send(session, (const uint8_t**)data);
  270. if (*len == 0) {
  271. if (submited) {
  272. void* content = submited->Content();
  273. int content_length = submited->ContentLength();
  274. if (content_length != 0) {
  275. if (state == HSS_SEND_HEADERS) {
  276. // HTTP2_DATA_FRAME_HD
  277. state = HSS_SEND_DATA_FRAME_HD;
  278. http2_frame_hd hd;
  279. hd.length = content_length;
  280. hd.type = HTTP2_DATA;
  281. hd.flags = HTTP2_FLAG_END_STREAM;
  282. hd.stream_id = stream_id;
  283. http2_frame_hd_pack(&hd, frame_hdbuf);
  284. *data = (char*)frame_hdbuf;
  285. *len = HTTP2_FRAME_HDLEN;
  286. }
  287. else if (state == HSS_SEND_DATA_FRAME_HD) {
  288. // HTTP2_DATA
  289. state = HSS_SEND_DATA;
  290. *data = (char*)content;
  291. *len = content_length;
  292. }
  293. }
  294. }
  295. }
  296. return *len;
  297. }
  298. virtual int FeedRecvData(const char* data, size_t len) {
  299. int ret = nghttp2_session_mem_recv(session, (const uint8_t*)data, len);
  300. if (ret != len) {
  301. error = ret;
  302. }
  303. return ret;
  304. }
  305. virtual bool WantRecv() {
  306. return stream_id == -1 || stream_closed == 0;
  307. }
  308. virtual int SubmitRequest(HttpRequest* req) {
  309. submited = req;
  310. std::vector<nghttp2_nv> nvs;
  311. char c_str[256] = {0};
  312. req->ParseUrl();
  313. nvs.push_back(make_nv(":method", http_method_str(req->method)));
  314. nvs.push_back(make_nv(":path", req->path.c_str()));
  315. nvs.push_back(make_nv(":scheme", req->https ? "https" : "http"));
  316. if (req->port == 0 ||
  317. req->port == DEFAULT_HTTP_PORT ||
  318. req->port == DEFAULT_HTTPS_PORT) {
  319. nvs.push_back(make_nv(":authority", req->host.c_str()));
  320. }
  321. else {
  322. snprintf(c_str, sizeof(c_str), "%s:%d", req->host.c_str(), req->port);
  323. nvs.push_back(make_nv(":authority", c_str));
  324. }
  325. req->FillContentType();
  326. req->FillContentLength();
  327. const char* name;
  328. const char* value;
  329. for (auto& header : req->headers) {
  330. name = header.first.c_str();
  331. value = header.second.c_str();
  332. strlower((char*)name);
  333. if (strcmp(name, "connection") == 0) {
  334. // HTTP2 use stream
  335. continue;
  336. }
  337. nvs.push_back(make_nv2(name, value, header.first.size(), header.second.size()));
  338. }
  339. int flags = NGHTTP2_FLAG_END_HEADERS;
  340. if (req->ContentLength() == 0) {
  341. flags |= NGHTTP2_FLAG_END_STREAM;
  342. }
  343. stream_id = nghttp2_submit_headers(session, flags, -1, NULL, &nvs[0], nvs.size(), NULL);
  344. // avoid DATA_SOURCE_COPY, we do not use nghttp2_submit_data
  345. // nghttp2_data_provider data_prd;
  346. // data_prd.read_callback = data_source_read_callback;
  347. //stream_id = nghttp2_submit_request(session, NULL, &nvs[0], nvs.size(), &data_prd, NULL);
  348. stream_closed = 0;
  349. state = HSS_SEND_HEADERS;
  350. return 0;
  351. }
  352. virtual int SubmitResponse(HttpResponse* res) {
  353. submited = res;
  354. std::vector<nghttp2_nv> nvs;
  355. char c_str[256] = {0};
  356. snprintf(c_str, sizeof(c_str), "%d", res->status_code);
  357. nvs.push_back(make_nv(":status", c_str));
  358. res->FillContentType();
  359. res->FillContentLength();
  360. const char* name;
  361. const char* value;
  362. for (auto& header : res->headers) {
  363. name = header.first.c_str();
  364. value = header.second.c_str();
  365. strlower((char*)name);
  366. if (strcmp(name, "connection") == 0) {
  367. // HTTP2 use stream
  368. continue;
  369. }
  370. nvs.push_back(make_nv2(name, value, header.first.size(), header.second.size()));
  371. }
  372. int flags = NGHTTP2_FLAG_END_HEADERS;
  373. if (res->ContentLength() == 0) {
  374. flags |= NGHTTP2_FLAG_END_STREAM;
  375. }
  376. nghttp2_submit_headers(session, flags, stream_id, NULL, &nvs[0], nvs.size(), NULL);
  377. // avoid DATA_SOURCE_COPY, we do not use nghttp2_submit_data
  378. // data_prd.read_callback = data_source_read_callback;
  379. //stream_id = nghttp2_submit_request(session, NULL, &nvs[0], nvs.size(), &data_prd, NULL);
  380. //nghttp2_submit_response(session, stream_id, &nvs[0], nvs.size(), &data_prd);
  381. stream_closed = 0;
  382. state = HSS_SEND_HEADERS;
  383. return 0;
  384. }
  385. virtual int InitResponse(HttpResponse* res) {
  386. res->Reset();
  387. res->http_major = 2;
  388. res->http_minor = 0;
  389. parsed = res;
  390. return 0;
  391. }
  392. virtual int InitRequest(HttpRequest* req) {
  393. req->Reset();
  394. req->http_major = 2;
  395. req->http_minor = 0;
  396. parsed = req;
  397. return 0;
  398. }
  399. virtual int GetError() {
  400. return error;
  401. }
  402. virtual const char* StrError(int error) {
  403. return nghttp2_http2_strerror(error);
  404. }
  405. };
  406. nghttp2_session_callbacks* Http2Session::cbs = NULL;
  407. int on_header_callback(nghttp2_session *session,
  408. const nghttp2_frame *frame,
  409. const uint8_t *_name, size_t namelen,
  410. const uint8_t *_value, size_t valuelen,
  411. uint8_t flags, void *userdata) {
  412. printd("on_header_callback\n");
  413. print_frame_hd(&frame->hd);
  414. const char* name = (const char*)_name;
  415. const char* value = (const char*)_value;
  416. printd("%s: %s\n", name, value);
  417. Http2Session* hss = (Http2Session*)userdata;
  418. if (*name == ':') {
  419. if (hss->parsed->type == HTTP_REQUEST) {
  420. // :method :path :scheme :authority
  421. HttpRequest* req = (HttpRequest*)hss->parsed;
  422. if (strcmp(name, ":method") == 0) {
  423. req->method = http_method_enum(value);
  424. }
  425. else if (strcmp(name, ":path") == 0) {
  426. req->url = value;
  427. }
  428. else if (strcmp(name, ":scheme") == 0) {
  429. req->headers["Scheme"] = value;
  430. }
  431. else if (strcmp(name, ":authority") == 0) {
  432. req->headers["Host"] = value;
  433. }
  434. }
  435. else if (hss->parsed->type == HTTP_RESPONSE) {
  436. HttpResponse* res = (HttpResponse*)hss->parsed;
  437. if (strcmp(name, ":status") == 0) {
  438. res->status_code = (http_status)atoi(value);
  439. }
  440. }
  441. }
  442. else {
  443. hss->parsed->headers[name] = value;
  444. if (strcmp(name, "content-type") == 0) {
  445. hss->parsed->content_type = http_content_type_enum(value);
  446. }
  447. }
  448. return 0;
  449. }
  450. int on_data_chunk_recv_callback(nghttp2_session *session,
  451. uint8_t flags, int32_t stream_id, const uint8_t *data,
  452. size_t len, void *userdata) {
  453. printd("on_data_chunk_recv_callback\n");
  454. printd("stream_id=%d length=%d\n", stream_id, (int)len);
  455. //printd("%.*s\n", (int)len, data);
  456. Http2Session* hss = (Http2Session*)userdata;
  457. hss->parsed->body.insert(hss->parsed->body.size(), (const char*)data, len);
  458. return 0;
  459. }
  460. static int on_frame_recv_callback(nghttp2_session *session,
  461. const nghttp2_frame *frame, void *userdata) {
  462. printd("on_frame_recv_callback\n");
  463. print_frame_hd(&frame->hd);
  464. Http2Session* hss = (Http2Session*)userdata;
  465. switch (frame->hd.type) {
  466. case NGHTTP2_DATA:
  467. case NGHTTP2_HEADERS:
  468. hss->stream_id = frame->hd.stream_id;
  469. if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
  470. printd("on_stream_closed stream_id=%d\n", hss->stream_id);
  471. hss->stream_closed = 1;
  472. }
  473. break;
  474. default:
  475. break;
  476. }
  477. return 0;
  478. }
  479. #endif
  480. HttpSession* HttpSession::New(http_session_type type, http_version version) {
  481. if (version == HTTP_V1) {
  482. return new Http1Session;
  483. }
  484. else if (version == HTTP_V2) {
  485. #ifdef WITH_NGHTTP2
  486. return new Http2Session(type);
  487. #else
  488. fprintf(stderr, "Please recompile WITH_NGHTTP2!\n");
  489. #endif
  490. }
  491. return NULL;
  492. }