| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470 | /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev * * Additional changes are licensed under the same terms as NGINX and * copyright Joyent, Inc. and other Node contributors. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */#include "http_parser.h"#include <assert.h>#include <stddef.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <limits.h>#ifndef ULLONG_MAX# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */#endif#ifndef MIN# define MIN(a,b) ((a) < (b) ? (a) : (b))#endif#ifndef ARRAY_SIZE# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))#endif#ifndef BIT_AT# define BIT_AT(a, i)                                                \  (!!((unsigned int) (a)[(unsigned int) (i) >> 3] &                  \   (1 << ((unsigned int) (i) & 7))))#endif#ifndef ELEM_AT# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))#endif#define SET_ERRNO(e)                                                 \do {                                                                 \  parser->http_errno = (e);                                          \} while(0)#define CURRENT_STATE() p_state#define UPDATE_STATE(V) p_state = (enum state) (V);#define RETURN(V)                                                    \do {                                                                 \  parser->state = CURRENT_STATE();                                   \  return (V);                                                        \} while (0);#define REEXECUTE()                                                  \  goto reexecute;                                                    \#ifdef __GNUC__# define LIKELY(X) __builtin_expect(!!(X), 1)# define UNLIKELY(X) __builtin_expect(!!(X), 0)#else# define LIKELY(X) (X)# define UNLIKELY(X) (X)#endif/* Run the notify callback FOR, returning ER if it fails */#define CALLBACK_NOTIFY_(FOR, ER)                                    \do {                                                                 \  assert(HTTP_PARSER_ERRNO(parser) == HPE_OK);                       \                                                                     \  if (LIKELY(settings->on_##FOR)) {                                  \    parser->state = CURRENT_STATE();                                 \    if (UNLIKELY(0 != settings->on_##FOR(parser))) {                 \      SET_ERRNO(HPE_CB_##FOR);                                       \    }                                                                \    UPDATE_STATE(parser->state);                                     \                                                                     \    /* We either errored above or got paused; get out */             \    if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {             \      return (ER);                                                   \    }                                                                \  }                                                                  \} while (0)/* Run the notify callback FOR and consume the current byte */#define CALLBACK_NOTIFY(FOR)            CALLBACK_NOTIFY_(FOR, p - data + 1)/* Run the notify callback FOR and don't consume the current byte */#define CALLBACK_NOTIFY_NOADVANCE(FOR)  CALLBACK_NOTIFY_(FOR, p - data)/* Run data callback FOR with LEN bytes, returning ER if it fails */#define CALLBACK_DATA_(FOR, LEN, ER)                                 \do {                                                                 \  assert(HTTP_PARSER_ERRNO(parser) == HPE_OK);                       \                                                                     \  if (FOR##_mark) {                                                  \    if (LIKELY(settings->on_##FOR)) {                                \      parser->state = CURRENT_STATE();                               \      if (UNLIKELY(0 !=                                              \                   settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \        SET_ERRNO(HPE_CB_##FOR);                                     \      }                                                              \      UPDATE_STATE(parser->state);                                   \                                                                     \      /* We either errored above or got paused; get out */           \      if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {           \        return (ER);                                                 \      }                                                              \    }                                                                \    FOR##_mark = NULL;                                               \  }                                                                  \} while (0)/* Run the data callback FOR and consume the current byte */#define CALLBACK_DATA(FOR)                                           \    CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)/* Run the data callback FOR and don't consume the current byte */#define CALLBACK_DATA_NOADVANCE(FOR)                                 \    CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)/* Set the mark FOR; non-destructive if mark is already set */#define MARK(FOR)                                                    \do {                                                                 \  if (!FOR##_mark) {                                                 \    FOR##_mark = p;                                                  \  }                                                                  \} while (0)/* Don't allow the total size of the HTTP headers (including the status * line) to exceed HTTP_MAX_HEADER_SIZE.  This check is here to protect * embedders against denial-of-service attacks where the attacker feeds * us a never-ending header that the embedder keeps buffering. * * This check is arguably the responsibility of embedders but we're doing * it on the embedder's behalf because most won't bother and this way we * make the web a little safer.  HTTP_MAX_HEADER_SIZE is still far bigger * than any reasonable request or response so this should never affect * day-to-day operation. */#define COUNT_HEADER_SIZE(V)                                         \do {                                                                 \  parser->nread += (V);                                              \  if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) {            \    SET_ERRNO(HPE_HEADER_OVERFLOW);                                  \    goto error;                                                      \  }                                                                  \} while (0)#define PROXY_CONNECTION "proxy-connection"#define CONNECTION "connection"#define CONTENT_LENGTH "content-length"#define TRANSFER_ENCODING "transfer-encoding"#define UPGRADE "upgrade"#define CHUNKED "chunked"#define KEEP_ALIVE "keep-alive"#define CLOSE "close"static const char *method_strings[] =  {#define XX(num, name, string) #string,  HTTP_METHOD_MAP(XX)#undef XX  };/* Tokens as defined by rfc 2616. Also lowercases them. *        token       = 1*<any CHAR except CTLs or separators> *     separators     = "(" | ")" | "<" | ">" | "@" *                    | "," | ";" | ":" | "\" | <"> *                    | "/" | "[" | "]" | "?" | "=" *                    | "{" | "}" | SP | HT */static const char tokens[256] = {/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */        0,       0,       0,       0,       0,       0,       0,       0,/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */        0,       0,       0,       0,       0,       0,       0,       0,/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */        0,       0,       0,       0,       0,       0,       0,       0,/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */        0,       0,       0,       0,       0,       0,       0,       0,/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */        0,      '!',      0,      '#',     '$',     '%',     '&',    '\'',/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */        0,       0,      '*',     '+',      0,      '-',     '.',      0,/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */       '0',     '1',     '2',     '3',     '4',     '5',     '6',     '7',/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */       '8',     '9',      0,       0,       0,       0,       0,       0,/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */        0,      'a',     'b',     'c',     'd',     'e',     'f',     'g',/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */       'x',     'y',     'z',      0,       0,       0,      '^',     '_',/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */       '`',     'a',     'b',     'c',     'd',     'e',     'f',     'g',/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */       'x',     'y',     'z',      0,      '|',      0,      '~',       0 };static const int8_t unhex[256] =  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  };#if HTTP_PARSER_STRICT# define T(v) 0#else# define T(v) v#endifstatic const uint8_t normal_url_char[32] = {/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */        0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */        0    | T(2)   |   0    |   0    | T(16)  |   0    |   0    |   0,/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */        0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */        0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */        0    |   2    |   4    |   0    |   16   |   32   |   64   |  128,/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |   0,/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */        1    |   2    |   4    |   8    |   16   |   32   |   64   |   0, };#undef Tenum state  { s_dead = 1 /* important that this is > 0 */  , s_start_req_or_res  , s_res_or_resp_H  , s_start_res  , s_res_H  , s_res_HT  , s_res_HTT  , s_res_HTTP  , s_res_first_http_major  , s_res_http_major  , s_res_first_http_minor  , s_res_http_minor  , s_res_first_status_code  , s_res_status_code  , s_res_status_start  , s_res_status  , s_res_line_almost_done  , s_start_req  , s_req_method  , s_req_spaces_before_url  , s_req_schema  , s_req_schema_slash  , s_req_schema_slash_slash  , s_req_server_start  , s_req_server  , s_req_server_with_at  , s_req_path  , s_req_query_string_start  , s_req_query_string  , s_req_fragment_start  , s_req_fragment  , s_req_http_start  , s_req_http_H  , s_req_http_HT  , s_req_http_HTT  , s_req_http_HTTP  , s_req_first_http_major  , s_req_http_major  , s_req_first_http_minor  , s_req_http_minor  , s_req_line_almost_done  , s_header_field_start  , s_header_field  , s_header_value_discard_ws  , s_header_value_discard_ws_almost_done  , s_header_value_discard_lws  , s_header_value_start  , s_header_value  , s_header_value_lws  , s_header_almost_done  , s_chunk_size_start  , s_chunk_size  , s_chunk_parameters  , s_chunk_size_almost_done  , s_headers_almost_done  , s_headers_done  /* Important: 's_headers_done' must be the last 'header' state. All   * states beyond this must be 'body' states. It is used for overflow   * checking. See the PARSING_HEADER() macro.   */  , s_chunk_data  , s_chunk_data_almost_done  , s_chunk_data_done  , s_body_identity  , s_body_identity_eof  , s_message_done  };#define PARSING_HEADER(state) (state <= s_headers_done)enum header_states  { h_general = 0  , h_C  , h_CO  , h_CON  , h_matching_connection  , h_matching_proxy_connection  , h_matching_content_length  , h_matching_transfer_encoding  , h_matching_upgrade  , h_connection  , h_content_length  , h_transfer_encoding  , h_upgrade  , h_matching_transfer_encoding_chunked  , h_matching_connection_token_start  , h_matching_connection_keep_alive  , h_matching_connection_close  , h_matching_connection_upgrade  , h_matching_connection_token  , h_transfer_encoding_chunked  , h_connection_keep_alive  , h_connection_close  , h_connection_upgrade  };enum http_host_state  {    s_http_host_dead = 1  , s_http_userinfo_start  , s_http_userinfo  , s_http_host_start  , s_http_host_v6_start  , s_http_host  , s_http_host_v6  , s_http_host_v6_end  , s_http_host_v6_zone_start  , s_http_host_v6_zone  , s_http_host_port_start  , s_http_host_port};/* Macros for character classes; depends on strict-mode  */#define CR                  '\r'#define LF                  '\n'#define LOWER(c)            (unsigned char)(c | 0x20)#define IS_ALPHA(c)         (LOWER(c) >= 'a' && LOWER(c) <= 'z')#define IS_NUM(c)           ((c) >= '0' && (c) <= '9')#define IS_ALPHANUM(c)      (IS_ALPHA(c) || IS_NUM(c))#define IS_HEX(c)           (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))#define IS_MARK(c)          ((c) == '-' || (c) == '_' || (c) == '.' || \  (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \  (c) == ')')#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \  (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \  (c) == '$' || (c) == ',')#define STRICT_TOKEN(c)     (tokens[(unsigned char)c])#if HTTP_PARSER_STRICT#define TOKEN(c)            (tokens[(unsigned char)c])#define IS_URL_CHAR(c)      (BIT_AT(normal_url_char, (unsigned char)c))#define IS_HOST_CHAR(c)     (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')#else#define TOKEN(c)            ((c == ' ') ? ' ' : tokens[(unsigned char)c])#define IS_URL_CHAR(c)                                                         \  (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))#define IS_HOST_CHAR(c)                                                        \  (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')#endif/** * Verify that a char is a valid visible (printable) US-ASCII * character or %x80-FF **/#define IS_HEADER_CHAR(ch)                                                     \  (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127))#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)#if HTTP_PARSER_STRICT# define STRICT_CHECK(cond)                                          \do {                                                                 \  if (cond) {                                                        \    SET_ERRNO(HPE_STRICT);                                           \    goto error;                                                      \  }                                                                  \} while (0)# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)#else# define STRICT_CHECK(cond)# define NEW_MESSAGE() start_state#endif/* Map errno values to strings for human-readable output */#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },static struct {  const char *name;  const char *description;} http_strerror_tab[] = {  HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)};#undef HTTP_STRERROR_GENint http_message_needs_eof(const http_parser *parser);/* Our URL parser. * * This is designed to be shared by http_parser_execute() for URL validation, * hence it has a state transition + byte-for-byte interface. In addition, it * is meant to be embedded in http_parser_parse_url(), which does the dirty * work of turning state transitions URL components for its API. * * This function should only be invoked with non-space characters. It is * assumed that the caller cares about (and can detect) the transition between * URL and non-URL states by looking for these. */static enum stateparse_url_char(enum state s, const char ch){  if (ch == ' ' || ch == '\r' || ch == '\n') {    return s_dead;  }#if HTTP_PARSER_STRICT  if (ch == '\t' || ch == '\f') {    return s_dead;  }#endif  switch (s) {    case s_req_spaces_before_url:      /* Proxied requests are followed by scheme of an absolute URI (alpha).       * All methods except CONNECT are followed by '/' or '*'.       */      if (ch == '/' || ch == '*') {        return s_req_path;      }      if (IS_ALPHA(ch)) {        return s_req_schema;      }      break;    case s_req_schema:      if (IS_ALPHA(ch)) {        return s;      }      if (ch == ':') {        return s_req_schema_slash;      }      break;    case s_req_schema_slash:      if (ch == '/') {        return s_req_schema_slash_slash;      }      break;    case s_req_schema_slash_slash:      if (ch == '/') {        return s_req_server_start;      }      break;    case s_req_server_with_at:      if (ch == '@') {        return s_dead;      }    /* FALLTHROUGH */    case s_req_server_start:    case s_req_server:      if (ch == '/') {        return s_req_path;      }      if (ch == '?') {        return s_req_query_string_start;      }      if (ch == '@') {        return s_req_server_with_at;      }      if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {        return s_req_server;      }      break;    case s_req_path:      if (IS_URL_CHAR(ch)) {        return s;      }      switch (ch) {        case '?':          return s_req_query_string_start;        case '#':          return s_req_fragment_start;      }      break;    case s_req_query_string_start:    case s_req_query_string:      if (IS_URL_CHAR(ch)) {        return s_req_query_string;      }      switch (ch) {        case '?':          /* allow extra '?' in query string */          return s_req_query_string;        case '#':          return s_req_fragment_start;      }      break;    case s_req_fragment_start:      if (IS_URL_CHAR(ch)) {        return s_req_fragment;      }      switch (ch) {        case '?':          return s_req_fragment;        case '#':          return s;      }      break;    case s_req_fragment:      if (IS_URL_CHAR(ch)) {        return s;      }      switch (ch) {        case '?':        case '#':          return s;      }      break;    default:      break;  }  /* We should never fall out of the switch above unless there's an error */  return s_dead;}size_t http_parser_execute (http_parser *parser,                            const http_parser_settings *settings,                            const char *data,                            size_t len){  char c, ch;  int8_t unhex_val;  const char *p = data;  const char *header_field_mark = 0;  const char *header_value_mark = 0;  const char *url_mark = 0;  const char *body_mark = 0;  const char *status_mark = 0;  enum state p_state = (enum state) parser->state;  const unsigned int lenient = parser->lenient_http_headers;  /* We're in an error state. Don't bother doing anything. */  if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {    return 0;  }  if (len == 0) {    switch (CURRENT_STATE()) {      case s_body_identity_eof:        /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if         * we got paused.         */        CALLBACK_NOTIFY_NOADVANCE(message_complete);        return 0;      case s_dead:      case s_start_req_or_res:      case s_start_res:      case s_start_req:        return 0;      default:        SET_ERRNO(HPE_INVALID_EOF_STATE);        return 1;    }  }  if (CURRENT_STATE() == s_header_field)    header_field_mark = data;  if (CURRENT_STATE() == s_header_value)    header_value_mark = data;  switch (CURRENT_STATE()) {  case s_req_path:  case s_req_schema:  case s_req_schema_slash:  case s_req_schema_slash_slash:  case s_req_server_start:  case s_req_server:  case s_req_server_with_at:  case s_req_query_string_start:  case s_req_query_string:  case s_req_fragment_start:  case s_req_fragment:    url_mark = data;    break;  case s_res_status:    status_mark = data;    break;  default:    break;  }  for (p=data; p != data + len; p++) {    ch = *p;    if (PARSING_HEADER(CURRENT_STATE()))      COUNT_HEADER_SIZE(1);reexecute:    switch (CURRENT_STATE()) {      case s_dead:        /* this state is used after a 'Connection: close' message         * the parser will error out if it reads another message         */        if (LIKELY(ch == CR || ch == LF))          break;        SET_ERRNO(HPE_CLOSED_CONNECTION);        goto error;      case s_start_req_or_res:      {        if (ch == CR || ch == LF)          break;        parser->flags = 0;        parser->content_length = ULLONG_MAX;        if (ch == 'H') {          UPDATE_STATE(s_res_or_resp_H);          CALLBACK_NOTIFY(message_begin);        } else {          parser->type = HTTP_REQUEST;          UPDATE_STATE(s_start_req);          REEXECUTE();        }        break;      }      case s_res_or_resp_H:        if (ch == 'T') {          parser->type = HTTP_RESPONSE;          UPDATE_STATE(s_res_HT);        } else {          if (UNLIKELY(ch != 'E')) {            SET_ERRNO(HPE_INVALID_CONSTANT);            goto error;          }          parser->type = HTTP_REQUEST;          parser->method = HTTP_HEAD;          parser->index = 2;          UPDATE_STATE(s_req_method);        }        break;      case s_start_res:      {        parser->flags = 0;        parser->content_length = ULLONG_MAX;        switch (ch) {          case 'H':            UPDATE_STATE(s_res_H);            break;          case CR:          case LF:            break;          default:            SET_ERRNO(HPE_INVALID_CONSTANT);            goto error;        }        CALLBACK_NOTIFY(message_begin);        break;      }      case s_res_H:        STRICT_CHECK(ch != 'T');        UPDATE_STATE(s_res_HT);        break;      case s_res_HT:        STRICT_CHECK(ch != 'T');        UPDATE_STATE(s_res_HTT);        break;      case s_res_HTT:        STRICT_CHECK(ch != 'P');        UPDATE_STATE(s_res_HTTP);        break;      case s_res_HTTP:        STRICT_CHECK(ch != '/');        UPDATE_STATE(s_res_first_http_major);        break;      case s_res_first_http_major:        if (UNLIKELY(ch < '0' || ch > '9')) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        parser->http_major = ch - '0';        UPDATE_STATE(s_res_http_major);        break;      /* major HTTP version or dot */      case s_res_http_major:      {        if (ch == '.') {          UPDATE_STATE(s_res_first_http_minor);          break;        }        if (!IS_NUM(ch)) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        parser->http_major *= 10;        parser->http_major += ch - '0';        if (UNLIKELY(parser->http_major > 999)) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        break;      }      /* first digit of minor HTTP version */      case s_res_first_http_minor:        if (UNLIKELY(!IS_NUM(ch))) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        parser->http_minor = ch - '0';        UPDATE_STATE(s_res_http_minor);        break;      /* minor HTTP version or end of request line */      case s_res_http_minor:      {        if (ch == ' ') {          UPDATE_STATE(s_res_first_status_code);          break;        }        if (UNLIKELY(!IS_NUM(ch))) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        parser->http_minor *= 10;        parser->http_minor += ch - '0';        if (UNLIKELY(parser->http_minor > 999)) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        break;      }      case s_res_first_status_code:      {        if (!IS_NUM(ch)) {          if (ch == ' ') {            break;          }          SET_ERRNO(HPE_INVALID_STATUS);          goto error;        }        parser->status_code = ch - '0';        UPDATE_STATE(s_res_status_code);        break;      }      case s_res_status_code:      {        if (!IS_NUM(ch)) {          switch (ch) {            case ' ':              UPDATE_STATE(s_res_status_start);              break;            case CR:              UPDATE_STATE(s_res_line_almost_done);              break;            case LF:              UPDATE_STATE(s_header_field_start);              break;            default:              SET_ERRNO(HPE_INVALID_STATUS);              goto error;          }          break;        }        parser->status_code *= 10;        parser->status_code += ch - '0';        if (UNLIKELY(parser->status_code > 999)) {          SET_ERRNO(HPE_INVALID_STATUS);          goto error;        }        break;      }      case s_res_status_start:      {        if (ch == CR) {          UPDATE_STATE(s_res_line_almost_done);          break;        }        if (ch == LF) {          UPDATE_STATE(s_header_field_start);          break;        }        MARK(status);        UPDATE_STATE(s_res_status);        parser->index = 0;        break;      }      case s_res_status:        if (ch == CR) {          UPDATE_STATE(s_res_line_almost_done);          CALLBACK_DATA(status);          break;        }        if (ch == LF) {          UPDATE_STATE(s_header_field_start);          CALLBACK_DATA(status);          break;        }        break;      case s_res_line_almost_done:        STRICT_CHECK(ch != LF);        UPDATE_STATE(s_header_field_start);        break;      case s_start_req:      {        if (ch == CR || ch == LF)          break;        parser->flags = 0;        parser->content_length = ULLONG_MAX;        if (UNLIKELY(!IS_ALPHA(ch))) {          SET_ERRNO(HPE_INVALID_METHOD);          goto error;        }        parser->method = (enum http_method) 0;        parser->index = 1;        switch (ch) {          case 'A': parser->method = HTTP_ACL; break;          case 'B': parser->method = HTTP_BIND; break;          case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;          case 'D': parser->method = HTTP_DELETE; break;          case 'G': parser->method = HTTP_GET; break;          case 'H': parser->method = HTTP_HEAD; break;          case 'L': parser->method = HTTP_LOCK; /* or LINK */ break;          case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;          case 'N': parser->method = HTTP_NOTIFY; break;          case 'O': parser->method = HTTP_OPTIONS; break;          case 'P': parser->method = HTTP_POST;            /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */            break;          case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;          case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;          case 'T': parser->method = HTTP_TRACE; break;          case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;          default:            SET_ERRNO(HPE_INVALID_METHOD);            goto error;        }        UPDATE_STATE(s_req_method);        CALLBACK_NOTIFY(message_begin);        break;      }      case s_req_method:      {        const char *matcher;        if (UNLIKELY(ch == '\0')) {          SET_ERRNO(HPE_INVALID_METHOD);          goto error;        }        matcher = method_strings[parser->method];        if (ch == ' ' && matcher[parser->index] == '\0') {          UPDATE_STATE(s_req_spaces_before_url);        } else if (ch == matcher[parser->index]) {          ; /* nada */        } else if (IS_ALPHA(ch)) {          switch (parser->method << 16 | parser->index << 8 | ch) {#define XX(meth, pos, ch, new_meth) \            case (HTTP_##meth << 16 | pos << 8 | ch): \              parser->method = HTTP_##new_meth; break;            XX(POST,      1, 'U', PUT)            XX(POST,      1, 'A', PATCH)            XX(CONNECT,   1, 'H', CHECKOUT)            XX(CONNECT,   2, 'P', COPY)            XX(MKCOL,     1, 'O', MOVE)            XX(MKCOL,     1, 'E', MERGE)            XX(MKCOL,     2, 'A', MKACTIVITY)            XX(MKCOL,     3, 'A', MKCALENDAR)            XX(SUBSCRIBE, 1, 'E', SEARCH)            XX(REPORT,    2, 'B', REBIND)            XX(POST,      1, 'R', PROPFIND)            XX(PROPFIND,  4, 'P', PROPPATCH)            XX(PUT,       2, 'R', PURGE)            XX(LOCK,      1, 'I', LINK)            XX(UNLOCK,    2, 'S', UNSUBSCRIBE)            XX(UNLOCK,    2, 'B', UNBIND)            XX(UNLOCK,    3, 'I', UNLINK)#undef XX            default:              SET_ERRNO(HPE_INVALID_METHOD);              goto error;          }        } else if (ch == '-' &&                   parser->index == 1 &&                   parser->method == HTTP_MKCOL) {          parser->method = HTTP_MSEARCH;        } else {          SET_ERRNO(HPE_INVALID_METHOD);          goto error;        }        ++parser->index;        break;      }      case s_req_spaces_before_url:      {        if (ch == ' ') break;        MARK(url);        if (parser->method == HTTP_CONNECT) {          UPDATE_STATE(s_req_server_start);        }        UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));        if (UNLIKELY(CURRENT_STATE() == s_dead)) {          SET_ERRNO(HPE_INVALID_URL);          goto error;        }        break;      }      case s_req_schema:      case s_req_schema_slash:      case s_req_schema_slash_slash:      case s_req_server_start:      {        switch (ch) {          /* No whitespace allowed here */          case ' ':          case CR:          case LF:            SET_ERRNO(HPE_INVALID_URL);            goto error;          default:            UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));            if (UNLIKELY(CURRENT_STATE() == s_dead)) {              SET_ERRNO(HPE_INVALID_URL);              goto error;            }        }        break;      }      case s_req_server:      case s_req_server_with_at:      case s_req_path:      case s_req_query_string_start:      case s_req_query_string:      case s_req_fragment_start:      case s_req_fragment:      {        switch (ch) {          case ' ':            UPDATE_STATE(s_req_http_start);            CALLBACK_DATA(url);            break;          case CR:          case LF:            parser->http_major = 0;            parser->http_minor = 9;            UPDATE_STATE((ch == CR) ?              s_req_line_almost_done :              s_header_field_start);            CALLBACK_DATA(url);            break;          default:            UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));            if (UNLIKELY(CURRENT_STATE() == s_dead)) {              SET_ERRNO(HPE_INVALID_URL);              goto error;            }        }        break;      }      case s_req_http_start:        switch (ch) {          case 'H':            UPDATE_STATE(s_req_http_H);            break;          case ' ':            break;          default:            SET_ERRNO(HPE_INVALID_CONSTANT);            goto error;        }        break;      case s_req_http_H:        STRICT_CHECK(ch != 'T');        UPDATE_STATE(s_req_http_HT);        break;      case s_req_http_HT:        STRICT_CHECK(ch != 'T');        UPDATE_STATE(s_req_http_HTT);        break;      case s_req_http_HTT:        STRICT_CHECK(ch != 'P');        UPDATE_STATE(s_req_http_HTTP);        break;      case s_req_http_HTTP:        STRICT_CHECK(ch != '/');        UPDATE_STATE(s_req_first_http_major);        break;      /* first digit of major HTTP version */      case s_req_first_http_major:        if (UNLIKELY(ch < '1' || ch > '9')) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        parser->http_major = ch - '0';        UPDATE_STATE(s_req_http_major);        break;      /* major HTTP version or dot */      case s_req_http_major:      {        if (ch == '.') {          UPDATE_STATE(s_req_first_http_minor);          break;        }        if (UNLIKELY(!IS_NUM(ch))) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        parser->http_major *= 10;        parser->http_major += ch - '0';        if (UNLIKELY(parser->http_major > 999)) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        break;      }      /* first digit of minor HTTP version */      case s_req_first_http_minor:        if (UNLIKELY(!IS_NUM(ch))) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        parser->http_minor = ch - '0';        UPDATE_STATE(s_req_http_minor);        break;      /* minor HTTP version or end of request line */      case s_req_http_minor:      {        if (ch == CR) {          UPDATE_STATE(s_req_line_almost_done);          break;        }        if (ch == LF) {          UPDATE_STATE(s_header_field_start);          break;        }        /* XXX allow spaces after digit? */        if (UNLIKELY(!IS_NUM(ch))) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        parser->http_minor *= 10;        parser->http_minor += ch - '0';        if (UNLIKELY(parser->http_minor > 999)) {          SET_ERRNO(HPE_INVALID_VERSION);          goto error;        }        break;      }      /* end of request line */      case s_req_line_almost_done:      {        if (UNLIKELY(ch != LF)) {          SET_ERRNO(HPE_LF_EXPECTED);          goto error;        }        UPDATE_STATE(s_header_field_start);        break;      }      case s_header_field_start:      {        if (ch == CR) {          UPDATE_STATE(s_headers_almost_done);          break;        }        if (ch == LF) {          /* they might be just sending \n instead of \r\n so this would be           * the second \n to denote the end of headers*/          UPDATE_STATE(s_headers_almost_done);          REEXECUTE();        }        c = TOKEN(ch);        if (UNLIKELY(!c)) {          SET_ERRNO(HPE_INVALID_HEADER_TOKEN);          goto error;        }        MARK(header_field);        parser->index = 0;        UPDATE_STATE(s_header_field);        switch (c) {          case 'c':            parser->header_state = h_C;            break;          case 'p':            parser->header_state = h_matching_proxy_connection;            break;          case 't':            parser->header_state = h_matching_transfer_encoding;            break;          case 'u':            parser->header_state = h_matching_upgrade;            break;          default:            parser->header_state = h_general;            break;        }        break;      }      case s_header_field:      {        const char* start = p;        for (; p != data + len; p++) {          ch = *p;          c = TOKEN(ch);          if (!c)            break;          switch (parser->header_state) {            case h_general:              break;            case h_C:              parser->index++;              parser->header_state = (c == 'o' ? h_CO : h_general);              break;            case h_CO:              parser->index++;              parser->header_state = (c == 'n' ? h_CON : h_general);              break;            case h_CON:              parser->index++;              switch (c) {                case 'n':                  parser->header_state = h_matching_connection;                  break;                case 't':                  parser->header_state = h_matching_content_length;                  break;                default:                  parser->header_state = h_general;                  break;              }              break;            /* connection */            case h_matching_connection:              parser->index++;              if (parser->index > sizeof(CONNECTION)-1                  || c != CONNECTION[parser->index]) {                parser->header_state = h_general;              } else if (parser->index == sizeof(CONNECTION)-2) {                parser->header_state = h_connection;              }              break;            /* proxy-connection */            case h_matching_proxy_connection:              parser->index++;              if (parser->index > sizeof(PROXY_CONNECTION)-1                  || c != PROXY_CONNECTION[parser->index]) {                parser->header_state = h_general;              } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {                parser->header_state = h_connection;              }              break;            /* content-length */            case h_matching_content_length:              parser->index++;              if (parser->index > sizeof(CONTENT_LENGTH)-1                  || c != CONTENT_LENGTH[parser->index]) {                parser->header_state = h_general;              } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {                parser->header_state = h_content_length;              }              break;            /* transfer-encoding */            case h_matching_transfer_encoding:              parser->index++;              if (parser->index > sizeof(TRANSFER_ENCODING)-1                  || c != TRANSFER_ENCODING[parser->index]) {                parser->header_state = h_general;              } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {                parser->header_state = h_transfer_encoding;              }              break;            /* upgrade */            case h_matching_upgrade:              parser->index++;              if (parser->index > sizeof(UPGRADE)-1                  || c != UPGRADE[parser->index]) {                parser->header_state = h_general;              } else if (parser->index == sizeof(UPGRADE)-2) {                parser->header_state = h_upgrade;              }              break;            case h_connection:            case h_content_length:            case h_transfer_encoding:            case h_upgrade:              if (ch != ' ') parser->header_state = h_general;              break;            default:              assert(0 && "Unknown header_state");              break;          }        }        COUNT_HEADER_SIZE(p - start);        if (p == data + len) {          --p;          break;        }        if (ch == ':') {          UPDATE_STATE(s_header_value_discard_ws);          CALLBACK_DATA(header_field);          break;        }        SET_ERRNO(HPE_INVALID_HEADER_TOKEN);        goto error;      }      case s_header_value_discard_ws:        if (ch == ' ' || ch == '\t') break;        if (ch == CR) {          UPDATE_STATE(s_header_value_discard_ws_almost_done);          break;        }        if (ch == LF) {          UPDATE_STATE(s_header_value_discard_lws);          break;        }        /* FALLTHROUGH */      case s_header_value_start:      {        MARK(header_value);        UPDATE_STATE(s_header_value);        parser->index = 0;        c = LOWER(ch);        switch (parser->header_state) {          case h_upgrade:            parser->flags |= F_UPGRADE;            parser->header_state = h_general;            break;          case h_transfer_encoding:            /* looking for 'Transfer-Encoding: chunked' */            if ('c' == c) {              parser->header_state = h_matching_transfer_encoding_chunked;            } else {              parser->header_state = h_general;            }            break;          case h_content_length:            if (UNLIKELY(!IS_NUM(ch))) {              SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);              goto error;            }            if (parser->flags & F_CONTENTLENGTH) {              SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);              goto error;            }            parser->flags |= F_CONTENTLENGTH;            parser->content_length = ch - '0';            break;          case h_connection:            /* looking for 'Connection: keep-alive' */            if (c == 'k') {              parser->header_state = h_matching_connection_keep_alive;            /* looking for 'Connection: close' */            } else if (c == 'c') {              parser->header_state = h_matching_connection_close;            } else if (c == 'u') {              parser->header_state = h_matching_connection_upgrade;            } else {              parser->header_state = h_matching_connection_token;            }            break;          /* Multi-value `Connection` header */          case h_matching_connection_token_start:            break;          default:            parser->header_state = h_general;            break;        }        break;      }      case s_header_value:      {        const char* start = p;        enum header_states h_state = (enum header_states) parser->header_state;        for (; p != data + len; p++) {          ch = *p;          if (ch == CR) {            UPDATE_STATE(s_header_almost_done);            parser->header_state = h_state;            CALLBACK_DATA(header_value);            break;          }          if (ch == LF) {            UPDATE_STATE(s_header_almost_done);            COUNT_HEADER_SIZE(p - start);            parser->header_state = h_state;            CALLBACK_DATA_NOADVANCE(header_value);            REEXECUTE();          }          if (!lenient && !IS_HEADER_CHAR(ch)) {            SET_ERRNO(HPE_INVALID_HEADER_TOKEN);            goto error;          }          c = LOWER(ch);          switch (h_state) {            case h_general:            {              const char* p_cr;              const char* p_lf;              size_t limit = data + len - p;              limit = MIN(limit, HTTP_MAX_HEADER_SIZE);              p_cr = (const char*) memchr(p, CR, limit);              p_lf = (const char*) memchr(p, LF, limit);              if (p_cr != NULL) {                if (p_lf != NULL && p_cr >= p_lf)                  p = p_lf;                else                  p = p_cr;              } else if (UNLIKELY(p_lf != NULL)) {                p = p_lf;              } else {                p = data + len;              }              --p;              break;            }            case h_connection:            case h_transfer_encoding:              assert(0 && "Shouldn't get here.");              break;            case h_content_length:            {              uint64_t t;              if (ch == ' ') break;              if (UNLIKELY(!IS_NUM(ch))) {                SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);                parser->header_state = h_state;                goto error;              }              t = parser->content_length;              t *= 10;              t += ch - '0';              /* Overflow? Test against a conservative limit for simplicity. */              if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {                SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);                parser->header_state = h_state;                goto error;              }              parser->content_length = t;              break;            }            /* Transfer-Encoding: chunked */            case h_matching_transfer_encoding_chunked:              parser->index++;              if (parser->index > sizeof(CHUNKED)-1                  || c != CHUNKED[parser->index]) {                h_state = h_general;              } else if (parser->index == sizeof(CHUNKED)-2) {                h_state = h_transfer_encoding_chunked;              }              break;            case h_matching_connection_token_start:              /* looking for 'Connection: keep-alive' */              if (c == 'k') {                h_state = h_matching_connection_keep_alive;              /* looking for 'Connection: close' */              } else if (c == 'c') {                h_state = h_matching_connection_close;              } else if (c == 'u') {                h_state = h_matching_connection_upgrade;              } else if (STRICT_TOKEN(c)) {                h_state = h_matching_connection_token;              } else if (c == ' ' || c == '\t') {                /* Skip lws */              } else {                h_state = h_general;              }              break;            /* looking for 'Connection: keep-alive' */            case h_matching_connection_keep_alive:              parser->index++;              if (parser->index > sizeof(KEEP_ALIVE)-1                  || c != KEEP_ALIVE[parser->index]) {                h_state = h_matching_connection_token;              } else if (parser->index == sizeof(KEEP_ALIVE)-2) {                h_state = h_connection_keep_alive;              }              break;            /* looking for 'Connection: close' */            case h_matching_connection_close:              parser->index++;              if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {                h_state = h_matching_connection_token;              } else if (parser->index == sizeof(CLOSE)-2) {                h_state = h_connection_close;              }              break;            /* looking for 'Connection: upgrade' */            case h_matching_connection_upgrade:              parser->index++;              if (parser->index > sizeof(UPGRADE) - 1 ||                  c != UPGRADE[parser->index]) {                h_state = h_matching_connection_token;              } else if (parser->index == sizeof(UPGRADE)-2) {                h_state = h_connection_upgrade;              }              break;            case h_matching_connection_token:              if (ch == ',') {                h_state = h_matching_connection_token_start;                parser->index = 0;              }              break;            case h_transfer_encoding_chunked:              if (ch != ' ') h_state = h_general;              break;            case h_connection_keep_alive:            case h_connection_close:            case h_connection_upgrade:              if (ch == ',') {                if (h_state == h_connection_keep_alive) {                  parser->flags |= F_CONNECTION_KEEP_ALIVE;                } else if (h_state == h_connection_close) {                  parser->flags |= F_CONNECTION_CLOSE;                } else if (h_state == h_connection_upgrade) {                  parser->flags |= F_CONNECTION_UPGRADE;                }                h_state = h_matching_connection_token_start;                parser->index = 0;              } else if (ch != ' ') {                h_state = h_matching_connection_token;              }              break;            default:              UPDATE_STATE(s_header_value);              h_state = h_general;              break;          }        }        parser->header_state = h_state;        COUNT_HEADER_SIZE(p - start);        if (p == data + len)          --p;        break;      }      case s_header_almost_done:      {        if (UNLIKELY(ch != LF)) {          SET_ERRNO(HPE_LF_EXPECTED);          goto error;        }        UPDATE_STATE(s_header_value_lws);        break;      }      case s_header_value_lws:      {        if (ch == ' ' || ch == '\t') {          UPDATE_STATE(s_header_value_start);          REEXECUTE();        }        /* finished the header */        switch (parser->header_state) {          case h_connection_keep_alive:            parser->flags |= F_CONNECTION_KEEP_ALIVE;            break;          case h_connection_close:            parser->flags |= F_CONNECTION_CLOSE;            break;          case h_transfer_encoding_chunked:            parser->flags |= F_CHUNKED;            break;          case h_connection_upgrade:            parser->flags |= F_CONNECTION_UPGRADE;            break;          default:            break;        }        UPDATE_STATE(s_header_field_start);        REEXECUTE();      }      case s_header_value_discard_ws_almost_done:      {        STRICT_CHECK(ch != LF);        UPDATE_STATE(s_header_value_discard_lws);        break;      }      case s_header_value_discard_lws:      {        if (ch == ' ' || ch == '\t') {          UPDATE_STATE(s_header_value_discard_ws);          break;        } else {          switch (parser->header_state) {            case h_connection_keep_alive:              parser->flags |= F_CONNECTION_KEEP_ALIVE;              break;            case h_connection_close:              parser->flags |= F_CONNECTION_CLOSE;              break;            case h_connection_upgrade:              parser->flags |= F_CONNECTION_UPGRADE;              break;            case h_transfer_encoding_chunked:              parser->flags |= F_CHUNKED;              break;            default:              break;          }          /* header value was empty */          MARK(header_value);          UPDATE_STATE(s_header_field_start);          CALLBACK_DATA_NOADVANCE(header_value);          REEXECUTE();        }      }      case s_headers_almost_done:      {        STRICT_CHECK(ch != LF);        if (parser->flags & F_TRAILING) {          /* End of a chunked request */          UPDATE_STATE(s_message_done);          CALLBACK_NOTIFY_NOADVANCE(chunk_complete);          REEXECUTE();        }        /* Cannot use chunked encoding and a content-length header together           per the HTTP specification. */        if ((parser->flags & F_CHUNKED) &&            (parser->flags & F_CONTENTLENGTH)) {          SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);          goto error;        }        UPDATE_STATE(s_headers_done);        /* Set this here so that on_headers_complete() callbacks can see it */        parser->upgrade =          ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) ==           (F_UPGRADE | F_CONNECTION_UPGRADE) ||           parser->method == HTTP_CONNECT);        /* Here we call the headers_complete callback. This is somewhat         * different than other callbacks because if the user returns 1, we         * will interpret that as saying that this message has no body. This         * is needed for the annoying case of recieving a response to a HEAD         * request.         *         * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so         * we have to simulate it by handling a change in errno below.         */        if (settings->on_headers_complete) {          switch (settings->on_headers_complete(parser)) {            case 0:              break;            case 2:              parser->upgrade = 1;            case 1:              parser->flags |= F_SKIPBODY;              break;            default:              SET_ERRNO(HPE_CB_headers_complete);              RETURN(p - data); /* Error */          }        }        if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {          RETURN(p - data);        }        REEXECUTE();      }      case s_headers_done:      {        int hasBody;        STRICT_CHECK(ch != LF);        parser->nread = 0;        hasBody = parser->flags & F_CHUNKED ||          (parser->content_length > 0 && parser->content_length != ULLONG_MAX);        if (parser->upgrade && (parser->method == HTTP_CONNECT ||                                (parser->flags & F_SKIPBODY) || !hasBody)) {          /* Exit, the rest of the message is in a different protocol. */          UPDATE_STATE(NEW_MESSAGE());          CALLBACK_NOTIFY(message_complete);          RETURN((p - data) + 1);        }        if (parser->flags & F_SKIPBODY) {          UPDATE_STATE(NEW_MESSAGE());          CALLBACK_NOTIFY(message_complete);        } else if (parser->flags & F_CHUNKED) {          /* chunked encoding - ignore Content-Length header */          UPDATE_STATE(s_chunk_size_start);        } else {          if (parser->content_length == 0) {            /* Content-Length header given but zero: Content-Length: 0\r\n */            UPDATE_STATE(NEW_MESSAGE());            CALLBACK_NOTIFY(message_complete);          } else if (parser->content_length != ULLONG_MAX) {            /* Content-Length header given and non-zero */            UPDATE_STATE(s_body_identity);          } else {            if (!http_message_needs_eof(parser)) {              /* Assume content-length 0 - read the next */              UPDATE_STATE(NEW_MESSAGE());              CALLBACK_NOTIFY(message_complete);            } else {              /* Read body until EOF */              UPDATE_STATE(s_body_identity_eof);            }          }        }        break;      }      case s_body_identity:      {        uint64_t to_read = MIN(parser->content_length,                               (uint64_t) ((data + len) - p));        assert(parser->content_length != 0            && parser->content_length != ULLONG_MAX);        /* The difference between advancing content_length and p is because         * the latter will automaticaly advance on the next loop iteration.         * Further, if content_length ends up at 0, we want to see the last         * byte again for our message complete callback.         */        MARK(body);        parser->content_length -= to_read;        p += to_read - 1;        if (parser->content_length == 0) {          UPDATE_STATE(s_message_done);          /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.           *           * The alternative to doing this is to wait for the next byte to           * trigger the data callback, just as in every other case. The           * problem with this is that this makes it difficult for the test           * harness to distinguish between complete-on-EOF and           * complete-on-length. It's not clear that this distinction is           * important for applications, but let's keep it for now.           */          CALLBACK_DATA_(body, p - body_mark + 1, p - data);          REEXECUTE();        }        break;      }      /* read until EOF */      case s_body_identity_eof:        MARK(body);        p = data + len - 1;        break;      case s_message_done:        UPDATE_STATE(NEW_MESSAGE());        CALLBACK_NOTIFY(message_complete);        if (parser->upgrade) {          /* Exit, the rest of the message is in a different protocol. */          RETURN((p - data) + 1);        }        break;      case s_chunk_size_start:      {        assert(parser->nread == 1);        assert(parser->flags & F_CHUNKED);        unhex_val = unhex[(unsigned char)ch];        if (UNLIKELY(unhex_val == -1)) {          SET_ERRNO(HPE_INVALID_CHUNK_SIZE);          goto error;        }        parser->content_length = unhex_val;        UPDATE_STATE(s_chunk_size);        break;      }      case s_chunk_size:      {        uint64_t t;        assert(parser->flags & F_CHUNKED);        if (ch == CR) {          UPDATE_STATE(s_chunk_size_almost_done);          break;        }        unhex_val = unhex[(unsigned char)ch];        if (unhex_val == -1) {          if (ch == ';' || ch == ' ') {            UPDATE_STATE(s_chunk_parameters);            break;          }          SET_ERRNO(HPE_INVALID_CHUNK_SIZE);          goto error;        }        t = parser->content_length;        t *= 16;        t += unhex_val;        /* Overflow? Test against a conservative limit for simplicity. */        if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {          SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);          goto error;        }        parser->content_length = t;        break;      }      case s_chunk_parameters:      {        assert(parser->flags & F_CHUNKED);        /* just ignore this shit. TODO check for overflow */        if (ch == CR) {          UPDATE_STATE(s_chunk_size_almost_done);          break;        }        break;      }      case s_chunk_size_almost_done:      {        assert(parser->flags & F_CHUNKED);        STRICT_CHECK(ch != LF);        parser->nread = 0;        if (parser->content_length == 0) {          parser->flags |= F_TRAILING;          UPDATE_STATE(s_header_field_start);        } else {          UPDATE_STATE(s_chunk_data);        }        CALLBACK_NOTIFY(chunk_header);        break;      }      case s_chunk_data:      {        uint64_t to_read = MIN(parser->content_length,                               (uint64_t) ((data + len) - p));        assert(parser->flags & F_CHUNKED);        assert(parser->content_length != 0            && parser->content_length != ULLONG_MAX);        /* See the explanation in s_body_identity for why the content         * length and data pointers are managed this way.         */        MARK(body);        parser->content_length -= to_read;        p += to_read - 1;        if (parser->content_length == 0) {          UPDATE_STATE(s_chunk_data_almost_done);        }        break;      }      case s_chunk_data_almost_done:        assert(parser->flags & F_CHUNKED);        assert(parser->content_length == 0);        STRICT_CHECK(ch != CR);        UPDATE_STATE(s_chunk_data_done);        CALLBACK_DATA(body);        break;      case s_chunk_data_done:        assert(parser->flags & F_CHUNKED);        STRICT_CHECK(ch != LF);        parser->nread = 0;        UPDATE_STATE(s_chunk_size_start);        CALLBACK_NOTIFY(chunk_complete);        break;      default:        assert(0 && "unhandled state");        SET_ERRNO(HPE_INVALID_INTERNAL_STATE);        goto error;    }  }  /* Run callbacks for any marks that we have leftover after we ran our of   * bytes. There should be at most one of these set, so it's OK to invoke   * them in series (unset marks will not result in callbacks).   *   * We use the NOADVANCE() variety of callbacks here because 'p' has already   * overflowed 'data' and this allows us to correct for the off-by-one that   * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'   * value that's in-bounds).   */  assert(((header_field_mark ? 1 : 0) +          (header_value_mark ? 1 : 0) +          (url_mark ? 1 : 0)  +          (body_mark ? 1 : 0) +          (status_mark ? 1 : 0)) <= 1);  CALLBACK_DATA_NOADVANCE(header_field);  CALLBACK_DATA_NOADVANCE(header_value);  CALLBACK_DATA_NOADVANCE(url);  CALLBACK_DATA_NOADVANCE(body);  CALLBACK_DATA_NOADVANCE(status);  RETURN(len);error:  if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {    SET_ERRNO(HPE_UNKNOWN);  }  RETURN(p - data);}/* Does the parser need to see an EOF to find the end of the message? */inthttp_message_needs_eof (const http_parser *parser){  if (parser->type == HTTP_REQUEST) {    return 0;  }  /* See RFC 2616 section 4.4 */  if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */      parser->status_code == 204 ||     /* No Content */      parser->status_code == 304 ||     /* Not Modified */      parser->flags & F_SKIPBODY) {     /* response to a HEAD request */    return 0;  }  if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {    return 0;  }  return 1;}inthttp_should_keep_alive (const http_parser *parser){  if (parser->http_major > 0 && parser->http_minor > 0) {    /* HTTP/1.1 */    if (parser->flags & F_CONNECTION_CLOSE) {      return 0;    }  } else {    /* HTTP/1.0 or earlier */    if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {      return 0;    }  }  return !http_message_needs_eof(parser);}const char *http_method_str (enum http_method m){  return ELEM_AT(method_strings, m, "<unknown>");}voidhttp_parser_init (http_parser *parser, enum http_parser_type t){  void *data = parser->data; /* preserve application data */  memset(parser, 0, sizeof(*parser));  parser->data = data;  parser->type = t;  parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));  parser->http_errno = HPE_OK;}voidhttp_parser_settings_init(http_parser_settings *settings){  memset(settings, 0, sizeof(*settings));}const char *http_errno_name(enum http_errno err) {  assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));  return http_strerror_tab[err].name;}const char *http_errno_description(enum http_errno err) {  assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));  return http_strerror_tab[err].description;}static enum http_host_statehttp_parse_host_char(enum http_host_state s, const char ch) {  switch(s) {    case s_http_userinfo:    case s_http_userinfo_start:      if (ch == '@') {        return s_http_host_start;      }      if (IS_USERINFO_CHAR(ch)) {        return s_http_userinfo;      }      break;    case s_http_host_start:      if (ch == '[') {        return s_http_host_v6_start;      }      if (IS_HOST_CHAR(ch)) {        return s_http_host;      }      break;    case s_http_host:      if (IS_HOST_CHAR(ch)) {        return s_http_host;      }    /* FALLTHROUGH */    case s_http_host_v6_end:      if (ch == ':') {        return s_http_host_port_start;      }      break;    case s_http_host_v6:      if (ch == ']') {        return s_http_host_v6_end;      }    /* FALLTHROUGH */    case s_http_host_v6_start:      if (IS_HEX(ch) || ch == ':' || ch == '.') {        return s_http_host_v6;      }      if (s == s_http_host_v6 && ch == '%') {        return s_http_host_v6_zone_start;      }      break;    case s_http_host_v6_zone:      if (ch == ']') {        return s_http_host_v6_end;      }    /* FALLTHROUGH */    case s_http_host_v6_zone_start:      /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */      if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||          ch == '~') {        return s_http_host_v6_zone;      }      break;    case s_http_host_port:    case s_http_host_port_start:      if (IS_NUM(ch)) {        return s_http_host_port;      }      break;    default:      break;  }  return s_http_host_dead;}static inthttp_parse_host(const char * buf, struct http_parser_url *u, int found_at) {  enum http_host_state s;  const char *p;  size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;  assert(u->field_set & (1 << UF_HOST));  u->field_data[UF_HOST].len = 0;  s = found_at ? s_http_userinfo_start : s_http_host_start;  for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {    enum http_host_state new_s = http_parse_host_char(s, *p);    if (new_s == s_http_host_dead) {      return 1;    }    switch(new_s) {      case s_http_host:        if (s != s_http_host) {          u->field_data[UF_HOST].off = p - buf;        }        u->field_data[UF_HOST].len++;        break;      case s_http_host_v6:        if (s != s_http_host_v6) {          u->field_data[UF_HOST].off = p - buf;        }        u->field_data[UF_HOST].len++;        break;      case s_http_host_v6_zone_start:      case s_http_host_v6_zone:        u->field_data[UF_HOST].len++;        break;      case s_http_host_port:        if (s != s_http_host_port) {          u->field_data[UF_PORT].off = p - buf;          u->field_data[UF_PORT].len = 0;          u->field_set |= (1 << UF_PORT);        }        u->field_data[UF_PORT].len++;        break;      case s_http_userinfo:        if (s != s_http_userinfo) {          u->field_data[UF_USERINFO].off = p - buf ;          u->field_data[UF_USERINFO].len = 0;          u->field_set |= (1 << UF_USERINFO);        }        u->field_data[UF_USERINFO].len++;        break;      default:        break;    }    s = new_s;  }  /* Make sure we don't end somewhere unexpected */  switch (s) {    case s_http_host_start:    case s_http_host_v6_start:    case s_http_host_v6:    case s_http_host_v6_zone_start:    case s_http_host_v6_zone:    case s_http_host_port_start:    case s_http_userinfo:    case s_http_userinfo_start:      return 1;    default:      break;  }  return 0;}voidhttp_parser_url_init(struct http_parser_url *u) {  memset(u, 0, sizeof(*u));}inthttp_parser_parse_url(const char *buf, size_t buflen, int is_connect,                      struct http_parser_url *u){  enum state s;  const char *p;  enum http_parser_url_fields uf, old_uf;  int found_at = 0;  u->port = u->field_set = 0;  s = is_connect ? s_req_server_start : s_req_spaces_before_url;  old_uf = UF_MAX;  for (p = buf; p < buf + buflen; p++) {    s = parse_url_char(s, *p);    /* Figure out the next field that we're operating on */    switch (s) {      case s_dead:        return 1;      /* Skip delimeters */      case s_req_schema_slash:      case s_req_schema_slash_slash:      case s_req_server_start:      case s_req_query_string_start:      case s_req_fragment_start:        continue;      case s_req_schema:        uf = UF_SCHEMA;        break;      case s_req_server_with_at:        found_at = 1;      /* FALLTROUGH */      case s_req_server:        uf = UF_HOST;        break;      case s_req_path:        uf = UF_PATH;        break;      case s_req_query_string:        uf = UF_QUERY;        break;      case s_req_fragment:        uf = UF_FRAGMENT;        break;      default:        assert(!"Unexpected state");        return 1;    }    /* Nothing's changed; soldier on */    if (uf == old_uf) {      u->field_data[uf].len++;      continue;    }    u->field_data[uf].off = p - buf;    u->field_data[uf].len = 1;    u->field_set |= (1 << uf);    old_uf = uf;  }  /* host must be present if there is a schema */  /* parsing http:///toto will fail */  if ((u->field_set & (1 << UF_SCHEMA)) &&      (u->field_set & (1 << UF_HOST)) == 0) {    return 1;  }  if (u->field_set & (1 << UF_HOST)) {    if (http_parse_host(buf, u, found_at) != 0) {      return 1;    }  }  /* CONNECT requests can only contain "hostname:port" */  if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {    return 1;  }  if (u->field_set & (1 << UF_PORT)) {    /* Don't bother with endp; we've already validated the string */    unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);    /* Ports have a max value of 2^16 */    if (v > 0xffff) {      return 1;    }    u->port = (uint16_t) v;  }  return 0;}voidhttp_parser_pause(http_parser *parser, int paused) {  /* Users should only be pausing/unpausing a parser that is not in an error   * state. In non-debug builds, there's not much that we can do about this   * other than ignore it.   */  if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||      HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {    SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);  } else {    assert(0 && "Attempting to pause parser in error state");  }}inthttp_body_is_final(const struct http_parser *parser) {    return parser->state == s_message_done;}unsigned longhttp_parser_version(void) {  return HTTP_PARSER_VERSION_MAJOR * 0x10000 |         HTTP_PARSER_VERSION_MINOR * 0x00100 |         HTTP_PARSER_VERSION_PATCH * 0x00001;}
 |