diff --git a/lib/context.c b/lib/context.c index ca211da7..c6f4b51f 100644 --- a/lib/context.c +++ b/lib/context.c @@ -79,9 +79,12 @@ const struct http2_settings lws_h2_defaults = { { * including the length of the name and value in octets plus an * overhead of 32 octets for each header field. */ - + /* H2SET_RESERVED7 */ 0, + /* H2SET_ENABLE_CONNECT_PROTOCOL */ 0, }}; +/* these are the "lws defaults"... they can be overridden in plat */ + const struct http2_settings lws_h2_stock_settings = { { 1, /* H2SET_HEADER_TABLE_SIZE */ 4096, @@ -106,7 +109,8 @@ const struct http2_settings lws_h2_stock_settings = { { * including the length of the name and value in octets plus an * overhead of 32 octets for each header field. */ - + /* H2SET_RESERVED7 */ 0, + /* H2SET_ENABLE_CONNECT_PROTOCOL */ 1, }}; #endif diff --git a/lib/handshake.c b/lib/handshake.c index df2a5c23..b7107de2 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -72,10 +72,15 @@ lws_read(struct lws *wsi, unsigned char *buf, lws_filepos_t len) case LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS: case LWSS_HTTP2_ESTABLISHED: n = 0; - //lwsl_debug("%s: starting new block of %d\n", __func__, (int)len); /* * wsi here is always the network connection wsi, not a stream - * wsi. + * wsi. Once we unpicked the framing we will find the right + * swsi and make it the target of the frame. + * + * If it's ws over h2, the nwsi will get us here to do the h2 + * processing, and that will call us back with the swsi + + * ESTABLISHED state for the inner payload, handled in a later + * case. */ while (n < len) { /* @@ -252,6 +257,7 @@ postbody_completion: goto bail; switch (wsi->mode) { case LWSCM_WS_SERVING: + case LWSCM_HTTP2_WS_SERVING: if (lws_interpret_incoming_packet(wsi, &buf, (size_t)len) < 0) { diff --git a/lib/http2/hpack.c b/lib/http2/hpack.c index 430fbc4f..70aff4ac 100644 --- a/lib/http2/hpack.c +++ b/lib/http2/hpack.c @@ -227,6 +227,7 @@ static int lws_frag_start(struct lws *wsi, int hdr_token_idx) if ((hdr_token_idx == WSI_TOKEN_HTTP_COLON_AUTHORITY || hdr_token_idx == WSI_TOKEN_HTTP_COLON_METHOD || hdr_token_idx == WSI_TOKEN_HTTP_COLON_PATH || + hdr_token_idx == WSI_TOKEN_COLON_PROTOCOL || hdr_token_idx == WSI_TOKEN_HTTP_COLON_SCHEME) && ah->frag_index[hdr_token_idx]) { if (!(ah->frags[ah->frag_index[hdr_token_idx]].flags & 1)) { diff --git a/lib/http2/http2.c b/lib/http2/http2.c index c0fdfa83..7bc2f1f7 100644 --- a/lib/http2/http2.c +++ b/lib/http2/http2.c @@ -1455,10 +1455,8 @@ lws_h2_parser(struct lws *wsi, unsigned char c) case LWS_H2_FRAME_TYPE_DATA: //lwsl_notice("incoming LWS_H2_FRAME_TYPE_DATA content\n"); - if (!h2n->swsi) { - //lwsl_notice("data sid %d has no swsi\n", h2n->sid); + if (!h2n->swsi) break; - } h2n->swsi->state = LWSS_HTTP_BODY; h2n->inside++; @@ -1473,11 +1471,9 @@ lws_h2_parser(struct lws *wsi, unsigned char c) } n = lws_read(h2n->swsi, &c, 1); - if (n < 0) { - // lws_h2_rst_stream(wsi, LWS_H2_PPS_RST_STREAM, - // "post body done"); + if (n < 0) break; - } + break; case LWS_H2_FRAME_TYPE_PRIORITY: @@ -1580,3 +1576,59 @@ try_frame_start: return 0; } +int +lws_h2_ws_handshake(struct lws *wsi) +{ + uint8_t buf[256], *p = buf, *start = p, *end = &buf[sizeof(buf) - 1]; + const struct lws_http_mount *hit; + const char * uri_ptr; + int n; + + if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) + return -1; + + if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) > 64) + return -1; + + /* we can only return the protocol header if: + * - one came in, and ... */ + if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) && + /* - it is not an empty string */ + wsi->protocol->name && wsi->protocol->name[0]) { + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_PROTOCOL, + (unsigned char *)wsi->protocol->name, + strlen(wsi->protocol->name), &p, end)) + return -1; + } + + if (lws_finalize_http_header(wsi, &p, end)) + return -1; + + n = lws_write(wsi, start, lws_ptr_diff(p, start), + LWS_WRITE_HTTP_HEADERS); + if (n != lws_ptr_diff(p, start)) { + lwsl_err("_write returned %d from %d\n", n, + lws_ptr_diff(p, start)); + + return -1; + } + + /* + * alright clean up, set our state to generic ws established, the + * mode / state of the nwsi will get the h2 processing done. + */ + + wsi->state = LWSS_ESTABLISHED; + wsi->lws_rx_parse_state = LWS_RXPS_NEW; + + uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH); + n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH); + hit = lws_find_mount(wsi, uri_ptr, n); + + if (hit && hit->cgienv && + wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO, wsi->user_space, + (void *)hit->cgienv, 0)) + return 1; + + return 0; +} diff --git a/lib/lextable-strings.h b/lib/lextable-strings.h index 035a822d..19e84e2a 100644 --- a/lib/lextable-strings.h +++ b/lib/lextable-strings.h @@ -99,6 +99,7 @@ STORE_IN_ROM static const char * const set[] = { "head ", "te:", /* http/2 wants it to reject it */ "replay-nonce:", /* ACME */ + ":protocol", /* defined in mcmanus-httpbis-h2-ws-02 */ "", /* not matchable */ diff --git a/lib/lextable.h b/lib/lextable.h index d048b948..a8cf671d 100644 --- a/lib/lextable.h +++ b/lib/lextable.h @@ -11,14 +11,14 @@ 0x64 /* 'd' */, 0x19, 0x02 /* (to 0x0237 state 265) */, 0x72 /* 'r' */, 0x22, 0x02 /* (to 0x0243 state 270) */, 0x3A /* ':' */, 0x56, 0x02 /* (to 0x027A state 299) */, - 0x65 /* 'e' */, 0xE2, 0x02 /* (to 0x0309 state 409) */, - 0x66 /* 'f' */, 0xFE, 0x02 /* (to 0x0328 state 425) */, - 0x6C /* 'l' */, 0x20, 0x03 /* (to 0x034D state 458) */, - 0x6D /* 'm' */, 0x43, 0x03 /* (to 0x0373 state 484) */, - 0x74 /* 't' */, 0xB2, 0x03 /* (to 0x03E5 state 578) */, - 0x76 /* 'v' */, 0xD3, 0x03 /* (to 0x0409 state 606) */, - 0x77 /* 'w' */, 0xE0, 0x03 /* (to 0x0419 state 614) */, - 0x78 /* 'x' */, 0x07, 0x04 /* (to 0x0443 state 650) */, + 0x65 /* 'e' */, 0xE8, 0x02 /* (to 0x030F state 409) */, + 0x66 /* 'f' */, 0x04, 0x03 /* (to 0x032E state 425) */, + 0x6C /* 'l' */, 0x26, 0x03 /* (to 0x0353 state 458) */, + 0x6D /* 'm' */, 0x49, 0x03 /* (to 0x0379 state 484) */, + 0x74 /* 't' */, 0xB8, 0x03 /* (to 0x03EB state 578) */, + 0x76 /* 'v' */, 0xD9, 0x03 /* (to 0x040F state 606) */, + 0x77 /* 'w' */, 0xE6, 0x03 /* (to 0x041F state 614) */, + 0x78 /* 'x' */, 0x0D, 0x04 /* (to 0x0449 state 650) */, 0x08, /* fail */ /* pos 0040: 1 */ 0xE5 /* 'e' -> */, /* pos 0041: 2 */ 0xF4 /* 't' -> */, @@ -26,8 +26,8 @@ /* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, /* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */, 0x72 /* 'r' */, 0x95, 0x01 /* (to 0x01DD state 211) */, - 0x61 /* 'a' */, 0xE0, 0x03 /* (to 0x042B state 631) */, - 0x75 /* 'u' */, 0xE2, 0x03 /* (to 0x0430 state 635) */, + 0x61 /* 'a' */, 0xE6, 0x03 /* (to 0x0431 state 631) */, + 0x75 /* 'u' */, 0xE8, 0x03 /* (to 0x0436 state 635) */, 0x08, /* fail */ /* pos 0052: 6 */ 0xF3 /* 's' -> */, /* pos 0053: 7 */ 0xF4 /* 't' -> */, @@ -45,7 +45,7 @@ /* pos 0064: 17 */ 0x00, 0x02 /* - terminal marker 2 - */, /* pos 0066: 18 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0070 state 19) */, 0x74 /* 't' */, 0xBF, 0x00 /* (to 0x0128 state 110) */, - 0x65 /* 'e' */, 0xFB, 0x03 /* (to 0x0467 state 676) */, + 0x65 /* 'e' */, 0x01, 0x04 /* (to 0x046D state 676) */, 0x08, /* fail */ /* pos 0070: 19 */ 0xF3 /* 's' -> */, /* pos 0071: 20 */ 0xF4 /* 't' -> */, @@ -64,15 +64,15 @@ /* pos 008b: 27 */ 0xE3 /* 'c' -> */, /* pos 008c: 28 */ 0xF4 /* 't' -> */, /* pos 008d: 29 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0094 state 30) */, - 0x20 /* ' ' */, 0xD5, 0x03 /* (to 0x0465 state 675) */, + 0x20 /* ' ' */, 0xDB, 0x03 /* (to 0x046B state 675) */, 0x08, /* fail */ /* pos 0094: 30 */ 0xEF /* 'o' -> */, /* pos 0095: 31 */ 0xEE /* 'n' -> */, /* pos 0096: 32 */ 0xBA /* ':' -> */, /* pos 0097: 33 */ 0x00, 0x04 /* - terminal marker 4 - */, /* pos 0099: 34 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x00A3 state 35) */, - 0x73 /* 's' */, 0x62, 0x03 /* (to 0x03FE state 596) */, - 0x72 /* 'r' */, 0x9A, 0x03 /* (to 0x0439 state 642) */, + 0x73 /* 's' */, 0x68, 0x03 /* (to 0x0404 state 596) */, + 0x72 /* 'r' */, 0xA0, 0x03 /* (to 0x043F state 642) */, 0x08, /* fail */ /* pos 00a3: 35 */ 0xE7 /* 'g' -> */, /* pos 00a4: 36 */ 0xF2 /* 'r' -> */, @@ -88,11 +88,11 @@ /* pos 00af: 46 */ 0xBA /* ':' -> */, /* pos 00b0: 47 */ 0x00, 0x06 /* - terminal marker 6 - */, /* pos 00b2: 48 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x00B9 state 49) */, - 0x74 /* 't' */, 0x16, 0x03 /* (to 0x03CB state 553) */, + 0x74 /* 't' */, 0x1C, 0x03 /* (to 0x03D1 state 553) */, 0x08, /* fail */ /* pos 00b9: 49 */ 0x63 /* 'c' */, 0x0A, 0x00 /* (to 0x00C3 state 50) */, - 0x72 /* 'r' */, 0xFF, 0x02 /* (to 0x03BB state 539) */, - 0x74 /* 't' */, 0x02, 0x03 /* (to 0x03C1 state 544) */, + 0x72 /* 'r' */, 0x05, 0x03 /* (to 0x03C1 state 539) */, + 0x74 /* 't' */, 0x08, 0x03 /* (to 0x03C7 state 544) */, 0x08, /* fail */ /* pos 00c3: 50 */ 0xAD /* '-' -> */, /* pos 00c4: 51 */ 0xF7 /* 'w' -> */, @@ -173,7 +173,7 @@ /* pos 0131: 113 */ 0xB1 /* '1' -> */, /* pos 0132: 114 */ 0xAE /* '.' -> */, /* pos 0133: 115 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x013A state 116) */, - 0x30 /* '0' */, 0x1E, 0x03 /* (to 0x0454 state 660) */, + 0x30 /* '0' */, 0x24, 0x03 /* (to 0x045A state 660) */, 0x08, /* fail */ /* pos 013a: 116 */ 0xA0 /* ' ' -> */, /* pos 013b: 117 */ 0x00, 0x0F /* - terminal marker 15 - */, @@ -190,8 +190,8 @@ /* pos 0147: 128 */ 0x00, 0x10 /* - terminal marker 16 - */, /* pos 0149: 129 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x0156 state 130) */, 0x75 /* 'u' */, 0xAC, 0x00 /* (to 0x01F8 state 230) */, - 0x67 /* 'g' */, 0x80, 0x01 /* (to 0x02CF state 358) */, - 0x6C /* 'l' */, 0x81, 0x01 /* (to 0x02D3 state 361) */, + 0x67 /* 'g' */, 0x86, 0x01 /* (to 0x02D5 state 358) */, + 0x6C /* 'l' */, 0x87, 0x01 /* (to 0x02D9 state 361) */, 0x08, /* fail */ /* pos 0156: 130 */ 0xE3 /* 'c' -> */, /* pos 0157: 131 */ 0xE5 /* 'e' -> */, @@ -214,7 +214,7 @@ /* pos 0171: 144 */ 0xEC /* 'l' -> */, /* pos 0172: 145 */ 0xAD /* '-' -> */, /* pos 0173: 146 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x017A state 147) */, - 0x61 /* 'a' */, 0x4B, 0x01 /* (to 0x02C1 state 345) */, + 0x61 /* 'a' */, 0x51, 0x01 /* (to 0x02C7 state 345) */, 0x08, /* fail */ /* pos 017a: 147 */ 0xE5 /* 'e' -> */, /* pos 017b: 148 */ 0xF1 /* 'q' -> */, @@ -236,11 +236,11 @@ /* pos 018c: 164 */ 0xAD /* '-' -> */, /* pos 018d: 165 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x019A state 166) */, 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x01B0 state 181) */, - 0x72 /* 'r' */, 0xA1, 0x01 /* (to 0x0334 state 435) */, - 0x75 /* 'u' */, 0xA5, 0x01 /* (to 0x033B state 441) */, + 0x72 /* 'r' */, 0xA7, 0x01 /* (to 0x033A state 435) */, + 0x75 /* 'u' */, 0xAB, 0x01 /* (to 0x0341 state 441) */, 0x08, /* fail */ /* pos 019a: 166 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x01A1 state 167) */, - 0x61 /* 'a' */, 0x91, 0x01 /* (to 0x032E state 430) */, + 0x61 /* 'a' */, 0x97, 0x01 /* (to 0x0334 state 430) */, 0x08, /* fail */ /* pos 01a1: 167 */ 0xE4 /* 'd' -> */, /* pos 01a2: 168 */ 0xE9 /* 'i' -> */, @@ -269,8 +269,8 @@ /* pos 01ba: 191 */ 0x00, 0x14 /* - terminal marker 20 - */, /* pos 01bc: 192 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x01C9 state 193) */, 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x01D3 state 202) */, - 0x63 /* 'c' */, 0xEE, 0x00 /* (to 0x02B0 state 330) */, - 0x72 /* 'r' */, 0xF4, 0x00 /* (to 0x02B9 state 338) */, + 0x63 /* 'c' */, 0xF4, 0x00 /* (to 0x02B6 state 330) */, + 0x72 /* 'r' */, 0xFA, 0x00 /* (to 0x02BF state 338) */, 0x08, /* fail */ /* pos 01c9: 193 */ 0xEE /* 'n' -> */, /* pos 01ca: 194 */ 0xE3 /* 'c' -> */, @@ -291,7 +291,7 @@ /* pos 01da: 209 */ 0xBA /* ':' -> */, /* pos 01db: 210 */ 0x00, 0x16 /* - terminal marker 22 - */, /* pos 01dd: 211 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01E4 state 212) */, - 0x6F /* 'o' */, 0xA1, 0x01 /* (to 0x0381 state 497) */, + 0x6F /* 'o' */, 0xA7, 0x01 /* (to 0x0387 state 497) */, 0x08, /* fail */ /* pos 01e4: 212 */ 0xE7 /* 'g' -> */, /* pos 01e5: 213 */ 0xED /* 'm' -> */, @@ -335,13 +335,13 @@ /* pos 020f: 251 */ 0xAD /* '-' -> */, /* pos 0210: 252 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0220 state 253) */, 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0231 state 260) */, - 0x64 /* 'd' */, 0xC3, 0x00 /* (to 0x02D9 state 366) */, - 0x65 /* 'e' */, 0xCD, 0x00 /* (to 0x02E6 state 378) */, - 0x72 /* 'r' */, 0xE6, 0x00 /* (to 0x0302 state 403) */, + 0x64 /* 'd' */, 0xC9, 0x00 /* (to 0x02DF state 366) */, + 0x65 /* 'e' */, 0xD3, 0x00 /* (to 0x02EC state 378) */, + 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x0308 state 403) */, 0x08, /* fail */ /* pos 0220: 253 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x022A state 254) */, - 0x61 /* 'a' */, 0xCD, 0x00 /* (to 0x02F0 state 387) */, - 0x6F /* 'o' */, 0xD3, 0x00 /* (to 0x02F9 state 395) */, + 0x61 /* 'a' */, 0xD3, 0x00 /* (to 0x02F6 state 387) */, + 0x6F /* 'o' */, 0xD9, 0x00 /* (to 0x02FF state 395) */, 0x08, /* fail */ /* pos 022a: 254 */ 0xEE /* 'n' -> */, /* pos 022b: 255 */ 0xE7 /* 'g' -> */, @@ -355,7 +355,7 @@ /* pos 0234: 263 */ 0xBA /* ':' -> */, /* pos 0235: 264 */ 0x00, 0x1C /* - terminal marker 28 - */, /* pos 0237: 265 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x023E state 266) */, - 0x65 /* 'e' */, 0xF9, 0x01 /* (to 0x0433 state 637) */, + 0x65 /* 'e' */, 0xFF, 0x01 /* (to 0x0439 state 637) */, 0x08, /* fail */ /* pos 023e: 266 */ 0xF4 /* 't' -> */, /* pos 023f: 267 */ 0xE5 /* 'e' -> */, @@ -370,11 +370,11 @@ /* pos 024d: 274 */ 0xBA /* ':' -> */, /* pos 024e: 275 */ 0x00, 0x1E /* - terminal marker 30 - */, /* pos 0250: 276 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x025A state 277) */, - 0x74 /* 't' */, 0x5D, 0x01 /* (to 0x03B0 state 529) */, - 0x70 /* 'p' */, 0x19, 0x02 /* (to 0x046F state 682) */, + 0x74 /* 't' */, 0x63, 0x01 /* (to 0x03B6 state 529) */, + 0x70 /* 'p' */, 0x1F, 0x02 /* (to 0x0475 state 682) */, 0x08, /* fail */ /* pos 025a: 277 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0261 state 278) */, - 0x72 /* 'r' */, 0x4D, 0x01 /* (to 0x03AA state 524) */, + 0x72 /* 'r' */, 0x53, 0x01 /* (to 0x03B0 state 524) */, 0x08, /* fail */ /* pos 0261: 278 */ 0xF2 /* 'r' -> */, /* pos 0262: 279 */ 0xE5 /* 'e' -> */, @@ -400,7 +400,7 @@ /* pos 027a: 299 */ 0x61 /* 'a' */, 0x0D, 0x00 /* (to 0x0287 state 300) */, 0x6D /* 'm' */, 0x14, 0x00 /* (to 0x0291 state 309) */, 0x70 /* 'p' */, 0x18, 0x00 /* (to 0x0298 state 315) */, - 0x73 /* 's' */, 0x1A, 0x00 /* (to 0x029D state 319) */, + 0x73 /* 's' */, 0x20, 0x00 /* (to 0x02A3 state 319) */, 0x08, /* fail */ /* pos 0287: 300 */ 0xF5 /* 'u' -> */, /* pos 0288: 301 */ 0xF4 /* 't' -> */, @@ -417,401 +417,410 @@ /* pos 0294: 312 */ 0xEF /* 'o' -> */, /* pos 0295: 313 */ 0xE4 /* 'd' -> */, /* pos 0296: 314 */ 0x00, 0x24 /* - terminal marker 36 - */, -/* pos 0298: 315 */ 0xE1 /* 'a' -> */, -/* pos 0299: 316 */ 0xF4 /* 't' -> */, -/* pos 029a: 317 */ 0xE8 /* 'h' -> */, -/* pos 029b: 318 */ 0x00, 0x25 /* - terminal marker 37 - */, -/* pos 029d: 319 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x02A4 state 320) */, - 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x02AA state 325) */, +/* pos 0298: 315 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x029F state 316) */, + 0x72 /* 'r' */, 0xE6, 0x01 /* (to 0x0481 state 693) */, 0x08, /* fail */ -/* pos 02a4: 320 */ 0xE8 /* 'h' -> */, -/* pos 02a5: 321 */ 0xE5 /* 'e' -> */, -/* pos 02a6: 322 */ 0xED /* 'm' -> */, -/* pos 02a7: 323 */ 0xE5 /* 'e' -> */, -/* pos 02a8: 324 */ 0x00, 0x26 /* - terminal marker 38 - */, -/* pos 02aa: 325 */ 0xE1 /* 'a' -> */, -/* pos 02ab: 326 */ 0xF4 /* 't' -> */, -/* pos 02ac: 327 */ 0xF5 /* 'u' -> */, -/* pos 02ad: 328 */ 0xF3 /* 's' -> */, -/* pos 02ae: 329 */ 0x00, 0x27 /* - terminal marker 39 - */, -/* pos 02b0: 330 */ 0xE8 /* 'h' -> */, -/* pos 02b1: 331 */ 0xE1 /* 'a' -> */, -/* pos 02b2: 332 */ 0xF2 /* 'r' -> */, -/* pos 02b3: 333 */ 0xF3 /* 's' -> */, -/* pos 02b4: 334 */ 0xE5 /* 'e' -> */, -/* pos 02b5: 335 */ 0xF4 /* 't' -> */, -/* pos 02b6: 336 */ 0xBA /* ':' -> */, -/* pos 02b7: 337 */ 0x00, 0x28 /* - terminal marker 40 - */, -/* pos 02b9: 338 */ 0xE1 /* 'a' -> */, -/* pos 02ba: 339 */ 0xEE /* 'n' -> */, -/* pos 02bb: 340 */ 0xE7 /* 'g' -> */, -/* pos 02bc: 341 */ 0xE5 /* 'e' -> */, -/* pos 02bd: 342 */ 0xF3 /* 's' -> */, -/* pos 02be: 343 */ 0xBA /* ':' -> */, -/* pos 02bf: 344 */ 0x00, 0x29 /* - terminal marker 41 - */, -/* pos 02c1: 345 */ 0xEC /* 'l' -> */, -/* pos 02c2: 346 */ 0xEC /* 'l' -> */, -/* pos 02c3: 347 */ 0xEF /* 'o' -> */, -/* pos 02c4: 348 */ 0xF7 /* 'w' -> */, -/* pos 02c5: 349 */ 0xAD /* '-' -> */, -/* pos 02c6: 350 */ 0xEF /* 'o' -> */, -/* pos 02c7: 351 */ 0xF2 /* 'r' -> */, -/* pos 02c8: 352 */ 0xE9 /* 'i' -> */, -/* pos 02c9: 353 */ 0xE7 /* 'g' -> */, -/* pos 02ca: 354 */ 0xE9 /* 'i' -> */, -/* pos 02cb: 355 */ 0xEE /* 'n' -> */, -/* pos 02cc: 356 */ 0xBA /* ':' -> */, -/* pos 02cd: 357 */ 0x00, 0x2A /* - terminal marker 42 - */, -/* pos 02cf: 358 */ 0xE5 /* 'e' -> */, -/* pos 02d0: 359 */ 0xBA /* ':' -> */, -/* pos 02d1: 360 */ 0x00, 0x2B /* - terminal marker 43 - */, -/* pos 02d3: 361 */ 0xEC /* 'l' -> */, -/* pos 02d4: 362 */ 0xEF /* 'o' -> */, -/* pos 02d5: 363 */ 0xF7 /* 'w' -> */, -/* pos 02d6: 364 */ 0xBA /* ':' -> */, -/* pos 02d7: 365 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 02d9: 366 */ 0xE9 /* 'i' -> */, -/* pos 02da: 367 */ 0xF3 /* 's' -> */, -/* pos 02db: 368 */ 0xF0 /* 'p' -> */, -/* pos 02dc: 369 */ 0xEF /* 'o' -> */, -/* pos 02dd: 370 */ 0xF3 /* 's' -> */, -/* pos 02de: 371 */ 0xE9 /* 'i' -> */, -/* pos 02df: 372 */ 0xF4 /* 't' -> */, -/* pos 02e0: 373 */ 0xE9 /* 'i' -> */, -/* pos 02e1: 374 */ 0xEF /* 'o' -> */, -/* pos 02e2: 375 */ 0xEE /* 'n' -> */, -/* pos 02e3: 376 */ 0xBA /* ':' -> */, -/* pos 02e4: 377 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 02e6: 378 */ 0xEE /* 'n' -> */, -/* pos 02e7: 379 */ 0xE3 /* 'c' -> */, -/* pos 02e8: 380 */ 0xEF /* 'o' -> */, -/* pos 02e9: 381 */ 0xE4 /* 'd' -> */, -/* pos 02ea: 382 */ 0xE9 /* 'i' -> */, -/* pos 02eb: 383 */ 0xEE /* 'n' -> */, -/* pos 02ec: 384 */ 0xE7 /* 'g' -> */, -/* pos 02ed: 385 */ 0xBA /* ':' -> */, -/* pos 02ee: 386 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 02f0: 387 */ 0xEE /* 'n' -> */, -/* pos 02f1: 388 */ 0xE7 /* 'g' -> */, -/* pos 02f2: 389 */ 0xF5 /* 'u' -> */, -/* pos 02f3: 390 */ 0xE1 /* 'a' -> */, -/* pos 02f4: 391 */ 0xE7 /* 'g' -> */, -/* pos 02f5: 392 */ 0xE5 /* 'e' -> */, -/* pos 02f6: 393 */ 0xBA /* ':' -> */, -/* pos 02f7: 394 */ 0x00, 0x2F /* - terminal marker 47 - */, -/* pos 02f9: 395 */ 0xE3 /* 'c' -> */, -/* pos 02fa: 396 */ 0xE1 /* 'a' -> */, -/* pos 02fb: 397 */ 0xF4 /* 't' -> */, -/* pos 02fc: 398 */ 0xE9 /* 'i' -> */, -/* pos 02fd: 399 */ 0xEF /* 'o' -> */, -/* pos 02fe: 400 */ 0xEE /* 'n' -> */, -/* pos 02ff: 401 */ 0xBA /* ':' -> */, -/* pos 0300: 402 */ 0x00, 0x30 /* - terminal marker 48 - */, -/* pos 0302: 403 */ 0xE1 /* 'a' -> */, -/* pos 0303: 404 */ 0xEE /* 'n' -> */, -/* pos 0304: 405 */ 0xE7 /* 'g' -> */, -/* pos 0305: 406 */ 0xE5 /* 'e' -> */, -/* pos 0306: 407 */ 0xBA /* ':' -> */, -/* pos 0307: 408 */ 0x00, 0x31 /* - terminal marker 49 - */, -/* pos 0309: 409 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x0310 state 410) */, - 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x0315 state 414) */, +/* pos 029f: 316 */ 0xF4 /* 't' -> */, +/* pos 02a0: 317 */ 0xE8 /* 'h' -> */, +/* pos 02a1: 318 */ 0x00, 0x25 /* - terminal marker 37 - */, +/* pos 02a3: 319 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x02AA state 320) */, + 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x02B0 state 325) */, 0x08, /* fail */ -/* pos 0310: 410 */ 0xE1 /* 'a' -> */, -/* pos 0311: 411 */ 0xE7 /* 'g' -> */, -/* pos 0312: 412 */ 0xBA /* ':' -> */, -/* pos 0313: 413 */ 0x00, 0x32 /* - terminal marker 50 - */, -/* pos 0315: 414 */ 0xF0 /* 'p' -> */, -/* pos 0316: 415 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x031D state 416) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0322 state 420) */, +/* pos 02aa: 320 */ 0xE8 /* 'h' -> */, +/* pos 02ab: 321 */ 0xE5 /* 'e' -> */, +/* pos 02ac: 322 */ 0xED /* 'm' -> */, +/* pos 02ad: 323 */ 0xE5 /* 'e' -> */, +/* pos 02ae: 324 */ 0x00, 0x26 /* - terminal marker 38 - */, +/* pos 02b0: 325 */ 0xE1 /* 'a' -> */, +/* pos 02b1: 326 */ 0xF4 /* 't' -> */, +/* pos 02b2: 327 */ 0xF5 /* 'u' -> */, +/* pos 02b3: 328 */ 0xF3 /* 's' -> */, +/* pos 02b4: 329 */ 0x00, 0x27 /* - terminal marker 39 - */, +/* pos 02b6: 330 */ 0xE8 /* 'h' -> */, +/* pos 02b7: 331 */ 0xE1 /* 'a' -> */, +/* pos 02b8: 332 */ 0xF2 /* 'r' -> */, +/* pos 02b9: 333 */ 0xF3 /* 's' -> */, +/* pos 02ba: 334 */ 0xE5 /* 'e' -> */, +/* pos 02bb: 335 */ 0xF4 /* 't' -> */, +/* pos 02bc: 336 */ 0xBA /* ':' -> */, +/* pos 02bd: 337 */ 0x00, 0x28 /* - terminal marker 40 - */, +/* pos 02bf: 338 */ 0xE1 /* 'a' -> */, +/* pos 02c0: 339 */ 0xEE /* 'n' -> */, +/* pos 02c1: 340 */ 0xE7 /* 'g' -> */, +/* pos 02c2: 341 */ 0xE5 /* 'e' -> */, +/* pos 02c3: 342 */ 0xF3 /* 's' -> */, +/* pos 02c4: 343 */ 0xBA /* ':' -> */, +/* pos 02c5: 344 */ 0x00, 0x29 /* - terminal marker 41 - */, +/* pos 02c7: 345 */ 0xEC /* 'l' -> */, +/* pos 02c8: 346 */ 0xEC /* 'l' -> */, +/* pos 02c9: 347 */ 0xEF /* 'o' -> */, +/* pos 02ca: 348 */ 0xF7 /* 'w' -> */, +/* pos 02cb: 349 */ 0xAD /* '-' -> */, +/* pos 02cc: 350 */ 0xEF /* 'o' -> */, +/* pos 02cd: 351 */ 0xF2 /* 'r' -> */, +/* pos 02ce: 352 */ 0xE9 /* 'i' -> */, +/* pos 02cf: 353 */ 0xE7 /* 'g' -> */, +/* pos 02d0: 354 */ 0xE9 /* 'i' -> */, +/* pos 02d1: 355 */ 0xEE /* 'n' -> */, +/* pos 02d2: 356 */ 0xBA /* ':' -> */, +/* pos 02d3: 357 */ 0x00, 0x2A /* - terminal marker 42 - */, +/* pos 02d5: 358 */ 0xE5 /* 'e' -> */, +/* pos 02d6: 359 */ 0xBA /* ':' -> */, +/* pos 02d7: 360 */ 0x00, 0x2B /* - terminal marker 43 - */, +/* pos 02d9: 361 */ 0xEC /* 'l' -> */, +/* pos 02da: 362 */ 0xEF /* 'o' -> */, +/* pos 02db: 363 */ 0xF7 /* 'w' -> */, +/* pos 02dc: 364 */ 0xBA /* ':' -> */, +/* pos 02dd: 365 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 02df: 366 */ 0xE9 /* 'i' -> */, +/* pos 02e0: 367 */ 0xF3 /* 's' -> */, +/* pos 02e1: 368 */ 0xF0 /* 'p' -> */, +/* pos 02e2: 369 */ 0xEF /* 'o' -> */, +/* pos 02e3: 370 */ 0xF3 /* 's' -> */, +/* pos 02e4: 371 */ 0xE9 /* 'i' -> */, +/* pos 02e5: 372 */ 0xF4 /* 't' -> */, +/* pos 02e6: 373 */ 0xE9 /* 'i' -> */, +/* pos 02e7: 374 */ 0xEF /* 'o' -> */, +/* pos 02e8: 375 */ 0xEE /* 'n' -> */, +/* pos 02e9: 376 */ 0xBA /* ':' -> */, +/* pos 02ea: 377 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 02ec: 378 */ 0xEE /* 'n' -> */, +/* pos 02ed: 379 */ 0xE3 /* 'c' -> */, +/* pos 02ee: 380 */ 0xEF /* 'o' -> */, +/* pos 02ef: 381 */ 0xE4 /* 'd' -> */, +/* pos 02f0: 382 */ 0xE9 /* 'i' -> */, +/* pos 02f1: 383 */ 0xEE /* 'n' -> */, +/* pos 02f2: 384 */ 0xE7 /* 'g' -> */, +/* pos 02f3: 385 */ 0xBA /* ':' -> */, +/* pos 02f4: 386 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 02f6: 387 */ 0xEE /* 'n' -> */, +/* pos 02f7: 388 */ 0xE7 /* 'g' -> */, +/* pos 02f8: 389 */ 0xF5 /* 'u' -> */, +/* pos 02f9: 390 */ 0xE1 /* 'a' -> */, +/* pos 02fa: 391 */ 0xE7 /* 'g' -> */, +/* pos 02fb: 392 */ 0xE5 /* 'e' -> */, +/* pos 02fc: 393 */ 0xBA /* ':' -> */, +/* pos 02fd: 394 */ 0x00, 0x2F /* - terminal marker 47 - */, +/* pos 02ff: 395 */ 0xE3 /* 'c' -> */, +/* pos 0300: 396 */ 0xE1 /* 'a' -> */, +/* pos 0301: 397 */ 0xF4 /* 't' -> */, +/* pos 0302: 398 */ 0xE9 /* 'i' -> */, +/* pos 0303: 399 */ 0xEF /* 'o' -> */, +/* pos 0304: 400 */ 0xEE /* 'n' -> */, +/* pos 0305: 401 */ 0xBA /* ':' -> */, +/* pos 0306: 402 */ 0x00, 0x30 /* - terminal marker 48 - */, +/* pos 0308: 403 */ 0xE1 /* 'a' -> */, +/* pos 0309: 404 */ 0xEE /* 'n' -> */, +/* pos 030a: 405 */ 0xE7 /* 'g' -> */, +/* pos 030b: 406 */ 0xE5 /* 'e' -> */, +/* pos 030c: 407 */ 0xBA /* ':' -> */, +/* pos 030d: 408 */ 0x00, 0x31 /* - terminal marker 49 - */, +/* pos 030f: 409 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x0316 state 410) */, + 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x031B state 414) */, 0x08, /* fail */ -/* pos 031d: 416 */ 0xE3 /* 'c' -> */, -/* pos 031e: 417 */ 0xF4 /* 't' -> */, -/* pos 031f: 418 */ 0xBA /* ':' -> */, -/* pos 0320: 419 */ 0x00, 0x33 /* - terminal marker 51 - */, -/* pos 0322: 420 */ 0xF2 /* 'r' -> */, -/* pos 0323: 421 */ 0xE5 /* 'e' -> */, -/* pos 0324: 422 */ 0xF3 /* 's' -> */, -/* pos 0325: 423 */ 0xBA /* ':' -> */, -/* pos 0326: 424 */ 0x00, 0x34 /* - terminal marker 52 - */, -/* pos 0328: 425 */ 0xF2 /* 'r' -> */, -/* pos 0329: 426 */ 0xEF /* 'o' -> */, -/* pos 032a: 427 */ 0xED /* 'm' -> */, -/* pos 032b: 428 */ 0xBA /* ':' -> */, -/* pos 032c: 429 */ 0x00, 0x35 /* - terminal marker 53 - */, -/* pos 032e: 430 */ 0xF4 /* 't' -> */, -/* pos 032f: 431 */ 0xE3 /* 'c' -> */, -/* pos 0330: 432 */ 0xE8 /* 'h' -> */, -/* pos 0331: 433 */ 0xBA /* ':' -> */, -/* pos 0332: 434 */ 0x00, 0x36 /* - terminal marker 54 - */, -/* pos 0334: 435 */ 0xE1 /* 'a' -> */, -/* pos 0335: 436 */ 0xEE /* 'n' -> */, -/* pos 0336: 437 */ 0xE7 /* 'g' -> */, -/* pos 0337: 438 */ 0xE5 /* 'e' -> */, -/* pos 0338: 439 */ 0xBA /* ':' -> */, -/* pos 0339: 440 */ 0x00, 0x37 /* - terminal marker 55 - */, -/* pos 033b: 441 */ 0xEE /* 'n' -> */, -/* pos 033c: 442 */ 0xED /* 'm' -> */, -/* pos 033d: 443 */ 0xEF /* 'o' -> */, -/* pos 033e: 444 */ 0xE4 /* 'd' -> */, -/* pos 033f: 445 */ 0xE9 /* 'i' -> */, -/* pos 0340: 446 */ 0xE6 /* 'f' -> */, -/* pos 0341: 447 */ 0xE9 /* 'i' -> */, -/* pos 0342: 448 */ 0xE5 /* 'e' -> */, -/* pos 0343: 449 */ 0xE4 /* 'd' -> */, -/* pos 0344: 450 */ 0xAD /* '-' -> */, -/* pos 0345: 451 */ 0xF3 /* 's' -> */, -/* pos 0346: 452 */ 0xE9 /* 'i' -> */, -/* pos 0347: 453 */ 0xEE /* 'n' -> */, -/* pos 0348: 454 */ 0xE3 /* 'c' -> */, -/* pos 0349: 455 */ 0xE5 /* 'e' -> */, -/* pos 034a: 456 */ 0xBA /* ':' -> */, -/* pos 034b: 457 */ 0x00, 0x38 /* - terminal marker 56 - */, -/* pos 034d: 458 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0357 state 459) */, - 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x0365 state 472) */, - 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x036A state 476) */, +/* pos 0316: 410 */ 0xE1 /* 'a' -> */, +/* pos 0317: 411 */ 0xE7 /* 'g' -> */, +/* pos 0318: 412 */ 0xBA /* ':' -> */, +/* pos 0319: 413 */ 0x00, 0x32 /* - terminal marker 50 - */, +/* pos 031b: 414 */ 0xF0 /* 'p' -> */, +/* pos 031c: 415 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0323 state 416) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0328 state 420) */, 0x08, /* fail */ -/* pos 0357: 459 */ 0xF3 /* 's' -> */, -/* pos 0358: 460 */ 0xF4 /* 't' -> */, -/* pos 0359: 461 */ 0xAD /* '-' -> */, -/* pos 035a: 462 */ 0xED /* 'm' -> */, -/* pos 035b: 463 */ 0xEF /* 'o' -> */, -/* pos 035c: 464 */ 0xE4 /* 'd' -> */, -/* pos 035d: 465 */ 0xE9 /* 'i' -> */, -/* pos 035e: 466 */ 0xE6 /* 'f' -> */, -/* pos 035f: 467 */ 0xE9 /* 'i' -> */, -/* pos 0360: 468 */ 0xE5 /* 'e' -> */, -/* pos 0361: 469 */ 0xE4 /* 'd' -> */, -/* pos 0362: 470 */ 0xBA /* ':' -> */, -/* pos 0363: 471 */ 0x00, 0x39 /* - terminal marker 57 - */, -/* pos 0365: 472 */ 0xEE /* 'n' -> */, -/* pos 0366: 473 */ 0xEB /* 'k' -> */, -/* pos 0367: 474 */ 0xBA /* ':' -> */, -/* pos 0368: 475 */ 0x00, 0x3A /* - terminal marker 58 - */, -/* pos 036a: 476 */ 0xE3 /* 'c' -> */, -/* pos 036b: 477 */ 0xE1 /* 'a' -> */, -/* pos 036c: 478 */ 0xF4 /* 't' -> */, -/* pos 036d: 479 */ 0xE9 /* 'i' -> */, -/* pos 036e: 480 */ 0xEF /* 'o' -> */, -/* pos 036f: 481 */ 0xEE /* 'n' -> */, -/* pos 0370: 482 */ 0xBA /* ':' -> */, -/* pos 0371: 483 */ 0x00, 0x3B /* - terminal marker 59 - */, -/* pos 0373: 484 */ 0xE1 /* 'a' -> */, -/* pos 0374: 485 */ 0xF8 /* 'x' -> */, -/* pos 0375: 486 */ 0xAD /* '-' -> */, -/* pos 0376: 487 */ 0xE6 /* 'f' -> */, -/* pos 0377: 488 */ 0xEF /* 'o' -> */, -/* pos 0378: 489 */ 0xF2 /* 'r' -> */, -/* pos 0379: 490 */ 0xF7 /* 'w' -> */, -/* pos 037a: 491 */ 0xE1 /* 'a' -> */, -/* pos 037b: 492 */ 0xF2 /* 'r' -> */, -/* pos 037c: 493 */ 0xE4 /* 'd' -> */, -/* pos 037d: 494 */ 0xF3 /* 's' -> */, -/* pos 037e: 495 */ 0xBA /* ':' -> */, -/* pos 037f: 496 */ 0x00, 0x3C /* - terminal marker 60 - */, -/* pos 0381: 497 */ 0xF8 /* 'x' -> */, -/* pos 0382: 498 */ 0xF9 /* 'y' -> */, -/* pos 0383: 499 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x038A state 500) */, - 0x20 /* ' ' */, 0xBB, 0x00 /* (to 0x0441 state 649) */, +/* pos 0323: 416 */ 0xE3 /* 'c' -> */, +/* pos 0324: 417 */ 0xF4 /* 't' -> */, +/* pos 0325: 418 */ 0xBA /* ':' -> */, +/* pos 0326: 419 */ 0x00, 0x33 /* - terminal marker 51 - */, +/* pos 0328: 420 */ 0xF2 /* 'r' -> */, +/* pos 0329: 421 */ 0xE5 /* 'e' -> */, +/* pos 032a: 422 */ 0xF3 /* 's' -> */, +/* pos 032b: 423 */ 0xBA /* ':' -> */, +/* pos 032c: 424 */ 0x00, 0x34 /* - terminal marker 52 - */, +/* pos 032e: 425 */ 0xF2 /* 'r' -> */, +/* pos 032f: 426 */ 0xEF /* 'o' -> */, +/* pos 0330: 427 */ 0xED /* 'm' -> */, +/* pos 0331: 428 */ 0xBA /* ':' -> */, +/* pos 0332: 429 */ 0x00, 0x35 /* - terminal marker 53 - */, +/* pos 0334: 430 */ 0xF4 /* 't' -> */, +/* pos 0335: 431 */ 0xE3 /* 'c' -> */, +/* pos 0336: 432 */ 0xE8 /* 'h' -> */, +/* pos 0337: 433 */ 0xBA /* ':' -> */, +/* pos 0338: 434 */ 0x00, 0x36 /* - terminal marker 54 - */, +/* pos 033a: 435 */ 0xE1 /* 'a' -> */, +/* pos 033b: 436 */ 0xEE /* 'n' -> */, +/* pos 033c: 437 */ 0xE7 /* 'g' -> */, +/* pos 033d: 438 */ 0xE5 /* 'e' -> */, +/* pos 033e: 439 */ 0xBA /* ':' -> */, +/* pos 033f: 440 */ 0x00, 0x37 /* - terminal marker 55 - */, +/* pos 0341: 441 */ 0xEE /* 'n' -> */, +/* pos 0342: 442 */ 0xED /* 'm' -> */, +/* pos 0343: 443 */ 0xEF /* 'o' -> */, +/* pos 0344: 444 */ 0xE4 /* 'd' -> */, +/* pos 0345: 445 */ 0xE9 /* 'i' -> */, +/* pos 0346: 446 */ 0xE6 /* 'f' -> */, +/* pos 0347: 447 */ 0xE9 /* 'i' -> */, +/* pos 0348: 448 */ 0xE5 /* 'e' -> */, +/* pos 0349: 449 */ 0xE4 /* 'd' -> */, +/* pos 034a: 450 */ 0xAD /* '-' -> */, +/* pos 034b: 451 */ 0xF3 /* 's' -> */, +/* pos 034c: 452 */ 0xE9 /* 'i' -> */, +/* pos 034d: 453 */ 0xEE /* 'n' -> */, +/* pos 034e: 454 */ 0xE3 /* 'c' -> */, +/* pos 034f: 455 */ 0xE5 /* 'e' -> */, +/* pos 0350: 456 */ 0xBA /* ':' -> */, +/* pos 0351: 457 */ 0x00, 0x38 /* - terminal marker 56 - */, +/* pos 0353: 458 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x035D state 459) */, + 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x036B state 472) */, + 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0370 state 476) */, 0x08, /* fail */ -/* pos 038a: 500 */ 0xE1 /* 'a' -> */, -/* pos 038b: 501 */ 0xF5 /* 'u' -> */, -/* pos 038c: 502 */ 0xF4 /* 't' -> */, -/* pos 038d: 503 */ 0xE8 /* 'h' -> */, -/* pos 038e: 504 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0395 state 505) */, - 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x039F state 514) */, +/* pos 035d: 459 */ 0xF3 /* 's' -> */, +/* pos 035e: 460 */ 0xF4 /* 't' -> */, +/* pos 035f: 461 */ 0xAD /* '-' -> */, +/* pos 0360: 462 */ 0xED /* 'm' -> */, +/* pos 0361: 463 */ 0xEF /* 'o' -> */, +/* pos 0362: 464 */ 0xE4 /* 'd' -> */, +/* pos 0363: 465 */ 0xE9 /* 'i' -> */, +/* pos 0364: 466 */ 0xE6 /* 'f' -> */, +/* pos 0365: 467 */ 0xE9 /* 'i' -> */, +/* pos 0366: 468 */ 0xE5 /* 'e' -> */, +/* pos 0367: 469 */ 0xE4 /* 'd' -> */, +/* pos 0368: 470 */ 0xBA /* ':' -> */, +/* pos 0369: 471 */ 0x00, 0x39 /* - terminal marker 57 - */, +/* pos 036b: 472 */ 0xEE /* 'n' -> */, +/* pos 036c: 473 */ 0xEB /* 'k' -> */, +/* pos 036d: 474 */ 0xBA /* ':' -> */, +/* pos 036e: 475 */ 0x00, 0x3A /* - terminal marker 58 - */, +/* pos 0370: 476 */ 0xE3 /* 'c' -> */, +/* pos 0371: 477 */ 0xE1 /* 'a' -> */, +/* pos 0372: 478 */ 0xF4 /* 't' -> */, +/* pos 0373: 479 */ 0xE9 /* 'i' -> */, +/* pos 0374: 480 */ 0xEF /* 'o' -> */, +/* pos 0375: 481 */ 0xEE /* 'n' -> */, +/* pos 0376: 482 */ 0xBA /* ':' -> */, +/* pos 0377: 483 */ 0x00, 0x3B /* - terminal marker 59 - */, +/* pos 0379: 484 */ 0xE1 /* 'a' -> */, +/* pos 037a: 485 */ 0xF8 /* 'x' -> */, +/* pos 037b: 486 */ 0xAD /* '-' -> */, +/* pos 037c: 487 */ 0xE6 /* 'f' -> */, +/* pos 037d: 488 */ 0xEF /* 'o' -> */, +/* pos 037e: 489 */ 0xF2 /* 'r' -> */, +/* pos 037f: 490 */ 0xF7 /* 'w' -> */, +/* pos 0380: 491 */ 0xE1 /* 'a' -> */, +/* pos 0381: 492 */ 0xF2 /* 'r' -> */, +/* pos 0382: 493 */ 0xE4 /* 'd' -> */, +/* pos 0383: 494 */ 0xF3 /* 's' -> */, +/* pos 0384: 495 */ 0xBA /* ':' -> */, +/* pos 0385: 496 */ 0x00, 0x3C /* - terminal marker 60 - */, +/* pos 0387: 497 */ 0xF8 /* 'x' -> */, +/* pos 0388: 498 */ 0xF9 /* 'y' -> */, +/* pos 0389: 499 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x0390 state 500) */, + 0x20 /* ' ' */, 0xBB, 0x00 /* (to 0x0447 state 649) */, 0x08, /* fail */ -/* pos 0395: 505 */ 0xEE /* 'n' -> */, -/* pos 0396: 506 */ 0xF4 /* 't' -> */, -/* pos 0397: 507 */ 0xE9 /* 'i' -> */, -/* pos 0398: 508 */ 0xE3 /* 'c' -> */, -/* pos 0399: 509 */ 0xE1 /* 'a' -> */, -/* pos 039a: 510 */ 0xF4 /* 't' -> */, -/* pos 039b: 511 */ 0xE5 /* 'e' -> */, -/* pos 039c: 512 */ 0xBA /* ':' -> */, -/* pos 039d: 513 */ 0x00, 0x3D /* - terminal marker 61 - */, -/* pos 039f: 514 */ 0xF2 /* 'r' -> */, -/* pos 03a0: 515 */ 0xE9 /* 'i' -> */, -/* pos 03a1: 516 */ 0xFA /* 'z' -> */, -/* pos 03a2: 517 */ 0xE1 /* 'a' -> */, -/* pos 03a3: 518 */ 0xF4 /* 't' -> */, -/* pos 03a4: 519 */ 0xE9 /* 'i' -> */, -/* pos 03a5: 520 */ 0xEF /* 'o' -> */, -/* pos 03a6: 521 */ 0xEE /* 'n' -> */, -/* pos 03a7: 522 */ 0xBA /* ':' -> */, -/* pos 03a8: 523 */ 0x00, 0x3E /* - terminal marker 62 - */, -/* pos 03aa: 524 */ 0xE5 /* 'e' -> */, -/* pos 03ab: 525 */ 0xF3 /* 's' -> */, -/* pos 03ac: 526 */ 0xE8 /* 'h' -> */, -/* pos 03ad: 527 */ 0xBA /* ':' -> */, -/* pos 03ae: 528 */ 0x00, 0x3F /* - terminal marker 63 - */, -/* pos 03b0: 529 */ 0xF2 /* 'r' -> */, -/* pos 03b1: 530 */ 0xF9 /* 'y' -> */, -/* pos 03b2: 531 */ 0xAD /* '-' -> */, -/* pos 03b3: 532 */ 0xE1 /* 'a' -> */, -/* pos 03b4: 533 */ 0xE6 /* 'f' -> */, -/* pos 03b5: 534 */ 0xF4 /* 't' -> */, -/* pos 03b6: 535 */ 0xE5 /* 'e' -> */, -/* pos 03b7: 536 */ 0xF2 /* 'r' -> */, -/* pos 03b8: 537 */ 0xBA /* ':' -> */, -/* pos 03b9: 538 */ 0x00, 0x40 /* - terminal marker 64 - */, -/* pos 03bb: 539 */ 0xF6 /* 'v' -> */, -/* pos 03bc: 540 */ 0xE5 /* 'e' -> */, -/* pos 03bd: 541 */ 0xF2 /* 'r' -> */, -/* pos 03be: 542 */ 0xBA /* ':' -> */, -/* pos 03bf: 543 */ 0x00, 0x41 /* - terminal marker 65 - */, -/* pos 03c1: 544 */ 0xAD /* '-' -> */, -/* pos 03c2: 545 */ 0xE3 /* 'c' -> */, -/* pos 03c3: 546 */ 0xEF /* 'o' -> */, -/* pos 03c4: 547 */ 0xEF /* 'o' -> */, -/* pos 03c5: 548 */ 0xEB /* 'k' -> */, -/* pos 03c6: 549 */ 0xE9 /* 'i' -> */, -/* pos 03c7: 550 */ 0xE5 /* 'e' -> */, -/* pos 03c8: 551 */ 0xBA /* ':' -> */, -/* pos 03c9: 552 */ 0x00, 0x42 /* - terminal marker 66 - */, -/* pos 03cb: 553 */ 0xF2 /* 'r' -> */, -/* pos 03cc: 554 */ 0xE9 /* 'i' -> */, -/* pos 03cd: 555 */ 0xE3 /* 'c' -> */, -/* pos 03ce: 556 */ 0xF4 /* 't' -> */, -/* pos 03cf: 557 */ 0xAD /* '-' -> */, -/* pos 03d0: 558 */ 0xF4 /* 't' -> */, -/* pos 03d1: 559 */ 0xF2 /* 'r' -> */, -/* pos 03d2: 560 */ 0xE1 /* 'a' -> */, -/* pos 03d3: 561 */ 0xEE /* 'n' -> */, -/* pos 03d4: 562 */ 0xF3 /* 's' -> */, -/* pos 03d5: 563 */ 0xF0 /* 'p' -> */, -/* pos 03d6: 564 */ 0xEF /* 'o' -> */, -/* pos 03d7: 565 */ 0xF2 /* 'r' -> */, -/* pos 03d8: 566 */ 0xF4 /* 't' -> */, -/* pos 03d9: 567 */ 0xAD /* '-' -> */, -/* pos 03da: 568 */ 0xF3 /* 's' -> */, -/* pos 03db: 569 */ 0xE5 /* 'e' -> */, -/* pos 03dc: 570 */ 0xE3 /* 'c' -> */, -/* pos 03dd: 571 */ 0xF5 /* 'u' -> */, -/* pos 03de: 572 */ 0xF2 /* 'r' -> */, -/* pos 03df: 573 */ 0xE9 /* 'i' -> */, -/* pos 03e0: 574 */ 0xF4 /* 't' -> */, -/* pos 03e1: 575 */ 0xF9 /* 'y' -> */, -/* pos 03e2: 576 */ 0xBA /* ':' -> */, -/* pos 03e3: 577 */ 0x00, 0x43 /* - terminal marker 67 - */, -/* pos 03e5: 578 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x03EC state 579) */, - 0x65 /* 'e' */, 0x84, 0x00 /* (to 0x046C state 680) */, +/* pos 0390: 500 */ 0xE1 /* 'a' -> */, +/* pos 0391: 501 */ 0xF5 /* 'u' -> */, +/* pos 0392: 502 */ 0xF4 /* 't' -> */, +/* pos 0393: 503 */ 0xE8 /* 'h' -> */, +/* pos 0394: 504 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x039B state 505) */, + 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x03A5 state 514) */, 0x08, /* fail */ -/* pos 03ec: 579 */ 0xE1 /* 'a' -> */, -/* pos 03ed: 580 */ 0xEE /* 'n' -> */, -/* pos 03ee: 581 */ 0xF3 /* 's' -> */, -/* pos 03ef: 582 */ 0xE6 /* 'f' -> */, -/* pos 03f0: 583 */ 0xE5 /* 'e' -> */, -/* pos 03f1: 584 */ 0xF2 /* 'r' -> */, -/* pos 03f2: 585 */ 0xAD /* '-' -> */, -/* pos 03f3: 586 */ 0xE5 /* 'e' -> */, -/* pos 03f4: 587 */ 0xEE /* 'n' -> */, -/* pos 03f5: 588 */ 0xE3 /* 'c' -> */, -/* pos 03f6: 589 */ 0xEF /* 'o' -> */, -/* pos 03f7: 590 */ 0xE4 /* 'd' -> */, -/* pos 03f8: 591 */ 0xE9 /* 'i' -> */, -/* pos 03f9: 592 */ 0xEE /* 'n' -> */, -/* pos 03fa: 593 */ 0xE7 /* 'g' -> */, -/* pos 03fb: 594 */ 0xBA /* ':' -> */, -/* pos 03fc: 595 */ 0x00, 0x44 /* - terminal marker 68 - */, -/* pos 03fe: 596 */ 0xE5 /* 'e' -> */, -/* pos 03ff: 597 */ 0xF2 /* 'r' -> */, -/* pos 0400: 598 */ 0xAD /* '-' -> */, -/* pos 0401: 599 */ 0xE1 /* 'a' -> */, -/* pos 0402: 600 */ 0xE7 /* 'g' -> */, -/* pos 0403: 601 */ 0xE5 /* 'e' -> */, -/* pos 0404: 602 */ 0xEE /* 'n' -> */, -/* pos 0405: 603 */ 0xF4 /* 't' -> */, -/* pos 0406: 604 */ 0xBA /* ':' -> */, -/* pos 0407: 605 */ 0x00, 0x45 /* - terminal marker 69 - */, -/* pos 0409: 606 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0410 state 607) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0415 state 611) */, +/* pos 039b: 505 */ 0xEE /* 'n' -> */, +/* pos 039c: 506 */ 0xF4 /* 't' -> */, +/* pos 039d: 507 */ 0xE9 /* 'i' -> */, +/* pos 039e: 508 */ 0xE3 /* 'c' -> */, +/* pos 039f: 509 */ 0xE1 /* 'a' -> */, +/* pos 03a0: 510 */ 0xF4 /* 't' -> */, +/* pos 03a1: 511 */ 0xE5 /* 'e' -> */, +/* pos 03a2: 512 */ 0xBA /* ':' -> */, +/* pos 03a3: 513 */ 0x00, 0x3D /* - terminal marker 61 - */, +/* pos 03a5: 514 */ 0xF2 /* 'r' -> */, +/* pos 03a6: 515 */ 0xE9 /* 'i' -> */, +/* pos 03a7: 516 */ 0xFA /* 'z' -> */, +/* pos 03a8: 517 */ 0xE1 /* 'a' -> */, +/* pos 03a9: 518 */ 0xF4 /* 't' -> */, +/* pos 03aa: 519 */ 0xE9 /* 'i' -> */, +/* pos 03ab: 520 */ 0xEF /* 'o' -> */, +/* pos 03ac: 521 */ 0xEE /* 'n' -> */, +/* pos 03ad: 522 */ 0xBA /* ':' -> */, +/* pos 03ae: 523 */ 0x00, 0x3E /* - terminal marker 62 - */, +/* pos 03b0: 524 */ 0xE5 /* 'e' -> */, +/* pos 03b1: 525 */ 0xF3 /* 's' -> */, +/* pos 03b2: 526 */ 0xE8 /* 'h' -> */, +/* pos 03b3: 527 */ 0xBA /* ':' -> */, +/* pos 03b4: 528 */ 0x00, 0x3F /* - terminal marker 63 - */, +/* pos 03b6: 529 */ 0xF2 /* 'r' -> */, +/* pos 03b7: 530 */ 0xF9 /* 'y' -> */, +/* pos 03b8: 531 */ 0xAD /* '-' -> */, +/* pos 03b9: 532 */ 0xE1 /* 'a' -> */, +/* pos 03ba: 533 */ 0xE6 /* 'f' -> */, +/* pos 03bb: 534 */ 0xF4 /* 't' -> */, +/* pos 03bc: 535 */ 0xE5 /* 'e' -> */, +/* pos 03bd: 536 */ 0xF2 /* 'r' -> */, +/* pos 03be: 537 */ 0xBA /* ':' -> */, +/* pos 03bf: 538 */ 0x00, 0x40 /* - terminal marker 64 - */, +/* pos 03c1: 539 */ 0xF6 /* 'v' -> */, +/* pos 03c2: 540 */ 0xE5 /* 'e' -> */, +/* pos 03c3: 541 */ 0xF2 /* 'r' -> */, +/* pos 03c4: 542 */ 0xBA /* ':' -> */, +/* pos 03c5: 543 */ 0x00, 0x41 /* - terminal marker 65 - */, +/* pos 03c7: 544 */ 0xAD /* '-' -> */, +/* pos 03c8: 545 */ 0xE3 /* 'c' -> */, +/* pos 03c9: 546 */ 0xEF /* 'o' -> */, +/* pos 03ca: 547 */ 0xEF /* 'o' -> */, +/* pos 03cb: 548 */ 0xEB /* 'k' -> */, +/* pos 03cc: 549 */ 0xE9 /* 'i' -> */, +/* pos 03cd: 550 */ 0xE5 /* 'e' -> */, +/* pos 03ce: 551 */ 0xBA /* ':' -> */, +/* pos 03cf: 552 */ 0x00, 0x42 /* - terminal marker 66 - */, +/* pos 03d1: 553 */ 0xF2 /* 'r' -> */, +/* pos 03d2: 554 */ 0xE9 /* 'i' -> */, +/* pos 03d3: 555 */ 0xE3 /* 'c' -> */, +/* pos 03d4: 556 */ 0xF4 /* 't' -> */, +/* pos 03d5: 557 */ 0xAD /* '-' -> */, +/* pos 03d6: 558 */ 0xF4 /* 't' -> */, +/* pos 03d7: 559 */ 0xF2 /* 'r' -> */, +/* pos 03d8: 560 */ 0xE1 /* 'a' -> */, +/* pos 03d9: 561 */ 0xEE /* 'n' -> */, +/* pos 03da: 562 */ 0xF3 /* 's' -> */, +/* pos 03db: 563 */ 0xF0 /* 'p' -> */, +/* pos 03dc: 564 */ 0xEF /* 'o' -> */, +/* pos 03dd: 565 */ 0xF2 /* 'r' -> */, +/* pos 03de: 566 */ 0xF4 /* 't' -> */, +/* pos 03df: 567 */ 0xAD /* '-' -> */, +/* pos 03e0: 568 */ 0xF3 /* 's' -> */, +/* pos 03e1: 569 */ 0xE5 /* 'e' -> */, +/* pos 03e2: 570 */ 0xE3 /* 'c' -> */, +/* pos 03e3: 571 */ 0xF5 /* 'u' -> */, +/* pos 03e4: 572 */ 0xF2 /* 'r' -> */, +/* pos 03e5: 573 */ 0xE9 /* 'i' -> */, +/* pos 03e6: 574 */ 0xF4 /* 't' -> */, +/* pos 03e7: 575 */ 0xF9 /* 'y' -> */, +/* pos 03e8: 576 */ 0xBA /* ':' -> */, +/* pos 03e9: 577 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 03eb: 578 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x03F2 state 579) */, + 0x65 /* 'e' */, 0x84, 0x00 /* (to 0x0472 state 680) */, 0x08, /* fail */ -/* pos 0410: 607 */ 0xF2 /* 'r' -> */, -/* pos 0411: 608 */ 0xF9 /* 'y' -> */, -/* pos 0412: 609 */ 0xBA /* ':' -> */, -/* pos 0413: 610 */ 0x00, 0x46 /* - terminal marker 70 - */, -/* pos 0415: 611 */ 0xE1 /* 'a' -> */, -/* pos 0416: 612 */ 0xBA /* ':' -> */, -/* pos 0417: 613 */ 0x00, 0x47 /* - terminal marker 71 - */, -/* pos 0419: 614 */ 0xF7 /* 'w' -> */, -/* pos 041a: 615 */ 0xF7 /* 'w' -> */, -/* pos 041b: 616 */ 0xAD /* '-' -> */, -/* pos 041c: 617 */ 0xE1 /* 'a' -> */, -/* pos 041d: 618 */ 0xF5 /* 'u' -> */, -/* pos 041e: 619 */ 0xF4 /* 't' -> */, -/* pos 041f: 620 */ 0xE8 /* 'h' -> */, -/* pos 0420: 621 */ 0xE5 /* 'e' -> */, -/* pos 0421: 622 */ 0xEE /* 'n' -> */, -/* pos 0422: 623 */ 0xF4 /* 't' -> */, -/* pos 0423: 624 */ 0xE9 /* 'i' -> */, -/* pos 0424: 625 */ 0xE3 /* 'c' -> */, -/* pos 0425: 626 */ 0xE1 /* 'a' -> */, -/* pos 0426: 627 */ 0xF4 /* 't' -> */, -/* pos 0427: 628 */ 0xE5 /* 'e' -> */, -/* pos 0428: 629 */ 0xBA /* ':' -> */, -/* pos 0429: 630 */ 0x00, 0x48 /* - terminal marker 72 - */, -/* pos 042b: 631 */ 0xF4 /* 't' -> */, -/* pos 042c: 632 */ 0xE3 /* 'c' -> */, -/* pos 042d: 633 */ 0xE8 /* 'h' -> */, -/* pos 042e: 634 */ 0x00, 0x49 /* - terminal marker 73 - */, -/* pos 0430: 635 */ 0xF4 /* 't' -> */, -/* pos 0431: 636 */ 0x00, 0x4A /* - terminal marker 74 - */, -/* pos 0433: 637 */ 0xEC /* 'l' -> */, -/* pos 0434: 638 */ 0xE5 /* 'e' -> */, -/* pos 0435: 639 */ 0xF4 /* 't' -> */, -/* pos 0436: 640 */ 0xE5 /* 'e' -> */, -/* pos 0437: 641 */ 0x00, 0x4B /* - terminal marker 75 - */, -/* pos 0439: 642 */ 0xE9 /* 'i' -> */, -/* pos 043a: 643 */ 0xAD /* '-' -> */, -/* pos 043b: 644 */ 0xE1 /* 'a' -> */, -/* pos 043c: 645 */ 0xF2 /* 'r' -> */, -/* pos 043d: 646 */ 0xE7 /* 'g' -> */, -/* pos 043e: 647 */ 0xF3 /* 's' -> */, -/* pos 043f: 648 */ 0x00, 0x4C /* - terminal marker 76 - */, -/* pos 0441: 649 */ 0x00, 0x4D /* - terminal marker 77 - */, -/* pos 0443: 650 */ 0xAD /* '-' -> */, -/* pos 0444: 651 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x044B state 652) */, - 0x66 /* 'f' */, 0x10, 0x00 /* (to 0x0457 state 662) */, +/* pos 03f2: 579 */ 0xE1 /* 'a' -> */, +/* pos 03f3: 580 */ 0xEE /* 'n' -> */, +/* pos 03f4: 581 */ 0xF3 /* 's' -> */, +/* pos 03f5: 582 */ 0xE6 /* 'f' -> */, +/* pos 03f6: 583 */ 0xE5 /* 'e' -> */, +/* pos 03f7: 584 */ 0xF2 /* 'r' -> */, +/* pos 03f8: 585 */ 0xAD /* '-' -> */, +/* pos 03f9: 586 */ 0xE5 /* 'e' -> */, +/* pos 03fa: 587 */ 0xEE /* 'n' -> */, +/* pos 03fb: 588 */ 0xE3 /* 'c' -> */, +/* pos 03fc: 589 */ 0xEF /* 'o' -> */, +/* pos 03fd: 590 */ 0xE4 /* 'd' -> */, +/* pos 03fe: 591 */ 0xE9 /* 'i' -> */, +/* pos 03ff: 592 */ 0xEE /* 'n' -> */, +/* pos 0400: 593 */ 0xE7 /* 'g' -> */, +/* pos 0401: 594 */ 0xBA /* ':' -> */, +/* pos 0402: 595 */ 0x00, 0x44 /* - terminal marker 68 - */, +/* pos 0404: 596 */ 0xE5 /* 'e' -> */, +/* pos 0405: 597 */ 0xF2 /* 'r' -> */, +/* pos 0406: 598 */ 0xAD /* '-' -> */, +/* pos 0407: 599 */ 0xE1 /* 'a' -> */, +/* pos 0408: 600 */ 0xE7 /* 'g' -> */, +/* pos 0409: 601 */ 0xE5 /* 'e' -> */, +/* pos 040a: 602 */ 0xEE /* 'n' -> */, +/* pos 040b: 603 */ 0xF4 /* 't' -> */, +/* pos 040c: 604 */ 0xBA /* ':' -> */, +/* pos 040d: 605 */ 0x00, 0x45 /* - terminal marker 69 - */, +/* pos 040f: 606 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0416 state 607) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x041B state 611) */, 0x08, /* fail */ -/* pos 044b: 652 */ 0xE5 /* 'e' -> */, -/* pos 044c: 653 */ 0xE1 /* 'a' -> */, -/* pos 044d: 654 */ 0xEC /* 'l' -> */, -/* pos 044e: 655 */ 0xAD /* '-' -> */, -/* pos 044f: 656 */ 0xE9 /* 'i' -> */, -/* pos 0450: 657 */ 0xF0 /* 'p' -> */, -/* pos 0451: 658 */ 0xBA /* ':' -> */, -/* pos 0452: 659 */ 0x00, 0x4E /* - terminal marker 78 - */, -/* pos 0454: 660 */ 0xA0 /* ' ' -> */, -/* pos 0455: 661 */ 0x00, 0x4F /* - terminal marker 79 - */, -/* pos 0457: 662 */ 0xEF /* 'o' -> */, -/* pos 0458: 663 */ 0xF2 /* 'r' -> */, -/* pos 0459: 664 */ 0xF7 /* 'w' -> */, -/* pos 045a: 665 */ 0xE1 /* 'a' -> */, -/* pos 045b: 666 */ 0xF2 /* 'r' -> */, -/* pos 045c: 667 */ 0xE4 /* 'd' -> */, -/* pos 045d: 668 */ 0xE5 /* 'e' -> */, -/* pos 045e: 669 */ 0xE4 /* 'd' -> */, -/* pos 045f: 670 */ 0xAD /* '-' -> */, -/* pos 0460: 671 */ 0xE6 /* 'f' -> */, -/* pos 0461: 672 */ 0xEF /* 'o' -> */, -/* pos 0462: 673 */ 0xF2 /* 'r' -> */, -/* pos 0463: 674 */ 0x00, 0x50 /* - terminal marker 80 - */, -/* pos 0465: 675 */ 0x00, 0x51 /* - terminal marker 81 - */, -/* pos 0467: 676 */ 0xE1 /* 'a' -> */, -/* pos 0468: 677 */ 0xE4 /* 'd' -> */, -/* pos 0469: 678 */ 0xA0 /* ' ' -> */, -/* pos 046a: 679 */ 0x00, 0x52 /* - terminal marker 82 - */, -/* pos 046c: 680 */ 0xBA /* ':' -> */, -/* pos 046d: 681 */ 0x00, 0x53 /* - terminal marker 83 - */, -/* pos 046f: 682 */ 0xEC /* 'l' -> */, -/* pos 0470: 683 */ 0xE1 /* 'a' -> */, -/* pos 0471: 684 */ 0xF9 /* 'y' -> */, -/* pos 0472: 685 */ 0xAD /* '-' -> */, -/* pos 0473: 686 */ 0xEE /* 'n' -> */, -/* pos 0474: 687 */ 0xEF /* 'o' -> */, -/* pos 0475: 688 */ 0xEE /* 'n' -> */, -/* pos 0476: 689 */ 0xE3 /* 'c' -> */, -/* pos 0477: 690 */ 0xE5 /* 'e' -> */, -/* pos 0478: 691 */ 0xBA /* ':' -> */, -/* pos 0479: 692 */ 0x00, 0x54 /* - terminal marker 84 - */, -/* total size 1147 bytes */ +/* pos 0416: 607 */ 0xF2 /* 'r' -> */, +/* pos 0417: 608 */ 0xF9 /* 'y' -> */, +/* pos 0418: 609 */ 0xBA /* ':' -> */, +/* pos 0419: 610 */ 0x00, 0x46 /* - terminal marker 70 - */, +/* pos 041b: 611 */ 0xE1 /* 'a' -> */, +/* pos 041c: 612 */ 0xBA /* ':' -> */, +/* pos 041d: 613 */ 0x00, 0x47 /* - terminal marker 71 - */, +/* pos 041f: 614 */ 0xF7 /* 'w' -> */, +/* pos 0420: 615 */ 0xF7 /* 'w' -> */, +/* pos 0421: 616 */ 0xAD /* '-' -> */, +/* pos 0422: 617 */ 0xE1 /* 'a' -> */, +/* pos 0423: 618 */ 0xF5 /* 'u' -> */, +/* pos 0424: 619 */ 0xF4 /* 't' -> */, +/* pos 0425: 620 */ 0xE8 /* 'h' -> */, +/* pos 0426: 621 */ 0xE5 /* 'e' -> */, +/* pos 0427: 622 */ 0xEE /* 'n' -> */, +/* pos 0428: 623 */ 0xF4 /* 't' -> */, +/* pos 0429: 624 */ 0xE9 /* 'i' -> */, +/* pos 042a: 625 */ 0xE3 /* 'c' -> */, +/* pos 042b: 626 */ 0xE1 /* 'a' -> */, +/* pos 042c: 627 */ 0xF4 /* 't' -> */, +/* pos 042d: 628 */ 0xE5 /* 'e' -> */, +/* pos 042e: 629 */ 0xBA /* ':' -> */, +/* pos 042f: 630 */ 0x00, 0x48 /* - terminal marker 72 - */, +/* pos 0431: 631 */ 0xF4 /* 't' -> */, +/* pos 0432: 632 */ 0xE3 /* 'c' -> */, +/* pos 0433: 633 */ 0xE8 /* 'h' -> */, +/* pos 0434: 634 */ 0x00, 0x49 /* - terminal marker 73 - */, +/* pos 0436: 635 */ 0xF4 /* 't' -> */, +/* pos 0437: 636 */ 0x00, 0x4A /* - terminal marker 74 - */, +/* pos 0439: 637 */ 0xEC /* 'l' -> */, +/* pos 043a: 638 */ 0xE5 /* 'e' -> */, +/* pos 043b: 639 */ 0xF4 /* 't' -> */, +/* pos 043c: 640 */ 0xE5 /* 'e' -> */, +/* pos 043d: 641 */ 0x00, 0x4B /* - terminal marker 75 - */, +/* pos 043f: 642 */ 0xE9 /* 'i' -> */, +/* pos 0440: 643 */ 0xAD /* '-' -> */, +/* pos 0441: 644 */ 0xE1 /* 'a' -> */, +/* pos 0442: 645 */ 0xF2 /* 'r' -> */, +/* pos 0443: 646 */ 0xE7 /* 'g' -> */, +/* pos 0444: 647 */ 0xF3 /* 's' -> */, +/* pos 0445: 648 */ 0x00, 0x4C /* - terminal marker 76 - */, +/* pos 0447: 649 */ 0x00, 0x4D /* - terminal marker 77 - */, +/* pos 0449: 650 */ 0xAD /* '-' -> */, +/* pos 044a: 651 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0451 state 652) */, + 0x66 /* 'f' */, 0x10, 0x00 /* (to 0x045D state 662) */, + 0x08, /* fail */ +/* pos 0451: 652 */ 0xE5 /* 'e' -> */, +/* pos 0452: 653 */ 0xE1 /* 'a' -> */, +/* pos 0453: 654 */ 0xEC /* 'l' -> */, +/* pos 0454: 655 */ 0xAD /* '-' -> */, +/* pos 0455: 656 */ 0xE9 /* 'i' -> */, +/* pos 0456: 657 */ 0xF0 /* 'p' -> */, +/* pos 0457: 658 */ 0xBA /* ':' -> */, +/* pos 0458: 659 */ 0x00, 0x4E /* - terminal marker 78 - */, +/* pos 045a: 660 */ 0xA0 /* ' ' -> */, +/* pos 045b: 661 */ 0x00, 0x4F /* - terminal marker 79 - */, +/* pos 045d: 662 */ 0xEF /* 'o' -> */, +/* pos 045e: 663 */ 0xF2 /* 'r' -> */, +/* pos 045f: 664 */ 0xF7 /* 'w' -> */, +/* pos 0460: 665 */ 0xE1 /* 'a' -> */, +/* pos 0461: 666 */ 0xF2 /* 'r' -> */, +/* pos 0462: 667 */ 0xE4 /* 'd' -> */, +/* pos 0463: 668 */ 0xE5 /* 'e' -> */, +/* pos 0464: 669 */ 0xE4 /* 'd' -> */, +/* pos 0465: 670 */ 0xAD /* '-' -> */, +/* pos 0466: 671 */ 0xE6 /* 'f' -> */, +/* pos 0467: 672 */ 0xEF /* 'o' -> */, +/* pos 0468: 673 */ 0xF2 /* 'r' -> */, +/* pos 0469: 674 */ 0x00, 0x50 /* - terminal marker 80 - */, +/* pos 046b: 675 */ 0x00, 0x51 /* - terminal marker 81 - */, +/* pos 046d: 676 */ 0xE1 /* 'a' -> */, +/* pos 046e: 677 */ 0xE4 /* 'd' -> */, +/* pos 046f: 678 */ 0xA0 /* ' ' -> */, +/* pos 0470: 679 */ 0x00, 0x52 /* - terminal marker 82 - */, +/* pos 0472: 680 */ 0xBA /* ':' -> */, +/* pos 0473: 681 */ 0x00, 0x53 /* - terminal marker 83 - */, +/* pos 0475: 682 */ 0xEC /* 'l' -> */, +/* pos 0476: 683 */ 0xE1 /* 'a' -> */, +/* pos 0477: 684 */ 0xF9 /* 'y' -> */, +/* pos 0478: 685 */ 0xAD /* '-' -> */, +/* pos 0479: 686 */ 0xEE /* 'n' -> */, +/* pos 047a: 687 */ 0xEF /* 'o' -> */, +/* pos 047b: 688 */ 0xEE /* 'n' -> */, +/* pos 047c: 689 */ 0xE3 /* 'c' -> */, +/* pos 047d: 690 */ 0xE5 /* 'e' -> */, +/* pos 047e: 691 */ 0xBA /* ':' -> */, +/* pos 047f: 692 */ 0x00, 0x54 /* - terminal marker 84 - */, +/* pos 0481: 693 */ 0xEF /* 'o' -> */, +/* pos 0482: 694 */ 0xF4 /* 't' -> */, +/* pos 0483: 695 */ 0xEF /* 'o' -> */, +/* pos 0484: 696 */ 0xE3 /* 'c' -> */, +/* pos 0485: 697 */ 0xEF /* 'o' -> */, +/* pos 0486: 698 */ 0xEC /* 'l' -> */, +/* pos 0487: 699 */ 0x00, 0x55 /* - terminal marker 85 - */, +/* total size 1161 bytes */ diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index a9e1f71a..e9fcb5af 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -423,19 +423,7 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason) #endif #if !defined(LWS_NO_CLIENT) - if (wsi->mode == LWSCM_HTTP_CLIENT || - wsi->mode == LWSCM_WSCL_WAITING_CONNECT || - wsi->mode == LWSCM_WSCL_WAITING_PROXY_REPLY || - wsi->mode == LWSCM_WSCL_ISSUE_HANDSHAKE || - wsi->mode == LWSCM_WSCL_ISSUE_HANDSHAKE2 || - wsi->mode == LWSCM_WSCL_WAITING_SSL || - wsi->mode == LWSCM_WSCL_WAITING_SERVER_REPLY || - wsi->mode == LWSCM_WSCL_WAITING_EXTENSION_CONNECT || - wsi->mode == LWSCM_WSCL_WAITING_SOCKS_GREETING_REPLY || - wsi->mode == LWSCM_WSCL_WAITING_SOCKS_CONNECT_REPLY || - wsi->mode == LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY) - if (wsi->stash) - lws_free_set_NULL(wsi->stash); + lws_free_set_NULL(wsi->stash); #endif if (wsi->mode == LWSCM_RAW) { @@ -560,7 +548,7 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason) * LWSS_AWAITING_CLOSE_ACK and will skip doing this a second time. */ - if (wsi->state_pre_close == LWSS_ESTABLISHED && + if (lws_state_is_ws(wsi->state_pre_close) && (wsi->ws->close_in_ping_buffer_len || /* already a reason */ (reason != LWS_CLOSE_STATUS_NOSTATUS && (reason != LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY)))) { @@ -704,11 +692,10 @@ just_kill_connection: #endif wsi->state = LWSS_DEAD_SOCKET; - lws_free_set_NULL(wsi->rxflow_buffer); - if (wsi->state_pre_close == LWSS_ESTABLISHED || - wsi->mode == LWSCM_WS_SERVING || - wsi->mode == LWSCM_WS_CLIENT) { + + if (lws_state_is_ws(wsi->state_pre_close) || + wsi->mode == LWSCM_WS_SERVING || wsi->mode == LWSCM_WS_CLIENT) { if (wsi->ws->rx_draining_ext) { struct lws **w = &pt->rx_draining_ext_list; @@ -751,21 +738,8 @@ just_kill_connection: /* tell the user it's all over for this guy */ - if (!wsi->told_user_closed && - wsi->mode != LWSCM_RAW && wsi->protocol && - wsi->protocol->callback && - (wsi->state_pre_close == LWSS_ESTABLISHED || - wsi->state_pre_close == LWSS_HTTP2_ESTABLISHED || - wsi->state_pre_close == LWSS_HTTP_BODY || - wsi->state_pre_close == LWSS_HTTP || - wsi->state_pre_close == LWSS_RETURNED_CLOSE_ALREADY || - wsi->state_pre_close == LWSS_AWAITING_CLOSE_ACK || - wsi->state_pre_close == LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION || - wsi->state_pre_close == LWSS_FLUSHING_SEND_BEFORE_CLOSE || - (wsi->mode == LWSCM_WS_CLIENT && - wsi->state_pre_close == LWSS_HTTP) || - (wsi->mode == LWSCM_WS_SERVING && - wsi->state_pre_close == LWSS_HTTP))) { + if (wsi->protocol && !wsi->told_user_closed && wsi->protocol->callback && + wsi->mode != LWSCM_RAW && (wsi->state_pre_close & _LSF_CCB)) { lwsl_debug("calling back CLOSED %d %d\n", wsi->mode, wsi->state); wsi->protocol->callback(wsi, LWS_CALLBACK_CLOSED, wsi->user_space, NULL, 0); @@ -2446,7 +2420,7 @@ lws_restart_ws_ping_pong_timer(struct lws *wsi) { if (!wsi->context->ws_ping_pong_interval) return; - if (wsi->state != LWSS_ESTABLISHED) + if (!lws_state_is_ws(wsi->state)) return; wsi->ws->time_next_ping_check = (time_t)lws_now_secs() + diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 5b9b2236..5e5ca529 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -3859,6 +3859,7 @@ enum lws_token_indexes { WSI_TOKEN_HEAD_URI = 82, WSI_TOKEN_TE = 83, WSI_TOKEN_REPLAY_NONCE = 84, + WSI_TOKEN_COLON_PROTOCOL = 85, /****** add new things just above ---^ ******/ diff --git a/lib/output.c b/lib/output.c index 0a9638bd..c3cca1fc 100644 --- a/lib/output.c +++ b/lib/output.c @@ -198,7 +198,7 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len, unsigned char *dropmask = NULL; struct lws_tokens eff_buf; size_t orig_len = len; - int pre = 0, n; + int pre = 0, n, wp1f = wp & 0x1f; if (wsi->parent_carries_io) { struct lws_write_passthru pas; @@ -233,7 +233,7 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len, if (wsi->vhost) wsi->vhost->conn_stats.tx += len; - if (wsi->state == LWSS_ESTABLISHED && wsi->ws->tx_draining_ext) { + if (wsi->ws && wsi->ws->tx_draining_ext && lws_state_is_ws(wsi->state)) { /* remove us from the list */ struct lws **w = &pt->tx_draining_ext_list; @@ -249,21 +249,22 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len, wsi->ws->tx_draining_ext_list = NULL; wp = (wsi->ws->tx_draining_stashed_wp & 0xc0) | LWS_WRITE_CONTINUATION; + wp1f = wp & 0x1f; lwsl_ext("FORCED draining wp to 0x%02X\n", wp); } lws_restart_ws_ping_pong_timer(wsi); - if ((wp & 0x1f) == LWS_WRITE_HTTP || - (wp & 0x1f) == LWS_WRITE_HTTP_FINAL || - (wp & 0x1f) == LWS_WRITE_HTTP_HEADERS_CONTINUATION || - (wp & 0x1f) == LWS_WRITE_HTTP_HEADERS) + if (wp1f == LWS_WRITE_HTTP || + wp1f == LWS_WRITE_HTTP_FINAL || + wp1f == LWS_WRITE_HTTP_HEADERS_CONTINUATION || + wp1f == LWS_WRITE_HTTP_HEADERS) goto send_raw; /* if not in a state to send stuff, then just send nothing */ - if (wsi->state != LWSS_ESTABLISHED && + if (!lws_state_is_ws(wsi->state) && ((wsi->state != LWSS_RETURNED_CLOSE_ALREADY && wsi->state != LWSS_AWAITING_CLOSE_ACK) || wp != LWS_WRITE_CLOSE)) @@ -331,6 +332,7 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len, if (eff_buf.token_len && wsi->ws->stashed_write_pending) { wsi->ws->stashed_write_pending = 0; wp = (wp &0xc0) | (int)wsi->ws->stashed_write_type; + wp1f = wp & 0x1f; } } @@ -465,7 +467,7 @@ do_more_inside_frame: } send_raw: - switch ((int)(wp & 0x1f)) { + switch (wp1f) { case LWS_WRITE_CLOSE: /* lwsl_hexdump(&buf[-pre], len); */ case LWS_WRITE_HTTP: @@ -475,11 +477,15 @@ send_raw: case LWS_WRITE_PONG: case LWS_WRITE_PING: #ifdef LWS_WITH_HTTP2 - if (wsi->mode == LWSCM_HTTP2_SERVING) { + /* + * ws-over-h2 ends up here after the ws framing applied + */ + if (wsi->mode == LWSCM_HTTP2_SERVING || + wsi->mode == LWSCM_HTTP2_WS_SERVING) { unsigned char flags = 0; n = LWS_H2_FRAME_TYPE_DATA; - if ((wp & 0x1f) == LWS_WRITE_HTTP_HEADERS) { + if (wp1f == LWS_WRITE_HTTP_HEADERS) { n = LWS_H2_FRAME_TYPE_HEADERS; if (!(wp & LWS_WRITE_NO_FIN)) flags = LWS_H2_FLAG_END_HEADERS; @@ -490,7 +496,7 @@ send_raw: } } - if ((wp & 0x1f) == LWS_WRITE_HTTP_HEADERS_CONTINUATION) { + if (wp1f == LWS_WRITE_HTTP_HEADERS_CONTINUATION) { n = LWS_H2_FRAME_TYPE_CONTINUATION; if (!(wp & LWS_WRITE_NO_FIN)) flags = LWS_H2_FLAG_END_HEADERS; @@ -501,20 +507,22 @@ send_raw: } } - if (((wp & 0x1f) == LWS_WRITE_HTTP || - (wp & 0x1f) == LWS_WRITE_HTTP_FINAL) && + if ((wp1f == LWS_WRITE_HTTP || + wp1f == LWS_WRITE_HTTP_FINAL) && wsi->http.tx_content_length) { wsi->http.tx_content_remain -= len; - lwsl_info("%s: wsi %p: tx_content_remain = %llu\n", __func__, wsi, + lwsl_info("%s: wsi %p: tx_content_remain = %llu\n", + __func__, wsi, (unsigned long long)wsi->http.tx_content_remain); if (!wsi->http.tx_content_remain) { lwsl_info("%s: selecting final write mode\n", __func__); wp = LWS_WRITE_HTTP_FINAL; + wp1f = wp & 0x1f; } } - if ((wp & 0x1f) == LWS_WRITE_HTTP_FINAL || + if (wp1f == LWS_WRITE_HTTP_FINAL || (wp & LWS_WRITE_H2_STREAM_END)) { //lws_get_network_wsi(wsi)->h2.END_STREAM) { lwsl_info("%s: setting END_STREAM\n", __func__); @@ -522,8 +530,9 @@ send_raw: wsi->h2.send_END_STREAM = 1; } - return lws_h2_frame_write(wsi, n, flags, - wsi->h2.my_sid, (int)len, buf); + /* if any ws framing, account for that too */ + return lws_h2_frame_write(wsi, n, flags, wsi->h2.my_sid, + (int)len + pre, buf - pre); } #endif return lws_issue_raw(wsi, (unsigned char *)buf - pre, len + pre); diff --git a/lib/plat/lws-plat-esp32.c b/lib/plat/lws-plat-esp32.c index ed614e06..efc1291a 100644 --- a/lib/plat/lws-plat-esp32.c +++ b/lib/plat/lws-plat-esp32.c @@ -567,6 +567,8 @@ const struct http2_settings const lws_h2_defaults_esp32 = { { /* H2SET_INITIAL_WINDOW_SIZE */ 65535, /* H2SET_MAX_FRAME_SIZE */ 16384, /* H2SET_MAX_HEADER_LIST_SIZE */ 512, + /* H2SET_RESERVED7 */ 0, + /* H2SET_ENABLE_CONNECT_PROTOCOL */ 1, }}; #endif diff --git a/lib/pollfd.c b/lib/pollfd.c index 8723054c..25c94827 100644 --- a/lib/pollfd.c +++ b/lib/pollfd.c @@ -461,7 +461,8 @@ lws_callback_on_writable(struct lws *wsi) #ifdef LWS_WITH_HTTP2 lwsl_info("%s: %p\n", __func__, wsi); - if (wsi->mode != LWSCM_HTTP2_SERVING) + if (wsi->mode != LWSCM_HTTP2_SERVING && + wsi->mode != LWSCM_HTTP2_WS_SERVING) goto network_sock; if (wsi->h2.requested_POLLOUT) { diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 528b2e29..20e884af 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -564,27 +564,44 @@ enum lws_websocket_opcodes_07 { enum lws_connection_states { - LWSS_HTTP, - LWSS_HTTP_ISSUING_FILE, - LWSS_HTTP_HEADERS, - LWSS_HTTP_BODY, - LWSS_DEAD_SOCKET, - LWSS_ESTABLISHED, - LWSS_CLIENT_HTTP_ESTABLISHED, - LWSS_CLIENT_UNCONNECTED, - LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION, - LWSS_RETURNED_CLOSE_ALREADY, - LWSS_AWAITING_CLOSE_ACK, - LWSS_FLUSHING_SEND_BEFORE_CLOSE, - LWSS_SHUTDOWN, + /* FLAG: one or another kind of ws link */ + _LSF_WEBSOCKET = (1 << 5), + /* FLAG: close callback */ + _LSF_CCB = (1 << 6), + /* FLAG: pollout capable */ + _LSF_POLLOUT = (1 << 7), - LWSS_HTTP2_AWAIT_CLIENT_PREFACE, - LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS, - LWSS_HTTP2_ESTABLISHED, + LWSS_HTTP = _LSF_CCB | 0, + LWSS_HTTP_ISSUING_FILE = 1, + LWSS_HTTP_HEADERS = 2, + LWSS_HTTP_BODY = _LSF_CCB | 3, + LWSS_DEAD_SOCKET = 4, + LWSS_ESTABLISHED = _LSF_CCB | 5 | + _LSF_WEBSOCKET | + _LSF_POLLOUT, + LWSS_CLIENT_HTTP_ESTABLISHED = 6, + LWSS_CLIENT_UNCONNECTED = 7, + LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION = _LSF_CCB | 8 | + _LSF_POLLOUT, + LWSS_RETURNED_CLOSE_ALREADY = _LSF_CCB | 9 | + _LSF_POLLOUT, + LWSS_AWAITING_CLOSE_ACK = _LSF_CCB | 10, + LWSS_FLUSHING_SEND_BEFORE_CLOSE = _LSF_CCB | 11 | + _LSF_POLLOUT, + LWSS_SHUTDOWN = 12, - LWSS_CGI, + LWSS_HTTP2_AWAIT_CLIENT_PREFACE = 13, + LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS = 14 | _LSF_POLLOUT, + LWSS_HTTP2_ESTABLISHED = _LSF_CCB | 15 | + _LSF_POLLOUT, + LWSS_HTTP2_ESTABLISHED_WS = _LSF_CCB | 16 | + _LSF_WEBSOCKET, + + LWSS_CGI = 17, }; +#define lws_state_is_ws(s) (!!(s & _LSF_WEBSOCKET)) + enum http_version { HTTP_VERSION_1_0, HTTP_VERSION_1_1, @@ -628,13 +645,15 @@ enum lws_rx_parse_state { enum connection_mode { LWSCM_HTTP_SERVING, - LWSCM_HTTP_SERVING_ACCEPTED, /* actual HTTP service going on */ + /* actual HTTP service going on */ + LWSCM_HTTP_SERVING_ACCEPTED, LWSCM_PRE_WS_SERVING_ACCEPT, LWSCM_WS_SERVING, LWSCM_WS_CLIENT, LWSCM_HTTP2_SERVING, + LWSCM_HTTP2_WS_SERVING, /* transient, ssl delay hiding */ LWSCM_SSL_ACK_PENDING, @@ -667,8 +686,6 @@ enum connection_mode { LWSCM_WSCL_WAITING_SOCKS_AUTH_REPLY, /****** add new things just above ---^ ******/ - - }; /* enums of socks version */ @@ -957,6 +974,8 @@ enum lws_h2_settings { H2SET_INITIAL_WINDOW_SIZE, H2SET_MAX_FRAME_SIZE, H2SET_MAX_HEADER_LIST_SIZE, + H2SET_RESERVED7, + H2SET_ENABLE_CONNECT_PROTOCOL, /* defined in mcmanus-httpbis-h2-ws-02 */ H2SET_COUNT /* always last */ }; @@ -1973,12 +1992,14 @@ struct lws { unsigned int hdr_parsing_completed:1; unsigned int http2_substream:1; unsigned int upgraded_to_http2:1; + unsigned int h2_stream_carries_ws:1; unsigned int seen_nonpseudoheader:1; unsigned int listener:1; unsigned int user_space_externally_allocated:1; unsigned int socket_is_permanently_unusable:1; unsigned int rxflow_change_to:2; - unsigned int more_rx_waiting:1; /* has to live here since ah may stick to end */ + /* has to live here since ah may stick to end */ + unsigned int more_rx_waiting:1; unsigned int conn_stat_done:1; unsigned int cache_reuse:1; unsigned int cache_revalidate:1; @@ -2028,14 +2049,14 @@ struct lws { #ifndef LWS_NO_CLIENT unsigned short c_port; #endif + uint8_t state; /* enum lws_connection_states */ + uint8_t mode; /* enum connection_mode */ /* chars */ #ifndef LWS_NO_EXTENSIONS uint8_t count_act_ext; #endif - char mode; /* enum connection_mode */ - char state; /* enum lws_connection_states */ - char state_pre_close; + uint8_t state_pre_close; char lws_rx_parse_state; /* enum lws_rx_parse_state */ char rx_frame_type; /* enum lws_write_protocol */ char pending_timeout; /* enum pending_timeout */ @@ -2266,6 +2287,8 @@ LWS_EXTERN void lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pss); LWS_EXTERN const struct http2_settings lws_h2_defaults; +LWS_EXTERN int +lws_h2_ws_handshake(struct lws *wsi); #else #define lws_h2_configure_if_upgraded(x) #endif diff --git a/lib/server/server.c b/lib/server/server.c index 6ded8b4d..627945e0 100644 --- a/lib/server/server.c +++ b/lib/server/server.c @@ -1307,7 +1307,8 @@ lws_server_init_wsi_for_ws(struct lws *wsi) lwsl_debug("Allocating RX buffer %d\n", n); #if LWS_POSIX && !defined(LWS_WITH_ESP32) - if (!wsi->parent_carries_io) + if (!wsi->parent_carries_io && + !wsi->h2_stream_carries_ws) if (setsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) { lwsl_warn("Failed to set SNDBUF to %d", n); @@ -1492,7 +1493,7 @@ raw_transition: lwsl_info("Upgrade to ws\n"); goto upgrade_ws; } -#ifdef LWS_WITH_HTTP2 +#if defined(LWS_WITH_HTTP2) if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE), "h2c")) { @@ -1506,6 +1507,27 @@ raw_transition: goto bail_nuke_ah; } +#if defined(LWS_WITH_HTTP2) + /* + * with H2 there's also a way to upgrade a stream to something + * else... :method is CONNECT and :protocol says the name of + * the new protocol we want to carry. We have to have sent a + * SETTINGS saying that we support it though. + */ + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD); + if (wsi->h2.h2n && + wsi->h2.h2n->set.s[H2SET_ENABLE_CONNECT_PROTOCOL] && + p && !strcmp(p, "CONNECT")) { + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_COLON_PROTOCOL); + if (p && !strcmp(p, "websocket")) { + wsi->vhost->conn_stats.ws_upg++; + lwsl_info("Upgrade h2 to ws\n"); + wsi->h2_stream_carries_ws = 1; + goto upgrade_ws; + } + } +#endif + /* no upgrade ack... he remained as HTTP */ lwsl_info("No upgrade\n"); @@ -1521,7 +1543,7 @@ raw_transition: return n; -#ifdef LWS_WITH_HTTP2 +#if defined(LWS_WITH_HTTP2) upgrade_h2c: if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP2_SETTINGS)) { lwsl_info("missing http2_settings\n"); @@ -1571,6 +1593,7 @@ upgrade_h2c: } wsi->state = LWSS_HTTP2_AWAIT_CLIENT_PREFACE; + wsi->upgraded_to_http2 = 1; return 0; #endif @@ -1580,7 +1603,7 @@ upgrade_ws: lwsl_err("NULL protocol at lws_read\n"); /* - * It's websocket + * It's either websocket or h2->websocket * * Select the first protocol we support from the list * the client sent us. @@ -1689,10 +1712,20 @@ upgrade_ws: switch (wsi->ws->ietf_spec_revision) { case 13: - lwsl_parser("lws_parse calling handshake_04\n"); - if (handshake_0405(context, wsi)) { - lwsl_info("hs0405 has failed the connection\n"); - goto bail_nuke_ah; +#if defined(LWS_WITH_HTTP2) + if (wsi->h2_stream_carries_ws) { + if (lws_h2_ws_handshake(wsi)) { + lwsl_info("h2 ws handshake failed\n"); + goto bail_nuke_ah; + } + } else +#endif + { + lwsl_parser("lws_parse calling handshake_04\n"); + if (handshake_0405(context, wsi)) { + lwsl_info("hs0405 has failed the connection\n"); + goto bail_nuke_ah; + } } break; @@ -1704,7 +1737,7 @@ upgrade_ws: lws_same_vh_protocol_insert(wsi, n); - /* we are upgrading to ws, so http/1.1 and keepalive + + /* we are upgrading to ws, so http/1.1 + h2 and keepalive + * pipelined header considerations about keeping the ah around * no longer apply. However it's common for the first ws * protocol data to have been coalesced with the browser @@ -1712,17 +1745,14 @@ upgrade_ws: */ lwsl_info("%s: %p: inheriting ws ah (rxpos:%d, rxlen:%d)\n", - __func__, wsi, wsi->ah->rxpos, - wsi->ah->rxlen); + __func__, wsi, wsi->ah->rxpos, wsi->ah->rxlen); lws_pt_lock(pt); - lws_union_transition(wsi, LWSCM_WS_SERVING); + if (wsi->h2_stream_carries_ws) + lws_union_transition(wsi, LWSCM_HTTP2_WS_SERVING); + else + lws_union_transition(wsi, LWSCM_WS_SERVING); /* - * first service is WS mode will notice this, use the RX and - * then detach the ah (caution: we are not in u.hdr union - * mode any more then... ah_temp member is at start the same - * though) - * * Because rxpos/rxlen shows something in the ah, we will get * service guaranteed next time around the event loop */ diff --git a/lib/service.c b/lib/service.c index 93269170..666c9af7 100644 --- a/lib/service.c +++ b/lib/service.c @@ -170,8 +170,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) /* else, the send failed and we should just hang up */ - if ((wsi->state == LWSS_ESTABLISHED && - wsi->ws->ping_pending_flag) || + if ((lws_state_is_ws(wsi->state) && wsi->ws->ping_pending_flag) || (wsi->state == LWSS_RETURNED_CLOSE_ALREADY && wsi->ws->payload_is_close)) { @@ -193,8 +192,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) goto bail_ok; } - if (wsi->state == LWSS_ESTABLISHED && - !wsi->socket_is_permanently_unusable && + if (lws_state_is_ws(wsi->state) && !wsi->socket_is_permanently_unusable && wsi->ws->send_check_ping) { lwsl_info("issuing ping on wsi %p\n", wsi); @@ -229,7 +227,7 @@ lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd) * payload ordering, but since they are always complete * fragments control packets can interleave OK. */ - if (wsi->state == LWSS_ESTABLISHED && wsi->ws->tx_draining_ext) { + if (lws_state_is_ws(wsi->state) && wsi->ws->tx_draining_ext) { lwsl_ext("SERVICING TX EXT DRAINING\n"); if (lws_write(wsi, NULL, 0, LWS_WRITE_CONTINUATION) < 0) goto bail_die; @@ -382,7 +380,8 @@ user_service_go_again: * notifications, so we can't hold pointers */ - if (wsi->mode != LWSCM_HTTP2_SERVING) { + if (wsi->mode != LWSCM_HTTP2_SERVING && + wsi->mode != LWSCM_HTTP2_WS_SERVING) { lwsl_info("%s: non http2\n", __func__); goto notify; } @@ -961,8 +960,7 @@ lws_is_ws_with_ext(struct lws *wsi) #if defined(LWS_NO_EXTENSIONS) return 0; #else - return wsi->state == LWSS_ESTABLISHED && - !!wsi->count_act_ext; + return lws_state_is_ws(wsi->state) && !!wsi->count_act_ext; #endif } @@ -1148,7 +1146,7 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, wsi = vh->same_vh_protocol_list[n]; while (wsi) { - if (wsi->state == LWSS_ESTABLISHED && + if (lws_state_is_ws(wsi->state) && !wsi->socket_is_permanently_unusable && !wsi->ws->send_check_ping && wsi->ws->time_next_ping_check && @@ -1333,17 +1331,13 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, case LWSCM_WS_SERVING: case LWSCM_WS_CLIENT: case LWSCM_HTTP2_SERVING: + case LWSCM_HTTP2_WS_SERVING: case LWSCM_HTTP_CLIENT_ACCEPTED: /* 1: something requested a callback when it was OK to write */ if ((pollfd->revents & LWS_POLLOUT) && - ((wsi->state == LWSS_ESTABLISHED || - wsi->state == LWSS_HTTP2_ESTABLISHED || - wsi->state == LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS || - wsi->state == LWSS_RETURNED_CLOSE_ALREADY || - wsi->state == LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION || - wsi->state == LWSS_FLUSHING_SEND_BEFORE_CLOSE)) && + (wsi->state & _LSF_POLLOUT) /* ...our state cares ... */ && lws_handle_POLLOUT_event(wsi, pollfd)) { if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY) wsi->state = LWSS_FLUSHING_SEND_BEFORE_CLOSE; @@ -1365,19 +1359,19 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, } if (wsi->ws && wsi->ws->tx_draining_ext) - /* we cannot deal with new RX until the TX ext - * path has been drained. It's because new - * rx will, eg, crap on the wsi rx buf that - * may be needed to retain state. + /* + * We cannot deal with new RX until the TX ext path has + * been drained. It's because new rx will, eg, crap on + * the wsi rx buf that may be needed to retain state. * - * TX ext drain path MUST go through event loop - * to avoid blocking. + * TX ext drain path MUST go through event loop to avoid + * blocking. */ break; if (lws_is_flowcontrolled(wsi)) - /* We cannot deal with any kind of new RX - * because we are RX-flowcontrolled. + /* We cannot deal with any kind of new RX because we are + * RX-flowcontrolled. */ break; @@ -1397,8 +1391,7 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, /* 2: RX Extension needs to be drained */ - if (wsi->state == LWSS_ESTABLISHED && - wsi->ws->rx_draining_ext) { + if (lws_state_is_ws(wsi->state) && wsi->ws->rx_draining_ext) { lwsl_ext("%s: RX EXT DRAINING: Service\n", __func__); #ifndef LWS_NO_CLIENT