From 61cd344c13c234548695ea6d841ee5a83b5d8a44 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 6 Mar 2020 15:22:36 +0000 Subject: [PATCH 0001/1062] minilex: fix ROLE_WS=0 case --- lib/roles/h2/hpack.c | 16 +- lib/roles/http/lextable.h | 12247 +++++++++++++++---------------- lib/roles/http/minilex.c | 97 +- lib/roles/http/server/server.c | 5 +- test-apps/test-server.c | 4 +- 5 files changed, 6192 insertions(+), 6177 deletions(-) diff --git a/lib/roles/h2/hpack.c b/lib/roles/h2/hpack.c index fb085ff2..2b9df394 100644 --- a/lib/roles/h2/hpack.c +++ b/lib/roles/h2/hpack.c @@ -754,40 +754,39 @@ lws_hpack_use_idx_hdr(struct lws *wsi, int idx, int known_token) return 0; } - #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x03,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x03,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x07,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x03,0x00,0x80,0x07,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x07,0x00,0x00,0x1e,0x00,0x00,0x00,0xc0,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { - 0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) @@ -796,7 +795,6 @@ static uint8_t lws_header_implies_psuedoheader_map[] = { }; #endif - static int lws_hpack_handle_pseudo_rules(struct lws *nwsi, struct lws *wsi, int m) { diff --git a/lib/roles/http/lextable.h b/lib/roles/http/lextable.h index a7334575..bf927373 100644 --- a/lib/roles/http/lextable.h +++ b/lib/roles/http/lextable.h @@ -7,555 +7,519 @@ /* 5: 6: origin: */ /* 6: 8: */ - /* 7: 16: http2-settings: */ - /* 8: 18: access-control-request-headers: */ - /* 9: 20: if-none-match: */ - /* 10: 21: accept-encoding: */ - /* 11: 22: accept-language: */ - /* 12: 23: pragma: */ - /* 13: 24: cache-control: */ - /* 14: 25: authorization: */ - /* 15: 26: cookie: */ - /* 16: 27: content-length: */ - /* 17: 28: content-type: */ - /* 18: 29: date: */ - /* 19: 30: range: */ - /* 20: 31: referer: */ - /* 21: 42: access-control-allow-origin: */ - /* 22: 44: allow: */ - /* 23: 45: content-disposition: */ - /* 24: 46: content-encoding: */ - /* 25: 47: content-language: */ - /* 26: 48: content-location: */ - /* 27: 49: content-range: */ - /* 28: 50: etag: */ - /* 29: 51: expect: */ - /* 30: 52: expires: */ - /* 31: 53: from: */ - /* 32: 54: if-match: */ - /* 33: 55: if-range: */ - /* 34: 56: if-unmodified-since: */ - /* 35: 57: last-modified: */ - /* 36: 58: link: */ - /* 37: 59: location: */ - /* 38: 60: max-forwards: */ - /* 39: 64: retry-after: */ - /* 40: 65: server: */ - /* 41: 66: set-cookie: */ - /* 42: 67: strict-transport-security: */ - /* 43: 69: user-agent: */ - /* 44: 77: proxy */ - /* 45: 80: x-forwarded-for: */ - /* 46: 81: connect */ - /* 47: 82: head */ - /* 48: 83: te: */ - /* 49: 87: */ -/* pos 0000: 0 */ 0x67 /* 'g' */, 0x37, 0x00 /* (to 0x0037 state 1) */, - 0x70 /* 'p' */, 0x39, 0x00 /* (to 0x003C state 5) */, - 0x68 /* 'h' */, 0x42, 0x00 /* (to 0x0048 state 10) */, - 0x63 /* 'c' */, 0x4E, 0x00 /* (to 0x0057 state 15) */, - 0x75 /* 'u' */, 0x6F, 0x00 /* (to 0x007B state 26) */, - 0x6F /* 'o' */, 0x7B, 0x00 /* (to 0x008A state 34) */, - 0x0D /* '.' */, 0x80, 0x00 /* (to 0x0092 state 41) */, - 0x61 /* 'a' */, 0x8F, 0x00 /* (to 0x00A4 state 57) */, - 0x69 /* 'i' */, 0xC1, 0x00 /* (to 0x00D9 state 88) */, - 0x64 /* 'd' */, 0x50, 0x01 /* (to 0x016B state 177) */, - 0x72 /* 'r' */, 0x53, 0x01 /* (to 0x0171 state 182) */, - 0x65 /* 'e' */, 0xAF, 0x01 /* (to 0x01D0 state 256) */, - 0x66 /* 'f' */, 0xCB, 0x01 /* (to 0x01EF state 272) */, - 0x6C /* 'l' */, 0xEE, 0x01 /* (to 0x0215 state 306) */, - 0x6D /* 'm' */, 0x11, 0x02 /* (to 0x023B state 332) */, - 0x73 /* 's' */, 0x27, 0x02 /* (to 0x0254 state 355) */, - 0x78 /* 'x' */, 0x6C, 0x02 /* (to 0x029C state 410) */, - 0x74 /* 't' */, 0x81, 0x02 /* (to 0x02B4 state 431) */, - 0x08, /* fail */ -/* pos 0037: 1 */ 0xE5 /* 'e' -> */, -/* pos 0038: 2 */ 0xF4 /* 't' -> */, -/* pos 0039: 3 */ 0xA0 /* ' ' -> */, -/* pos 003a: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, -/* pos 003c: 5 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x0043 state 6) */, - 0x72 /* 'r' */, 0xD2, 0x00 /* (to 0x0111 state 123) */, - 0x08, /* fail */ -/* pos 0043: 6 */ 0xF3 /* 's' -> */, -/* pos 0044: 7 */ 0xF4 /* 't' -> */, -/* pos 0045: 8 */ 0xA0 /* ' ' -> */, -/* pos 0046: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, -/* pos 0048: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0052 state 11) */, - 0x74 /* 't' */, 0x4A, 0x00 /* (to 0x0095 state 43) */, - 0x65 /* 'e' */, 0x61, 0x02 /* (to 0x02AF state 427) */, - 0x08, /* fail */ -/* pos 0052: 11 */ 0xF3 /* 's' -> */, -/* pos 0053: 12 */ 0xF4 /* 't' -> */, -/* pos 0054: 13 */ 0xBA /* ':' -> */, -/* pos 0055: 14 */ 0x00, 0x02 /* - terminal marker 2 - */, -/* pos 0057: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x005E state 16) */, - 0x61 /* 'a' */, 0xC4, 0x00 /* (to 0x011E state 129) */, - 0x08, /* fail */ -/* pos 005e: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0065 state 17) */, - 0x6F /* 'o' */, 0xD9, 0x00 /* (to 0x013A state 155) */, - 0x08, /* fail */ -/* pos 0065: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x006C state 18) */, - 0x74 /* 't' */, 0xD8, 0x00 /* (to 0x0140 state 160) */, - 0x08, /* fail */ -/* pos 006c: 18 */ 0xE5 /* 'e' -> */, -/* pos 006d: 19 */ 0xE3 /* 'c' -> */, -/* pos 006e: 20 */ 0xF4 /* 't' -> */, -/* pos 006f: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0076 state 22) */, - 0x20 /* ' ' */, 0x3B, 0x02 /* (to 0x02AD state 426) */, - 0x08, /* fail */ -/* pos 0076: 22 */ 0xEF /* 'o' -> */, -/* pos 0077: 23 */ 0xEE /* 'n' -> */, -/* pos 0078: 24 */ 0xBA /* ':' -> */, -/* pos 0079: 25 */ 0x00, 0x03 /* - terminal marker 3 - */, -/* pos 007b: 26 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x0082 state 27) */, - 0x73 /* 's' */, 0x0E, 0x02 /* (to 0x028C state 396) */, - 0x08, /* fail */ -/* pos 0082: 27 */ 0xE7 /* 'g' -> */, -/* pos 0083: 28 */ 0xF2 /* 'r' -> */, -/* pos 0084: 29 */ 0xE1 /* 'a' -> */, -/* pos 0085: 30 */ 0xE4 /* 'd' -> */, -/* pos 0086: 31 */ 0xE5 /* 'e' -> */, -/* pos 0087: 32 */ 0xBA /* ':' -> */, -/* pos 0088: 33 */ 0x00, 0x04 /* - terminal marker 4 - */, -/* pos 008a: 34 */ 0xF2 /* 'r' -> */, -/* pos 008b: 35 */ 0xE9 /* 'i' -> */, -/* pos 008c: 36 */ 0xE7 /* 'g' -> */, -/* pos 008d: 37 */ 0xE9 /* 'i' -> */, -/* pos 008e: 38 */ 0xEE /* 'n' -> */, -/* pos 008f: 39 */ 0xBA /* ':' -> */, -/* pos 0090: 40 */ 0x00, 0x05 /* - terminal marker 5 - */, -/* pos 0092: 41 */ 0x8A /* '.' -> */, -/* pos 0093: 42 */ 0x00, 0x06 /* - terminal marker 6 - */, -/* pos 0095: 43 */ 0xF4 /* 't' -> */, -/* pos 0096: 44 */ 0xF0 /* 'p' -> */, -/* pos 0097: 45 */ 0xB2 /* '2' -> */, -/* pos 0098: 46 */ 0xAD /* '-' -> */, -/* pos 0099: 47 */ 0xF3 /* 's' -> */, -/* pos 009a: 48 */ 0xE5 /* 'e' -> */, -/* pos 009b: 49 */ 0xF4 /* 't' -> */, -/* pos 009c: 50 */ 0xF4 /* 't' -> */, -/* pos 009d: 51 */ 0xE9 /* 'i' -> */, -/* pos 009e: 52 */ 0xEE /* 'n' -> */, -/* pos 009f: 53 */ 0xE7 /* 'g' -> */, -/* pos 00a0: 54 */ 0xF3 /* 's' -> */, -/* pos 00a1: 55 */ 0xBA /* ':' -> */, -/* pos 00a2: 56 */ 0x00, 0x07 /* - terminal marker 7 - */, -/* pos 00a4: 57 */ 0x63 /* 'c' */, 0x0A, 0x00 /* (to 0x00AE state 58) */, - 0x75 /* 'u' */, 0x85, 0x00 /* (to 0x012C state 142) */, - 0x6C /* 'l' */, 0xF0, 0x00 /* (to 0x019A state 208) */, - 0x08, /* fail */ -/* pos 00ae: 58 */ 0xE3 /* 'c' -> */, -/* pos 00af: 59 */ 0xE5 /* 'e' -> */, -/* pos 00b0: 60 */ 0x73 /* 's' */, 0x07, 0x00 /* (to 0x00B7 state 61) */, - 0x70 /* 'p' */, 0x41, 0x00 /* (to 0x00F4 state 102) */, - 0x08, /* fail */ -/* pos 00b7: 61 */ 0xF3 /* 's' -> */, -/* pos 00b8: 62 */ 0xAD /* '-' -> */, -/* pos 00b9: 63 */ 0xE3 /* 'c' -> */, -/* pos 00ba: 64 */ 0xEF /* 'o' -> */, -/* pos 00bb: 65 */ 0xEE /* 'n' -> */, -/* pos 00bc: 66 */ 0xF4 /* 't' -> */, -/* pos 00bd: 67 */ 0xF2 /* 'r' -> */, -/* pos 00be: 68 */ 0xEF /* 'o' -> */, -/* pos 00bf: 69 */ 0xEC /* 'l' -> */, -/* pos 00c0: 70 */ 0xAD /* '-' -> */, -/* pos 00c1: 71 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00C8 state 72) */, - 0x61 /* 'a' */, 0xC8, 0x00 /* (to 0x018C state 195) */, - 0x08, /* fail */ -/* pos 00c8: 72 */ 0xE5 /* 'e' -> */, -/* pos 00c9: 73 */ 0xF1 /* 'q' -> */, -/* pos 00ca: 74 */ 0xF5 /* 'u' -> */, -/* pos 00cb: 75 */ 0xE5 /* 'e' -> */, -/* pos 00cc: 76 */ 0xF3 /* 's' -> */, -/* pos 00cd: 77 */ 0xF4 /* 't' -> */, -/* pos 00ce: 78 */ 0xAD /* '-' -> */, -/* pos 00cf: 79 */ 0xE8 /* 'h' -> */, -/* pos 00d0: 80 */ 0xE5 /* 'e' -> */, -/* pos 00d1: 81 */ 0xE1 /* 'a' -> */, -/* pos 00d2: 82 */ 0xE4 /* 'd' -> */, -/* pos 00d3: 83 */ 0xE5 /* 'e' -> */, -/* pos 00d4: 84 */ 0xF2 /* 'r' -> */, -/* pos 00d5: 85 */ 0xF3 /* 's' -> */, -/* pos 00d6: 86 */ 0xBA /* ':' -> */, -/* pos 00d7: 87 */ 0x00, 0x08 /* - terminal marker 8 - */, -/* pos 00d9: 88 */ 0xE6 /* 'f' -> */, -/* pos 00da: 89 */ 0xAD /* '-' -> */, -/* pos 00db: 90 */ 0x6E /* 'n' */, 0x0D, 0x00 /* (to 0x00E8 state 91) */, - 0x6D /* 'm' */, 0x17, 0x01 /* (to 0x01F5 state 277) */, - 0x72 /* 'r' */, 0x1B, 0x01 /* (to 0x01FC state 283) */, - 0x75 /* 'u' */, 0x1F, 0x01 /* (to 0x0203 state 289) */, - 0x08, /* fail */ -/* pos 00e8: 91 */ 0xEF /* 'o' -> */, -/* pos 00e9: 92 */ 0xEE /* 'n' -> */, -/* pos 00ea: 93 */ 0xE5 /* 'e' -> */, -/* pos 00eb: 94 */ 0xAD /* '-' -> */, -/* pos 00ec: 95 */ 0xED /* 'm' -> */, -/* pos 00ed: 96 */ 0xE1 /* 'a' -> */, -/* pos 00ee: 97 */ 0xF4 /* 't' -> */, -/* pos 00ef: 98 */ 0xE3 /* 'c' -> */, -/* pos 00f0: 99 */ 0xE8 /* 'h' -> */, -/* pos 00f1: 100 */ 0xBA /* ':' -> */, -/* pos 00f2: 101 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 00f4: 102 */ 0xF4 /* 't' -> */, -/* pos 00f5: 103 */ 0xAD /* '-' -> */, -/* pos 00f6: 104 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x00FD state 105) */, - 0x6C /* 'l' */, 0x0E, 0x00 /* (to 0x0107 state 114) */, - 0x08, /* fail */ -/* pos 00fd: 105 */ 0xEE /* 'n' -> */, -/* pos 00fe: 106 */ 0xE3 /* 'c' -> */, -/* pos 00ff: 107 */ 0xEF /* 'o' -> */, -/* pos 0100: 108 */ 0xE4 /* 'd' -> */, -/* pos 0101: 109 */ 0xE9 /* 'i' -> */, -/* pos 0102: 110 */ 0xEE /* 'n' -> */, -/* pos 0103: 111 */ 0xE7 /* 'g' -> */, -/* pos 0104: 112 */ 0xBA /* ':' -> */, -/* pos 0105: 113 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 0107: 114 */ 0xE1 /* 'a' -> */, -/* pos 0108: 115 */ 0xEE /* 'n' -> */, -/* pos 0109: 116 */ 0xE7 /* 'g' -> */, -/* pos 010a: 117 */ 0xF5 /* 'u' -> */, -/* pos 010b: 118 */ 0xE1 /* 'a' -> */, -/* pos 010c: 119 */ 0xE7 /* 'g' -> */, -/* pos 010d: 120 */ 0xE5 /* 'e' -> */, -/* pos 010e: 121 */ 0xBA /* ':' -> */, -/* pos 010f: 122 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 0111: 123 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0118 state 124) */, - 0x6F /* 'o' */, 0x83, 0x01 /* (to 0x0297 state 406) */, - 0x08, /* fail */ -/* pos 0118: 124 */ 0xE7 /* 'g' -> */, -/* pos 0119: 125 */ 0xED /* 'm' -> */, -/* pos 011a: 126 */ 0xE1 /* 'a' -> */, -/* pos 011b: 127 */ 0xBA /* ':' -> */, -/* pos 011c: 128 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 011e: 129 */ 0xE3 /* 'c' -> */, -/* pos 011f: 130 */ 0xE8 /* 'h' -> */, -/* pos 0120: 131 */ 0xE5 /* 'e' -> */, -/* pos 0121: 132 */ 0xAD /* '-' -> */, -/* pos 0122: 133 */ 0xE3 /* 'c' -> */, -/* pos 0123: 134 */ 0xEF /* 'o' -> */, -/* pos 0124: 135 */ 0xEE /* 'n' -> */, -/* pos 0125: 136 */ 0xF4 /* 't' -> */, -/* pos 0126: 137 */ 0xF2 /* 'r' -> */, -/* pos 0127: 138 */ 0xEF /* 'o' -> */, -/* pos 0128: 139 */ 0xEC /* 'l' -> */, -/* pos 0129: 140 */ 0xBA /* ':' -> */, -/* pos 012a: 141 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 012c: 142 */ 0xF4 /* 't' -> */, -/* pos 012d: 143 */ 0xE8 /* 'h' -> */, -/* pos 012e: 144 */ 0xEF /* 'o' -> */, -/* pos 012f: 145 */ 0xF2 /* 'r' -> */, -/* pos 0130: 146 */ 0xE9 /* 'i' -> */, -/* pos 0131: 147 */ 0xFA /* 'z' -> */, -/* pos 0132: 148 */ 0xE1 /* 'a' -> */, -/* pos 0133: 149 */ 0xF4 /* 't' -> */, -/* pos 0134: 150 */ 0xE9 /* 'i' -> */, -/* pos 0135: 151 */ 0xEF /* 'o' -> */, -/* pos 0136: 152 */ 0xEE /* 'n' -> */, -/* pos 0137: 153 */ 0xBA /* ':' -> */, -/* pos 0138: 154 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 013a: 155 */ 0xEB /* 'k' -> */, -/* pos 013b: 156 */ 0xE9 /* 'i' -> */, -/* pos 013c: 157 */ 0xE5 /* 'e' -> */, -/* pos 013d: 158 */ 0xBA /* ':' -> */, -/* pos 013e: 159 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 0140: 160 */ 0xE5 /* 'e' -> */, -/* pos 0141: 161 */ 0xEE /* 'n' -> */, -/* pos 0142: 162 */ 0xF4 /* 't' -> */, -/* pos 0143: 163 */ 0xAD /* '-' -> */, -/* pos 0144: 164 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0154 state 165) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0165 state 172) */, - 0x64 /* 'd' */, 0x56, 0x00 /* (to 0x01A0 state 213) */, - 0x65 /* 'e' */, 0x60, 0x00 /* (to 0x01AD state 225) */, - 0x72 /* 'r' */, 0x79, 0x00 /* (to 0x01C9 state 250) */, - 0x08, /* fail */ -/* pos 0154: 165 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x015E state 166) */, - 0x61 /* 'a' */, 0x60, 0x00 /* (to 0x01B7 state 234) */, - 0x6F /* 'o' */, 0x66, 0x00 /* (to 0x01C0 state 242) */, - 0x08, /* fail */ -/* pos 015e: 166 */ 0xEE /* 'n' -> */, -/* pos 015f: 167 */ 0xE7 /* 'g' -> */, -/* pos 0160: 168 */ 0xF4 /* 't' -> */, -/* pos 0161: 169 */ 0xE8 /* 'h' -> */, -/* pos 0162: 170 */ 0xBA /* ':' -> */, -/* pos 0163: 171 */ 0x00, 0x10 /* - terminal marker 16 - */, -/* pos 0165: 172 */ 0xF9 /* 'y' -> */, -/* pos 0166: 173 */ 0xF0 /* 'p' -> */, -/* pos 0167: 174 */ 0xE5 /* 'e' -> */, -/* pos 0168: 175 */ 0xBA /* ':' -> */, -/* pos 0169: 176 */ 0x00, 0x11 /* - terminal marker 17 - */, -/* pos 016b: 177 */ 0xE1 /* 'a' -> */, -/* pos 016c: 178 */ 0xF4 /* 't' -> */, -/* pos 016d: 179 */ 0xE5 /* 'e' -> */, -/* pos 016e: 180 */ 0xBA /* ':' -> */, -/* pos 016f: 181 */ 0x00, 0x12 /* - terminal marker 18 - */, -/* pos 0171: 182 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0178 state 183) */, - 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x017E state 188) */, - 0x08, /* fail */ -/* pos 0178: 183 */ 0xEE /* 'n' -> */, -/* pos 0179: 184 */ 0xE7 /* 'g' -> */, -/* pos 017a: 185 */ 0xE5 /* 'e' -> */, -/* pos 017b: 186 */ 0xBA /* ':' -> */, -/* pos 017c: 187 */ 0x00, 0x13 /* - terminal marker 19 - */, -/* pos 017e: 188 */ 0x66 /* 'f' */, 0x07, 0x00 /* (to 0x0185 state 189) */, - 0x74 /* 't' */, 0xC8, 0x00 /* (to 0x0249 state 345) */, - 0x08, /* fail */ -/* pos 0185: 189 */ 0xE5 /* 'e' -> */, -/* pos 0186: 190 */ 0xF2 /* 'r' -> */, -/* pos 0187: 191 */ 0xE5 /* 'e' -> */, -/* pos 0188: 192 */ 0xF2 /* 'r' -> */, -/* pos 0189: 193 */ 0xBA /* ':' -> */, -/* pos 018a: 194 */ 0x00, 0x14 /* - terminal marker 20 - */, -/* pos 018c: 195 */ 0xEC /* 'l' -> */, -/* pos 018d: 196 */ 0xEC /* 'l' -> */, -/* pos 018e: 197 */ 0xEF /* 'o' -> */, -/* pos 018f: 198 */ 0xF7 /* 'w' -> */, -/* pos 0190: 199 */ 0xAD /* '-' -> */, -/* pos 0191: 200 */ 0xEF /* 'o' -> */, -/* pos 0192: 201 */ 0xF2 /* 'r' -> */, -/* pos 0193: 202 */ 0xE9 /* 'i' -> */, -/* pos 0194: 203 */ 0xE7 /* 'g' -> */, -/* pos 0195: 204 */ 0xE9 /* 'i' -> */, -/* pos 0196: 205 */ 0xEE /* 'n' -> */, -/* pos 0197: 206 */ 0xBA /* ':' -> */, -/* pos 0198: 207 */ 0x00, 0x15 /* - terminal marker 21 - */, -/* pos 019a: 208 */ 0xEC /* 'l' -> */, -/* pos 019b: 209 */ 0xEF /* 'o' -> */, -/* pos 019c: 210 */ 0xF7 /* 'w' -> */, -/* pos 019d: 211 */ 0xBA /* ':' -> */, -/* pos 019e: 212 */ 0x00, 0x16 /* - terminal marker 22 - */, -/* pos 01a0: 213 */ 0xE9 /* 'i' -> */, -/* pos 01a1: 214 */ 0xF3 /* 's' -> */, -/* pos 01a2: 215 */ 0xF0 /* 'p' -> */, -/* pos 01a3: 216 */ 0xEF /* 'o' -> */, -/* pos 01a4: 217 */ 0xF3 /* 's' -> */, -/* pos 01a5: 218 */ 0xE9 /* 'i' -> */, -/* pos 01a6: 219 */ 0xF4 /* 't' -> */, -/* pos 01a7: 220 */ 0xE9 /* 'i' -> */, -/* pos 01a8: 221 */ 0xEF /* 'o' -> */, -/* pos 01a9: 222 */ 0xEE /* 'n' -> */, -/* pos 01aa: 223 */ 0xBA /* ':' -> */, -/* pos 01ab: 224 */ 0x00, 0x17 /* - terminal marker 23 - */, -/* pos 01ad: 225 */ 0xEE /* 'n' -> */, -/* pos 01ae: 226 */ 0xE3 /* 'c' -> */, -/* pos 01af: 227 */ 0xEF /* 'o' -> */, -/* pos 01b0: 228 */ 0xE4 /* 'd' -> */, -/* pos 01b1: 229 */ 0xE9 /* 'i' -> */, -/* pos 01b2: 230 */ 0xEE /* 'n' -> */, -/* pos 01b3: 231 */ 0xE7 /* 'g' -> */, -/* pos 01b4: 232 */ 0xBA /* ':' -> */, -/* pos 01b5: 233 */ 0x00, 0x18 /* - terminal marker 24 - */, -/* pos 01b7: 234 */ 0xEE /* 'n' -> */, -/* pos 01b8: 235 */ 0xE7 /* 'g' -> */, -/* pos 01b9: 236 */ 0xF5 /* 'u' -> */, -/* pos 01ba: 237 */ 0xE1 /* 'a' -> */, -/* pos 01bb: 238 */ 0xE7 /* 'g' -> */, -/* pos 01bc: 239 */ 0xE5 /* 'e' -> */, -/* pos 01bd: 240 */ 0xBA /* ':' -> */, -/* pos 01be: 241 */ 0x00, 0x19 /* - terminal marker 25 - */, -/* pos 01c0: 242 */ 0xE3 /* 'c' -> */, -/* pos 01c1: 243 */ 0xE1 /* 'a' -> */, -/* pos 01c2: 244 */ 0xF4 /* 't' -> */, -/* pos 01c3: 245 */ 0xE9 /* 'i' -> */, -/* pos 01c4: 246 */ 0xEF /* 'o' -> */, -/* pos 01c5: 247 */ 0xEE /* 'n' -> */, -/* pos 01c6: 248 */ 0xBA /* ':' -> */, -/* pos 01c7: 249 */ 0x00, 0x1A /* - terminal marker 26 - */, -/* pos 01c9: 250 */ 0xE1 /* 'a' -> */, -/* pos 01ca: 251 */ 0xEE /* 'n' -> */, -/* pos 01cb: 252 */ 0xE7 /* 'g' -> */, -/* pos 01cc: 253 */ 0xE5 /* 'e' -> */, -/* pos 01cd: 254 */ 0xBA /* ':' -> */, -/* pos 01ce: 255 */ 0x00, 0x1B /* - terminal marker 27 - */, -/* pos 01d0: 256 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x01D7 state 257) */, - 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x01DC state 261) */, - 0x08, /* fail */ -/* pos 01d7: 257 */ 0xE1 /* 'a' -> */, -/* pos 01d8: 258 */ 0xE7 /* 'g' -> */, -/* pos 01d9: 259 */ 0xBA /* ':' -> */, -/* pos 01da: 260 */ 0x00, 0x1C /* - terminal marker 28 - */, -/* pos 01dc: 261 */ 0xF0 /* 'p' -> */, -/* pos 01dd: 262 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01E4 state 263) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x01E9 state 267) */, - 0x08, /* fail */ -/* pos 01e4: 263 */ 0xE3 /* 'c' -> */, -/* pos 01e5: 264 */ 0xF4 /* 't' -> */, -/* pos 01e6: 265 */ 0xBA /* ':' -> */, -/* pos 01e7: 266 */ 0x00, 0x1D /* - terminal marker 29 - */, -/* pos 01e9: 267 */ 0xF2 /* 'r' -> */, -/* pos 01ea: 268 */ 0xE5 /* 'e' -> */, -/* pos 01eb: 269 */ 0xF3 /* 's' -> */, -/* pos 01ec: 270 */ 0xBA /* ':' -> */, -/* pos 01ed: 271 */ 0x00, 0x1E /* - terminal marker 30 - */, -/* pos 01ef: 272 */ 0xF2 /* 'r' -> */, -/* pos 01f0: 273 */ 0xEF /* 'o' -> */, -/* pos 01f1: 274 */ 0xED /* 'm' -> */, -/* pos 01f2: 275 */ 0xBA /* ':' -> */, -/* pos 01f3: 276 */ 0x00, 0x1F /* - terminal marker 31 - */, -/* pos 01f5: 277 */ 0xE1 /* 'a' -> */, -/* pos 01f6: 278 */ 0xF4 /* 't' -> */, -/* pos 01f7: 279 */ 0xE3 /* 'c' -> */, -/* pos 01f8: 280 */ 0xE8 /* 'h' -> */, -/* pos 01f9: 281 */ 0xBA /* ':' -> */, -/* pos 01fa: 282 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 01fc: 283 */ 0xE1 /* 'a' -> */, -/* pos 01fd: 284 */ 0xEE /* 'n' -> */, -/* pos 01fe: 285 */ 0xE7 /* 'g' -> */, -/* pos 01ff: 286 */ 0xE5 /* 'e' -> */, -/* pos 0200: 287 */ 0xBA /* ':' -> */, -/* pos 0201: 288 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 0203: 289 */ 0xEE /* 'n' -> */, -/* pos 0204: 290 */ 0xED /* 'm' -> */, -/* pos 0205: 291 */ 0xEF /* 'o' -> */, -/* pos 0206: 292 */ 0xE4 /* 'd' -> */, -/* pos 0207: 293 */ 0xE9 /* 'i' -> */, -/* pos 0208: 294 */ 0xE6 /* 'f' -> */, -/* pos 0209: 295 */ 0xE9 /* 'i' -> */, -/* pos 020a: 296 */ 0xE5 /* 'e' -> */, -/* pos 020b: 297 */ 0xE4 /* 'd' -> */, -/* pos 020c: 298 */ 0xAD /* '-' -> */, -/* pos 020d: 299 */ 0xF3 /* 's' -> */, -/* pos 020e: 300 */ 0xE9 /* 'i' -> */, -/* pos 020f: 301 */ 0xEE /* 'n' -> */, -/* pos 0210: 302 */ 0xE3 /* 'c' -> */, -/* pos 0211: 303 */ 0xE5 /* 'e' -> */, -/* pos 0212: 304 */ 0xBA /* ':' -> */, -/* pos 0213: 305 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* pos 0215: 306 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x021F state 307) */, - 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x022D state 320) */, - 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0232 state 324) */, - 0x08, /* fail */ -/* pos 021f: 307 */ 0xF3 /* 's' -> */, -/* pos 0220: 308 */ 0xF4 /* 't' -> */, -/* pos 0221: 309 */ 0xAD /* '-' -> */, -/* pos 0222: 310 */ 0xED /* 'm' -> */, -/* pos 0223: 311 */ 0xEF /* 'o' -> */, -/* pos 0224: 312 */ 0xE4 /* 'd' -> */, -/* pos 0225: 313 */ 0xE9 /* 'i' -> */, -/* pos 0226: 314 */ 0xE6 /* 'f' -> */, -/* pos 0227: 315 */ 0xE9 /* 'i' -> */, -/* pos 0228: 316 */ 0xE5 /* 'e' -> */, -/* pos 0229: 317 */ 0xE4 /* 'd' -> */, -/* pos 022a: 318 */ 0xBA /* ':' -> */, -/* pos 022b: 319 */ 0x00, 0x23 /* - terminal marker 35 - */, -/* pos 022d: 320 */ 0xEE /* 'n' -> */, -/* pos 022e: 321 */ 0xEB /* 'k' -> */, -/* pos 022f: 322 */ 0xBA /* ':' -> */, -/* pos 0230: 323 */ 0x00, 0x24 /* - terminal marker 36 - */, -/* pos 0232: 324 */ 0xE3 /* 'c' -> */, -/* pos 0233: 325 */ 0xE1 /* 'a' -> */, -/* pos 0234: 326 */ 0xF4 /* 't' -> */, -/* pos 0235: 327 */ 0xE9 /* 'i' -> */, -/* pos 0236: 328 */ 0xEF /* 'o' -> */, -/* pos 0237: 329 */ 0xEE /* 'n' -> */, -/* pos 0238: 330 */ 0xBA /* ':' -> */, -/* pos 0239: 331 */ 0x00, 0x25 /* - terminal marker 37 - */, -/* pos 023b: 332 */ 0xE1 /* 'a' -> */, -/* pos 023c: 333 */ 0xF8 /* 'x' -> */, -/* pos 023d: 334 */ 0xAD /* '-' -> */, -/* pos 023e: 335 */ 0xE6 /* 'f' -> */, -/* pos 023f: 336 */ 0xEF /* 'o' -> */, -/* pos 0240: 337 */ 0xF2 /* 'r' -> */, -/* pos 0241: 338 */ 0xF7 /* 'w' -> */, -/* pos 0242: 339 */ 0xE1 /* 'a' -> */, -/* pos 0243: 340 */ 0xF2 /* 'r' -> */, -/* pos 0244: 341 */ 0xE4 /* 'd' -> */, -/* pos 0245: 342 */ 0xF3 /* 's' -> */, -/* pos 0246: 343 */ 0xBA /* ':' -> */, -/* pos 0247: 344 */ 0x00, 0x26 /* - terminal marker 38 - */, -/* pos 0249: 345 */ 0xF2 /* 'r' -> */, -/* pos 024a: 346 */ 0xF9 /* 'y' -> */, -/* pos 024b: 347 */ 0xAD /* '-' -> */, -/* pos 024c: 348 */ 0xE1 /* 'a' -> */, -/* pos 024d: 349 */ 0xE6 /* 'f' -> */, -/* pos 024e: 350 */ 0xF4 /* 't' -> */, -/* pos 024f: 351 */ 0xE5 /* 'e' -> */, -/* pos 0250: 352 */ 0xF2 /* 'r' -> */, -/* pos 0251: 353 */ 0xBA /* ':' -> */, -/* pos 0252: 354 */ 0x00, 0x27 /* - terminal marker 39 - */, -/* pos 0254: 355 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x025B state 356) */, - 0x74 /* 't' */, 0x1B, 0x00 /* (to 0x0272 state 371) */, - 0x08, /* fail */ -/* pos 025b: 356 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0262 state 357) */, - 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x0268 state 362) */, - 0x08, /* fail */ -/* pos 0262: 357 */ 0xF6 /* 'v' -> */, -/* pos 0263: 358 */ 0xE5 /* 'e' -> */, -/* pos 0264: 359 */ 0xF2 /* 'r' -> */, -/* pos 0265: 360 */ 0xBA /* ':' -> */, -/* pos 0266: 361 */ 0x00, 0x28 /* - terminal marker 40 - */, -/* pos 0268: 362 */ 0xAD /* '-' -> */, -/* pos 0269: 363 */ 0xE3 /* 'c' -> */, -/* pos 026a: 364 */ 0xEF /* 'o' -> */, -/* pos 026b: 365 */ 0xEF /* 'o' -> */, -/* pos 026c: 366 */ 0xEB /* 'k' -> */, -/* pos 026d: 367 */ 0xE9 /* 'i' -> */, -/* pos 026e: 368 */ 0xE5 /* 'e' -> */, -/* pos 026f: 369 */ 0xBA /* ':' -> */, -/* pos 0270: 370 */ 0x00, 0x29 /* - terminal marker 41 - */, -/* pos 0272: 371 */ 0xF2 /* 'r' -> */, -/* pos 0273: 372 */ 0xE9 /* 'i' -> */, -/* pos 0274: 373 */ 0xE3 /* 'c' -> */, -/* pos 0275: 374 */ 0xF4 /* 't' -> */, -/* pos 0276: 375 */ 0xAD /* '-' -> */, -/* pos 0277: 376 */ 0xF4 /* 't' -> */, -/* pos 0278: 377 */ 0xF2 /* 'r' -> */, -/* pos 0279: 378 */ 0xE1 /* 'a' -> */, -/* pos 027a: 379 */ 0xEE /* 'n' -> */, -/* pos 027b: 380 */ 0xF3 /* 's' -> */, -/* pos 027c: 381 */ 0xF0 /* 'p' -> */, -/* pos 027d: 382 */ 0xEF /* 'o' -> */, -/* pos 027e: 383 */ 0xF2 /* 'r' -> */, -/* pos 027f: 384 */ 0xF4 /* 't' -> */, -/* pos 0280: 385 */ 0xAD /* '-' -> */, -/* pos 0281: 386 */ 0xF3 /* 's' -> */, -/* pos 0282: 387 */ 0xE5 /* 'e' -> */, -/* pos 0283: 388 */ 0xE3 /* 'c' -> */, -/* pos 0284: 389 */ 0xF5 /* 'u' -> */, -/* pos 0285: 390 */ 0xF2 /* 'r' -> */, -/* pos 0286: 391 */ 0xE9 /* 'i' -> */, -/* pos 0287: 392 */ 0xF4 /* 't' -> */, -/* pos 0288: 393 */ 0xF9 /* 'y' -> */, -/* pos 0289: 394 */ 0xBA /* ':' -> */, -/* pos 028a: 395 */ 0x00, 0x2A /* - terminal marker 42 - */, -/* pos 028c: 396 */ 0xE5 /* 'e' -> */, -/* pos 028d: 397 */ 0xF2 /* 'r' -> */, -/* pos 028e: 398 */ 0xAD /* '-' -> */, -/* pos 028f: 399 */ 0xE1 /* 'a' -> */, -/* pos 0290: 400 */ 0xE7 /* 'g' -> */, -/* pos 0291: 401 */ 0xE5 /* 'e' -> */, -/* pos 0292: 402 */ 0xEE /* 'n' -> */, -/* pos 0293: 403 */ 0xF4 /* 't' -> */, -/* pos 0294: 404 */ 0xBA /* ':' -> */, -/* pos 0295: 405 */ 0x00, 0x2B /* - terminal marker 43 - */, -/* pos 0297: 406 */ 0xF8 /* 'x' -> */, -/* pos 0298: 407 */ 0xF9 /* 'y' -> */, -/* pos 0299: 408 */ 0xA0 /* ' ' -> */, -/* pos 029a: 409 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 029c: 410 */ 0xAD /* '-' -> */, -/* pos 029d: 411 */ 0xE6 /* 'f' -> */, -/* pos 029e: 412 */ 0xEF /* 'o' -> */, -/* pos 029f: 413 */ 0xF2 /* 'r' -> */, -/* pos 02a0: 414 */ 0xF7 /* 'w' -> */, -/* pos 02a1: 415 */ 0xE1 /* 'a' -> */, -/* pos 02a2: 416 */ 0xF2 /* 'r' -> */, -/* pos 02a3: 417 */ 0xE4 /* 'd' -> */, -/* pos 02a4: 418 */ 0xE5 /* 'e' -> */, -/* pos 02a5: 419 */ 0xE4 /* 'd' -> */, -/* pos 02a6: 420 */ 0xAD /* '-' -> */, -/* pos 02a7: 421 */ 0xE6 /* 'f' -> */, -/* pos 02a8: 422 */ 0xEF /* 'o' -> */, -/* pos 02a9: 423 */ 0xF2 /* 'r' -> */, -/* pos 02aa: 424 */ 0xBA /* ':' -> */, -/* pos 02ab: 425 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 02ad: 426 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 02af: 427 */ 0xE1 /* 'a' -> */, -/* pos 02b0: 428 */ 0xE4 /* 'd' -> */, -/* pos 02b1: 429 */ 0xA0 /* ' ' -> */, -/* pos 02b2: 430 */ 0x00, 0x2F /* - terminal marker 47 - */, -/* pos 02b4: 431 */ 0xE5 /* 'e' -> */, -/* pos 02b5: 432 */ 0xBA /* ':' -> */, -/* pos 02b6: 433 */ 0x00, 0x30 /* - terminal marker 48 - */, -/* total size 696 bytes */ + /* 7: 15: http/1.1 */ + /* 8: 17: accept: */ + /* 9: 19: if-modified-since: */ + /* 10: 20: if-none-match: */ + /* 11: 21: accept-encoding: */ + /* 12: 22: accept-language: */ + /* 13: 23: pragma: */ + /* 14: 24: cache-control: */ + /* 15: 25: authorization: */ + /* 16: 26: cookie: */ + /* 17: 27: content-length: */ + /* 18: 28: content-type: */ + /* 19: 29: date: */ + /* 20: 30: range: */ + /* 21: 41: accept-ranges: */ + /* 22: 43: age: */ + /* 23: 44: allow: */ + /* 24: 45: content-disposition: */ + /* 25: 46: content-encoding: */ + /* 26: 47: content-language: */ + /* 27: 48: content-location: */ + /* 28: 49: content-range: */ + /* 29: 50: etag: */ + /* 30: 51: expect: */ + /* 31: 52: expires: */ + /* 32: 53: from: */ + /* 33: 54: if-match: */ + /* 34: 55: if-range: */ + /* 35: 56: if-unmodified-since: */ + /* 36: 57: last-modified: */ + /* 37: 58: link: */ + /* 38: 59: location: */ + /* 39: 63: refresh: */ + /* 40: 64: retry-after: */ + /* 41: 65: server: */ + /* 42: 66: set-cookie: */ + /* 43: 68: transfer-encoding: */ + /* 44: 76: uri-args */ + /* 45: 79: http/1.0 */ + /* 46: 80: x-forwarded-for: */ + /* 47: 81: connect */ + /* 48: 82: head */ + /* 49: 86: x-auth-token: */ + /* 50: 87: */ +/* pos 0000: 0 */ 0x67 /* 'g' */, 0x34, 0x00 /* (to 0x0034 state 1) */, + 0x70 /* 'p' */, 0x36, 0x00 /* (to 0x0039 state 5) */, + 0x68 /* 'h' */, 0x3F, 0x00 /* (to 0x0045 state 10) */, + 0x63 /* 'c' */, 0x4B, 0x00 /* (to 0x0054 state 15) */, + 0x75 /* 'u' */, 0x6C, 0x00 /* (to 0x0078 state 26) */, + 0x6F /* 'o' */, 0x78, 0x00 /* (to 0x0087 state 34) */, + 0x0D /* '.' */, 0x7D, 0x00 /* (to 0x008F state 41) */, + 0x61 /* 'a' */, 0x8C, 0x00 /* (to 0x00A1 state 51) */, + 0x69 /* 'i' */, 0xA3, 0x00 /* (to 0x00BB state 58) */, + 0x64 /* 'd' */, 0x43, 0x01 /* (to 0x015E state 160) */, + 0x72 /* 'r' */, 0x46, 0x01 /* (to 0x0164 state 165) */, + 0x65 /* 'e' */, 0x92, 0x01 /* (to 0x01B3 state 229) */, + 0x66 /* 'f' */, 0xAE, 0x01 /* (to 0x01D2 state 245) */, + 0x6C /* 'l' */, 0xD0, 0x01 /* (to 0x01F7 state 278) */, + 0x73 /* 's' */, 0x0C, 0x02 /* (to 0x0236 state 321) */, + 0x74 /* 't' */, 0x21, 0x02 /* (to 0x024E state 337) */, + 0x78 /* 'x' */, 0x3C, 0x02 /* (to 0x026C state 364) */, + 0x08, /* fail */ +/* pos 0034: 1 */ 0xE5 /* 'e' -> */, +/* pos 0035: 2 */ 0xF4 /* 't' -> */, +/* pos 0036: 3 */ 0xA0 /* ' ' -> */, +/* pos 0037: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, +/* pos 0039: 5 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x0040 state 6) */, + 0x72 /* 'r' */, 0xCE, 0x00 /* (to 0x010A state 106) */, + 0x08, /* fail */ +/* pos 0040: 6 */ 0xF3 /* 's' -> */, +/* pos 0041: 7 */ 0xF4 /* 't' -> */, +/* pos 0042: 8 */ 0xA0 /* ' ' -> */, +/* pos 0043: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, +/* pos 0045: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x004F state 11) */, + 0x74 /* 't' */, 0x4A, 0x00 /* (to 0x0092 state 43) */, + 0x65 /* 'e' */, 0x3A, 0x02 /* (to 0x0285 state 381) */, + 0x08, /* fail */ +/* pos 004f: 11 */ 0xF3 /* 's' -> */, +/* pos 0050: 12 */ 0xF4 /* 't' -> */, +/* pos 0051: 13 */ 0xBA /* ':' -> */, +/* pos 0052: 14 */ 0x00, 0x02 /* - terminal marker 2 - */, +/* pos 0054: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x005B state 16) */, + 0x61 /* 'a' */, 0xBA, 0x00 /* (to 0x0111 state 112) */, + 0x08, /* fail */ +/* pos 005b: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0062 state 17) */, + 0x6F /* 'o' */, 0xCF, 0x00 /* (to 0x012D state 138) */, + 0x08, /* fail */ +/* pos 0062: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0069 state 18) */, + 0x74 /* 't' */, 0xCE, 0x00 /* (to 0x0133 state 143) */, + 0x08, /* fail */ +/* pos 0069: 18 */ 0xE5 /* 'e' -> */, +/* pos 006a: 19 */ 0xE3 /* 'c' -> */, +/* pos 006b: 20 */ 0xF4 /* 't' -> */, +/* pos 006c: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0073 state 22) */, + 0x20 /* ' ' */, 0x14, 0x02 /* (to 0x0283 state 380) */, + 0x08, /* fail */ +/* pos 0073: 22 */ 0xEF /* 'o' -> */, +/* pos 0074: 23 */ 0xEE /* 'n' -> */, +/* pos 0075: 24 */ 0xBA /* ':' -> */, +/* pos 0076: 25 */ 0x00, 0x03 /* - terminal marker 3 - */, +/* pos 0078: 26 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x007F state 27) */, + 0x72 /* 'r' */, 0xE6, 0x01 /* (to 0x0261 state 355) */, + 0x08, /* fail */ +/* pos 007f: 27 */ 0xE7 /* 'g' -> */, +/* pos 0080: 28 */ 0xF2 /* 'r' -> */, +/* pos 0081: 29 */ 0xE1 /* 'a' -> */, +/* pos 0082: 30 */ 0xE4 /* 'd' -> */, +/* pos 0083: 31 */ 0xE5 /* 'e' -> */, +/* pos 0084: 32 */ 0xBA /* ':' -> */, +/* pos 0085: 33 */ 0x00, 0x04 /* - terminal marker 4 - */, +/* pos 0087: 34 */ 0xF2 /* 'r' -> */, +/* pos 0088: 35 */ 0xE9 /* 'i' -> */, +/* pos 0089: 36 */ 0xE7 /* 'g' -> */, +/* pos 008a: 37 */ 0xE9 /* 'i' -> */, +/* pos 008b: 38 */ 0xEE /* 'n' -> */, +/* pos 008c: 39 */ 0xBA /* ':' -> */, +/* pos 008d: 40 */ 0x00, 0x05 /* - terminal marker 5 - */, +/* pos 008f: 41 */ 0x8A /* '.' -> */, +/* pos 0090: 42 */ 0x00, 0x06 /* - terminal marker 6 - */, +/* pos 0092: 43 */ 0xF4 /* 't' -> */, +/* pos 0093: 44 */ 0xF0 /* 'p' -> */, +/* pos 0094: 45 */ 0xAF /* '/' -> */, +/* pos 0095: 46 */ 0xB1 /* '1' -> */, +/* pos 0096: 47 */ 0xAE /* '.' -> */, +/* pos 0097: 48 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x009E state 49) */, + 0x30 /* '0' */, 0xCF, 0x01 /* (to 0x0269 state 362) */, + 0x08, /* fail */ +/* pos 009e: 49 */ 0xA0 /* ' ' -> */, +/* pos 009f: 50 */ 0x00, 0x07 /* - terminal marker 7 - */, +/* pos 00a1: 51 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00AE state 52) */, + 0x75 /* 'u' */, 0x7B, 0x00 /* (to 0x011F state 125) */, + 0x67 /* 'g' */, 0xD2, 0x00 /* (to 0x0179 state 178) */, + 0x6C /* 'l' */, 0xD3, 0x00 /* (to 0x017D state 181) */, + 0x08, /* fail */ +/* pos 00ae: 52 */ 0xE3 /* 'c' -> */, +/* pos 00af: 53 */ 0xE5 /* 'e' -> */, +/* pos 00b0: 54 */ 0xF0 /* 'p' -> */, +/* pos 00b1: 55 */ 0xF4 /* 't' -> */, +/* pos 00b2: 56 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x00B9 state 57) */, + 0x2D /* '-' */, 0x37, 0x00 /* (to 0x00EC state 87) */, + 0x08, /* fail */ +/* pos 00b9: 57 */ 0x00, 0x08 /* - terminal marker 8 - */, +/* pos 00bb: 58 */ 0xE6 /* 'f' -> */, +/* pos 00bc: 59 */ 0xAD /* '-' -> */, +/* pos 00bd: 60 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x00CA state 61) */, + 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x00E0 state 76) */, + 0x72 /* 'r' */, 0x1B, 0x01 /* (to 0x01DE state 255) */, + 0x75 /* 'u' */, 0x1F, 0x01 /* (to 0x01E5 state 261) */, + 0x08, /* fail */ +/* pos 00ca: 61 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x00D1 state 62) */, + 0x61 /* 'a' */, 0x0B, 0x01 /* (to 0x01D8 state 250) */, + 0x08, /* fail */ +/* pos 00d1: 62 */ 0xE4 /* 'd' -> */, +/* pos 00d2: 63 */ 0xE9 /* 'i' -> */, +/* pos 00d3: 64 */ 0xE6 /* 'f' -> */, +/* pos 00d4: 65 */ 0xE9 /* 'i' -> */, +/* pos 00d5: 66 */ 0xE5 /* 'e' -> */, +/* pos 00d6: 67 */ 0xE4 /* 'd' -> */, +/* pos 00d7: 68 */ 0xAD /* '-' -> */, +/* pos 00d8: 69 */ 0xF3 /* 's' -> */, +/* pos 00d9: 70 */ 0xE9 /* 'i' -> */, +/* pos 00da: 71 */ 0xEE /* 'n' -> */, +/* pos 00db: 72 */ 0xE3 /* 'c' -> */, +/* pos 00dc: 73 */ 0xE5 /* 'e' -> */, +/* pos 00dd: 74 */ 0xBA /* ':' -> */, +/* pos 00de: 75 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 00e0: 76 */ 0xEF /* 'o' -> */, +/* pos 00e1: 77 */ 0xEE /* 'n' -> */, +/* pos 00e2: 78 */ 0xE5 /* 'e' -> */, +/* pos 00e3: 79 */ 0xAD /* '-' -> */, +/* pos 00e4: 80 */ 0xED /* 'm' -> */, +/* pos 00e5: 81 */ 0xE1 /* 'a' -> */, +/* pos 00e6: 82 */ 0xF4 /* 't' -> */, +/* pos 00e7: 83 */ 0xE3 /* 'c' -> */, +/* pos 00e8: 84 */ 0xE8 /* 'h' -> */, +/* pos 00e9: 85 */ 0xBA /* ':' -> */, +/* pos 00ea: 86 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 00ec: 87 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x00F6 state 88) */, + 0x6C /* 'l' */, 0x11, 0x00 /* (to 0x0100 state 97) */, + 0x72 /* 'r' */, 0x7F, 0x00 /* (to 0x0171 state 171) */, + 0x08, /* fail */ +/* pos 00f6: 88 */ 0xEE /* 'n' -> */, +/* pos 00f7: 89 */ 0xE3 /* 'c' -> */, +/* pos 00f8: 90 */ 0xEF /* 'o' -> */, +/* pos 00f9: 91 */ 0xE4 /* 'd' -> */, +/* pos 00fa: 92 */ 0xE9 /* 'i' -> */, +/* pos 00fb: 93 */ 0xEE /* 'n' -> */, +/* pos 00fc: 94 */ 0xE7 /* 'g' -> */, +/* pos 00fd: 95 */ 0xBA /* ':' -> */, +/* pos 00fe: 96 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 0100: 97 */ 0xE1 /* 'a' -> */, +/* pos 0101: 98 */ 0xEE /* 'n' -> */, +/* pos 0102: 99 */ 0xE7 /* 'g' -> */, +/* pos 0103: 100 */ 0xF5 /* 'u' -> */, +/* pos 0104: 101 */ 0xE1 /* 'a' -> */, +/* pos 0105: 102 */ 0xE7 /* 'g' -> */, +/* pos 0106: 103 */ 0xE5 /* 'e' -> */, +/* pos 0107: 104 */ 0xBA /* ':' -> */, +/* pos 0108: 105 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 010a: 106 */ 0xE1 /* 'a' -> */, +/* pos 010b: 107 */ 0xE7 /* 'g' -> */, +/* pos 010c: 108 */ 0xED /* 'm' -> */, +/* pos 010d: 109 */ 0xE1 /* 'a' -> */, +/* pos 010e: 110 */ 0xBA /* ':' -> */, +/* pos 010f: 111 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 0111: 112 */ 0xE3 /* 'c' -> */, +/* pos 0112: 113 */ 0xE8 /* 'h' -> */, +/* pos 0113: 114 */ 0xE5 /* 'e' -> */, +/* pos 0114: 115 */ 0xAD /* '-' -> */, +/* pos 0115: 116 */ 0xE3 /* 'c' -> */, +/* pos 0116: 117 */ 0xEF /* 'o' -> */, +/* pos 0117: 118 */ 0xEE /* 'n' -> */, +/* pos 0118: 119 */ 0xF4 /* 't' -> */, +/* pos 0119: 120 */ 0xF2 /* 'r' -> */, +/* pos 011a: 121 */ 0xEF /* 'o' -> */, +/* pos 011b: 122 */ 0xEC /* 'l' -> */, +/* pos 011c: 123 */ 0xBA /* ':' -> */, +/* pos 011d: 124 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 011f: 125 */ 0xF4 /* 't' -> */, +/* pos 0120: 126 */ 0xE8 /* 'h' -> */, +/* pos 0121: 127 */ 0xEF /* 'o' -> */, +/* pos 0122: 128 */ 0xF2 /* 'r' -> */, +/* pos 0123: 129 */ 0xE9 /* 'i' -> */, +/* pos 0124: 130 */ 0xFA /* 'z' -> */, +/* pos 0125: 131 */ 0xE1 /* 'a' -> */, +/* pos 0126: 132 */ 0xF4 /* 't' -> */, +/* pos 0127: 133 */ 0xE9 /* 'i' -> */, +/* pos 0128: 134 */ 0xEF /* 'o' -> */, +/* pos 0129: 135 */ 0xEE /* 'n' -> */, +/* pos 012a: 136 */ 0xBA /* ':' -> */, +/* pos 012b: 137 */ 0x00, 0x0F /* - terminal marker 15 - */, +/* pos 012d: 138 */ 0xEB /* 'k' -> */, +/* pos 012e: 139 */ 0xE9 /* 'i' -> */, +/* pos 012f: 140 */ 0xE5 /* 'e' -> */, +/* pos 0130: 141 */ 0xBA /* ':' -> */, +/* pos 0131: 142 */ 0x00, 0x10 /* - terminal marker 16 - */, +/* pos 0133: 143 */ 0xE5 /* 'e' -> */, +/* pos 0134: 144 */ 0xEE /* 'n' -> */, +/* pos 0135: 145 */ 0xF4 /* 't' -> */, +/* pos 0136: 146 */ 0xAD /* '-' -> */, +/* pos 0137: 147 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0147 state 148) */, + 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0158 state 155) */, + 0x64 /* 'd' */, 0x46, 0x00 /* (to 0x0183 state 186) */, + 0x65 /* 'e' */, 0x50, 0x00 /* (to 0x0190 state 198) */, + 0x72 /* 'r' */, 0x69, 0x00 /* (to 0x01AC state 223) */, + 0x08, /* fail */ +/* pos 0147: 148 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0151 state 149) */, + 0x61 /* 'a' */, 0x50, 0x00 /* (to 0x019A state 207) */, + 0x6F /* 'o' */, 0x56, 0x00 /* (to 0x01A3 state 215) */, + 0x08, /* fail */ +/* pos 0151: 149 */ 0xEE /* 'n' -> */, +/* pos 0152: 150 */ 0xE7 /* 'g' -> */, +/* pos 0153: 151 */ 0xF4 /* 't' -> */, +/* pos 0154: 152 */ 0xE8 /* 'h' -> */, +/* pos 0155: 153 */ 0xBA /* ':' -> */, +/* pos 0156: 154 */ 0x00, 0x11 /* - terminal marker 17 - */, +/* pos 0158: 155 */ 0xF9 /* 'y' -> */, +/* pos 0159: 156 */ 0xF0 /* 'p' -> */, +/* pos 015a: 157 */ 0xE5 /* 'e' -> */, +/* pos 015b: 158 */ 0xBA /* ':' -> */, +/* pos 015c: 159 */ 0x00, 0x12 /* - terminal marker 18 - */, +/* pos 015e: 160 */ 0xE1 /* 'a' -> */, +/* pos 015f: 161 */ 0xF4 /* 't' -> */, +/* pos 0160: 162 */ 0xE5 /* 'e' -> */, +/* pos 0161: 163 */ 0xBA /* ':' -> */, +/* pos 0162: 164 */ 0x00, 0x13 /* - terminal marker 19 - */, +/* pos 0164: 165 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x016B state 166) */, + 0x65 /* 'e' */, 0xB6, 0x00 /* (to 0x021D state 304) */, + 0x08, /* fail */ +/* pos 016b: 166 */ 0xEE /* 'n' -> */, +/* pos 016c: 167 */ 0xE7 /* 'g' -> */, +/* pos 016d: 168 */ 0xE5 /* 'e' -> */, +/* pos 016e: 169 */ 0xBA /* ':' -> */, +/* pos 016f: 170 */ 0x00, 0x14 /* - terminal marker 20 - */, +/* pos 0171: 171 */ 0xE1 /* 'a' -> */, +/* pos 0172: 172 */ 0xEE /* 'n' -> */, +/* pos 0173: 173 */ 0xE7 /* 'g' -> */, +/* pos 0174: 174 */ 0xE5 /* 'e' -> */, +/* pos 0175: 175 */ 0xF3 /* 's' -> */, +/* pos 0176: 176 */ 0xBA /* ':' -> */, +/* pos 0177: 177 */ 0x00, 0x15 /* - terminal marker 21 - */, +/* pos 0179: 178 */ 0xE5 /* 'e' -> */, +/* pos 017a: 179 */ 0xBA /* ':' -> */, +/* pos 017b: 180 */ 0x00, 0x16 /* - terminal marker 22 - */, +/* pos 017d: 181 */ 0xEC /* 'l' -> */, +/* pos 017e: 182 */ 0xEF /* 'o' -> */, +/* pos 017f: 183 */ 0xF7 /* 'w' -> */, +/* pos 0180: 184 */ 0xBA /* ':' -> */, +/* pos 0181: 185 */ 0x00, 0x17 /* - terminal marker 23 - */, +/* pos 0183: 186 */ 0xE9 /* 'i' -> */, +/* pos 0184: 187 */ 0xF3 /* 's' -> */, +/* pos 0185: 188 */ 0xF0 /* 'p' -> */, +/* pos 0186: 189 */ 0xEF /* 'o' -> */, +/* pos 0187: 190 */ 0xF3 /* 's' -> */, +/* pos 0188: 191 */ 0xE9 /* 'i' -> */, +/* pos 0189: 192 */ 0xF4 /* 't' -> */, +/* pos 018a: 193 */ 0xE9 /* 'i' -> */, +/* pos 018b: 194 */ 0xEF /* 'o' -> */, +/* pos 018c: 195 */ 0xEE /* 'n' -> */, +/* pos 018d: 196 */ 0xBA /* ':' -> */, +/* pos 018e: 197 */ 0x00, 0x18 /* - terminal marker 24 - */, +/* pos 0190: 198 */ 0xEE /* 'n' -> */, +/* pos 0191: 199 */ 0xE3 /* 'c' -> */, +/* pos 0192: 200 */ 0xEF /* 'o' -> */, +/* pos 0193: 201 */ 0xE4 /* 'd' -> */, +/* pos 0194: 202 */ 0xE9 /* 'i' -> */, +/* pos 0195: 203 */ 0xEE /* 'n' -> */, +/* pos 0196: 204 */ 0xE7 /* 'g' -> */, +/* pos 0197: 205 */ 0xBA /* ':' -> */, +/* pos 0198: 206 */ 0x00, 0x19 /* - terminal marker 25 - */, +/* pos 019a: 207 */ 0xEE /* 'n' -> */, +/* pos 019b: 208 */ 0xE7 /* 'g' -> */, +/* pos 019c: 209 */ 0xF5 /* 'u' -> */, +/* pos 019d: 210 */ 0xE1 /* 'a' -> */, +/* pos 019e: 211 */ 0xE7 /* 'g' -> */, +/* pos 019f: 212 */ 0xE5 /* 'e' -> */, +/* pos 01a0: 213 */ 0xBA /* ':' -> */, +/* pos 01a1: 214 */ 0x00, 0x1A /* - terminal marker 26 - */, +/* pos 01a3: 215 */ 0xE3 /* 'c' -> */, +/* pos 01a4: 216 */ 0xE1 /* 'a' -> */, +/* pos 01a5: 217 */ 0xF4 /* 't' -> */, +/* pos 01a6: 218 */ 0xE9 /* 'i' -> */, +/* pos 01a7: 219 */ 0xEF /* 'o' -> */, +/* pos 01a8: 220 */ 0xEE /* 'n' -> */, +/* pos 01a9: 221 */ 0xBA /* ':' -> */, +/* pos 01aa: 222 */ 0x00, 0x1B /* - terminal marker 27 - */, +/* pos 01ac: 223 */ 0xE1 /* 'a' -> */, +/* pos 01ad: 224 */ 0xEE /* 'n' -> */, +/* pos 01ae: 225 */ 0xE7 /* 'g' -> */, +/* pos 01af: 226 */ 0xE5 /* 'e' -> */, +/* pos 01b0: 227 */ 0xBA /* ':' -> */, +/* pos 01b1: 228 */ 0x00, 0x1C /* - terminal marker 28 - */, +/* pos 01b3: 229 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x01BA state 230) */, + 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x01BF state 234) */, + 0x08, /* fail */ +/* pos 01ba: 230 */ 0xE1 /* 'a' -> */, +/* pos 01bb: 231 */ 0xE7 /* 'g' -> */, +/* pos 01bc: 232 */ 0xBA /* ':' -> */, +/* pos 01bd: 233 */ 0x00, 0x1D /* - terminal marker 29 - */, +/* pos 01bf: 234 */ 0xF0 /* 'p' -> */, +/* pos 01c0: 235 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01C7 state 236) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x01CC state 240) */, + 0x08, /* fail */ +/* pos 01c7: 236 */ 0xE3 /* 'c' -> */, +/* pos 01c8: 237 */ 0xF4 /* 't' -> */, +/* pos 01c9: 238 */ 0xBA /* ':' -> */, +/* pos 01ca: 239 */ 0x00, 0x1E /* - terminal marker 30 - */, +/* pos 01cc: 240 */ 0xF2 /* 'r' -> */, +/* pos 01cd: 241 */ 0xE5 /* 'e' -> */, +/* pos 01ce: 242 */ 0xF3 /* 's' -> */, +/* pos 01cf: 243 */ 0xBA /* ':' -> */, +/* pos 01d0: 244 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 01d2: 245 */ 0xF2 /* 'r' -> */, +/* pos 01d3: 246 */ 0xEF /* 'o' -> */, +/* pos 01d4: 247 */ 0xED /* 'm' -> */, +/* pos 01d5: 248 */ 0xBA /* ':' -> */, +/* pos 01d6: 249 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 01d8: 250 */ 0xF4 /* 't' -> */, +/* pos 01d9: 251 */ 0xE3 /* 'c' -> */, +/* pos 01da: 252 */ 0xE8 /* 'h' -> */, +/* pos 01db: 253 */ 0xBA /* ':' -> */, +/* pos 01dc: 254 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* pos 01de: 255 */ 0xE1 /* 'a' -> */, +/* pos 01df: 256 */ 0xEE /* 'n' -> */, +/* pos 01e0: 257 */ 0xE7 /* 'g' -> */, +/* pos 01e1: 258 */ 0xE5 /* 'e' -> */, +/* pos 01e2: 259 */ 0xBA /* ':' -> */, +/* pos 01e3: 260 */ 0x00, 0x22 /* - terminal marker 34 - */, +/* pos 01e5: 261 */ 0xEE /* 'n' -> */, +/* pos 01e6: 262 */ 0xED /* 'm' -> */, +/* pos 01e7: 263 */ 0xEF /* 'o' -> */, +/* pos 01e8: 264 */ 0xE4 /* 'd' -> */, +/* pos 01e9: 265 */ 0xE9 /* 'i' -> */, +/* pos 01ea: 266 */ 0xE6 /* 'f' -> */, +/* pos 01eb: 267 */ 0xE9 /* 'i' -> */, +/* pos 01ec: 268 */ 0xE5 /* 'e' -> */, +/* pos 01ed: 269 */ 0xE4 /* 'd' -> */, +/* pos 01ee: 270 */ 0xAD /* '-' -> */, +/* pos 01ef: 271 */ 0xF3 /* 's' -> */, +/* pos 01f0: 272 */ 0xE9 /* 'i' -> */, +/* pos 01f1: 273 */ 0xEE /* 'n' -> */, +/* pos 01f2: 274 */ 0xE3 /* 'c' -> */, +/* pos 01f3: 275 */ 0xE5 /* 'e' -> */, +/* pos 01f4: 276 */ 0xBA /* ':' -> */, +/* pos 01f5: 277 */ 0x00, 0x23 /* - terminal marker 35 - */, +/* pos 01f7: 278 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0201 state 279) */, + 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x020F state 292) */, + 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0214 state 296) */, + 0x08, /* fail */ +/* pos 0201: 279 */ 0xF3 /* 's' -> */, +/* pos 0202: 280 */ 0xF4 /* 't' -> */, +/* pos 0203: 281 */ 0xAD /* '-' -> */, +/* pos 0204: 282 */ 0xED /* 'm' -> */, +/* pos 0205: 283 */ 0xEF /* 'o' -> */, +/* pos 0206: 284 */ 0xE4 /* 'd' -> */, +/* pos 0207: 285 */ 0xE9 /* 'i' -> */, +/* pos 0208: 286 */ 0xE6 /* 'f' -> */, +/* pos 0209: 287 */ 0xE9 /* 'i' -> */, +/* pos 020a: 288 */ 0xE5 /* 'e' -> */, +/* pos 020b: 289 */ 0xE4 /* 'd' -> */, +/* pos 020c: 290 */ 0xBA /* ':' -> */, +/* pos 020d: 291 */ 0x00, 0x24 /* - terminal marker 36 - */, +/* pos 020f: 292 */ 0xEE /* 'n' -> */, +/* pos 0210: 293 */ 0xEB /* 'k' -> */, +/* pos 0211: 294 */ 0xBA /* ':' -> */, +/* pos 0212: 295 */ 0x00, 0x25 /* - terminal marker 37 - */, +/* pos 0214: 296 */ 0xE3 /* 'c' -> */, +/* pos 0215: 297 */ 0xE1 /* 'a' -> */, +/* pos 0216: 298 */ 0xF4 /* 't' -> */, +/* pos 0217: 299 */ 0xE9 /* 'i' -> */, +/* pos 0218: 300 */ 0xEF /* 'o' -> */, +/* pos 0219: 301 */ 0xEE /* 'n' -> */, +/* pos 021a: 302 */ 0xBA /* ':' -> */, +/* pos 021b: 303 */ 0x00, 0x26 /* - terminal marker 38 - */, +/* pos 021d: 304 */ 0x66 /* 'f' */, 0x07, 0x00 /* (to 0x0224 state 305) */, + 0x74 /* 't' */, 0x0B, 0x00 /* (to 0x022B state 311) */, + 0x08, /* fail */ +/* pos 0224: 305 */ 0xF2 /* 'r' -> */, +/* pos 0225: 306 */ 0xE5 /* 'e' -> */, +/* pos 0226: 307 */ 0xF3 /* 's' -> */, +/* pos 0227: 308 */ 0xE8 /* 'h' -> */, +/* pos 0228: 309 */ 0xBA /* ':' -> */, +/* pos 0229: 310 */ 0x00, 0x27 /* - terminal marker 39 - */, +/* pos 022b: 311 */ 0xF2 /* 'r' -> */, +/* pos 022c: 312 */ 0xF9 /* 'y' -> */, +/* pos 022d: 313 */ 0xAD /* '-' -> */, +/* pos 022e: 314 */ 0xE1 /* 'a' -> */, +/* pos 022f: 315 */ 0xE6 /* 'f' -> */, +/* pos 0230: 316 */ 0xF4 /* 't' -> */, +/* pos 0231: 317 */ 0xE5 /* 'e' -> */, +/* pos 0232: 318 */ 0xF2 /* 'r' -> */, +/* pos 0233: 319 */ 0xBA /* ':' -> */, +/* pos 0234: 320 */ 0x00, 0x28 /* - terminal marker 40 - */, +/* pos 0236: 321 */ 0xE5 /* 'e' -> */, +/* pos 0237: 322 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x023E state 323) */, + 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x0244 state 328) */, + 0x08, /* fail */ +/* pos 023e: 323 */ 0xF6 /* 'v' -> */, +/* pos 023f: 324 */ 0xE5 /* 'e' -> */, +/* pos 0240: 325 */ 0xF2 /* 'r' -> */, +/* pos 0241: 326 */ 0xBA /* ':' -> */, +/* pos 0242: 327 */ 0x00, 0x29 /* - terminal marker 41 - */, +/* pos 0244: 328 */ 0xAD /* '-' -> */, +/* pos 0245: 329 */ 0xE3 /* 'c' -> */, +/* pos 0246: 330 */ 0xEF /* 'o' -> */, +/* pos 0247: 331 */ 0xEF /* 'o' -> */, +/* pos 0248: 332 */ 0xEB /* 'k' -> */, +/* pos 0249: 333 */ 0xE9 /* 'i' -> */, +/* pos 024a: 334 */ 0xE5 /* 'e' -> */, +/* pos 024b: 335 */ 0xBA /* ':' -> */, +/* pos 024c: 336 */ 0x00, 0x2A /* - terminal marker 42 - */, +/* pos 024e: 337 */ 0xF2 /* 'r' -> */, +/* pos 024f: 338 */ 0xE1 /* 'a' -> */, +/* pos 0250: 339 */ 0xEE /* 'n' -> */, +/* pos 0251: 340 */ 0xF3 /* 's' -> */, +/* pos 0252: 341 */ 0xE6 /* 'f' -> */, +/* pos 0253: 342 */ 0xE5 /* 'e' -> */, +/* pos 0254: 343 */ 0xF2 /* 'r' -> */, +/* pos 0255: 344 */ 0xAD /* '-' -> */, +/* pos 0256: 345 */ 0xE5 /* 'e' -> */, +/* pos 0257: 346 */ 0xEE /* 'n' -> */, +/* pos 0258: 347 */ 0xE3 /* 'c' -> */, +/* pos 0259: 348 */ 0xEF /* 'o' -> */, +/* pos 025a: 349 */ 0xE4 /* 'd' -> */, +/* pos 025b: 350 */ 0xE9 /* 'i' -> */, +/* pos 025c: 351 */ 0xEE /* 'n' -> */, +/* pos 025d: 352 */ 0xE7 /* 'g' -> */, +/* pos 025e: 353 */ 0xBA /* ':' -> */, +/* pos 025f: 354 */ 0x00, 0x2B /* - terminal marker 43 - */, +/* pos 0261: 355 */ 0xE9 /* 'i' -> */, +/* pos 0262: 356 */ 0xAD /* '-' -> */, +/* pos 0263: 357 */ 0xE1 /* 'a' -> */, +/* pos 0264: 358 */ 0xF2 /* 'r' -> */, +/* pos 0265: 359 */ 0xE7 /* 'g' -> */, +/* pos 0266: 360 */ 0xF3 /* 's' -> */, +/* pos 0267: 361 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 0269: 362 */ 0xA0 /* ' ' -> */, +/* pos 026a: 363 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 026c: 364 */ 0xAD /* '-' -> */, +/* pos 026d: 365 */ 0x66 /* 'f' */, 0x07, 0x00 /* (to 0x0274 state 366) */, + 0x61 /* 'a' */, 0x1A, 0x00 /* (to 0x028A state 385) */, + 0x08, /* fail */ +/* pos 0274: 366 */ 0xEF /* 'o' -> */, +/* pos 0275: 367 */ 0xF2 /* 'r' -> */, +/* pos 0276: 368 */ 0xF7 /* 'w' -> */, +/* pos 0277: 369 */ 0xE1 /* 'a' -> */, +/* pos 0278: 370 */ 0xF2 /* 'r' -> */, +/* pos 0279: 371 */ 0xE4 /* 'd' -> */, +/* pos 027a: 372 */ 0xE5 /* 'e' -> */, +/* pos 027b: 373 */ 0xE4 /* 'd' -> */, +/* pos 027c: 374 */ 0xAD /* '-' -> */, +/* pos 027d: 375 */ 0xE6 /* 'f' -> */, +/* pos 027e: 376 */ 0xEF /* 'o' -> */, +/* pos 027f: 377 */ 0xF2 /* 'r' -> */, +/* pos 0280: 378 */ 0xBA /* ':' -> */, +/* pos 0281: 379 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 0283: 380 */ 0x00, 0x2F /* - terminal marker 47 - */, +/* pos 0285: 381 */ 0xE1 /* 'a' -> */, +/* pos 0286: 382 */ 0xE4 /* 'd' -> */, +/* pos 0287: 383 */ 0xA0 /* ' ' -> */, +/* pos 0288: 384 */ 0x00, 0x30 /* - terminal marker 48 - */, +/* pos 028a: 385 */ 0xF5 /* 'u' -> */, +/* pos 028b: 386 */ 0xF4 /* 't' -> */, +/* pos 028c: 387 */ 0xE8 /* 'h' -> */, +/* pos 028d: 388 */ 0xAD /* '-' -> */, +/* pos 028e: 389 */ 0xF4 /* 't' -> */, +/* pos 028f: 390 */ 0xEF /* 'o' -> */, +/* pos 0290: 391 */ 0xEB /* 'k' -> */, +/* pos 0291: 392 */ 0xE5 /* 'e' -> */, +/* pos 0292: 393 */ 0xEE /* 'n' -> */, +/* pos 0293: 394 */ 0xBA /* ':' -> */, +/* pos 0294: 395 */ 0x00, 0x31 /* - terminal marker 49 - */, +/* total size 662 bytes */ #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) @@ -568,773 +532,762 @@ /* 6: 6: origin: */ /* 7: 8: */ - /* 8: 16: http2-settings: */ - /* 9: 18: access-control-request-headers: */ - /* 10: 19: if-modified-since: */ - /* 11: 20: if-none-match: */ - /* 12: 21: accept-encoding: */ - /* 13: 22: accept-language: */ - /* 14: 23: pragma: */ - /* 15: 24: cache-control: */ - /* 16: 25: authorization: */ - /* 17: 26: cookie: */ - /* 18: 27: content-length: */ - /* 19: 28: content-type: */ - /* 20: 29: date: */ - /* 21: 30: range: */ - /* 22: 31: referer: */ - /* 23: 32: sec-websocket-key: */ - /* 24: 41: accept-ranges: */ - /* 25: 42: access-control-allow-origin: */ - /* 26: 43: age: */ - /* 27: 44: allow: */ - /* 28: 45: content-disposition: */ - /* 29: 46: content-encoding: */ - /* 30: 47: content-language: */ - /* 31: 48: content-location: */ - /* 32: 49: content-range: */ - /* 33: 50: etag: */ - /* 34: 51: expect: */ - /* 35: 52: expires: */ - /* 36: 53: from: */ - /* 37: 54: if-match: */ - /* 38: 55: if-range: */ - /* 39: 56: if-unmodified-since: */ - /* 40: 57: last-modified: */ - /* 41: 58: link: */ - /* 42: 59: location: */ - /* 43: 60: max-forwards: */ - /* 44: 61: proxy-authenticate: */ - /* 45: 62: proxy-authorization: */ - /* 46: 63: refresh: */ - /* 47: 64: retry-after: */ - /* 48: 65: server: */ - /* 49: 66: set-cookie: */ - /* 50: 67: strict-transport-security: */ - /* 51: 68: transfer-encoding: */ - /* 52: 69: user-agent: */ - /* 53: 70: vary: */ - /* 54: 71: via: */ - /* 55: 72: www-authenticate: */ - /* 56: 73: patch */ - /* 57: 74: put */ - /* 58: 75: delete */ - /* 59: 76: uri-args */ - /* 60: 77: proxy */ - /* 61: 78: x-real-ip: */ - /* 62: 79: http/1.0 */ - /* 63: 80: x-forwarded-for: */ - /* 64: 81: connect */ - /* 65: 82: head */ - /* 66: 83: te: */ - /* 67: 84: replay-nonce: */ - /* 68: 85: :protocol */ - /* 69: 87: */ -/* pos 0000: 0 */ 0x67 /* 'g' */, 0x40, 0x00 /* (to 0x0040 state 1) */, - 0x70 /* 'p' */, 0x42, 0x00 /* (to 0x0045 state 5) */, - 0x68 /* 'h' */, 0x51, 0x00 /* (to 0x0057 state 10) */, - 0x63 /* 'c' */, 0x5D, 0x00 /* (to 0x0066 state 15) */, - 0x75 /* 'u' */, 0x7E, 0x00 /* (to 0x008A state 26) */, - 0x6F /* 'o' */, 0x8D, 0x00 /* (to 0x009C state 34) */, - 0x0D /* '.' */, 0x98, 0x00 /* (to 0x00AA state 41) */, - 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 57) */, - 0x69 /* 'i' */, 0xE2, 0x00 /* (to 0x00FA state 88) */, - 0x64 /* 'd' */, 0x74, 0x01 /* (to 0x018F state 177) */, - 0x72 /* 'r' */, 0x7D, 0x01 /* (to 0x019B state 182) */, - 0x65 /* 'e' */, 0xE2, 0x01 /* (to 0x0203 state 256) */, - 0x66 /* 'f' */, 0xFE, 0x01 /* (to 0x0222 state 272) */, - 0x6C /* 'l' */, 0x27, 0x02 /* (to 0x024E state 306) */, - 0x6D /* 'm' */, 0x4A, 0x02 /* (to 0x0274 state 332) */, - 0x73 /* 's' */, 0x60, 0x02 /* (to 0x028D state 355) */, - 0x78 /* 'x' */, 0xAE, 0x02 /* (to 0x02DE state 410) */, - 0x74 /* 't' */, 0xC9, 0x02 /* (to 0x02FC state 431) */, - 0x76 /* 'v' */, 0x3C, 0x03 /* (to 0x0372 state 527) */, - 0x77 /* 'w' */, 0x49, 0x03 /* (to 0x0382 state 535) */, - 0x3A /* ':' */, 0x89, 0x03 /* (to 0x03C5 state 594) */, - 0x08, /* fail */ -/* pos 0040: 1 */ 0xE5 /* 'e' -> */, -/* pos 0041: 2 */ 0xF4 /* 't' -> */, -/* pos 0042: 3 */ 0xA0 /* ' ' -> */, -/* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, -/* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */, - 0x72 /* 'r' */, 0xED, 0x00 /* (to 0x0135 state 123) */, - 0x61 /* 'a' */, 0x49, 0x03 /* (to 0x0394 state 552) */, - 0x75 /* 'u' */, 0x4B, 0x03 /* (to 0x0399 state 556) */, - 0x08, /* fail */ -/* pos 0052: 6 */ 0xF3 /* 's' -> */, -/* pos 0053: 7 */ 0xF4 /* 't' -> */, -/* pos 0054: 8 */ 0xA0 /* ' ' -> */, -/* pos 0055: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, -/* pos 0057: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0061 state 11) */, - 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AD state 43) */, - 0x65 /* 'e' */, 0x9A, 0x02 /* (to 0x02F7 state 427) */, - 0x08, /* fail */ -/* pos 0061: 11 */ 0xF3 /* 's' -> */, -/* pos 0062: 12 */ 0xF4 /* 't' -> */, -/* pos 0063: 13 */ 0xBA /* ':' -> */, -/* pos 0064: 14 */ 0x00, 0x03 /* - terminal marker 3 - */, -/* pos 0066: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006D state 16) */, - 0x61 /* 'a' */, 0xD9, 0x00 /* (to 0x0142 state 129) */, - 0x08, /* fail */ -/* pos 006d: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0074 state 17) */, - 0x6F /* 'o' */, 0xEE, 0x00 /* (to 0x015E state 155) */, - 0x08, /* fail */ -/* pos 0074: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x007B state 18) */, - 0x74 /* 't' */, 0xED, 0x00 /* (to 0x0164 state 160) */, - 0x08, /* fail */ -/* pos 007b: 18 */ 0xE5 /* 'e' -> */, -/* pos 007c: 19 */ 0xE3 /* 'c' -> */, -/* pos 007d: 20 */ 0xF4 /* 't' -> */, -/* pos 007e: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0085 state 22) */, - 0x20 /* ' ' */, 0x74, 0x02 /* (to 0x02F5 state 426) */, - 0x08, /* fail */ -/* pos 0085: 22 */ 0xEF /* 'o' -> */, -/* pos 0086: 23 */ 0xEE /* 'n' -> */, -/* pos 0087: 24 */ 0xBA /* ':' -> */, -/* pos 0088: 25 */ 0x00, 0x04 /* - terminal marker 4 - */, -/* pos 008a: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0094 state 27) */, - 0x73 /* 's' */, 0x3B, 0x02 /* (to 0x02C8 state 396) */, - 0x72 /* 'r' */, 0x12, 0x03 /* (to 0x03A2 state 563) */, - 0x08, /* fail */ -/* pos 0094: 27 */ 0xE7 /* 'g' -> */, -/* pos 0095: 28 */ 0xF2 /* 'r' -> */, -/* pos 0096: 29 */ 0xE1 /* 'a' -> */, -/* pos 0097: 30 */ 0xE4 /* 'd' -> */, -/* pos 0098: 31 */ 0xE5 /* 'e' -> */, -/* pos 0099: 32 */ 0xBA /* ':' -> */, -/* pos 009a: 33 */ 0x00, 0x05 /* - terminal marker 5 - */, -/* pos 009c: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A3 state 35) */, - 0x70 /* 'p' */, 0x67, 0x02 /* (to 0x0306 state 434) */, - 0x08, /* fail */ -/* pos 00a3: 35 */ 0xE9 /* 'i' -> */, -/* pos 00a4: 36 */ 0xE7 /* 'g' -> */, -/* pos 00a5: 37 */ 0xE9 /* 'i' -> */, -/* pos 00a6: 38 */ 0xEE /* 'n' -> */, -/* pos 00a7: 39 */ 0xBA /* ':' -> */, -/* pos 00a8: 40 */ 0x00, 0x06 /* - terminal marker 6 - */, -/* pos 00aa: 41 */ 0x8A /* '.' -> */, -/* pos 00ab: 42 */ 0x00, 0x07 /* - terminal marker 7 - */, -/* pos 00ad: 43 */ 0xF4 /* 't' -> */, -/* pos 00ae: 44 */ 0xF0 /* 'p' -> */, -/* pos 00af: 45 */ 0x32 /* '2' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, - 0x2F /* '/' */, 0x01, 0x03 /* (to 0x03B3 state 578) */, - 0x08, /* fail */ -/* pos 00b6: 46 */ 0xAD /* '-' -> */, -/* pos 00b7: 47 */ 0xF3 /* 's' -> */, -/* pos 00b8: 48 */ 0xE5 /* 'e' -> */, -/* pos 00b9: 49 */ 0xF4 /* 't' -> */, -/* pos 00ba: 50 */ 0xF4 /* 't' -> */, -/* pos 00bb: 51 */ 0xE9 /* 'i' -> */, -/* pos 00bc: 52 */ 0xEE /* 'n' -> */, -/* pos 00bd: 53 */ 0xE7 /* 'g' -> */, -/* pos 00be: 54 */ 0xF3 /* 's' -> */, -/* pos 00bf: 55 */ 0xBA /* ':' -> */, -/* pos 00c0: 56 */ 0x00, 0x08 /* - terminal marker 8 - */, -/* pos 00c2: 57 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 58) */, - 0x75 /* 'u' */, 0x8B, 0x00 /* (to 0x0150 state 142) */, - 0x6C /* 'l' */, 0x05, 0x01 /* (to 0x01CD state 208) */, - 0x67 /* 'g' */, 0x6B, 0x02 /* (to 0x0336 state 478) */, - 0x08, /* fail */ -/* pos 00cf: 58 */ 0xE3 /* 'c' -> */, -/* pos 00d0: 59 */ 0xE5 /* 'e' -> */, -/* pos 00d1: 60 */ 0x73 /* 's' */, 0x07, 0x00 /* (to 0x00D8 state 61) */, - 0x70 /* 'p' */, 0x41, 0x00 /* (to 0x0115 state 102) */, - 0x08, /* fail */ -/* pos 00d8: 61 */ 0xF3 /* 's' -> */, -/* pos 00d9: 62 */ 0xAD /* '-' -> */, -/* pos 00da: 63 */ 0xE3 /* 'c' -> */, -/* pos 00db: 64 */ 0xEF /* 'o' -> */, -/* pos 00dc: 65 */ 0xEE /* 'n' -> */, -/* pos 00dd: 66 */ 0xF4 /* 't' -> */, -/* pos 00de: 67 */ 0xF2 /* 'r' -> */, -/* pos 00df: 68 */ 0xEF /* 'o' -> */, -/* pos 00e0: 69 */ 0xEC /* 'l' -> */, -/* pos 00e1: 70 */ 0xAD /* '-' -> */, -/* pos 00e2: 71 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00E9 state 72) */, - 0x61 /* 'a' */, 0xDA, 0x00 /* (to 0x01BF state 195) */, - 0x08, /* fail */ -/* pos 00e9: 72 */ 0xE5 /* 'e' -> */, -/* pos 00ea: 73 */ 0xF1 /* 'q' -> */, -/* pos 00eb: 74 */ 0xF5 /* 'u' -> */, -/* pos 00ec: 75 */ 0xE5 /* 'e' -> */, -/* pos 00ed: 76 */ 0xF3 /* 's' -> */, -/* pos 00ee: 77 */ 0xF4 /* 't' -> */, -/* pos 00ef: 78 */ 0xAD /* '-' -> */, -/* pos 00f0: 79 */ 0xE8 /* 'h' -> */, -/* pos 00f1: 80 */ 0xE5 /* 'e' -> */, -/* pos 00f2: 81 */ 0xE1 /* 'a' -> */, -/* pos 00f3: 82 */ 0xE4 /* 'd' -> */, -/* pos 00f4: 83 */ 0xE5 /* 'e' -> */, -/* pos 00f5: 84 */ 0xF2 /* 'r' -> */, -/* pos 00f6: 85 */ 0xF3 /* 's' -> */, -/* pos 00f7: 86 */ 0xBA /* ':' -> */, -/* pos 00f8: 87 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 00fa: 88 */ 0xE6 /* 'f' -> */, -/* pos 00fb: 89 */ 0xAD /* '-' -> */, -/* pos 00fc: 90 */ 0x6E /* 'n' */, 0x0D, 0x00 /* (to 0x0109 state 91) */, - 0x6D /* 'm' */, 0x29, 0x01 /* (to 0x0228 state 277) */, - 0x72 /* 'r' */, 0x33, 0x01 /* (to 0x0235 state 283) */, - 0x75 /* 'u' */, 0x37, 0x01 /* (to 0x023C state 289) */, - 0x08, /* fail */ -/* pos 0109: 91 */ 0xEF /* 'o' -> */, -/* pos 010a: 92 */ 0xEE /* 'n' -> */, -/* pos 010b: 93 */ 0xE5 /* 'e' -> */, -/* pos 010c: 94 */ 0xAD /* '-' -> */, -/* pos 010d: 95 */ 0xED /* 'm' -> */, -/* pos 010e: 96 */ 0xE1 /* 'a' -> */, -/* pos 010f: 97 */ 0xF4 /* 't' -> */, -/* pos 0110: 98 */ 0xE3 /* 'c' -> */, -/* pos 0111: 99 */ 0xE8 /* 'h' -> */, -/* pos 0112: 100 */ 0xBA /* ':' -> */, -/* pos 0113: 101 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 0115: 102 */ 0xF4 /* 't' -> */, -/* pos 0116: 103 */ 0xAD /* '-' -> */, -/* pos 0117: 104 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0121 state 105) */, - 0x6C /* 'l' */, 0x11, 0x00 /* (to 0x012B state 114) */, - 0x72 /* 'r' */, 0x11, 0x02 /* (to 0x032E state 471) */, - 0x08, /* fail */ -/* pos 0121: 105 */ 0xEE /* 'n' -> */, -/* pos 0122: 106 */ 0xE3 /* 'c' -> */, -/* pos 0123: 107 */ 0xEF /* 'o' -> */, -/* pos 0124: 108 */ 0xE4 /* 'd' -> */, -/* pos 0125: 109 */ 0xE9 /* 'i' -> */, -/* pos 0126: 110 */ 0xEE /* 'n' -> */, -/* pos 0127: 111 */ 0xE7 /* 'g' -> */, -/* pos 0128: 112 */ 0xBA /* ':' -> */, -/* pos 0129: 113 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 012b: 114 */ 0xE1 /* 'a' -> */, -/* pos 012c: 115 */ 0xEE /* 'n' -> */, -/* pos 012d: 116 */ 0xE7 /* 'g' -> */, -/* pos 012e: 117 */ 0xF5 /* 'u' -> */, -/* pos 012f: 118 */ 0xE1 /* 'a' -> */, -/* pos 0130: 119 */ 0xE7 /* 'g' -> */, -/* pos 0131: 120 */ 0xE5 /* 'e' -> */, -/* pos 0132: 121 */ 0xBA /* ':' -> */, -/* pos 0133: 122 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 0135: 123 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x013C state 124) */, - 0x6F /* 'o' */, 0x9B, 0x01 /* (to 0x02D3 state 406) */, - 0x08, /* fail */ -/* pos 013c: 124 */ 0xE7 /* 'g' -> */, -/* pos 013d: 125 */ 0xED /* 'm' -> */, -/* pos 013e: 126 */ 0xE1 /* 'a' -> */, -/* pos 013f: 127 */ 0xBA /* ':' -> */, -/* pos 0140: 128 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 0142: 129 */ 0xE3 /* 'c' -> */, -/* pos 0143: 130 */ 0xE8 /* 'h' -> */, -/* pos 0144: 131 */ 0xE5 /* 'e' -> */, -/* pos 0145: 132 */ 0xAD /* '-' -> */, -/* pos 0146: 133 */ 0xE3 /* 'c' -> */, -/* pos 0147: 134 */ 0xEF /* 'o' -> */, -/* pos 0148: 135 */ 0xEE /* 'n' -> */, -/* pos 0149: 136 */ 0xF4 /* 't' -> */, -/* pos 014a: 137 */ 0xF2 /* 'r' -> */, -/* pos 014b: 138 */ 0xEF /* 'o' -> */, -/* pos 014c: 139 */ 0xEC /* 'l' -> */, -/* pos 014d: 140 */ 0xBA /* ':' -> */, -/* pos 014e: 141 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 0150: 142 */ 0xF4 /* 't' -> */, -/* pos 0151: 143 */ 0xE8 /* 'h' -> */, -/* pos 0152: 144 */ 0xEF /* 'o' -> */, -/* pos 0153: 145 */ 0xF2 /* 'r' -> */, -/* pos 0154: 146 */ 0xE9 /* 'i' -> */, -/* pos 0155: 147 */ 0xFA /* 'z' -> */, -/* pos 0156: 148 */ 0xE1 /* 'a' -> */, -/* pos 0157: 149 */ 0xF4 /* 't' -> */, -/* pos 0158: 150 */ 0xE9 /* 'i' -> */, -/* pos 0159: 151 */ 0xEF /* 'o' -> */, -/* pos 015a: 152 */ 0xEE /* 'n' -> */, -/* pos 015b: 153 */ 0xBA /* ':' -> */, -/* pos 015c: 154 */ 0x00, 0x10 /* - terminal marker 16 - */, -/* pos 015e: 155 */ 0xEB /* 'k' -> */, -/* pos 015f: 156 */ 0xE9 /* 'i' -> */, -/* pos 0160: 157 */ 0xE5 /* 'e' -> */, -/* pos 0161: 158 */ 0xBA /* ':' -> */, -/* pos 0162: 159 */ 0x00, 0x11 /* - terminal marker 17 - */, -/* pos 0164: 160 */ 0xE5 /* 'e' -> */, -/* pos 0165: 161 */ 0xEE /* 'n' -> */, -/* pos 0166: 162 */ 0xF4 /* 't' -> */, -/* pos 0167: 163 */ 0xAD /* '-' -> */, -/* pos 0168: 164 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0178 state 165) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0189 state 172) */, - 0x64 /* 'd' */, 0x65, 0x00 /* (to 0x01D3 state 213) */, - 0x65 /* 'e' */, 0x6F, 0x00 /* (to 0x01E0 state 225) */, - 0x72 /* 'r' */, 0x88, 0x00 /* (to 0x01FC state 250) */, - 0x08, /* fail */ -/* pos 0178: 165 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0182 state 166) */, - 0x61 /* 'a' */, 0x6F, 0x00 /* (to 0x01EA state 234) */, - 0x6F /* 'o' */, 0x75, 0x00 /* (to 0x01F3 state 242) */, - 0x08, /* fail */ -/* pos 0182: 166 */ 0xEE /* 'n' -> */, -/* pos 0183: 167 */ 0xE7 /* 'g' -> */, -/* pos 0184: 168 */ 0xF4 /* 't' -> */, -/* pos 0185: 169 */ 0xE8 /* 'h' -> */, -/* pos 0186: 170 */ 0xBA /* ':' -> */, -/* pos 0187: 171 */ 0x00, 0x12 /* - terminal marker 18 - */, -/* pos 0189: 172 */ 0xF9 /* 'y' -> */, -/* pos 018a: 173 */ 0xF0 /* 'p' -> */, -/* pos 018b: 174 */ 0xE5 /* 'e' -> */, -/* pos 018c: 175 */ 0xBA /* ':' -> */, -/* pos 018d: 176 */ 0x00, 0x13 /* - terminal marker 19 - */, -/* pos 018f: 177 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0196 state 178) */, - 0x65 /* 'e' */, 0x0A, 0x02 /* (to 0x039C state 558) */, - 0x08, /* fail */ -/* pos 0196: 178 */ 0xF4 /* 't' -> */, -/* pos 0197: 179 */ 0xE5 /* 'e' -> */, -/* pos 0198: 180 */ 0xBA /* ':' -> */, -/* pos 0199: 181 */ 0x00, 0x14 /* - terminal marker 20 - */, -/* pos 019b: 182 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01A2 state 183) */, - 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x01A8 state 188) */, - 0x08, /* fail */ -/* pos 01a2: 183 */ 0xEE /* 'n' -> */, -/* pos 01a3: 184 */ 0xE7 /* 'g' -> */, -/* pos 01a4: 185 */ 0xE5 /* 'e' -> */, -/* pos 01a5: 186 */ 0xBA /* ':' -> */, -/* pos 01a6: 187 */ 0x00, 0x15 /* - terminal marker 21 - */, -/* pos 01a8: 188 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x01B2 state 189) */, - 0x74 /* 't' */, 0xD7, 0x00 /* (to 0x0282 state 345) */, - 0x70 /* 'p' */, 0x0B, 0x02 /* (to 0x03B9 state 583) */, - 0x08, /* fail */ -/* pos 01b2: 189 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01B9 state 190) */, - 0x72 /* 'r' */, 0xA5, 0x01 /* (to 0x035A state 505) */, - 0x08, /* fail */ -/* pos 01b9: 190 */ 0xF2 /* 'r' -> */, -/* pos 01ba: 191 */ 0xE5 /* 'e' -> */, -/* pos 01bb: 192 */ 0xF2 /* 'r' -> */, -/* pos 01bc: 193 */ 0xBA /* ':' -> */, -/* pos 01bd: 194 */ 0x00, 0x16 /* - terminal marker 22 - */, -/* pos 01bf: 195 */ 0xEC /* 'l' -> */, -/* pos 01c0: 196 */ 0xEC /* 'l' -> */, -/* pos 01c1: 197 */ 0xEF /* 'o' -> */, -/* pos 01c2: 198 */ 0xF7 /* 'w' -> */, -/* pos 01c3: 199 */ 0xAD /* '-' -> */, -/* pos 01c4: 200 */ 0xEF /* 'o' -> */, -/* pos 01c5: 201 */ 0xF2 /* 'r' -> */, -/* pos 01c6: 202 */ 0xE9 /* 'i' -> */, -/* pos 01c7: 203 */ 0xE7 /* 'g' -> */, -/* pos 01c8: 204 */ 0xE9 /* 'i' -> */, -/* pos 01c9: 205 */ 0xEE /* 'n' -> */, -/* pos 01ca: 206 */ 0xBA /* ':' -> */, -/* pos 01cb: 207 */ 0x00, 0x19 /* - terminal marker 25 - */, -/* pos 01cd: 208 */ 0xEC /* 'l' -> */, -/* pos 01ce: 209 */ 0xEF /* 'o' -> */, -/* pos 01cf: 210 */ 0xF7 /* 'w' -> */, -/* pos 01d0: 211 */ 0xBA /* ':' -> */, -/* pos 01d1: 212 */ 0x00, 0x1B /* - terminal marker 27 - */, -/* pos 01d3: 213 */ 0xE9 /* 'i' -> */, -/* pos 01d4: 214 */ 0xF3 /* 's' -> */, -/* pos 01d5: 215 */ 0xF0 /* 'p' -> */, -/* pos 01d6: 216 */ 0xEF /* 'o' -> */, -/* pos 01d7: 217 */ 0xF3 /* 's' -> */, -/* pos 01d8: 218 */ 0xE9 /* 'i' -> */, -/* pos 01d9: 219 */ 0xF4 /* 't' -> */, -/* pos 01da: 220 */ 0xE9 /* 'i' -> */, -/* pos 01db: 221 */ 0xEF /* 'o' -> */, -/* pos 01dc: 222 */ 0xEE /* 'n' -> */, -/* pos 01dd: 223 */ 0xBA /* ':' -> */, -/* pos 01de: 224 */ 0x00, 0x1C /* - terminal marker 28 - */, -/* pos 01e0: 225 */ 0xEE /* 'n' -> */, -/* pos 01e1: 226 */ 0xE3 /* 'c' -> */, -/* pos 01e2: 227 */ 0xEF /* 'o' -> */, -/* pos 01e3: 228 */ 0xE4 /* 'd' -> */, -/* pos 01e4: 229 */ 0xE9 /* 'i' -> */, -/* pos 01e5: 230 */ 0xEE /* 'n' -> */, -/* pos 01e6: 231 */ 0xE7 /* 'g' -> */, -/* pos 01e7: 232 */ 0xBA /* ':' -> */, -/* pos 01e8: 233 */ 0x00, 0x1D /* - terminal marker 29 - */, -/* pos 01ea: 234 */ 0xEE /* 'n' -> */, -/* pos 01eb: 235 */ 0xE7 /* 'g' -> */, -/* pos 01ec: 236 */ 0xF5 /* 'u' -> */, -/* pos 01ed: 237 */ 0xE1 /* 'a' -> */, -/* pos 01ee: 238 */ 0xE7 /* 'g' -> */, -/* pos 01ef: 239 */ 0xE5 /* 'e' -> */, -/* pos 01f0: 240 */ 0xBA /* ':' -> */, -/* pos 01f1: 241 */ 0x00, 0x1E /* - terminal marker 30 - */, -/* pos 01f3: 242 */ 0xE3 /* 'c' -> */, -/* pos 01f4: 243 */ 0xE1 /* 'a' -> */, -/* pos 01f5: 244 */ 0xF4 /* 't' -> */, -/* pos 01f6: 245 */ 0xE9 /* 'i' -> */, -/* pos 01f7: 246 */ 0xEF /* 'o' -> */, -/* pos 01f8: 247 */ 0xEE /* 'n' -> */, -/* pos 01f9: 248 */ 0xBA /* ':' -> */, -/* pos 01fa: 249 */ 0x00, 0x1F /* - terminal marker 31 - */, -/* pos 01fc: 250 */ 0xE1 /* 'a' -> */, -/* pos 01fd: 251 */ 0xEE /* 'n' -> */, -/* pos 01fe: 252 */ 0xE7 /* 'g' -> */, -/* pos 01ff: 253 */ 0xE5 /* 'e' -> */, -/* pos 0200: 254 */ 0xBA /* ':' -> */, -/* pos 0201: 255 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 0203: 256 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x020A state 257) */, - 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x020F state 261) */, - 0x08, /* fail */ -/* pos 020a: 257 */ 0xE1 /* 'a' -> */, -/* pos 020b: 258 */ 0xE7 /* 'g' -> */, -/* pos 020c: 259 */ 0xBA /* ':' -> */, -/* pos 020d: 260 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 020f: 261 */ 0xF0 /* 'p' -> */, -/* pos 0210: 262 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0217 state 263) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x021C state 267) */, - 0x08, /* fail */ -/* pos 0217: 263 */ 0xE3 /* 'c' -> */, -/* pos 0218: 264 */ 0xF4 /* 't' -> */, -/* pos 0219: 265 */ 0xBA /* ':' -> */, -/* pos 021a: 266 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* pos 021c: 267 */ 0xF2 /* 'r' -> */, -/* pos 021d: 268 */ 0xE5 /* 'e' -> */, -/* pos 021e: 269 */ 0xF3 /* 's' -> */, -/* pos 021f: 270 */ 0xBA /* ':' -> */, -/* pos 0220: 271 */ 0x00, 0x23 /* - terminal marker 35 - */, -/* pos 0222: 272 */ 0xF2 /* 'r' -> */, -/* pos 0223: 273 */ 0xEF /* 'o' -> */, -/* pos 0224: 274 */ 0xED /* 'm' -> */, -/* pos 0225: 275 */ 0xBA /* ':' -> */, -/* pos 0226: 276 */ 0x00, 0x24 /* - terminal marker 36 - */, -/* pos 0228: 277 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x022F state 278) */, - 0x6F /* 'o' */, 0xE3, 0x00 /* (to 0x030E state 441) */, - 0x08, /* fail */ -/* pos 022f: 278 */ 0xF4 /* 't' -> */, -/* pos 0230: 279 */ 0xE3 /* 'c' -> */, -/* pos 0231: 280 */ 0xE8 /* 'h' -> */, -/* pos 0232: 281 */ 0xBA /* ':' -> */, -/* pos 0233: 282 */ 0x00, 0x25 /* - terminal marker 37 - */, -/* pos 0235: 283 */ 0xE1 /* 'a' -> */, -/* pos 0236: 284 */ 0xEE /* 'n' -> */, -/* pos 0237: 285 */ 0xE7 /* 'g' -> */, -/* pos 0238: 286 */ 0xE5 /* 'e' -> */, -/* pos 0239: 287 */ 0xBA /* ':' -> */, -/* pos 023a: 288 */ 0x00, 0x26 /* - terminal marker 38 - */, -/* pos 023c: 289 */ 0xEE /* 'n' -> */, -/* pos 023d: 290 */ 0xED /* 'm' -> */, -/* pos 023e: 291 */ 0xEF /* 'o' -> */, -/* pos 023f: 292 */ 0xE4 /* 'd' -> */, -/* pos 0240: 293 */ 0xE9 /* 'i' -> */, -/* pos 0241: 294 */ 0xE6 /* 'f' -> */, -/* pos 0242: 295 */ 0xE9 /* 'i' -> */, -/* pos 0243: 296 */ 0xE5 /* 'e' -> */, -/* pos 0244: 297 */ 0xE4 /* 'd' -> */, -/* pos 0245: 298 */ 0xAD /* '-' -> */, -/* pos 0246: 299 */ 0xF3 /* 's' -> */, -/* pos 0247: 300 */ 0xE9 /* 'i' -> */, -/* pos 0248: 301 */ 0xEE /* 'n' -> */, -/* pos 0249: 302 */ 0xE3 /* 'c' -> */, -/* pos 024a: 303 */ 0xE5 /* 'e' -> */, -/* pos 024b: 304 */ 0xBA /* ':' -> */, -/* pos 024c: 305 */ 0x00, 0x27 /* - terminal marker 39 - */, -/* pos 024e: 306 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0258 state 307) */, - 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x0266 state 320) */, - 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x026B state 324) */, - 0x08, /* fail */ -/* pos 0258: 307 */ 0xF3 /* 's' -> */, -/* pos 0259: 308 */ 0xF4 /* 't' -> */, -/* pos 025a: 309 */ 0xAD /* '-' -> */, -/* pos 025b: 310 */ 0xED /* 'm' -> */, -/* pos 025c: 311 */ 0xEF /* 'o' -> */, -/* pos 025d: 312 */ 0xE4 /* 'd' -> */, -/* pos 025e: 313 */ 0xE9 /* 'i' -> */, -/* pos 025f: 314 */ 0xE6 /* 'f' -> */, -/* pos 0260: 315 */ 0xE9 /* 'i' -> */, -/* pos 0261: 316 */ 0xE5 /* 'e' -> */, -/* pos 0262: 317 */ 0xE4 /* 'd' -> */, -/* pos 0263: 318 */ 0xBA /* ':' -> */, -/* pos 0264: 319 */ 0x00, 0x28 /* - terminal marker 40 - */, -/* pos 0266: 320 */ 0xEE /* 'n' -> */, -/* pos 0267: 321 */ 0xEB /* 'k' -> */, -/* pos 0268: 322 */ 0xBA /* ':' -> */, -/* pos 0269: 323 */ 0x00, 0x29 /* - terminal marker 41 - */, -/* pos 026b: 324 */ 0xE3 /* 'c' -> */, -/* pos 026c: 325 */ 0xE1 /* 'a' -> */, -/* pos 026d: 326 */ 0xF4 /* 't' -> */, -/* pos 026e: 327 */ 0xE9 /* 'i' -> */, -/* pos 026f: 328 */ 0xEF /* 'o' -> */, -/* pos 0270: 329 */ 0xEE /* 'n' -> */, -/* pos 0271: 330 */ 0xBA /* ':' -> */, -/* pos 0272: 331 */ 0x00, 0x2A /* - terminal marker 42 - */, -/* pos 0274: 332 */ 0xE1 /* 'a' -> */, -/* pos 0275: 333 */ 0xF8 /* 'x' -> */, -/* pos 0276: 334 */ 0xAD /* '-' -> */, -/* pos 0277: 335 */ 0xE6 /* 'f' -> */, -/* pos 0278: 336 */ 0xEF /* 'o' -> */, -/* pos 0279: 337 */ 0xF2 /* 'r' -> */, -/* pos 027a: 338 */ 0xF7 /* 'w' -> */, -/* pos 027b: 339 */ 0xE1 /* 'a' -> */, -/* pos 027c: 340 */ 0xF2 /* 'r' -> */, -/* pos 027d: 341 */ 0xE4 /* 'd' -> */, -/* pos 027e: 342 */ 0xF3 /* 's' -> */, -/* pos 027f: 343 */ 0xBA /* ':' -> */, -/* pos 0280: 344 */ 0x00, 0x2B /* - terminal marker 43 - */, -/* pos 0282: 345 */ 0xF2 /* 'r' -> */, -/* pos 0283: 346 */ 0xF9 /* 'y' -> */, -/* pos 0284: 347 */ 0xAD /* '-' -> */, -/* pos 0285: 348 */ 0xE1 /* 'a' -> */, -/* pos 0286: 349 */ 0xE6 /* 'f' -> */, -/* pos 0287: 350 */ 0xF4 /* 't' -> */, -/* pos 0288: 351 */ 0xE5 /* 'e' -> */, -/* pos 0289: 352 */ 0xF2 /* 'r' -> */, -/* pos 028a: 353 */ 0xBA /* ':' -> */, -/* pos 028b: 354 */ 0x00, 0x2F /* - terminal marker 47 - */, -/* pos 028d: 355 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0294 state 356) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x02AE state 371) */, - 0x08, /* fail */ -/* pos 0294: 356 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x029E state 357) */, - 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x02A4 state 362) */, - 0x63 /* 'c' */, 0x83, 0x00 /* (to 0x031D state 455) */, - 0x08, /* fail */ -/* pos 029e: 357 */ 0xF6 /* 'v' -> */, -/* pos 029f: 358 */ 0xE5 /* 'e' -> */, -/* pos 02a0: 359 */ 0xF2 /* 'r' -> */, -/* pos 02a1: 360 */ 0xBA /* ':' -> */, -/* pos 02a2: 361 */ 0x00, 0x30 /* - terminal marker 48 - */, -/* pos 02a4: 362 */ 0xAD /* '-' -> */, -/* pos 02a5: 363 */ 0xE3 /* 'c' -> */, -/* pos 02a6: 364 */ 0xEF /* 'o' -> */, -/* pos 02a7: 365 */ 0xEF /* 'o' -> */, -/* pos 02a8: 366 */ 0xEB /* 'k' -> */, -/* pos 02a9: 367 */ 0xE9 /* 'i' -> */, -/* pos 02aa: 368 */ 0xE5 /* 'e' -> */, -/* pos 02ab: 369 */ 0xBA /* ':' -> */, -/* pos 02ac: 370 */ 0x00, 0x31 /* - terminal marker 49 - */, -/* pos 02ae: 371 */ 0xF2 /* 'r' -> */, -/* pos 02af: 372 */ 0xE9 /* 'i' -> */, -/* pos 02b0: 373 */ 0xE3 /* 'c' -> */, -/* pos 02b1: 374 */ 0xF4 /* 't' -> */, -/* pos 02b2: 375 */ 0xAD /* '-' -> */, -/* pos 02b3: 376 */ 0xF4 /* 't' -> */, -/* pos 02b4: 377 */ 0xF2 /* 'r' -> */, -/* pos 02b5: 378 */ 0xE1 /* 'a' -> */, -/* pos 02b6: 379 */ 0xEE /* 'n' -> */, -/* pos 02b7: 380 */ 0xF3 /* 's' -> */, -/* pos 02b8: 381 */ 0xF0 /* 'p' -> */, -/* pos 02b9: 382 */ 0xEF /* 'o' -> */, -/* pos 02ba: 383 */ 0xF2 /* 'r' -> */, -/* pos 02bb: 384 */ 0xF4 /* 't' -> */, -/* pos 02bc: 385 */ 0xAD /* '-' -> */, -/* pos 02bd: 386 */ 0xF3 /* 's' -> */, -/* pos 02be: 387 */ 0xE5 /* 'e' -> */, -/* pos 02bf: 388 */ 0xE3 /* 'c' -> */, -/* pos 02c0: 389 */ 0xF5 /* 'u' -> */, -/* pos 02c1: 390 */ 0xF2 /* 'r' -> */, -/* pos 02c2: 391 */ 0xE9 /* 'i' -> */, -/* pos 02c3: 392 */ 0xF4 /* 't' -> */, -/* pos 02c4: 393 */ 0xF9 /* 'y' -> */, -/* pos 02c5: 394 */ 0xBA /* ':' -> */, -/* pos 02c6: 395 */ 0x00, 0x32 /* - terminal marker 50 - */, -/* pos 02c8: 396 */ 0xE5 /* 'e' -> */, -/* pos 02c9: 397 */ 0xF2 /* 'r' -> */, -/* pos 02ca: 398 */ 0xAD /* '-' -> */, -/* pos 02cb: 399 */ 0xE1 /* 'a' -> */, -/* pos 02cc: 400 */ 0xE7 /* 'g' -> */, -/* pos 02cd: 401 */ 0xE5 /* 'e' -> */, -/* pos 02ce: 402 */ 0xEE /* 'n' -> */, -/* pos 02cf: 403 */ 0xF4 /* 't' -> */, -/* pos 02d0: 404 */ 0xBA /* ':' -> */, -/* pos 02d1: 405 */ 0x00, 0x34 /* - terminal marker 52 - */, -/* pos 02d3: 406 */ 0xF8 /* 'x' -> */, -/* pos 02d4: 407 */ 0xF9 /* 'y' -> */, -/* pos 02d5: 408 */ 0x20 /* ' ' */, 0x07, 0x00 /* (to 0x02DC state 409) */, - 0x2D /* '-' */, 0x62, 0x00 /* (to 0x033A state 481) */, - 0x08, /* fail */ -/* pos 02dc: 409 */ 0x00, 0x3C /* - terminal marker 60 - */, -/* pos 02de: 410 */ 0xAD /* '-' -> */, -/* pos 02df: 411 */ 0x66 /* 'f' */, 0x07, 0x00 /* (to 0x02E6 state 412) */, - 0x72 /* 'r' */, 0xC8, 0x00 /* (to 0x03AA state 570) */, - 0x08, /* fail */ -/* pos 02e6: 412 */ 0xEF /* 'o' -> */, -/* pos 02e7: 413 */ 0xF2 /* 'r' -> */, -/* pos 02e8: 414 */ 0xF7 /* 'w' -> */, -/* pos 02e9: 415 */ 0xE1 /* 'a' -> */, -/* pos 02ea: 416 */ 0xF2 /* 'r' -> */, -/* pos 02eb: 417 */ 0xE4 /* 'd' -> */, -/* pos 02ec: 418 */ 0xE5 /* 'e' -> */, -/* pos 02ed: 419 */ 0xE4 /* 'd' -> */, -/* pos 02ee: 420 */ 0xAD /* '-' -> */, -/* pos 02ef: 421 */ 0xE6 /* 'f' -> */, -/* pos 02f0: 422 */ 0xEF /* 'o' -> */, -/* pos 02f1: 423 */ 0xF2 /* 'r' -> */, -/* pos 02f2: 424 */ 0xBA /* ':' -> */, -/* pos 02f3: 425 */ 0x00, 0x3F /* - terminal marker 63 - */, -/* pos 02f5: 426 */ 0x00, 0x40 /* - terminal marker 64 - */, -/* pos 02f7: 427 */ 0xE1 /* 'a' -> */, -/* pos 02f8: 428 */ 0xE4 /* 'd' -> */, -/* pos 02f9: 429 */ 0xA0 /* ' ' -> */, -/* pos 02fa: 430 */ 0x00, 0x41 /* - terminal marker 65 - */, -/* pos 02fc: 431 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0303 state 432) */, - 0x72 /* 'r' */, 0x61, 0x00 /* (to 0x0360 state 510) */, - 0x08, /* fail */ -/* pos 0303: 432 */ 0xBA /* ':' -> */, -/* pos 0304: 433 */ 0x00, 0x42 /* - terminal marker 66 - */, -/* pos 0306: 434 */ 0xF4 /* 't' -> */, -/* pos 0307: 435 */ 0xE9 /* 'i' -> */, -/* pos 0308: 436 */ 0xEF /* 'o' -> */, -/* pos 0309: 437 */ 0xEE /* 'n' -> */, -/* pos 030a: 438 */ 0xF3 /* 's' -> */, -/* pos 030b: 439 */ 0xA0 /* ' ' -> */, -/* pos 030c: 440 */ 0x00, 0x02 /* - terminal marker 2 - */, -/* pos 030e: 441 */ 0xE4 /* 'd' -> */, -/* pos 030f: 442 */ 0xE9 /* 'i' -> */, -/* pos 0310: 443 */ 0xE6 /* 'f' -> */, -/* pos 0311: 444 */ 0xE9 /* 'i' -> */, -/* pos 0312: 445 */ 0xE5 /* 'e' -> */, -/* pos 0313: 446 */ 0xE4 /* 'd' -> */, -/* pos 0314: 447 */ 0xAD /* '-' -> */, -/* pos 0315: 448 */ 0xF3 /* 's' -> */, -/* pos 0316: 449 */ 0xE9 /* 'i' -> */, -/* pos 0317: 450 */ 0xEE /* 'n' -> */, -/* pos 0318: 451 */ 0xE3 /* 'c' -> */, -/* pos 0319: 452 */ 0xE5 /* 'e' -> */, -/* pos 031a: 453 */ 0xBA /* ':' -> */, -/* pos 031b: 454 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 031d: 455 */ 0xAD /* '-' -> */, -/* pos 031e: 456 */ 0xF7 /* 'w' -> */, -/* pos 031f: 457 */ 0xE5 /* 'e' -> */, -/* pos 0320: 458 */ 0xE2 /* 'b' -> */, -/* pos 0321: 459 */ 0xF3 /* 's' -> */, -/* pos 0322: 460 */ 0xEF /* 'o' -> */, -/* pos 0323: 461 */ 0xE3 /* 'c' -> */, -/* pos 0324: 462 */ 0xEB /* 'k' -> */, -/* pos 0325: 463 */ 0xE5 /* 'e' -> */, -/* pos 0326: 464 */ 0xF4 /* 't' -> */, -/* pos 0327: 465 */ 0xAD /* '-' -> */, -/* pos 0328: 466 */ 0xEB /* 'k' -> */, -/* pos 0329: 467 */ 0xE5 /* 'e' -> */, -/* pos 032a: 468 */ 0xF9 /* 'y' -> */, -/* pos 032b: 469 */ 0xBA /* ':' -> */, -/* pos 032c: 470 */ 0x00, 0x17 /* - terminal marker 23 - */, -/* pos 032e: 471 */ 0xE1 /* 'a' -> */, -/* pos 032f: 472 */ 0xEE /* 'n' -> */, -/* pos 0330: 473 */ 0xE7 /* 'g' -> */, -/* pos 0331: 474 */ 0xE5 /* 'e' -> */, -/* pos 0332: 475 */ 0xF3 /* 's' -> */, -/* pos 0333: 476 */ 0xBA /* ':' -> */, -/* pos 0334: 477 */ 0x00, 0x18 /* - terminal marker 24 - */, -/* pos 0336: 478 */ 0xE5 /* 'e' -> */, -/* pos 0337: 479 */ 0xBA /* ':' -> */, -/* pos 0338: 480 */ 0x00, 0x1A /* - terminal marker 26 - */, -/* pos 033a: 481 */ 0xE1 /* 'a' -> */, -/* pos 033b: 482 */ 0xF5 /* 'u' -> */, -/* pos 033c: 483 */ 0xF4 /* 't' -> */, -/* pos 033d: 484 */ 0xE8 /* 'h' -> */, -/* pos 033e: 485 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0345 state 486) */, - 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x034F state 495) */, - 0x08, /* fail */ -/* pos 0345: 486 */ 0xEE /* 'n' -> */, -/* pos 0346: 487 */ 0xF4 /* 't' -> */, -/* pos 0347: 488 */ 0xE9 /* 'i' -> */, -/* pos 0348: 489 */ 0xE3 /* 'c' -> */, -/* pos 0349: 490 */ 0xE1 /* 'a' -> */, -/* pos 034a: 491 */ 0xF4 /* 't' -> */, -/* pos 034b: 492 */ 0xE5 /* 'e' -> */, -/* pos 034c: 493 */ 0xBA /* ':' -> */, -/* pos 034d: 494 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 034f: 495 */ 0xF2 /* 'r' -> */, -/* pos 0350: 496 */ 0xE9 /* 'i' -> */, -/* pos 0351: 497 */ 0xFA /* 'z' -> */, -/* pos 0352: 498 */ 0xE1 /* 'a' -> */, -/* pos 0353: 499 */ 0xF4 /* 't' -> */, -/* pos 0354: 500 */ 0xE9 /* 'i' -> */, -/* pos 0355: 501 */ 0xEF /* 'o' -> */, -/* pos 0356: 502 */ 0xEE /* 'n' -> */, -/* pos 0357: 503 */ 0xBA /* ':' -> */, -/* pos 0358: 504 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 035a: 505 */ 0xE5 /* 'e' -> */, -/* pos 035b: 506 */ 0xF3 /* 's' -> */, -/* pos 035c: 507 */ 0xE8 /* 'h' -> */, -/* pos 035d: 508 */ 0xBA /* ':' -> */, -/* pos 035e: 509 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 0360: 510 */ 0xE1 /* 'a' -> */, -/* pos 0361: 511 */ 0xEE /* 'n' -> */, -/* pos 0362: 512 */ 0xF3 /* 's' -> */, -/* pos 0363: 513 */ 0xE6 /* 'f' -> */, -/* pos 0364: 514 */ 0xE5 /* 'e' -> */, -/* pos 0365: 515 */ 0xF2 /* 'r' -> */, -/* pos 0366: 516 */ 0xAD /* '-' -> */, -/* pos 0367: 517 */ 0xE5 /* 'e' -> */, -/* pos 0368: 518 */ 0xEE /* 'n' -> */, -/* pos 0369: 519 */ 0xE3 /* 'c' -> */, -/* pos 036a: 520 */ 0xEF /* 'o' -> */, -/* pos 036b: 521 */ 0xE4 /* 'd' -> */, -/* pos 036c: 522 */ 0xE9 /* 'i' -> */, -/* pos 036d: 523 */ 0xEE /* 'n' -> */, -/* pos 036e: 524 */ 0xE7 /* 'g' -> */, -/* pos 036f: 525 */ 0xBA /* ':' -> */, -/* pos 0370: 526 */ 0x00, 0x33 /* - terminal marker 51 - */, -/* pos 0372: 527 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0379 state 528) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x037E state 532) */, - 0x08, /* fail */ -/* pos 0379: 528 */ 0xF2 /* 'r' -> */, -/* pos 037a: 529 */ 0xF9 /* 'y' -> */, -/* pos 037b: 530 */ 0xBA /* ':' -> */, -/* pos 037c: 531 */ 0x00, 0x35 /* - terminal marker 53 - */, -/* pos 037e: 532 */ 0xE1 /* 'a' -> */, -/* pos 037f: 533 */ 0xBA /* ':' -> */, -/* pos 0380: 534 */ 0x00, 0x36 /* - terminal marker 54 - */, -/* pos 0382: 535 */ 0xF7 /* 'w' -> */, -/* pos 0383: 536 */ 0xF7 /* 'w' -> */, -/* pos 0384: 537 */ 0xAD /* '-' -> */, -/* pos 0385: 538 */ 0xE1 /* 'a' -> */, -/* pos 0386: 539 */ 0xF5 /* 'u' -> */, -/* pos 0387: 540 */ 0xF4 /* 't' -> */, -/* pos 0388: 541 */ 0xE8 /* 'h' -> */, -/* pos 0389: 542 */ 0xE5 /* 'e' -> */, -/* pos 038a: 543 */ 0xEE /* 'n' -> */, -/* pos 038b: 544 */ 0xF4 /* 't' -> */, -/* pos 038c: 545 */ 0xE9 /* 'i' -> */, -/* pos 038d: 546 */ 0xE3 /* 'c' -> */, -/* pos 038e: 547 */ 0xE1 /* 'a' -> */, -/* pos 038f: 548 */ 0xF4 /* 't' -> */, -/* pos 0390: 549 */ 0xE5 /* 'e' -> */, -/* pos 0391: 550 */ 0xBA /* ':' -> */, -/* pos 0392: 551 */ 0x00, 0x37 /* - terminal marker 55 - */, -/* pos 0394: 552 */ 0xF4 /* 't' -> */, -/* pos 0395: 553 */ 0xE3 /* 'c' -> */, -/* pos 0396: 554 */ 0xE8 /* 'h' -> */, -/* pos 0397: 555 */ 0x00, 0x38 /* - terminal marker 56 - */, -/* pos 0399: 556 */ 0xF4 /* 't' -> */, -/* pos 039a: 557 */ 0x00, 0x39 /* - terminal marker 57 - */, -/* pos 039c: 558 */ 0xEC /* 'l' -> */, -/* pos 039d: 559 */ 0xE5 /* 'e' -> */, -/* pos 039e: 560 */ 0xF4 /* 't' -> */, -/* pos 039f: 561 */ 0xE5 /* 'e' -> */, -/* pos 03a0: 562 */ 0x00, 0x3A /* - terminal marker 58 - */, -/* pos 03a2: 563 */ 0xE9 /* 'i' -> */, -/* pos 03a3: 564 */ 0xAD /* '-' -> */, -/* pos 03a4: 565 */ 0xE1 /* 'a' -> */, -/* pos 03a5: 566 */ 0xF2 /* 'r' -> */, -/* pos 03a6: 567 */ 0xE7 /* 'g' -> */, -/* pos 03a7: 568 */ 0xF3 /* 's' -> */, -/* pos 03a8: 569 */ 0x00, 0x3B /* - terminal marker 59 - */, -/* pos 03aa: 570 */ 0xE5 /* 'e' -> */, -/* pos 03ab: 571 */ 0xE1 /* 'a' -> */, -/* pos 03ac: 572 */ 0xEC /* 'l' -> */, -/* pos 03ad: 573 */ 0xAD /* '-' -> */, -/* pos 03ae: 574 */ 0xE9 /* 'i' -> */, -/* pos 03af: 575 */ 0xF0 /* 'p' -> */, -/* pos 03b0: 576 */ 0xBA /* ':' -> */, -/* pos 03b1: 577 */ 0x00, 0x3D /* - terminal marker 61 - */, -/* pos 03b3: 578 */ 0xB1 /* '1' -> */, -/* pos 03b4: 579 */ 0xAE /* '.' -> */, -/* pos 03b5: 580 */ 0xB0 /* '0' -> */, -/* pos 03b6: 581 */ 0xA0 /* ' ' -> */, -/* pos 03b7: 582 */ 0x00, 0x3E /* - terminal marker 62 - */, -/* pos 03b9: 583 */ 0xEC /* 'l' -> */, -/* pos 03ba: 584 */ 0xE1 /* 'a' -> */, -/* pos 03bb: 585 */ 0xF9 /* 'y' -> */, -/* pos 03bc: 586 */ 0xAD /* '-' -> */, -/* pos 03bd: 587 */ 0xEE /* 'n' -> */, -/* pos 03be: 588 */ 0xEF /* 'o' -> */, -/* pos 03bf: 589 */ 0xEE /* 'n' -> */, -/* pos 03c0: 590 */ 0xE3 /* 'c' -> */, -/* pos 03c1: 591 */ 0xE5 /* 'e' -> */, -/* pos 03c2: 592 */ 0xBA /* ':' -> */, -/* pos 03c3: 593 */ 0x00, 0x43 /* - terminal marker 67 - */, -/* pos 03c5: 594 */ 0xF0 /* 'p' -> */, -/* pos 03c6: 595 */ 0xF2 /* 'r' -> */, -/* pos 03c7: 596 */ 0xEF /* 'o' -> */, -/* pos 03c8: 597 */ 0xF4 /* 't' -> */, -/* pos 03c9: 598 */ 0xEF /* 'o' -> */, -/* pos 03ca: 599 */ 0xE3 /* 'c' -> */, -/* pos 03cb: 600 */ 0xEF /* 'o' -> */, -/* pos 03cc: 601 */ 0xEC /* 'l' -> */, -/* pos 03cd: 602 */ 0x00, 0x44 /* - terminal marker 68 - */, -/* total size 975 bytes */ + /* 8: 15: http/1.1 */ + /* 9: 17: accept: */ + /* 10: 18: access-control-request-headers: */ + /* 11: 19: if-modified-since: */ + /* 12: 20: if-none-match: */ + /* 13: 21: accept-encoding: */ + /* 14: 22: accept-language: */ + /* 15: 23: pragma: */ + /* 16: 24: cache-control: */ + /* 17: 25: authorization: */ + /* 18: 26: cookie: */ + /* 19: 27: content-length: */ + /* 20: 28: content-type: */ + /* 21: 29: date: */ + /* 22: 30: range: */ + /* 23: 31: referer: */ + /* 24: 40: accept-charset: */ + /* 25: 41: accept-ranges: */ + /* 26: 42: access-control-allow-origin: */ + /* 27: 43: age: */ + /* 28: 44: allow: */ + /* 29: 45: content-disposition: */ + /* 30: 46: content-encoding: */ + /* 31: 47: content-language: */ + /* 32: 48: content-location: */ + /* 33: 49: content-range: */ + /* 34: 50: etag: */ + /* 35: 51: expect: */ + /* 36: 52: expires: */ + /* 37: 53: from: */ + /* 38: 54: if-match: */ + /* 39: 55: if-range: */ + /* 40: 56: if-unmodified-since: */ + /* 41: 57: last-modified: */ + /* 42: 58: link: */ + /* 43: 59: location: */ + /* 44: 60: max-forwards: */ + /* 45: 61: proxy-authenticate: */ + /* 46: 62: proxy-authorization: */ + /* 47: 63: refresh: */ + /* 48: 64: retry-after: */ + /* 49: 65: server: */ + /* 50: 66: set-cookie: */ + /* 51: 67: strict-transport-security: */ + /* 52: 68: transfer-encoding: */ + /* 53: 69: user-agent: */ + /* 54: 70: vary: */ + /* 55: 71: via: */ + /* 56: 72: www-authenticate: */ + /* 57: 73: patch */ + /* 58: 74: put */ + /* 59: 75: delete */ + /* 60: 76: uri-args */ + /* 61: 77: proxy */ + /* 62: 78: x-real-ip: */ + /* 63: 79: http/1.0 */ + /* 64: 80: x-forwarded-for: */ + /* 65: 81: connect */ + /* 66: 82: head */ + /* 67: 83: te: */ + /* 68: 84: replay-nonce: */ + /* 69: 86: x-auth-token: */ + /* 70: 87: */ +/* pos 0000: 0 */ 0x67 /* 'g' */, 0x3D, 0x00 /* (to 0x003D state 1) */, + 0x70 /* 'p' */, 0x3F, 0x00 /* (to 0x0042 state 5) */, + 0x68 /* 'h' */, 0x4E, 0x00 /* (to 0x0054 state 10) */, + 0x63 /* 'c' */, 0x5A, 0x00 /* (to 0x0063 state 15) */, + 0x75 /* 'u' */, 0x7B, 0x00 /* (to 0x0087 state 26) */, + 0x6F /* 'o' */, 0x8A, 0x00 /* (to 0x0099 state 34) */, + 0x0D /* '.' */, 0x95, 0x00 /* (to 0x00A7 state 41) */, + 0x61 /* 'a' */, 0xA4, 0x00 /* (to 0x00B9 state 51) */, + 0x69 /* 'i' */, 0xC1, 0x00 /* (to 0x00D9 state 58) */, + 0x64 /* 'd' */, 0x6A, 0x01 /* (to 0x0185 state 160) */, + 0x72 /* 'r' */, 0x73, 0x01 /* (to 0x0191 state 165) */, + 0x65 /* 'e' */, 0xBF, 0x01 /* (to 0x01E0 state 229) */, + 0x66 /* 'f' */, 0xDB, 0x01 /* (to 0x01FF state 245) */, + 0x6C /* 'l' */, 0xFD, 0x01 /* (to 0x0224 state 278) */, + 0x73 /* 's' */, 0x42, 0x02 /* (to 0x026C state 321) */, + 0x74 /* 't' */, 0x5D, 0x02 /* (to 0x028A state 337) */, + 0x78 /* 'x' */, 0x7E, 0x02 /* (to 0x02AE state 364) */, + 0x6D /* 'm' */, 0xEF, 0x02 /* (to 0x0322 state 456) */, + 0x76 /* 'v' */, 0x48, 0x03 /* (to 0x037E state 531) */, + 0x77 /* 'w' */, 0x55, 0x03 /* (to 0x038E state 539) */, + 0x08, /* fail */ +/* pos 003d: 1 */ 0xE5 /* 'e' -> */, +/* pos 003e: 2 */ 0xF4 /* 't' -> */, +/* pos 003f: 3 */ 0xA0 /* ' ' -> */, +/* pos 0040: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, +/* pos 0042: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x004F state 6) */, + 0x72 /* 'r' */, 0xE6, 0x00 /* (to 0x012B state 106) */, + 0x61 /* 'a' */, 0x58, 0x03 /* (to 0x03A0 state 556) */, + 0x75 /* 'u' */, 0x5A, 0x03 /* (to 0x03A5 state 560) */, + 0x08, /* fail */ +/* pos 004f: 6 */ 0xF3 /* 's' -> */, +/* pos 0050: 7 */ 0xF4 /* 't' -> */, +/* pos 0051: 8 */ 0xA0 /* ' ' -> */, +/* pos 0052: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, +/* pos 0054: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x005E state 11) */, + 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AA state 43) */, + 0x65 /* 'e' */, 0x70, 0x02 /* (to 0x02CA state 381) */, + 0x08, /* fail */ +/* pos 005e: 11 */ 0xF3 /* 's' -> */, +/* pos 005f: 12 */ 0xF4 /* 't' -> */, +/* pos 0060: 13 */ 0xBA /* ':' -> */, +/* pos 0061: 14 */ 0x00, 0x03 /* - terminal marker 3 - */, +/* pos 0063: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006A state 16) */, + 0x61 /* 'a' */, 0xD2, 0x00 /* (to 0x0138 state 112) */, + 0x08, /* fail */ +/* pos 006a: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0071 state 17) */, + 0x6F /* 'o' */, 0xE7, 0x00 /* (to 0x0154 state 138) */, + 0x08, /* fail */ +/* pos 0071: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0078 state 18) */, + 0x74 /* 't' */, 0xE6, 0x00 /* (to 0x015A state 143) */, + 0x08, /* fail */ +/* pos 0078: 18 */ 0xE5 /* 'e' -> */, +/* pos 0079: 19 */ 0xE3 /* 'c' -> */, +/* pos 007a: 20 */ 0xF4 /* 't' -> */, +/* pos 007b: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0082 state 22) */, + 0x20 /* ' ' */, 0x4A, 0x02 /* (to 0x02C8 state 380) */, + 0x08, /* fail */ +/* pos 0082: 22 */ 0xEF /* 'o' -> */, +/* pos 0083: 23 */ 0xEE /* 'n' -> */, +/* pos 0084: 24 */ 0xBA /* ':' -> */, +/* pos 0085: 25 */ 0x00, 0x04 /* - terminal marker 4 - */, +/* pos 0087: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0091 state 27) */, + 0x72 /* 'r' */, 0x19, 0x02 /* (to 0x02A3 state 355) */, + 0x73 /* 's' */, 0xE6, 0x02 /* (to 0x0373 state 521) */, + 0x08, /* fail */ +/* pos 0091: 27 */ 0xE7 /* 'g' -> */, +/* pos 0092: 28 */ 0xF2 /* 'r' -> */, +/* pos 0093: 29 */ 0xE1 /* 'a' -> */, +/* pos 0094: 30 */ 0xE4 /* 'd' -> */, +/* pos 0095: 31 */ 0xE5 /* 'e' -> */, +/* pos 0096: 32 */ 0xBA /* ':' -> */, +/* pos 0097: 33 */ 0x00, 0x05 /* - terminal marker 5 - */, +/* pos 0099: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A0 state 35) */, + 0x70 /* 'p' */, 0x3F, 0x02 /* (to 0x02DB state 396) */, + 0x08, /* fail */ +/* pos 00a0: 35 */ 0xE9 /* 'i' -> */, +/* pos 00a1: 36 */ 0xE7 /* 'g' -> */, +/* pos 00a2: 37 */ 0xE9 /* 'i' -> */, +/* pos 00a3: 38 */ 0xEE /* 'n' -> */, +/* pos 00a4: 39 */ 0xBA /* ':' -> */, +/* pos 00a5: 40 */ 0x00, 0x06 /* - terminal marker 6 - */, +/* pos 00a7: 41 */ 0x8A /* '.' -> */, +/* pos 00a8: 42 */ 0x00, 0x07 /* - terminal marker 7 - */, +/* pos 00aa: 43 */ 0xF4 /* 't' -> */, +/* pos 00ab: 44 */ 0xF0 /* 'p' -> */, +/* pos 00ac: 45 */ 0xAF /* '/' -> */, +/* pos 00ad: 46 */ 0xB1 /* '1' -> */, +/* pos 00ae: 47 */ 0xAE /* '.' -> */, +/* pos 00af: 48 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x00B6 state 49) */, + 0x30 /* '0' */, 0xF9, 0x01 /* (to 0x02AB state 362) */, + 0x08, /* fail */ +/* pos 00b6: 49 */ 0xA0 /* ' ' -> */, +/* pos 00b7: 50 */ 0x00, 0x08 /* - terminal marker 8 - */, +/* pos 00b9: 51 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00C6 state 52) */, + 0x75 /* 'u' */, 0x8A, 0x00 /* (to 0x0146 state 125) */, + 0x67 /* 'g' */, 0xE7, 0x00 /* (to 0x01A6 state 178) */, + 0x6C /* 'l' */, 0xE8, 0x00 /* (to 0x01AA state 181) */, + 0x08, /* fail */ +/* pos 00c6: 52 */ 0xE3 /* 'c' -> */, +/* pos 00c7: 53 */ 0xE5 /* 'e' -> */, +/* pos 00c8: 54 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x00CF state 55) */, + 0x73 /* 's' */, 0x18, 0x02 /* (to 0x02E3 state 403) */, + 0x08, /* fail */ +/* pos 00cf: 55 */ 0xF4 /* 't' -> */, +/* pos 00d0: 56 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x00D7 state 57) */, + 0x2D /* '-' */, 0x37, 0x00 /* (to 0x010A state 87) */, + 0x08, /* fail */ +/* pos 00d7: 57 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 00d9: 58 */ 0xE6 /* 'f' -> */, +/* pos 00da: 59 */ 0xAD /* '-' -> */, +/* pos 00db: 60 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x00E8 state 61) */, + 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x00FE state 76) */, + 0x72 /* 'r' */, 0x2A, 0x01 /* (to 0x020B state 255) */, + 0x75 /* 'u' */, 0x2E, 0x01 /* (to 0x0212 state 261) */, + 0x08, /* fail */ +/* pos 00e8: 61 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x00EF state 62) */, + 0x61 /* 'a' */, 0x1A, 0x01 /* (to 0x0205 state 250) */, + 0x08, /* fail */ +/* pos 00ef: 62 */ 0xE4 /* 'd' -> */, +/* pos 00f0: 63 */ 0xE9 /* 'i' -> */, +/* pos 00f1: 64 */ 0xE6 /* 'f' -> */, +/* pos 00f2: 65 */ 0xE9 /* 'i' -> */, +/* pos 00f3: 66 */ 0xE5 /* 'e' -> */, +/* pos 00f4: 67 */ 0xE4 /* 'd' -> */, +/* pos 00f5: 68 */ 0xAD /* '-' -> */, +/* pos 00f6: 69 */ 0xF3 /* 's' -> */, +/* pos 00f7: 70 */ 0xE9 /* 'i' -> */, +/* pos 00f8: 71 */ 0xEE /* 'n' -> */, +/* pos 00f9: 72 */ 0xE3 /* 'c' -> */, +/* pos 00fa: 73 */ 0xE5 /* 'e' -> */, +/* pos 00fb: 74 */ 0xBA /* ':' -> */, +/* pos 00fc: 75 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 00fe: 76 */ 0xEF /* 'o' -> */, +/* pos 00ff: 77 */ 0xEE /* 'n' -> */, +/* pos 0100: 78 */ 0xE5 /* 'e' -> */, +/* pos 0101: 79 */ 0xAD /* '-' -> */, +/* pos 0102: 80 */ 0xED /* 'm' -> */, +/* pos 0103: 81 */ 0xE1 /* 'a' -> */, +/* pos 0104: 82 */ 0xF4 /* 't' -> */, +/* pos 0105: 83 */ 0xE3 /* 'c' -> */, +/* pos 0106: 84 */ 0xE8 /* 'h' -> */, +/* pos 0107: 85 */ 0xBA /* ':' -> */, +/* pos 0108: 86 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 010a: 87 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x0117 state 88) */, + 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x0121 state 97) */, + 0x72 /* 'r' */, 0x8E, 0x00 /* (to 0x019E state 171) */, + 0x63 /* 'c' */, 0xF8, 0x01 /* (to 0x030B state 435) */, + 0x08, /* fail */ +/* pos 0117: 88 */ 0xEE /* 'n' -> */, +/* pos 0118: 89 */ 0xE3 /* 'c' -> */, +/* pos 0119: 90 */ 0xEF /* 'o' -> */, +/* pos 011a: 91 */ 0xE4 /* 'd' -> */, +/* pos 011b: 92 */ 0xE9 /* 'i' -> */, +/* pos 011c: 93 */ 0xEE /* 'n' -> */, +/* pos 011d: 94 */ 0xE7 /* 'g' -> */, +/* pos 011e: 95 */ 0xBA /* ':' -> */, +/* pos 011f: 96 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 0121: 97 */ 0xE1 /* 'a' -> */, +/* pos 0122: 98 */ 0xEE /* 'n' -> */, +/* pos 0123: 99 */ 0xE7 /* 'g' -> */, +/* pos 0124: 100 */ 0xF5 /* 'u' -> */, +/* pos 0125: 101 */ 0xE1 /* 'a' -> */, +/* pos 0126: 102 */ 0xE7 /* 'g' -> */, +/* pos 0127: 103 */ 0xE5 /* 'e' -> */, +/* pos 0128: 104 */ 0xBA /* ':' -> */, +/* pos 0129: 105 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 012b: 106 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0132 state 107) */, + 0x6F /* 'o' */, 0x02, 0x02 /* (to 0x0330 state 469) */, + 0x08, /* fail */ +/* pos 0132: 107 */ 0xE7 /* 'g' -> */, +/* pos 0133: 108 */ 0xED /* 'm' -> */, +/* pos 0134: 109 */ 0xE1 /* 'a' -> */, +/* pos 0135: 110 */ 0xBA /* ':' -> */, +/* pos 0136: 111 */ 0x00, 0x0F /* - terminal marker 15 - */, +/* pos 0138: 112 */ 0xE3 /* 'c' -> */, +/* pos 0139: 113 */ 0xE8 /* 'h' -> */, +/* pos 013a: 114 */ 0xE5 /* 'e' -> */, +/* pos 013b: 115 */ 0xAD /* '-' -> */, +/* pos 013c: 116 */ 0xE3 /* 'c' -> */, +/* pos 013d: 117 */ 0xEF /* 'o' -> */, +/* pos 013e: 118 */ 0xEE /* 'n' -> */, +/* pos 013f: 119 */ 0xF4 /* 't' -> */, +/* pos 0140: 120 */ 0xF2 /* 'r' -> */, +/* pos 0141: 121 */ 0xEF /* 'o' -> */, +/* pos 0142: 122 */ 0xEC /* 'l' -> */, +/* pos 0143: 123 */ 0xBA /* ':' -> */, +/* pos 0144: 124 */ 0x00, 0x10 /* - terminal marker 16 - */, +/* pos 0146: 125 */ 0xF4 /* 't' -> */, +/* pos 0147: 126 */ 0xE8 /* 'h' -> */, +/* pos 0148: 127 */ 0xEF /* 'o' -> */, +/* pos 0149: 128 */ 0xF2 /* 'r' -> */, +/* pos 014a: 129 */ 0xE9 /* 'i' -> */, +/* pos 014b: 130 */ 0xFA /* 'z' -> */, +/* pos 014c: 131 */ 0xE1 /* 'a' -> */, +/* pos 014d: 132 */ 0xF4 /* 't' -> */, +/* pos 014e: 133 */ 0xE9 /* 'i' -> */, +/* pos 014f: 134 */ 0xEF /* 'o' -> */, +/* pos 0150: 135 */ 0xEE /* 'n' -> */, +/* pos 0151: 136 */ 0xBA /* ':' -> */, +/* pos 0152: 137 */ 0x00, 0x11 /* - terminal marker 17 - */, +/* pos 0154: 138 */ 0xEB /* 'k' -> */, +/* pos 0155: 139 */ 0xE9 /* 'i' -> */, +/* pos 0156: 140 */ 0xE5 /* 'e' -> */, +/* pos 0157: 141 */ 0xBA /* ':' -> */, +/* pos 0158: 142 */ 0x00, 0x12 /* - terminal marker 18 - */, +/* pos 015a: 143 */ 0xE5 /* 'e' -> */, +/* pos 015b: 144 */ 0xEE /* 'n' -> */, +/* pos 015c: 145 */ 0xF4 /* 't' -> */, +/* pos 015d: 146 */ 0xAD /* '-' -> */, +/* pos 015e: 147 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x016E state 148) */, + 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x017F state 155) */, + 0x64 /* 'd' */, 0x4C, 0x00 /* (to 0x01B0 state 186) */, + 0x65 /* 'e' */, 0x56, 0x00 /* (to 0x01BD state 198) */, + 0x72 /* 'r' */, 0x6F, 0x00 /* (to 0x01D9 state 223) */, + 0x08, /* fail */ +/* pos 016e: 148 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0178 state 149) */, + 0x61 /* 'a' */, 0x56, 0x00 /* (to 0x01C7 state 207) */, + 0x6F /* 'o' */, 0x5C, 0x00 /* (to 0x01D0 state 215) */, + 0x08, /* fail */ +/* pos 0178: 149 */ 0xEE /* 'n' -> */, +/* pos 0179: 150 */ 0xE7 /* 'g' -> */, +/* pos 017a: 151 */ 0xF4 /* 't' -> */, +/* pos 017b: 152 */ 0xE8 /* 'h' -> */, +/* pos 017c: 153 */ 0xBA /* ':' -> */, +/* pos 017d: 154 */ 0x00, 0x13 /* - terminal marker 19 - */, +/* pos 017f: 155 */ 0xF9 /* 'y' -> */, +/* pos 0180: 156 */ 0xF0 /* 'p' -> */, +/* pos 0181: 157 */ 0xE5 /* 'e' -> */, +/* pos 0182: 158 */ 0xBA /* ':' -> */, +/* pos 0183: 159 */ 0x00, 0x14 /* - terminal marker 20 - */, +/* pos 0185: 160 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x018C state 161) */, + 0x65 /* 'e' */, 0x20, 0x02 /* (to 0x03A8 state 562) */, + 0x08, /* fail */ +/* pos 018c: 161 */ 0xF4 /* 't' -> */, +/* pos 018d: 162 */ 0xE5 /* 'e' -> */, +/* pos 018e: 163 */ 0xBA /* ':' -> */, +/* pos 018f: 164 */ 0x00, 0x15 /* - terminal marker 21 - */, +/* pos 0191: 165 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0198 state 166) */, + 0x65 /* 'e' */, 0xB6, 0x00 /* (to 0x024A state 304) */, + 0x08, /* fail */ +/* pos 0198: 166 */ 0xEE /* 'n' -> */, +/* pos 0199: 167 */ 0xE7 /* 'g' -> */, +/* pos 019a: 168 */ 0xE5 /* 'e' -> */, +/* pos 019b: 169 */ 0xBA /* ':' -> */, +/* pos 019c: 170 */ 0x00, 0x16 /* - terminal marker 22 - */, +/* pos 019e: 171 */ 0xE1 /* 'a' -> */, +/* pos 019f: 172 */ 0xEE /* 'n' -> */, +/* pos 01a0: 173 */ 0xE7 /* 'g' -> */, +/* pos 01a1: 174 */ 0xE5 /* 'e' -> */, +/* pos 01a2: 175 */ 0xF3 /* 's' -> */, +/* pos 01a3: 176 */ 0xBA /* ':' -> */, +/* pos 01a4: 177 */ 0x00, 0x19 /* - terminal marker 25 - */, +/* pos 01a6: 178 */ 0xE5 /* 'e' -> */, +/* pos 01a7: 179 */ 0xBA /* ':' -> */, +/* pos 01a8: 180 */ 0x00, 0x1B /* - terminal marker 27 - */, +/* pos 01aa: 181 */ 0xEC /* 'l' -> */, +/* pos 01ab: 182 */ 0xEF /* 'o' -> */, +/* pos 01ac: 183 */ 0xF7 /* 'w' -> */, +/* pos 01ad: 184 */ 0xBA /* ':' -> */, +/* pos 01ae: 185 */ 0x00, 0x1C /* - terminal marker 28 - */, +/* pos 01b0: 186 */ 0xE9 /* 'i' -> */, +/* pos 01b1: 187 */ 0xF3 /* 's' -> */, +/* pos 01b2: 188 */ 0xF0 /* 'p' -> */, +/* pos 01b3: 189 */ 0xEF /* 'o' -> */, +/* pos 01b4: 190 */ 0xF3 /* 's' -> */, +/* pos 01b5: 191 */ 0xE9 /* 'i' -> */, +/* pos 01b6: 192 */ 0xF4 /* 't' -> */, +/* pos 01b7: 193 */ 0xE9 /* 'i' -> */, +/* pos 01b8: 194 */ 0xEF /* 'o' -> */, +/* pos 01b9: 195 */ 0xEE /* 'n' -> */, +/* pos 01ba: 196 */ 0xBA /* ':' -> */, +/* pos 01bb: 197 */ 0x00, 0x1D /* - terminal marker 29 - */, +/* pos 01bd: 198 */ 0xEE /* 'n' -> */, +/* pos 01be: 199 */ 0xE3 /* 'c' -> */, +/* pos 01bf: 200 */ 0xEF /* 'o' -> */, +/* pos 01c0: 201 */ 0xE4 /* 'd' -> */, +/* pos 01c1: 202 */ 0xE9 /* 'i' -> */, +/* pos 01c2: 203 */ 0xEE /* 'n' -> */, +/* pos 01c3: 204 */ 0xE7 /* 'g' -> */, +/* pos 01c4: 205 */ 0xBA /* ':' -> */, +/* pos 01c5: 206 */ 0x00, 0x1E /* - terminal marker 30 - */, +/* pos 01c7: 207 */ 0xEE /* 'n' -> */, +/* pos 01c8: 208 */ 0xE7 /* 'g' -> */, +/* pos 01c9: 209 */ 0xF5 /* 'u' -> */, +/* pos 01ca: 210 */ 0xE1 /* 'a' -> */, +/* pos 01cb: 211 */ 0xE7 /* 'g' -> */, +/* pos 01cc: 212 */ 0xE5 /* 'e' -> */, +/* pos 01cd: 213 */ 0xBA /* ':' -> */, +/* pos 01ce: 214 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 01d0: 215 */ 0xE3 /* 'c' -> */, +/* pos 01d1: 216 */ 0xE1 /* 'a' -> */, +/* pos 01d2: 217 */ 0xF4 /* 't' -> */, +/* pos 01d3: 218 */ 0xE9 /* 'i' -> */, +/* pos 01d4: 219 */ 0xEF /* 'o' -> */, +/* pos 01d5: 220 */ 0xEE /* 'n' -> */, +/* pos 01d6: 221 */ 0xBA /* ':' -> */, +/* pos 01d7: 222 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 01d9: 223 */ 0xE1 /* 'a' -> */, +/* pos 01da: 224 */ 0xEE /* 'n' -> */, +/* pos 01db: 225 */ 0xE7 /* 'g' -> */, +/* pos 01dc: 226 */ 0xE5 /* 'e' -> */, +/* pos 01dd: 227 */ 0xBA /* ':' -> */, +/* pos 01de: 228 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* pos 01e0: 229 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x01E7 state 230) */, + 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x01EC state 234) */, + 0x08, /* fail */ +/* pos 01e7: 230 */ 0xE1 /* 'a' -> */, +/* pos 01e8: 231 */ 0xE7 /* 'g' -> */, +/* pos 01e9: 232 */ 0xBA /* ':' -> */, +/* pos 01ea: 233 */ 0x00, 0x22 /* - terminal marker 34 - */, +/* pos 01ec: 234 */ 0xF0 /* 'p' -> */, +/* pos 01ed: 235 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01F4 state 236) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x01F9 state 240) */, + 0x08, /* fail */ +/* pos 01f4: 236 */ 0xE3 /* 'c' -> */, +/* pos 01f5: 237 */ 0xF4 /* 't' -> */, +/* pos 01f6: 238 */ 0xBA /* ':' -> */, +/* pos 01f7: 239 */ 0x00, 0x23 /* - terminal marker 35 - */, +/* pos 01f9: 240 */ 0xF2 /* 'r' -> */, +/* pos 01fa: 241 */ 0xE5 /* 'e' -> */, +/* pos 01fb: 242 */ 0xF3 /* 's' -> */, +/* pos 01fc: 243 */ 0xBA /* ':' -> */, +/* pos 01fd: 244 */ 0x00, 0x24 /* - terminal marker 36 - */, +/* pos 01ff: 245 */ 0xF2 /* 'r' -> */, +/* pos 0200: 246 */ 0xEF /* 'o' -> */, +/* pos 0201: 247 */ 0xED /* 'm' -> */, +/* pos 0202: 248 */ 0xBA /* ':' -> */, +/* pos 0203: 249 */ 0x00, 0x25 /* - terminal marker 37 - */, +/* pos 0205: 250 */ 0xF4 /* 't' -> */, +/* pos 0206: 251 */ 0xE3 /* 'c' -> */, +/* pos 0207: 252 */ 0xE8 /* 'h' -> */, +/* pos 0208: 253 */ 0xBA /* ':' -> */, +/* pos 0209: 254 */ 0x00, 0x26 /* - terminal marker 38 - */, +/* pos 020b: 255 */ 0xE1 /* 'a' -> */, +/* pos 020c: 256 */ 0xEE /* 'n' -> */, +/* pos 020d: 257 */ 0xE7 /* 'g' -> */, +/* pos 020e: 258 */ 0xE5 /* 'e' -> */, +/* pos 020f: 259 */ 0xBA /* ':' -> */, +/* pos 0210: 260 */ 0x00, 0x27 /* - terminal marker 39 - */, +/* pos 0212: 261 */ 0xEE /* 'n' -> */, +/* pos 0213: 262 */ 0xED /* 'm' -> */, +/* pos 0214: 263 */ 0xEF /* 'o' -> */, +/* pos 0215: 264 */ 0xE4 /* 'd' -> */, +/* pos 0216: 265 */ 0xE9 /* 'i' -> */, +/* pos 0217: 266 */ 0xE6 /* 'f' -> */, +/* pos 0218: 267 */ 0xE9 /* 'i' -> */, +/* pos 0219: 268 */ 0xE5 /* 'e' -> */, +/* pos 021a: 269 */ 0xE4 /* 'd' -> */, +/* pos 021b: 270 */ 0xAD /* '-' -> */, +/* pos 021c: 271 */ 0xF3 /* 's' -> */, +/* pos 021d: 272 */ 0xE9 /* 'i' -> */, +/* pos 021e: 273 */ 0xEE /* 'n' -> */, +/* pos 021f: 274 */ 0xE3 /* 'c' -> */, +/* pos 0220: 275 */ 0xE5 /* 'e' -> */, +/* pos 0221: 276 */ 0xBA /* ':' -> */, +/* pos 0222: 277 */ 0x00, 0x28 /* - terminal marker 40 - */, +/* pos 0224: 278 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x022E state 279) */, + 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x023C state 292) */, + 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0241 state 296) */, + 0x08, /* fail */ +/* pos 022e: 279 */ 0xF3 /* 's' -> */, +/* pos 022f: 280 */ 0xF4 /* 't' -> */, +/* pos 0230: 281 */ 0xAD /* '-' -> */, +/* pos 0231: 282 */ 0xED /* 'm' -> */, +/* pos 0232: 283 */ 0xEF /* 'o' -> */, +/* pos 0233: 284 */ 0xE4 /* 'd' -> */, +/* pos 0234: 285 */ 0xE9 /* 'i' -> */, +/* pos 0235: 286 */ 0xE6 /* 'f' -> */, +/* pos 0236: 287 */ 0xE9 /* 'i' -> */, +/* pos 0237: 288 */ 0xE5 /* 'e' -> */, +/* pos 0238: 289 */ 0xE4 /* 'd' -> */, +/* pos 0239: 290 */ 0xBA /* ':' -> */, +/* pos 023a: 291 */ 0x00, 0x29 /* - terminal marker 41 - */, +/* pos 023c: 292 */ 0xEE /* 'n' -> */, +/* pos 023d: 293 */ 0xEB /* 'k' -> */, +/* pos 023e: 294 */ 0xBA /* ':' -> */, +/* pos 023f: 295 */ 0x00, 0x2A /* - terminal marker 42 - */, +/* pos 0241: 296 */ 0xE3 /* 'c' -> */, +/* pos 0242: 297 */ 0xE1 /* 'a' -> */, +/* pos 0243: 298 */ 0xF4 /* 't' -> */, +/* pos 0244: 299 */ 0xE9 /* 'i' -> */, +/* pos 0245: 300 */ 0xEF /* 'o' -> */, +/* pos 0246: 301 */ 0xEE /* 'n' -> */, +/* pos 0247: 302 */ 0xBA /* ':' -> */, +/* pos 0248: 303 */ 0x00, 0x2B /* - terminal marker 43 - */, +/* pos 024a: 304 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x0254 state 305) */, + 0x74 /* 't' */, 0x14, 0x00 /* (to 0x0261 state 311) */, + 0x70 /* 'p' */, 0x6C, 0x01 /* (to 0x03BC state 578) */, + 0x08, /* fail */ +/* pos 0254: 305 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x025B state 306) */, + 0x65 /* 'e' */, 0xAE, 0x00 /* (to 0x0305 state 430) */, + 0x08, /* fail */ +/* pos 025b: 306 */ 0xE5 /* 'e' -> */, +/* pos 025c: 307 */ 0xF3 /* 's' -> */, +/* pos 025d: 308 */ 0xE8 /* 'h' -> */, +/* pos 025e: 309 */ 0xBA /* ':' -> */, +/* pos 025f: 310 */ 0x00, 0x2F /* - terminal marker 47 - */, +/* pos 0261: 311 */ 0xF2 /* 'r' -> */, +/* pos 0262: 312 */ 0xF9 /* 'y' -> */, +/* pos 0263: 313 */ 0xAD /* '-' -> */, +/* pos 0264: 314 */ 0xE1 /* 'a' -> */, +/* pos 0265: 315 */ 0xE6 /* 'f' -> */, +/* pos 0266: 316 */ 0xF4 /* 't' -> */, +/* pos 0267: 317 */ 0xE5 /* 'e' -> */, +/* pos 0268: 318 */ 0xF2 /* 'r' -> */, +/* pos 0269: 319 */ 0xBA /* ':' -> */, +/* pos 026a: 320 */ 0x00, 0x30 /* - terminal marker 48 - */, +/* pos 026c: 321 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0273 state 322) */, + 0x74 /* 't' */, 0xEA, 0x00 /* (to 0x0359 state 496) */, + 0x08, /* fail */ +/* pos 0273: 322 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x027A state 323) */, + 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x0280 state 328) */, + 0x08, /* fail */ +/* pos 027a: 323 */ 0xF6 /* 'v' -> */, +/* pos 027b: 324 */ 0xE5 /* 'e' -> */, +/* pos 027c: 325 */ 0xF2 /* 'r' -> */, +/* pos 027d: 326 */ 0xBA /* ':' -> */, +/* pos 027e: 327 */ 0x00, 0x31 /* - terminal marker 49 - */, +/* pos 0280: 328 */ 0xAD /* '-' -> */, +/* pos 0281: 329 */ 0xE3 /* 'c' -> */, +/* pos 0282: 330 */ 0xEF /* 'o' -> */, +/* pos 0283: 331 */ 0xEF /* 'o' -> */, +/* pos 0284: 332 */ 0xEB /* 'k' -> */, +/* pos 0285: 333 */ 0xE9 /* 'i' -> */, +/* pos 0286: 334 */ 0xE5 /* 'e' -> */, +/* pos 0287: 335 */ 0xBA /* ':' -> */, +/* pos 0288: 336 */ 0x00, 0x32 /* - terminal marker 50 - */, +/* pos 028a: 337 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0291 state 338) */, + 0x65 /* 'e' */, 0x2C, 0x01 /* (to 0x03B9 state 576) */, + 0x08, /* fail */ +/* pos 0291: 338 */ 0xE1 /* 'a' -> */, +/* pos 0292: 339 */ 0xEE /* 'n' -> */, +/* pos 0293: 340 */ 0xF3 /* 's' -> */, +/* pos 0294: 341 */ 0xE6 /* 'f' -> */, +/* pos 0295: 342 */ 0xE5 /* 'e' -> */, +/* pos 0296: 343 */ 0xF2 /* 'r' -> */, +/* pos 0297: 344 */ 0xAD /* '-' -> */, +/* pos 0298: 345 */ 0xE5 /* 'e' -> */, +/* pos 0299: 346 */ 0xEE /* 'n' -> */, +/* pos 029a: 347 */ 0xE3 /* 'c' -> */, +/* pos 029b: 348 */ 0xEF /* 'o' -> */, +/* pos 029c: 349 */ 0xE4 /* 'd' -> */, +/* pos 029d: 350 */ 0xE9 /* 'i' -> */, +/* pos 029e: 351 */ 0xEE /* 'n' -> */, +/* pos 029f: 352 */ 0xE7 /* 'g' -> */, +/* pos 02a0: 353 */ 0xBA /* ':' -> */, +/* pos 02a1: 354 */ 0x00, 0x34 /* - terminal marker 52 - */, +/* pos 02a3: 355 */ 0xE9 /* 'i' -> */, +/* pos 02a4: 356 */ 0xAD /* '-' -> */, +/* pos 02a5: 357 */ 0xE1 /* 'a' -> */, +/* pos 02a6: 358 */ 0xF2 /* 'r' -> */, +/* pos 02a7: 359 */ 0xE7 /* 'g' -> */, +/* pos 02a8: 360 */ 0xF3 /* 's' -> */, +/* pos 02a9: 361 */ 0x00, 0x3C /* - terminal marker 60 - */, +/* pos 02ab: 362 */ 0xA0 /* ' ' -> */, +/* pos 02ac: 363 */ 0x00, 0x3F /* - terminal marker 63 - */, +/* pos 02ae: 364 */ 0xAD /* '-' -> */, +/* pos 02af: 365 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02B9 state 366) */, + 0x61 /* 'a' */, 0x1D, 0x00 /* (to 0x02CF state 385) */, + 0x72 /* 'r' */, 0xFB, 0x00 /* (to 0x03B0 state 568) */, + 0x08, /* fail */ +/* pos 02b9: 366 */ 0xEF /* 'o' -> */, +/* pos 02ba: 367 */ 0xF2 /* 'r' -> */, +/* pos 02bb: 368 */ 0xF7 /* 'w' -> */, +/* pos 02bc: 369 */ 0xE1 /* 'a' -> */, +/* pos 02bd: 370 */ 0xF2 /* 'r' -> */, +/* pos 02be: 371 */ 0xE4 /* 'd' -> */, +/* pos 02bf: 372 */ 0xE5 /* 'e' -> */, +/* pos 02c0: 373 */ 0xE4 /* 'd' -> */, +/* pos 02c1: 374 */ 0xAD /* '-' -> */, +/* pos 02c2: 375 */ 0xE6 /* 'f' -> */, +/* pos 02c3: 376 */ 0xEF /* 'o' -> */, +/* pos 02c4: 377 */ 0xF2 /* 'r' -> */, +/* pos 02c5: 378 */ 0xBA /* ':' -> */, +/* pos 02c6: 379 */ 0x00, 0x40 /* - terminal marker 64 - */, +/* pos 02c8: 380 */ 0x00, 0x41 /* - terminal marker 65 - */, +/* pos 02ca: 381 */ 0xE1 /* 'a' -> */, +/* pos 02cb: 382 */ 0xE4 /* 'd' -> */, +/* pos 02cc: 383 */ 0xA0 /* ' ' -> */, +/* pos 02cd: 384 */ 0x00, 0x42 /* - terminal marker 66 - */, +/* pos 02cf: 385 */ 0xF5 /* 'u' -> */, +/* pos 02d0: 386 */ 0xF4 /* 't' -> */, +/* pos 02d1: 387 */ 0xE8 /* 'h' -> */, +/* pos 02d2: 388 */ 0xAD /* '-' -> */, +/* pos 02d3: 389 */ 0xF4 /* 't' -> */, +/* pos 02d4: 390 */ 0xEF /* 'o' -> */, +/* pos 02d5: 391 */ 0xEB /* 'k' -> */, +/* pos 02d6: 392 */ 0xE5 /* 'e' -> */, +/* pos 02d7: 393 */ 0xEE /* 'n' -> */, +/* pos 02d8: 394 */ 0xBA /* ':' -> */, +/* pos 02d9: 395 */ 0x00, 0x45 /* - terminal marker 69 - */, +/* pos 02db: 396 */ 0xF4 /* 't' -> */, +/* pos 02dc: 397 */ 0xE9 /* 'i' -> */, +/* pos 02dd: 398 */ 0xEF /* 'o' -> */, +/* pos 02de: 399 */ 0xEE /* 'n' -> */, +/* pos 02df: 400 */ 0xF3 /* 's' -> */, +/* pos 02e0: 401 */ 0xA0 /* ' ' -> */, +/* pos 02e1: 402 */ 0x00, 0x02 /* - terminal marker 2 - */, +/* pos 02e3: 403 */ 0xF3 /* 's' -> */, +/* pos 02e4: 404 */ 0xAD /* '-' -> */, +/* pos 02e5: 405 */ 0xE3 /* 'c' -> */, +/* pos 02e6: 406 */ 0xEF /* 'o' -> */, +/* pos 02e7: 407 */ 0xEE /* 'n' -> */, +/* pos 02e8: 408 */ 0xF4 /* 't' -> */, +/* pos 02e9: 409 */ 0xF2 /* 'r' -> */, +/* pos 02ea: 410 */ 0xEF /* 'o' -> */, +/* pos 02eb: 411 */ 0xEC /* 'l' -> */, +/* pos 02ec: 412 */ 0xAD /* '-' -> */, +/* pos 02ed: 413 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x02F4 state 414) */, + 0x61 /* 'a' */, 0x24, 0x00 /* (to 0x0314 state 443) */, + 0x08, /* fail */ +/* pos 02f4: 414 */ 0xE5 /* 'e' -> */, +/* pos 02f5: 415 */ 0xF1 /* 'q' -> */, +/* pos 02f6: 416 */ 0xF5 /* 'u' -> */, +/* pos 02f7: 417 */ 0xE5 /* 'e' -> */, +/* pos 02f8: 418 */ 0xF3 /* 's' -> */, +/* pos 02f9: 419 */ 0xF4 /* 't' -> */, +/* pos 02fa: 420 */ 0xAD /* '-' -> */, +/* pos 02fb: 421 */ 0xE8 /* 'h' -> */, +/* pos 02fc: 422 */ 0xE5 /* 'e' -> */, +/* pos 02fd: 423 */ 0xE1 /* 'a' -> */, +/* pos 02fe: 424 */ 0xE4 /* 'd' -> */, +/* pos 02ff: 425 */ 0xE5 /* 'e' -> */, +/* pos 0300: 426 */ 0xF2 /* 'r' -> */, +/* pos 0301: 427 */ 0xF3 /* 's' -> */, +/* pos 0302: 428 */ 0xBA /* ':' -> */, +/* pos 0303: 429 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 0305: 430 */ 0xF2 /* 'r' -> */, +/* pos 0306: 431 */ 0xE5 /* 'e' -> */, +/* pos 0307: 432 */ 0xF2 /* 'r' -> */, +/* pos 0308: 433 */ 0xBA /* ':' -> */, +/* pos 0309: 434 */ 0x00, 0x17 /* - terminal marker 23 - */, +/* pos 030b: 435 */ 0xE8 /* 'h' -> */, +/* pos 030c: 436 */ 0xE1 /* 'a' -> */, +/* pos 030d: 437 */ 0xF2 /* 'r' -> */, +/* pos 030e: 438 */ 0xF3 /* 's' -> */, +/* pos 030f: 439 */ 0xE5 /* 'e' -> */, +/* pos 0310: 440 */ 0xF4 /* 't' -> */, +/* pos 0311: 441 */ 0xBA /* ':' -> */, +/* pos 0312: 442 */ 0x00, 0x18 /* - terminal marker 24 - */, +/* pos 0314: 443 */ 0xEC /* 'l' -> */, +/* pos 0315: 444 */ 0xEC /* 'l' -> */, +/* pos 0316: 445 */ 0xEF /* 'o' -> */, +/* pos 0317: 446 */ 0xF7 /* 'w' -> */, +/* pos 0318: 447 */ 0xAD /* '-' -> */, +/* pos 0319: 448 */ 0xEF /* 'o' -> */, +/* pos 031a: 449 */ 0xF2 /* 'r' -> */, +/* pos 031b: 450 */ 0xE9 /* 'i' -> */, +/* pos 031c: 451 */ 0xE7 /* 'g' -> */, +/* pos 031d: 452 */ 0xE9 /* 'i' -> */, +/* pos 031e: 453 */ 0xEE /* 'n' -> */, +/* pos 031f: 454 */ 0xBA /* ':' -> */, +/* pos 0320: 455 */ 0x00, 0x1A /* - terminal marker 26 - */, +/* pos 0322: 456 */ 0xE1 /* 'a' -> */, +/* pos 0323: 457 */ 0xF8 /* 'x' -> */, +/* pos 0324: 458 */ 0xAD /* '-' -> */, +/* pos 0325: 459 */ 0xE6 /* 'f' -> */, +/* pos 0326: 460 */ 0xEF /* 'o' -> */, +/* pos 0327: 461 */ 0xF2 /* 'r' -> */, +/* pos 0328: 462 */ 0xF7 /* 'w' -> */, +/* pos 0329: 463 */ 0xE1 /* 'a' -> */, +/* pos 032a: 464 */ 0xF2 /* 'r' -> */, +/* pos 032b: 465 */ 0xE4 /* 'd' -> */, +/* pos 032c: 466 */ 0xF3 /* 's' -> */, +/* pos 032d: 467 */ 0xBA /* ':' -> */, +/* pos 032e: 468 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 0330: 469 */ 0xF8 /* 'x' -> */, +/* pos 0331: 470 */ 0xF9 /* 'y' -> */, +/* pos 0332: 471 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x0339 state 472) */, + 0x20 /* ' ' */, 0x79, 0x00 /* (to 0x03AE state 567) */, + 0x08, /* fail */ +/* pos 0339: 472 */ 0xE1 /* 'a' -> */, +/* pos 033a: 473 */ 0xF5 /* 'u' -> */, +/* pos 033b: 474 */ 0xF4 /* 't' -> */, +/* pos 033c: 475 */ 0xE8 /* 'h' -> */, +/* pos 033d: 476 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0344 state 477) */, + 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x034E state 486) */, + 0x08, /* fail */ +/* pos 0344: 477 */ 0xEE /* 'n' -> */, +/* pos 0345: 478 */ 0xF4 /* 't' -> */, +/* pos 0346: 479 */ 0xE9 /* 'i' -> */, +/* pos 0347: 480 */ 0xE3 /* 'c' -> */, +/* pos 0348: 481 */ 0xE1 /* 'a' -> */, +/* pos 0349: 482 */ 0xF4 /* 't' -> */, +/* pos 034a: 483 */ 0xE5 /* 'e' -> */, +/* pos 034b: 484 */ 0xBA /* ':' -> */, +/* pos 034c: 485 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 034e: 486 */ 0xF2 /* 'r' -> */, +/* pos 034f: 487 */ 0xE9 /* 'i' -> */, +/* pos 0350: 488 */ 0xFA /* 'z' -> */, +/* pos 0351: 489 */ 0xE1 /* 'a' -> */, +/* pos 0352: 490 */ 0xF4 /* 't' -> */, +/* pos 0353: 491 */ 0xE9 /* 'i' -> */, +/* pos 0354: 492 */ 0xEF /* 'o' -> */, +/* pos 0355: 493 */ 0xEE /* 'n' -> */, +/* pos 0356: 494 */ 0xBA /* ':' -> */, +/* pos 0357: 495 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 0359: 496 */ 0xF2 /* 'r' -> */, +/* pos 035a: 497 */ 0xE9 /* 'i' -> */, +/* pos 035b: 498 */ 0xE3 /* 'c' -> */, +/* pos 035c: 499 */ 0xF4 /* 't' -> */, +/* pos 035d: 500 */ 0xAD /* '-' -> */, +/* pos 035e: 501 */ 0xF4 /* 't' -> */, +/* pos 035f: 502 */ 0xF2 /* 'r' -> */, +/* pos 0360: 503 */ 0xE1 /* 'a' -> */, +/* pos 0361: 504 */ 0xEE /* 'n' -> */, +/* pos 0362: 505 */ 0xF3 /* 's' -> */, +/* pos 0363: 506 */ 0xF0 /* 'p' -> */, +/* pos 0364: 507 */ 0xEF /* 'o' -> */, +/* pos 0365: 508 */ 0xF2 /* 'r' -> */, +/* pos 0366: 509 */ 0xF4 /* 't' -> */, +/* pos 0367: 510 */ 0xAD /* '-' -> */, +/* pos 0368: 511 */ 0xF3 /* 's' -> */, +/* pos 0369: 512 */ 0xE5 /* 'e' -> */, +/* pos 036a: 513 */ 0xE3 /* 'c' -> */, +/* pos 036b: 514 */ 0xF5 /* 'u' -> */, +/* pos 036c: 515 */ 0xF2 /* 'r' -> */, +/* pos 036d: 516 */ 0xE9 /* 'i' -> */, +/* pos 036e: 517 */ 0xF4 /* 't' -> */, +/* pos 036f: 518 */ 0xF9 /* 'y' -> */, +/* pos 0370: 519 */ 0xBA /* ':' -> */, +/* pos 0371: 520 */ 0x00, 0x33 /* - terminal marker 51 - */, +/* pos 0373: 521 */ 0xE5 /* 'e' -> */, +/* pos 0374: 522 */ 0xF2 /* 'r' -> */, +/* pos 0375: 523 */ 0xAD /* '-' -> */, +/* pos 0376: 524 */ 0xE1 /* 'a' -> */, +/* pos 0377: 525 */ 0xE7 /* 'g' -> */, +/* pos 0378: 526 */ 0xE5 /* 'e' -> */, +/* pos 0379: 527 */ 0xEE /* 'n' -> */, +/* pos 037a: 528 */ 0xF4 /* 't' -> */, +/* pos 037b: 529 */ 0xBA /* ':' -> */, +/* pos 037c: 530 */ 0x00, 0x35 /* - terminal marker 53 - */, +/* pos 037e: 531 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0385 state 532) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x038A state 536) */, + 0x08, /* fail */ +/* pos 0385: 532 */ 0xF2 /* 'r' -> */, +/* pos 0386: 533 */ 0xF9 /* 'y' -> */, +/* pos 0387: 534 */ 0xBA /* ':' -> */, +/* pos 0388: 535 */ 0x00, 0x36 /* - terminal marker 54 - */, +/* pos 038a: 536 */ 0xE1 /* 'a' -> */, +/* pos 038b: 537 */ 0xBA /* ':' -> */, +/* pos 038c: 538 */ 0x00, 0x37 /* - terminal marker 55 - */, +/* pos 038e: 539 */ 0xF7 /* 'w' -> */, +/* pos 038f: 540 */ 0xF7 /* 'w' -> */, +/* pos 0390: 541 */ 0xAD /* '-' -> */, +/* pos 0391: 542 */ 0xE1 /* 'a' -> */, +/* pos 0392: 543 */ 0xF5 /* 'u' -> */, +/* pos 0393: 544 */ 0xF4 /* 't' -> */, +/* pos 0394: 545 */ 0xE8 /* 'h' -> */, +/* pos 0395: 546 */ 0xE5 /* 'e' -> */, +/* pos 0396: 547 */ 0xEE /* 'n' -> */, +/* pos 0397: 548 */ 0xF4 /* 't' -> */, +/* pos 0398: 549 */ 0xE9 /* 'i' -> */, +/* pos 0399: 550 */ 0xE3 /* 'c' -> */, +/* pos 039a: 551 */ 0xE1 /* 'a' -> */, +/* pos 039b: 552 */ 0xF4 /* 't' -> */, +/* pos 039c: 553 */ 0xE5 /* 'e' -> */, +/* pos 039d: 554 */ 0xBA /* ':' -> */, +/* pos 039e: 555 */ 0x00, 0x38 /* - terminal marker 56 - */, +/* pos 03a0: 556 */ 0xF4 /* 't' -> */, +/* pos 03a1: 557 */ 0xE3 /* 'c' -> */, +/* pos 03a2: 558 */ 0xE8 /* 'h' -> */, +/* pos 03a3: 559 */ 0x00, 0x39 /* - terminal marker 57 - */, +/* pos 03a5: 560 */ 0xF4 /* 't' -> */, +/* pos 03a6: 561 */ 0x00, 0x3A /* - terminal marker 58 - */, +/* pos 03a8: 562 */ 0xEC /* 'l' -> */, +/* pos 03a9: 563 */ 0xE5 /* 'e' -> */, +/* pos 03aa: 564 */ 0xF4 /* 't' -> */, +/* pos 03ab: 565 */ 0xE5 /* 'e' -> */, +/* pos 03ac: 566 */ 0x00, 0x3B /* - terminal marker 59 - */, +/* pos 03ae: 567 */ 0x00, 0x3D /* - terminal marker 61 - */, +/* pos 03b0: 568 */ 0xE5 /* 'e' -> */, +/* pos 03b1: 569 */ 0xE1 /* 'a' -> */, +/* pos 03b2: 570 */ 0xEC /* 'l' -> */, +/* pos 03b3: 571 */ 0xAD /* '-' -> */, +/* pos 03b4: 572 */ 0xE9 /* 'i' -> */, +/* pos 03b5: 573 */ 0xF0 /* 'p' -> */, +/* pos 03b6: 574 */ 0xBA /* ':' -> */, +/* pos 03b7: 575 */ 0x00, 0x3E /* - terminal marker 62 - */, +/* pos 03b9: 576 */ 0xBA /* ':' -> */, +/* pos 03ba: 577 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 03bc: 578 */ 0xEC /* 'l' -> */, +/* pos 03bd: 579 */ 0xE1 /* 'a' -> */, +/* pos 03be: 580 */ 0xF9 /* 'y' -> */, +/* pos 03bf: 581 */ 0xAD /* '-' -> */, +/* pos 03c0: 582 */ 0xEE /* 'n' -> */, +/* pos 03c1: 583 */ 0xEF /* 'o' -> */, +/* pos 03c2: 584 */ 0xEE /* 'n' -> */, +/* pos 03c3: 585 */ 0xE3 /* 'c' -> */, +/* pos 03c4: 586 */ 0xE5 /* 'e' -> */, +/* pos 03c5: 587 */ 0xBA /* ':' -> */, +/* pos 03c6: 588 */ 0x00, 0x44 /* - terminal marker 68 - */, +/* total size 968 bytes */ #endif #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) @@ -1354,8 +1307,8 @@ /* 12: 13: sec-websocket-accept: */ /* 13: 14: sec-websocket-nonce: */ /* 14: 15: http/1.1 */ - /* 15: 16: http2-settings: */ - /* 16: 18: access-control-request-headers: */ + /* 15: 17: accept: */ + /* 16: 19: if-modified-since: */ /* 17: 20: if-none-match: */ /* 18: 21: accept-encoding: */ /* 19: 22: accept-language: */ @@ -1367,11 +1320,11 @@ /* 25: 28: content-type: */ /* 26: 29: date: */ /* 27: 30: range: */ - /* 28: 31: referer: */ + /* 28: 32: sec-websocket-key: */ /* 29: 33: sec-websocket-version: */ /* 30: 34: sec-websocket-origin: */ - /* 31: 35: :authority */ - /* 32: 42: access-control-allow-origin: */ + /* 31: 41: accept-ranges: */ + /* 32: 43: age: */ /* 33: 44: allow: */ /* 34: 45: content-disposition: */ /* 35: 46: content-encoding: */ @@ -1388,807 +1341,797 @@ /* 46: 57: last-modified: */ /* 47: 58: link: */ /* 48: 59: location: */ - /* 49: 60: max-forwards: */ + /* 49: 63: refresh: */ /* 50: 64: retry-after: */ /* 51: 65: server: */ /* 52: 66: set-cookie: */ - /* 53: 67: strict-transport-security: */ - /* 54: 69: user-agent: */ - /* 55: 77: proxy */ + /* 53: 68: transfer-encoding: */ + /* 54: 76: uri-args */ + /* 55: 79: http/1.0 */ /* 56: 80: x-forwarded-for: */ /* 57: 81: connect */ /* 58: 82: head */ - /* 59: 83: te: */ + /* 59: 86: x-auth-token: */ /* 60: 87: */ -/* pos 0000: 0 */ 0x67 /* 'g' */, 0x40, 0x00 /* (to 0x0040 state 1) */, - 0x70 /* 'p' */, 0x42, 0x00 /* (to 0x0045 state 5) */, - 0x68 /* 'h' */, 0x51, 0x00 /* (to 0x0057 state 10) */, - 0x63 /* 'c' */, 0x5D, 0x00 /* (to 0x0066 state 15) */, - 0x75 /* 'u' */, 0x7E, 0x00 /* (to 0x008A state 26) */, - 0x6F /* 'o' */, 0x8D, 0x00 /* (to 0x009C state 34) */, - 0x0D /* '.' */, 0x98, 0x00 /* (to 0x00AA state 41) */, - 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 57) */, - 0x69 /* 'i' */, 0xE2, 0x00 /* (to 0x00FA state 88) */, - 0x64 /* 'd' */, 0x74, 0x01 /* (to 0x018F state 177) */, - 0x72 /* 'r' */, 0x7D, 0x01 /* (to 0x019B state 182) */, - 0x65 /* 'e' */, 0xE2, 0x01 /* (to 0x0203 state 256) */, - 0x66 /* 'f' */, 0xFE, 0x01 /* (to 0x0222 state 272) */, - 0x6C /* 'l' */, 0x27, 0x02 /* (to 0x024E state 306) */, - 0x6D /* 'm' */, 0x4A, 0x02 /* (to 0x0274 state 332) */, - 0x73 /* 's' */, 0x60, 0x02 /* (to 0x028D state 355) */, - 0x78 /* 'x' */, 0xAE, 0x02 /* (to 0x02DE state 410) */, - 0x74 /* 't' */, 0xC9, 0x02 /* (to 0x02FC state 431) */, - 0x76 /* 'v' */, 0x5D, 0x03 /* (to 0x0393 state 527) */, - 0x77 /* 'w' */, 0x6A, 0x03 /* (to 0x03A3 state 535) */, - 0x3A /* ':' */, 0xB0, 0x03 /* (to 0x03EC state 594) */, - 0x08, /* fail */ -/* pos 0040: 1 */ 0xE5 /* 'e' -> */, -/* pos 0041: 2 */ 0xF4 /* 't' -> */, -/* pos 0042: 3 */ 0xA0 /* ' ' -> */, -/* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, -/* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */, - 0x72 /* 'r' */, 0xED, 0x00 /* (to 0x0135 state 123) */, - 0x61 /* 'a' */, 0x6A, 0x03 /* (to 0x03B5 state 552) */, - 0x75 /* 'u' */, 0x6C, 0x03 /* (to 0x03BA state 556) */, - 0x08, /* fail */ -/* pos 0052: 6 */ 0xF3 /* 's' -> */, -/* pos 0053: 7 */ 0xF4 /* 't' -> */, -/* pos 0054: 8 */ 0xA0 /* ' ' -> */, -/* pos 0055: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, -/* pos 0057: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0061 state 11) */, - 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AD state 43) */, - 0x65 /* 'e' */, 0x9A, 0x02 /* (to 0x02F7 state 427) */, - 0x08, /* fail */ -/* pos 0061: 11 */ 0xF3 /* 's' -> */, -/* pos 0062: 12 */ 0xF4 /* 't' -> */, -/* pos 0063: 13 */ 0xBA /* ':' -> */, -/* pos 0064: 14 */ 0x00, 0x02 /* - terminal marker 2 - */, -/* pos 0066: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006D state 16) */, - 0x61 /* 'a' */, 0xD9, 0x00 /* (to 0x0142 state 129) */, - 0x08, /* fail */ -/* pos 006d: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0074 state 17) */, - 0x6F /* 'o' */, 0xEE, 0x00 /* (to 0x015E state 155) */, - 0x08, /* fail */ -/* pos 0074: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x007B state 18) */, - 0x74 /* 't' */, 0xED, 0x00 /* (to 0x0164 state 160) */, - 0x08, /* fail */ -/* pos 007b: 18 */ 0xE5 /* 'e' -> */, -/* pos 007c: 19 */ 0xE3 /* 'c' -> */, -/* pos 007d: 20 */ 0xF4 /* 't' -> */, -/* pos 007e: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0085 state 22) */, - 0x20 /* ' ' */, 0x74, 0x02 /* (to 0x02F5 state 426) */, - 0x08, /* fail */ -/* pos 0085: 22 */ 0xEF /* 'o' -> */, -/* pos 0086: 23 */ 0xEE /* 'n' -> */, -/* pos 0087: 24 */ 0xBA /* ':' -> */, -/* pos 0088: 25 */ 0x00, 0x03 /* - terminal marker 3 - */, -/* pos 008a: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0094 state 27) */, - 0x73 /* 's' */, 0x3B, 0x02 /* (to 0x02C8 state 396) */, - 0x72 /* 'r' */, 0x33, 0x03 /* (to 0x03C3 state 563) */, - 0x08, /* fail */ -/* pos 0094: 27 */ 0xE7 /* 'g' -> */, -/* pos 0095: 28 */ 0xF2 /* 'r' -> */, -/* pos 0096: 29 */ 0xE1 /* 'a' -> */, -/* pos 0097: 30 */ 0xE4 /* 'd' -> */, -/* pos 0098: 31 */ 0xE5 /* 'e' -> */, -/* pos 0099: 32 */ 0xBA /* ':' -> */, -/* pos 009a: 33 */ 0x00, 0x04 /* - terminal marker 4 - */, -/* pos 009c: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A3 state 35) */, - 0x70 /* 'p' */, 0x67, 0x02 /* (to 0x0306 state 434) */, - 0x08, /* fail */ -/* pos 00a3: 35 */ 0xE9 /* 'i' -> */, -/* pos 00a4: 36 */ 0xE7 /* 'g' -> */, -/* pos 00a5: 37 */ 0xE9 /* 'i' -> */, -/* pos 00a6: 38 */ 0xEE /* 'n' -> */, -/* pos 00a7: 39 */ 0xBA /* ':' -> */, -/* pos 00a8: 40 */ 0x00, 0x05 /* - terminal marker 5 - */, -/* pos 00aa: 41 */ 0x8A /* '.' -> */, -/* pos 00ab: 42 */ 0x00, 0x07 /* - terminal marker 7 - */, -/* pos 00ad: 43 */ 0xF4 /* 't' -> */, -/* pos 00ae: 44 */ 0xF0 /* 'p' -> */, -/* pos 00af: 45 */ 0x32 /* '2' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, - 0x2F /* '/' */, 0x22, 0x03 /* (to 0x03D4 state 578) */, - 0x08, /* fail */ -/* pos 00b6: 46 */ 0xAD /* '-' -> */, -/* pos 00b7: 47 */ 0xF3 /* 's' -> */, -/* pos 00b8: 48 */ 0xE5 /* 'e' -> */, -/* pos 00b9: 49 */ 0xF4 /* 't' -> */, -/* pos 00ba: 50 */ 0xF4 /* 't' -> */, -/* pos 00bb: 51 */ 0xE9 /* 'i' -> */, -/* pos 00bc: 52 */ 0xEE /* 'n' -> */, -/* pos 00bd: 53 */ 0xE7 /* 'g' -> */, -/* pos 00be: 54 */ 0xF3 /* 's' -> */, -/* pos 00bf: 55 */ 0xBA /* ':' -> */, -/* pos 00c0: 56 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 00c2: 57 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 58) */, - 0x75 /* 'u' */, 0x8B, 0x00 /* (to 0x0150 state 142) */, - 0x6C /* 'l' */, 0x05, 0x01 /* (to 0x01CD state 208) */, - 0x67 /* 'g' */, 0x8C, 0x02 /* (to 0x0357 state 478) */, - 0x08, /* fail */ -/* pos 00cf: 58 */ 0xE3 /* 'c' -> */, -/* pos 00d0: 59 */ 0xE5 /* 'e' -> */, -/* pos 00d1: 60 */ 0x73 /* 's' */, 0x07, 0x00 /* (to 0x00D8 state 61) */, - 0x70 /* 'p' */, 0x41, 0x00 /* (to 0x0115 state 102) */, - 0x08, /* fail */ -/* pos 00d8: 61 */ 0xF3 /* 's' -> */, -/* pos 00d9: 62 */ 0xAD /* '-' -> */, -/* pos 00da: 63 */ 0xE3 /* 'c' -> */, -/* pos 00db: 64 */ 0xEF /* 'o' -> */, -/* pos 00dc: 65 */ 0xEE /* 'n' -> */, -/* pos 00dd: 66 */ 0xF4 /* 't' -> */, -/* pos 00de: 67 */ 0xF2 /* 'r' -> */, -/* pos 00df: 68 */ 0xEF /* 'o' -> */, -/* pos 00e0: 69 */ 0xEC /* 'l' -> */, -/* pos 00e1: 70 */ 0xAD /* '-' -> */, -/* pos 00e2: 71 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00E9 state 72) */, - 0x61 /* 'a' */, 0xDA, 0x00 /* (to 0x01BF state 195) */, - 0x08, /* fail */ -/* pos 00e9: 72 */ 0xE5 /* 'e' -> */, -/* pos 00ea: 73 */ 0xF1 /* 'q' -> */, -/* pos 00eb: 74 */ 0xF5 /* 'u' -> */, -/* pos 00ec: 75 */ 0xE5 /* 'e' -> */, -/* pos 00ed: 76 */ 0xF3 /* 's' -> */, -/* pos 00ee: 77 */ 0xF4 /* 't' -> */, -/* pos 00ef: 78 */ 0xAD /* '-' -> */, -/* pos 00f0: 79 */ 0xE8 /* 'h' -> */, -/* pos 00f1: 80 */ 0xE5 /* 'e' -> */, -/* pos 00f2: 81 */ 0xE1 /* 'a' -> */, -/* pos 00f3: 82 */ 0xE4 /* 'd' -> */, -/* pos 00f4: 83 */ 0xE5 /* 'e' -> */, -/* pos 00f5: 84 */ 0xF2 /* 'r' -> */, -/* pos 00f6: 85 */ 0xF3 /* 's' -> */, -/* pos 00f7: 86 */ 0xBA /* ':' -> */, -/* pos 00f8: 87 */ 0x00, 0x10 /* - terminal marker 16 - */, -/* pos 00fa: 88 */ 0xE6 /* 'f' -> */, -/* pos 00fb: 89 */ 0xAD /* '-' -> */, -/* pos 00fc: 90 */ 0x6E /* 'n' */, 0x0D, 0x00 /* (to 0x0109 state 91) */, - 0x6D /* 'm' */, 0x29, 0x01 /* (to 0x0228 state 277) */, - 0x72 /* 'r' */, 0x33, 0x01 /* (to 0x0235 state 283) */, - 0x75 /* 'u' */, 0x37, 0x01 /* (to 0x023C state 289) */, - 0x08, /* fail */ -/* pos 0109: 91 */ 0xEF /* 'o' -> */, -/* pos 010a: 92 */ 0xEE /* 'n' -> */, -/* pos 010b: 93 */ 0xE5 /* 'e' -> */, -/* pos 010c: 94 */ 0xAD /* '-' -> */, -/* pos 010d: 95 */ 0xED /* 'm' -> */, -/* pos 010e: 96 */ 0xE1 /* 'a' -> */, -/* pos 010f: 97 */ 0xF4 /* 't' -> */, -/* pos 0110: 98 */ 0xE3 /* 'c' -> */, -/* pos 0111: 99 */ 0xE8 /* 'h' -> */, -/* pos 0112: 100 */ 0xBA /* ':' -> */, -/* pos 0113: 101 */ 0x00, 0x11 /* - terminal marker 17 - */, -/* pos 0115: 102 */ 0xF4 /* 't' -> */, -/* pos 0116: 103 */ 0xAD /* '-' -> */, -/* pos 0117: 104 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0121 state 105) */, - 0x6C /* 'l' */, 0x11, 0x00 /* (to 0x012B state 114) */, - 0x72 /* 'r' */, 0x32, 0x02 /* (to 0x034F state 471) */, - 0x08, /* fail */ -/* pos 0121: 105 */ 0xEE /* 'n' -> */, -/* pos 0122: 106 */ 0xE3 /* 'c' -> */, -/* pos 0123: 107 */ 0xEF /* 'o' -> */, -/* pos 0124: 108 */ 0xE4 /* 'd' -> */, -/* pos 0125: 109 */ 0xE9 /* 'i' -> */, -/* pos 0126: 110 */ 0xEE /* 'n' -> */, -/* pos 0127: 111 */ 0xE7 /* 'g' -> */, -/* pos 0128: 112 */ 0xBA /* ':' -> */, -/* pos 0129: 113 */ 0x00, 0x12 /* - terminal marker 18 - */, -/* pos 012b: 114 */ 0xE1 /* 'a' -> */, -/* pos 012c: 115 */ 0xEE /* 'n' -> */, -/* pos 012d: 116 */ 0xE7 /* 'g' -> */, -/* pos 012e: 117 */ 0xF5 /* 'u' -> */, -/* pos 012f: 118 */ 0xE1 /* 'a' -> */, -/* pos 0130: 119 */ 0xE7 /* 'g' -> */, -/* pos 0131: 120 */ 0xE5 /* 'e' -> */, -/* pos 0132: 121 */ 0xBA /* ':' -> */, -/* pos 0133: 122 */ 0x00, 0x13 /* - terminal marker 19 - */, -/* pos 0135: 123 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x013C state 124) */, - 0x6F /* 'o' */, 0x9B, 0x01 /* (to 0x02D3 state 406) */, - 0x08, /* fail */ -/* pos 013c: 124 */ 0xE7 /* 'g' -> */, -/* pos 013d: 125 */ 0xED /* 'm' -> */, -/* pos 013e: 126 */ 0xE1 /* 'a' -> */, -/* pos 013f: 127 */ 0xBA /* ':' -> */, -/* pos 0140: 128 */ 0x00, 0x14 /* - terminal marker 20 - */, -/* pos 0142: 129 */ 0xE3 /* 'c' -> */, -/* pos 0143: 130 */ 0xE8 /* 'h' -> */, -/* pos 0144: 131 */ 0xE5 /* 'e' -> */, -/* pos 0145: 132 */ 0xAD /* '-' -> */, -/* pos 0146: 133 */ 0xE3 /* 'c' -> */, -/* pos 0147: 134 */ 0xEF /* 'o' -> */, -/* pos 0148: 135 */ 0xEE /* 'n' -> */, -/* pos 0149: 136 */ 0xF4 /* 't' -> */, -/* pos 014a: 137 */ 0xF2 /* 'r' -> */, -/* pos 014b: 138 */ 0xEF /* 'o' -> */, -/* pos 014c: 139 */ 0xEC /* 'l' -> */, -/* pos 014d: 140 */ 0xBA /* ':' -> */, -/* pos 014e: 141 */ 0x00, 0x15 /* - terminal marker 21 - */, -/* pos 0150: 142 */ 0xF4 /* 't' -> */, -/* pos 0151: 143 */ 0xE8 /* 'h' -> */, -/* pos 0152: 144 */ 0xEF /* 'o' -> */, -/* pos 0153: 145 */ 0xF2 /* 'r' -> */, -/* pos 0154: 146 */ 0xE9 /* 'i' -> */, -/* pos 0155: 147 */ 0xFA /* 'z' -> */, -/* pos 0156: 148 */ 0xE1 /* 'a' -> */, -/* pos 0157: 149 */ 0xF4 /* 't' -> */, -/* pos 0158: 150 */ 0xE9 /* 'i' -> */, -/* pos 0159: 151 */ 0xEF /* 'o' -> */, -/* pos 015a: 152 */ 0xEE /* 'n' -> */, -/* pos 015b: 153 */ 0xBA /* ':' -> */, -/* pos 015c: 154 */ 0x00, 0x16 /* - terminal marker 22 - */, -/* pos 015e: 155 */ 0xEB /* 'k' -> */, -/* pos 015f: 156 */ 0xE9 /* 'i' -> */, -/* pos 0160: 157 */ 0xE5 /* 'e' -> */, -/* pos 0161: 158 */ 0xBA /* ':' -> */, -/* pos 0162: 159 */ 0x00, 0x17 /* - terminal marker 23 - */, -/* pos 0164: 160 */ 0xE5 /* 'e' -> */, -/* pos 0165: 161 */ 0xEE /* 'n' -> */, -/* pos 0166: 162 */ 0xF4 /* 't' -> */, -/* pos 0167: 163 */ 0xAD /* '-' -> */, -/* pos 0168: 164 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0178 state 165) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0189 state 172) */, - 0x64 /* 'd' */, 0x65, 0x00 /* (to 0x01D3 state 213) */, - 0x65 /* 'e' */, 0x6F, 0x00 /* (to 0x01E0 state 225) */, - 0x72 /* 'r' */, 0x88, 0x00 /* (to 0x01FC state 250) */, - 0x08, /* fail */ -/* pos 0178: 165 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0182 state 166) */, - 0x61 /* 'a' */, 0x6F, 0x00 /* (to 0x01EA state 234) */, - 0x6F /* 'o' */, 0x75, 0x00 /* (to 0x01F3 state 242) */, - 0x08, /* fail */ -/* pos 0182: 166 */ 0xEE /* 'n' -> */, -/* pos 0183: 167 */ 0xE7 /* 'g' -> */, -/* pos 0184: 168 */ 0xF4 /* 't' -> */, -/* pos 0185: 169 */ 0xE8 /* 'h' -> */, -/* pos 0186: 170 */ 0xBA /* ':' -> */, -/* pos 0187: 171 */ 0x00, 0x18 /* - terminal marker 24 - */, -/* pos 0189: 172 */ 0xF9 /* 'y' -> */, -/* pos 018a: 173 */ 0xF0 /* 'p' -> */, -/* pos 018b: 174 */ 0xE5 /* 'e' -> */, -/* pos 018c: 175 */ 0xBA /* ':' -> */, -/* pos 018d: 176 */ 0x00, 0x19 /* - terminal marker 25 - */, -/* pos 018f: 177 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0196 state 178) */, - 0x65 /* 'e' */, 0x2B, 0x02 /* (to 0x03BD state 558) */, - 0x08, /* fail */ -/* pos 0196: 178 */ 0xF4 /* 't' -> */, -/* pos 0197: 179 */ 0xE5 /* 'e' -> */, -/* pos 0198: 180 */ 0xBA /* ':' -> */, -/* pos 0199: 181 */ 0x00, 0x1A /* - terminal marker 26 - */, -/* pos 019b: 182 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01A2 state 183) */, - 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x01A8 state 188) */, - 0x08, /* fail */ -/* pos 01a2: 183 */ 0xEE /* 'n' -> */, -/* pos 01a3: 184 */ 0xE7 /* 'g' -> */, -/* pos 01a4: 185 */ 0xE5 /* 'e' -> */, -/* pos 01a5: 186 */ 0xBA /* ':' -> */, -/* pos 01a6: 187 */ 0x00, 0x1B /* - terminal marker 27 - */, -/* pos 01a8: 188 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x01B2 state 189) */, - 0x74 /* 't' */, 0xD7, 0x00 /* (to 0x0282 state 345) */, - 0x70 /* 'p' */, 0x32, 0x02 /* (to 0x03E0 state 583) */, - 0x08, /* fail */ -/* pos 01b2: 189 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01B9 state 190) */, - 0x72 /* 'r' */, 0xC6, 0x01 /* (to 0x037B state 505) */, - 0x08, /* fail */ -/* pos 01b9: 190 */ 0xF2 /* 'r' -> */, -/* pos 01ba: 191 */ 0xE5 /* 'e' -> */, -/* pos 01bb: 192 */ 0xF2 /* 'r' -> */, -/* pos 01bc: 193 */ 0xBA /* ':' -> */, -/* pos 01bd: 194 */ 0x00, 0x1C /* - terminal marker 28 - */, -/* pos 01bf: 195 */ 0xEC /* 'l' -> */, -/* pos 01c0: 196 */ 0xEC /* 'l' -> */, -/* pos 01c1: 197 */ 0xEF /* 'o' -> */, -/* pos 01c2: 198 */ 0xF7 /* 'w' -> */, -/* pos 01c3: 199 */ 0xAD /* '-' -> */, -/* pos 01c4: 200 */ 0xEF /* 'o' -> */, -/* pos 01c5: 201 */ 0xF2 /* 'r' -> */, -/* pos 01c6: 202 */ 0xE9 /* 'i' -> */, -/* pos 01c7: 203 */ 0xE7 /* 'g' -> */, -/* pos 01c8: 204 */ 0xE9 /* 'i' -> */, -/* pos 01c9: 205 */ 0xEE /* 'n' -> */, -/* pos 01ca: 206 */ 0xBA /* ':' -> */, -/* pos 01cb: 207 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 01cd: 208 */ 0xEC /* 'l' -> */, -/* pos 01ce: 209 */ 0xEF /* 'o' -> */, -/* pos 01cf: 210 */ 0xF7 /* 'w' -> */, -/* pos 01d0: 211 */ 0xBA /* ':' -> */, -/* pos 01d1: 212 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 01d3: 213 */ 0xE9 /* 'i' -> */, -/* pos 01d4: 214 */ 0xF3 /* 's' -> */, -/* pos 01d5: 215 */ 0xF0 /* 'p' -> */, -/* pos 01d6: 216 */ 0xEF /* 'o' -> */, -/* pos 01d7: 217 */ 0xF3 /* 's' -> */, -/* pos 01d8: 218 */ 0xE9 /* 'i' -> */, -/* pos 01d9: 219 */ 0xF4 /* 't' -> */, -/* pos 01da: 220 */ 0xE9 /* 'i' -> */, -/* pos 01db: 221 */ 0xEF /* 'o' -> */, -/* pos 01dc: 222 */ 0xEE /* 'n' -> */, -/* pos 01dd: 223 */ 0xBA /* ':' -> */, -/* pos 01de: 224 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* pos 01e0: 225 */ 0xEE /* 'n' -> */, -/* pos 01e1: 226 */ 0xE3 /* 'c' -> */, -/* pos 01e2: 227 */ 0xEF /* 'o' -> */, -/* pos 01e3: 228 */ 0xE4 /* 'd' -> */, -/* pos 01e4: 229 */ 0xE9 /* 'i' -> */, -/* pos 01e5: 230 */ 0xEE /* 'n' -> */, -/* pos 01e6: 231 */ 0xE7 /* 'g' -> */, -/* pos 01e7: 232 */ 0xBA /* ':' -> */, -/* pos 01e8: 233 */ 0x00, 0x23 /* - terminal marker 35 - */, -/* pos 01ea: 234 */ 0xEE /* 'n' -> */, -/* pos 01eb: 235 */ 0xE7 /* 'g' -> */, -/* pos 01ec: 236 */ 0xF5 /* 'u' -> */, -/* pos 01ed: 237 */ 0xE1 /* 'a' -> */, -/* pos 01ee: 238 */ 0xE7 /* 'g' -> */, -/* pos 01ef: 239 */ 0xE5 /* 'e' -> */, -/* pos 01f0: 240 */ 0xBA /* ':' -> */, -/* pos 01f1: 241 */ 0x00, 0x24 /* - terminal marker 36 - */, -/* pos 01f3: 242 */ 0xE3 /* 'c' -> */, -/* pos 01f4: 243 */ 0xE1 /* 'a' -> */, -/* pos 01f5: 244 */ 0xF4 /* 't' -> */, -/* pos 01f6: 245 */ 0xE9 /* 'i' -> */, -/* pos 01f7: 246 */ 0xEF /* 'o' -> */, -/* pos 01f8: 247 */ 0xEE /* 'n' -> */, -/* pos 01f9: 248 */ 0xBA /* ':' -> */, -/* pos 01fa: 249 */ 0x00, 0x25 /* - terminal marker 37 - */, -/* pos 01fc: 250 */ 0xE1 /* 'a' -> */, -/* pos 01fd: 251 */ 0xEE /* 'n' -> */, -/* pos 01fe: 252 */ 0xE7 /* 'g' -> */, -/* pos 01ff: 253 */ 0xE5 /* 'e' -> */, -/* pos 0200: 254 */ 0xBA /* ':' -> */, -/* pos 0201: 255 */ 0x00, 0x26 /* - terminal marker 38 - */, -/* pos 0203: 256 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x020A state 257) */, - 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x020F state 261) */, - 0x08, /* fail */ -/* pos 020a: 257 */ 0xE1 /* 'a' -> */, -/* pos 020b: 258 */ 0xE7 /* 'g' -> */, -/* pos 020c: 259 */ 0xBA /* ':' -> */, -/* pos 020d: 260 */ 0x00, 0x27 /* - terminal marker 39 - */, -/* pos 020f: 261 */ 0xF0 /* 'p' -> */, -/* pos 0210: 262 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0217 state 263) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x021C state 267) */, - 0x08, /* fail */ -/* pos 0217: 263 */ 0xE3 /* 'c' -> */, -/* pos 0218: 264 */ 0xF4 /* 't' -> */, -/* pos 0219: 265 */ 0xBA /* ':' -> */, -/* pos 021a: 266 */ 0x00, 0x28 /* - terminal marker 40 - */, -/* pos 021c: 267 */ 0xF2 /* 'r' -> */, -/* pos 021d: 268 */ 0xE5 /* 'e' -> */, -/* pos 021e: 269 */ 0xF3 /* 's' -> */, -/* pos 021f: 270 */ 0xBA /* ':' -> */, -/* pos 0220: 271 */ 0x00, 0x29 /* - terminal marker 41 - */, -/* pos 0222: 272 */ 0xF2 /* 'r' -> */, -/* pos 0223: 273 */ 0xEF /* 'o' -> */, -/* pos 0224: 274 */ 0xED /* 'm' -> */, -/* pos 0225: 275 */ 0xBA /* ':' -> */, -/* pos 0226: 276 */ 0x00, 0x2A /* - terminal marker 42 - */, -/* pos 0228: 277 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x022F state 278) */, - 0x6F /* 'o' */, 0xE3, 0x00 /* (to 0x030E state 441) */, - 0x08, /* fail */ -/* pos 022f: 278 */ 0xF4 /* 't' -> */, -/* pos 0230: 279 */ 0xE3 /* 'c' -> */, -/* pos 0231: 280 */ 0xE8 /* 'h' -> */, -/* pos 0232: 281 */ 0xBA /* ':' -> */, -/* pos 0233: 282 */ 0x00, 0x2B /* - terminal marker 43 - */, -/* pos 0235: 283 */ 0xE1 /* 'a' -> */, -/* pos 0236: 284 */ 0xEE /* 'n' -> */, -/* pos 0237: 285 */ 0xE7 /* 'g' -> */, -/* pos 0238: 286 */ 0xE5 /* 'e' -> */, -/* pos 0239: 287 */ 0xBA /* ':' -> */, -/* pos 023a: 288 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 023c: 289 */ 0xEE /* 'n' -> */, -/* pos 023d: 290 */ 0xED /* 'm' -> */, -/* pos 023e: 291 */ 0xEF /* 'o' -> */, -/* pos 023f: 292 */ 0xE4 /* 'd' -> */, -/* pos 0240: 293 */ 0xE9 /* 'i' -> */, -/* pos 0241: 294 */ 0xE6 /* 'f' -> */, -/* pos 0242: 295 */ 0xE9 /* 'i' -> */, -/* pos 0243: 296 */ 0xE5 /* 'e' -> */, -/* pos 0244: 297 */ 0xE4 /* 'd' -> */, -/* pos 0245: 298 */ 0xAD /* '-' -> */, -/* pos 0246: 299 */ 0xF3 /* 's' -> */, -/* pos 0247: 300 */ 0xE9 /* 'i' -> */, -/* pos 0248: 301 */ 0xEE /* 'n' -> */, -/* pos 0249: 302 */ 0xE3 /* 'c' -> */, -/* pos 024a: 303 */ 0xE5 /* 'e' -> */, -/* pos 024b: 304 */ 0xBA /* ':' -> */, -/* pos 024c: 305 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 024e: 306 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0258 state 307) */, - 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x0266 state 320) */, - 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x026B state 324) */, - 0x08, /* fail */ -/* pos 0258: 307 */ 0xF3 /* 's' -> */, -/* pos 0259: 308 */ 0xF4 /* 't' -> */, -/* pos 025a: 309 */ 0xAD /* '-' -> */, -/* pos 025b: 310 */ 0xED /* 'm' -> */, -/* pos 025c: 311 */ 0xEF /* 'o' -> */, -/* pos 025d: 312 */ 0xE4 /* 'd' -> */, -/* pos 025e: 313 */ 0xE9 /* 'i' -> */, -/* pos 025f: 314 */ 0xE6 /* 'f' -> */, -/* pos 0260: 315 */ 0xE9 /* 'i' -> */, -/* pos 0261: 316 */ 0xE5 /* 'e' -> */, -/* pos 0262: 317 */ 0xE4 /* 'd' -> */, -/* pos 0263: 318 */ 0xBA /* ':' -> */, -/* pos 0264: 319 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 0266: 320 */ 0xEE /* 'n' -> */, -/* pos 0267: 321 */ 0xEB /* 'k' -> */, -/* pos 0268: 322 */ 0xBA /* ':' -> */, -/* pos 0269: 323 */ 0x00, 0x2F /* - terminal marker 47 - */, -/* pos 026b: 324 */ 0xE3 /* 'c' -> */, -/* pos 026c: 325 */ 0xE1 /* 'a' -> */, -/* pos 026d: 326 */ 0xF4 /* 't' -> */, -/* pos 026e: 327 */ 0xE9 /* 'i' -> */, -/* pos 026f: 328 */ 0xEF /* 'o' -> */, -/* pos 0270: 329 */ 0xEE /* 'n' -> */, -/* pos 0271: 330 */ 0xBA /* ':' -> */, -/* pos 0272: 331 */ 0x00, 0x30 /* - terminal marker 48 - */, -/* pos 0274: 332 */ 0xE1 /* 'a' -> */, -/* pos 0275: 333 */ 0xF8 /* 'x' -> */, -/* pos 0276: 334 */ 0xAD /* '-' -> */, -/* pos 0277: 335 */ 0xE6 /* 'f' -> */, -/* pos 0278: 336 */ 0xEF /* 'o' -> */, -/* pos 0279: 337 */ 0xF2 /* 'r' -> */, -/* pos 027a: 338 */ 0xF7 /* 'w' -> */, -/* pos 027b: 339 */ 0xE1 /* 'a' -> */, -/* pos 027c: 340 */ 0xF2 /* 'r' -> */, -/* pos 027d: 341 */ 0xE4 /* 'd' -> */, -/* pos 027e: 342 */ 0xF3 /* 's' -> */, -/* pos 027f: 343 */ 0xBA /* ':' -> */, -/* pos 0280: 344 */ 0x00, 0x31 /* - terminal marker 49 - */, -/* pos 0282: 345 */ 0xF2 /* 'r' -> */, -/* pos 0283: 346 */ 0xF9 /* 'y' -> */, -/* pos 0284: 347 */ 0xAD /* '-' -> */, -/* pos 0285: 348 */ 0xE1 /* 'a' -> */, -/* pos 0286: 349 */ 0xE6 /* 'f' -> */, -/* pos 0287: 350 */ 0xF4 /* 't' -> */, -/* pos 0288: 351 */ 0xE5 /* 'e' -> */, -/* pos 0289: 352 */ 0xF2 /* 'r' -> */, -/* pos 028a: 353 */ 0xBA /* ':' -> */, -/* pos 028b: 354 */ 0x00, 0x32 /* - terminal marker 50 - */, -/* pos 028d: 355 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0294 state 356) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x02AE state 371) */, - 0x08, /* fail */ -/* pos 0294: 356 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x029E state 357) */, - 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x02A4 state 362) */, - 0x63 /* 'c' */, 0x83, 0x00 /* (to 0x031D state 455) */, - 0x08, /* fail */ -/* pos 029e: 357 */ 0xF6 /* 'v' -> */, -/* pos 029f: 358 */ 0xE5 /* 'e' -> */, -/* pos 02a0: 359 */ 0xF2 /* 'r' -> */, -/* pos 02a1: 360 */ 0xBA /* ':' -> */, -/* pos 02a2: 361 */ 0x00, 0x33 /* - terminal marker 51 - */, -/* pos 02a4: 362 */ 0xAD /* '-' -> */, -/* pos 02a5: 363 */ 0xE3 /* 'c' -> */, -/* pos 02a6: 364 */ 0xEF /* 'o' -> */, -/* pos 02a7: 365 */ 0xEF /* 'o' -> */, -/* pos 02a8: 366 */ 0xEB /* 'k' -> */, -/* pos 02a9: 367 */ 0xE9 /* 'i' -> */, -/* pos 02aa: 368 */ 0xE5 /* 'e' -> */, -/* pos 02ab: 369 */ 0xBA /* ':' -> */, -/* pos 02ac: 370 */ 0x00, 0x34 /* - terminal marker 52 - */, -/* pos 02ae: 371 */ 0xF2 /* 'r' -> */, -/* pos 02af: 372 */ 0xE9 /* 'i' -> */, -/* pos 02b0: 373 */ 0xE3 /* 'c' -> */, -/* pos 02b1: 374 */ 0xF4 /* 't' -> */, -/* pos 02b2: 375 */ 0xAD /* '-' -> */, -/* pos 02b3: 376 */ 0xF4 /* 't' -> */, -/* pos 02b4: 377 */ 0xF2 /* 'r' -> */, -/* pos 02b5: 378 */ 0xE1 /* 'a' -> */, -/* pos 02b6: 379 */ 0xEE /* 'n' -> */, -/* pos 02b7: 380 */ 0xF3 /* 's' -> */, -/* pos 02b8: 381 */ 0xF0 /* 'p' -> */, -/* pos 02b9: 382 */ 0xEF /* 'o' -> */, -/* pos 02ba: 383 */ 0xF2 /* 'r' -> */, -/* pos 02bb: 384 */ 0xF4 /* 't' -> */, -/* pos 02bc: 385 */ 0xAD /* '-' -> */, -/* pos 02bd: 386 */ 0xF3 /* 's' -> */, -/* pos 02be: 387 */ 0xE5 /* 'e' -> */, -/* pos 02bf: 388 */ 0xE3 /* 'c' -> */, -/* pos 02c0: 389 */ 0xF5 /* 'u' -> */, -/* pos 02c1: 390 */ 0xF2 /* 'r' -> */, -/* pos 02c2: 391 */ 0xE9 /* 'i' -> */, -/* pos 02c3: 392 */ 0xF4 /* 't' -> */, -/* pos 02c4: 393 */ 0xF9 /* 'y' -> */, -/* pos 02c5: 394 */ 0xBA /* ':' -> */, -/* pos 02c6: 395 */ 0x00, 0x35 /* - terminal marker 53 - */, -/* pos 02c8: 396 */ 0xE5 /* 'e' -> */, -/* pos 02c9: 397 */ 0xF2 /* 'r' -> */, -/* pos 02ca: 398 */ 0xAD /* '-' -> */, -/* pos 02cb: 399 */ 0xE1 /* 'a' -> */, -/* pos 02cc: 400 */ 0xE7 /* 'g' -> */, -/* pos 02cd: 401 */ 0xE5 /* 'e' -> */, -/* pos 02ce: 402 */ 0xEE /* 'n' -> */, -/* pos 02cf: 403 */ 0xF4 /* 't' -> */, -/* pos 02d0: 404 */ 0xBA /* ':' -> */, -/* pos 02d1: 405 */ 0x00, 0x36 /* - terminal marker 54 - */, -/* pos 02d3: 406 */ 0xF8 /* 'x' -> */, -/* pos 02d4: 407 */ 0xF9 /* 'y' -> */, -/* pos 02d5: 408 */ 0x20 /* ' ' */, 0x07, 0x00 /* (to 0x02DC state 409) */, - 0x2D /* '-' */, 0x83, 0x00 /* (to 0x035B state 481) */, - 0x08, /* fail */ -/* pos 02dc: 409 */ 0x00, 0x37 /* - terminal marker 55 - */, -/* pos 02de: 410 */ 0xAD /* '-' -> */, -/* pos 02df: 411 */ 0x66 /* 'f' */, 0x07, 0x00 /* (to 0x02E6 state 412) */, - 0x72 /* 'r' */, 0xE9, 0x00 /* (to 0x03CB state 570) */, - 0x08, /* fail */ -/* pos 02e6: 412 */ 0xEF /* 'o' -> */, -/* pos 02e7: 413 */ 0xF2 /* 'r' -> */, -/* pos 02e8: 414 */ 0xF7 /* 'w' -> */, -/* pos 02e9: 415 */ 0xE1 /* 'a' -> */, -/* pos 02ea: 416 */ 0xF2 /* 'r' -> */, -/* pos 02eb: 417 */ 0xE4 /* 'd' -> */, -/* pos 02ec: 418 */ 0xE5 /* 'e' -> */, -/* pos 02ed: 419 */ 0xE4 /* 'd' -> */, -/* pos 02ee: 420 */ 0xAD /* '-' -> */, -/* pos 02ef: 421 */ 0xE6 /* 'f' -> */, -/* pos 02f0: 422 */ 0xEF /* 'o' -> */, -/* pos 02f1: 423 */ 0xF2 /* 'r' -> */, -/* pos 02f2: 424 */ 0xBA /* ':' -> */, -/* pos 02f3: 425 */ 0x00, 0x38 /* - terminal marker 56 - */, -/* pos 02f5: 426 */ 0x00, 0x39 /* - terminal marker 57 - */, -/* pos 02f7: 427 */ 0xE1 /* 'a' -> */, -/* pos 02f8: 428 */ 0xE4 /* 'd' -> */, -/* pos 02f9: 429 */ 0xA0 /* ' ' -> */, -/* pos 02fa: 430 */ 0x00, 0x3A /* - terminal marker 58 - */, -/* pos 02fc: 431 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0303 state 432) */, - 0x72 /* 'r' */, 0x82, 0x00 /* (to 0x0381 state 510) */, - 0x08, /* fail */ -/* pos 0303: 432 */ 0xBA /* ':' -> */, -/* pos 0304: 433 */ 0x00, 0x3B /* - terminal marker 59 - */, -/* pos 0306: 434 */ 0xF4 /* 't' -> */, -/* pos 0307: 435 */ 0xE9 /* 'i' -> */, -/* pos 0308: 436 */ 0xEF /* 'o' -> */, -/* pos 0309: 437 */ 0xEE /* 'n' -> */, -/* pos 030a: 438 */ 0xF3 /* 's' -> */, -/* pos 030b: 439 */ 0xA0 /* ' ' -> */, -/* pos 030c: 440 */ 0x00, 0x02 /* - terminal marker 2 - */, -/* pos 030e: 441 */ 0xE4 /* 'd' -> */, -/* pos 030f: 442 */ 0xE9 /* 'i' -> */, -/* pos 0310: 443 */ 0xE6 /* 'f' -> */, -/* pos 0311: 444 */ 0xE9 /* 'i' -> */, -/* pos 0312: 445 */ 0xE5 /* 'e' -> */, -/* pos 0313: 446 */ 0xE4 /* 'd' -> */, -/* pos 0314: 447 */ 0xAD /* '-' -> */, -/* pos 0315: 448 */ 0xF3 /* 's' -> */, -/* pos 0316: 449 */ 0xE9 /* 'i' -> */, -/* pos 0317: 450 */ 0xEE /* 'n' -> */, -/* pos 0318: 451 */ 0xE3 /* 'c' -> */, -/* pos 0319: 452 */ 0xE5 /* 'e' -> */, -/* pos 031a: 453 */ 0xBA /* ':' -> */, -/* pos 031b: 454 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 031d: 455 */ 0xAD /* '-' -> */, -/* pos 031e: 456 */ 0xF7 /* 'w' -> */, -/* pos 031f: 457 */ 0xE5 /* 'e' -> */, -/* pos 0320: 458 */ 0xE2 /* 'b' -> */, -/* pos 0321: 459 */ 0xF3 /* 's' -> */, -/* pos 0322: 460 */ 0xEF /* 'o' -> */, -/* pos 0323: 461 */ 0xE3 /* 'c' -> */, -/* pos 0324: 462 */ 0xEB /* 'k' -> */, -/* pos 0325: 463 */ 0xE5 /* 'e' -> */, -/* pos 0326: 464 */ 0xF4 /* 't' -> */, -/* pos 0327: 465 */ 0xAD /* '-' -> */, -/* pos 0328: 466 */ 0x6B /* 'k' */, 0x19, 0x00 /* (to 0x0341 state 467) */, - 0x64 /* 'd' */, 0xD1, 0x00 /* (to 0x03FC state 603) */, - 0x65 /* 'e' */, 0xD5, 0x00 /* (to 0x0403 state 609) */, - 0x70 /* 'p' */, 0xE4, 0x00 /* (to 0x0415 state 624) */, - 0x61 /* 'a' */, 0xEB, 0x00 /* (to 0x041F state 633) */, - 0x6E /* 'n' */, 0xF0, 0x00 /* (to 0x0427 state 640) */, - 0x76 /* 'v' */, 0xF7, 0x00 /* (to 0x0431 state 648) */, - 0x6F /* 'o' */, 0xFD, 0x00 /* (to 0x043A state 656) */, - 0x08, /* fail */ -/* pos 0341: 467 */ 0xE5 /* 'e' -> */, -/* pos 0342: 468 */ 0xF9 /* 'y' -> */, -/* pos 0343: 469 */ 0x3A /* ':' */, 0x0A, 0x00 /* (to 0x034D state 470) */, - 0x31 /* '1' */, 0xC9, 0x00 /* (to 0x040F state 620) */, - 0x32 /* '2' */, 0xC9, 0x00 /* (to 0x0412 state 622) */, - 0x08, /* fail */ -/* pos 034d: 470 */ 0x00, 0x17 /* - terminal marker 23 - */, -/* pos 034f: 471 */ 0xE1 /* 'a' -> */, -/* pos 0350: 472 */ 0xEE /* 'n' -> */, -/* pos 0351: 473 */ 0xE7 /* 'g' -> */, -/* pos 0352: 474 */ 0xE5 /* 'e' -> */, -/* pos 0353: 475 */ 0xF3 /* 's' -> */, -/* pos 0354: 476 */ 0xBA /* ':' -> */, -/* pos 0355: 477 */ 0x00, 0x18 /* - terminal marker 24 - */, -/* pos 0357: 478 */ 0xE5 /* 'e' -> */, -/* pos 0358: 479 */ 0xBA /* ':' -> */, -/* pos 0359: 480 */ 0x00, 0x1A /* - terminal marker 26 - */, -/* pos 035b: 481 */ 0xE1 /* 'a' -> */, -/* pos 035c: 482 */ 0xF5 /* 'u' -> */, -/* pos 035d: 483 */ 0xF4 /* 't' -> */, -/* pos 035e: 484 */ 0xE8 /* 'h' -> */, -/* pos 035f: 485 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0366 state 486) */, - 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x0370 state 495) */, - 0x08, /* fail */ -/* pos 0366: 486 */ 0xEE /* 'n' -> */, -/* pos 0367: 487 */ 0xF4 /* 't' -> */, -/* pos 0368: 488 */ 0xE9 /* 'i' -> */, -/* pos 0369: 489 */ 0xE3 /* 'c' -> */, -/* pos 036a: 490 */ 0xE1 /* 'a' -> */, -/* pos 036b: 491 */ 0xF4 /* 't' -> */, -/* pos 036c: 492 */ 0xE5 /* 'e' -> */, -/* pos 036d: 493 */ 0xBA /* ':' -> */, -/* pos 036e: 494 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 0370: 495 */ 0xF2 /* 'r' -> */, -/* pos 0371: 496 */ 0xE9 /* 'i' -> */, -/* pos 0372: 497 */ 0xFA /* 'z' -> */, -/* pos 0373: 498 */ 0xE1 /* 'a' -> */, -/* pos 0374: 499 */ 0xF4 /* 't' -> */, -/* pos 0375: 500 */ 0xE9 /* 'i' -> */, -/* pos 0376: 501 */ 0xEF /* 'o' -> */, -/* pos 0377: 502 */ 0xEE /* 'n' -> */, -/* pos 0378: 503 */ 0xBA /* ':' -> */, -/* pos 0379: 504 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 037b: 505 */ 0xE5 /* 'e' -> */, -/* pos 037c: 506 */ 0xF3 /* 's' -> */, -/* pos 037d: 507 */ 0xE8 /* 'h' -> */, -/* pos 037e: 508 */ 0xBA /* ':' -> */, -/* pos 037f: 509 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 0381: 510 */ 0xE1 /* 'a' -> */, -/* pos 0382: 511 */ 0xEE /* 'n' -> */, -/* pos 0383: 512 */ 0xF3 /* 's' -> */, -/* pos 0384: 513 */ 0xE6 /* 'f' -> */, -/* pos 0385: 514 */ 0xE5 /* 'e' -> */, -/* pos 0386: 515 */ 0xF2 /* 'r' -> */, -/* pos 0387: 516 */ 0xAD /* '-' -> */, -/* pos 0388: 517 */ 0xE5 /* 'e' -> */, -/* pos 0389: 518 */ 0xEE /* 'n' -> */, -/* pos 038a: 519 */ 0xE3 /* 'c' -> */, -/* pos 038b: 520 */ 0xEF /* 'o' -> */, -/* pos 038c: 521 */ 0xE4 /* 'd' -> */, -/* pos 038d: 522 */ 0xE9 /* 'i' -> */, -/* pos 038e: 523 */ 0xEE /* 'n' -> */, -/* pos 038f: 524 */ 0xE7 /* 'g' -> */, -/* pos 0390: 525 */ 0xBA /* ':' -> */, -/* pos 0391: 526 */ 0x00, 0x33 /* - terminal marker 51 - */, -/* pos 0393: 527 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x039A state 528) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x039F state 532) */, - 0x08, /* fail */ -/* pos 039a: 528 */ 0xF2 /* 'r' -> */, -/* pos 039b: 529 */ 0xF9 /* 'y' -> */, -/* pos 039c: 530 */ 0xBA /* ':' -> */, -/* pos 039d: 531 */ 0x00, 0x35 /* - terminal marker 53 - */, -/* pos 039f: 532 */ 0xE1 /* 'a' -> */, -/* pos 03a0: 533 */ 0xBA /* ':' -> */, -/* pos 03a1: 534 */ 0x00, 0x36 /* - terminal marker 54 - */, -/* pos 03a3: 535 */ 0xF7 /* 'w' -> */, -/* pos 03a4: 536 */ 0xF7 /* 'w' -> */, -/* pos 03a5: 537 */ 0xAD /* '-' -> */, -/* pos 03a6: 538 */ 0xE1 /* 'a' -> */, -/* pos 03a7: 539 */ 0xF5 /* 'u' -> */, -/* pos 03a8: 540 */ 0xF4 /* 't' -> */, -/* pos 03a9: 541 */ 0xE8 /* 'h' -> */, -/* pos 03aa: 542 */ 0xE5 /* 'e' -> */, -/* pos 03ab: 543 */ 0xEE /* 'n' -> */, -/* pos 03ac: 544 */ 0xF4 /* 't' -> */, -/* pos 03ad: 545 */ 0xE9 /* 'i' -> */, -/* pos 03ae: 546 */ 0xE3 /* 'c' -> */, -/* pos 03af: 547 */ 0xE1 /* 'a' -> */, -/* pos 03b0: 548 */ 0xF4 /* 't' -> */, -/* pos 03b1: 549 */ 0xE5 /* 'e' -> */, -/* pos 03b2: 550 */ 0xBA /* ':' -> */, -/* pos 03b3: 551 */ 0x00, 0x37 /* - terminal marker 55 - */, -/* pos 03b5: 552 */ 0xF4 /* 't' -> */, -/* pos 03b6: 553 */ 0xE3 /* 'c' -> */, -/* pos 03b7: 554 */ 0xE8 /* 'h' -> */, -/* pos 03b8: 555 */ 0x00, 0x38 /* - terminal marker 56 - */, -/* pos 03ba: 556 */ 0xF4 /* 't' -> */, -/* pos 03bb: 557 */ 0x00, 0x39 /* - terminal marker 57 - */, -/* pos 03bd: 558 */ 0xEC /* 'l' -> */, -/* pos 03be: 559 */ 0xE5 /* 'e' -> */, -/* pos 03bf: 560 */ 0xF4 /* 't' -> */, -/* pos 03c0: 561 */ 0xE5 /* 'e' -> */, -/* pos 03c1: 562 */ 0x00, 0x3A /* - terminal marker 58 - */, -/* pos 03c3: 563 */ 0xE9 /* 'i' -> */, -/* pos 03c4: 564 */ 0xAD /* '-' -> */, -/* pos 03c5: 565 */ 0xE1 /* 'a' -> */, -/* pos 03c6: 566 */ 0xF2 /* 'r' -> */, -/* pos 03c7: 567 */ 0xE7 /* 'g' -> */, -/* pos 03c8: 568 */ 0xF3 /* 's' -> */, -/* pos 03c9: 569 */ 0x00, 0x3B /* - terminal marker 59 - */, -/* pos 03cb: 570 */ 0xE5 /* 'e' -> */, -/* pos 03cc: 571 */ 0xE1 /* 'a' -> */, -/* pos 03cd: 572 */ 0xEC /* 'l' -> */, -/* pos 03ce: 573 */ 0xAD /* '-' -> */, -/* pos 03cf: 574 */ 0xE9 /* 'i' -> */, -/* pos 03d0: 575 */ 0xF0 /* 'p' -> */, -/* pos 03d1: 576 */ 0xBA /* ':' -> */, -/* pos 03d2: 577 */ 0x00, 0x3D /* - terminal marker 61 - */, -/* pos 03d4: 578 */ 0xB1 /* '1' -> */, -/* pos 03d5: 579 */ 0xAE /* '.' -> */, -/* pos 03d6: 580 */ 0x30 /* '0' */, 0x07, 0x00 /* (to 0x03DD state 581) */, - 0x31 /* '1' */, 0x55, 0x00 /* (to 0x042E state 646) */, - 0x08, /* fail */ -/* pos 03dd: 581 */ 0xA0 /* ' ' -> */, -/* pos 03de: 582 */ 0x00, 0x3E /* - terminal marker 62 - */, -/* pos 03e0: 583 */ 0xEC /* 'l' -> */, -/* pos 03e1: 584 */ 0xE1 /* 'a' -> */, -/* pos 03e2: 585 */ 0xF9 /* 'y' -> */, -/* pos 03e3: 586 */ 0xAD /* '-' -> */, -/* pos 03e4: 587 */ 0xEE /* 'n' -> */, -/* pos 03e5: 588 */ 0xEF /* 'o' -> */, -/* pos 03e6: 589 */ 0xEE /* 'n' -> */, -/* pos 03e7: 590 */ 0xE3 /* 'c' -> */, -/* pos 03e8: 591 */ 0xE5 /* 'e' -> */, -/* pos 03e9: 592 */ 0xBA /* ':' -> */, -/* pos 03ea: 593 */ 0x00, 0x43 /* - terminal marker 67 - */, -/* pos 03ec: 594 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x03F3 state 595) */, - 0x61 /* 'a' */, 0x53, 0x00 /* (to 0x0442 state 663) */, - 0x08, /* fail */ -/* pos 03f3: 595 */ 0xF2 /* 'r' -> */, -/* pos 03f4: 596 */ 0xEF /* 'o' -> */, -/* pos 03f5: 597 */ 0xF4 /* 't' -> */, -/* pos 03f6: 598 */ 0xEF /* 'o' -> */, -/* pos 03f7: 599 */ 0xE3 /* 'c' -> */, -/* pos 03f8: 600 */ 0xEF /* 'o' -> */, -/* pos 03f9: 601 */ 0xEC /* 'l' -> */, -/* pos 03fa: 602 */ 0x00, 0x44 /* - terminal marker 68 - */, -/* pos 03fc: 603 */ 0xF2 /* 'r' -> */, -/* pos 03fd: 604 */ 0xE1 /* 'a' -> */, -/* pos 03fe: 605 */ 0xE6 /* 'f' -> */, -/* pos 03ff: 606 */ 0xF4 /* 't' -> */, -/* pos 0400: 607 */ 0xBA /* ':' -> */, -/* pos 0401: 608 */ 0x00, 0x06 /* - terminal marker 6 - */, -/* pos 0403: 609 */ 0xF8 /* 'x' -> */, -/* pos 0404: 610 */ 0xF4 /* 't' -> */, -/* pos 0405: 611 */ 0xE5 /* 'e' -> */, -/* pos 0406: 612 */ 0xEE /* 'n' -> */, -/* pos 0407: 613 */ 0xF3 /* 's' -> */, -/* pos 0408: 614 */ 0xE9 /* 'i' -> */, -/* pos 0409: 615 */ 0xEF /* 'o' -> */, -/* pos 040a: 616 */ 0xEE /* 'n' -> */, -/* pos 040b: 617 */ 0xF3 /* 's' -> */, -/* pos 040c: 618 */ 0xBA /* ':' -> */, -/* pos 040d: 619 */ 0x00, 0x08 /* - terminal marker 8 - */, -/* pos 040f: 620 */ 0xBA /* ':' -> */, -/* pos 0410: 621 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 0412: 622 */ 0xBA /* ':' -> */, -/* pos 0413: 623 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 0415: 624 */ 0xF2 /* 'r' -> */, -/* pos 0416: 625 */ 0xEF /* 'o' -> */, -/* pos 0417: 626 */ 0xF4 /* 't' -> */, -/* pos 0418: 627 */ 0xEF /* 'o' -> */, -/* pos 0419: 628 */ 0xE3 /* 'c' -> */, -/* pos 041a: 629 */ 0xEF /* 'o' -> */, -/* pos 041b: 630 */ 0xEC /* 'l' -> */, -/* pos 041c: 631 */ 0xBA /* ':' -> */, -/* pos 041d: 632 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 041f: 633 */ 0xE3 /* 'c' -> */, -/* pos 0420: 634 */ 0xE3 /* 'c' -> */, -/* pos 0421: 635 */ 0xE5 /* 'e' -> */, -/* pos 0422: 636 */ 0xF0 /* 'p' -> */, -/* pos 0423: 637 */ 0xF4 /* 't' -> */, -/* pos 0424: 638 */ 0xBA /* ':' -> */, -/* pos 0425: 639 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 0427: 640 */ 0xEF /* 'o' -> */, -/* pos 0428: 641 */ 0xEE /* 'n' -> */, -/* pos 0429: 642 */ 0xE3 /* 'c' -> */, -/* pos 042a: 643 */ 0xE5 /* 'e' -> */, -/* pos 042b: 644 */ 0xBA /* ':' -> */, -/* pos 042c: 645 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 042e: 646 */ 0xA0 /* ' ' -> */, -/* pos 042f: 647 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 0431: 648 */ 0xE5 /* 'e' -> */, -/* pos 0432: 649 */ 0xF2 /* 'r' -> */, -/* pos 0433: 650 */ 0xF3 /* 's' -> */, -/* pos 0434: 651 */ 0xE9 /* 'i' -> */, -/* pos 0435: 652 */ 0xEF /* 'o' -> */, -/* pos 0436: 653 */ 0xEE /* 'n' -> */, -/* pos 0437: 654 */ 0xBA /* ':' -> */, -/* pos 0438: 655 */ 0x00, 0x1D /* - terminal marker 29 - */, -/* pos 043a: 656 */ 0xF2 /* 'r' -> */, -/* pos 043b: 657 */ 0xE9 /* 'i' -> */, -/* pos 043c: 658 */ 0xE7 /* 'g' -> */, -/* pos 043d: 659 */ 0xE9 /* 'i' -> */, -/* pos 043e: 660 */ 0xEE /* 'n' -> */, -/* pos 043f: 661 */ 0xBA /* ':' -> */, -/* pos 0440: 662 */ 0x00, 0x1E /* - terminal marker 30 - */, -/* pos 0442: 663 */ 0xF5 /* 'u' -> */, -/* pos 0443: 664 */ 0xF4 /* 't' -> */, -/* pos 0444: 665 */ 0xE8 /* 'h' -> */, -/* pos 0445: 666 */ 0xEF /* 'o' -> */, -/* pos 0446: 667 */ 0xF2 /* 'r' -> */, -/* pos 0447: 668 */ 0xE9 /* 'i' -> */, -/* pos 0448: 669 */ 0xF4 /* 't' -> */, -/* pos 0449: 670 */ 0xF9 /* 'y' -> */, -/* pos 044a: 671 */ 0x00, 0x1F /* - terminal marker 31 - */, -/* total size 1100 bytes */ +/* pos 0000: 0 */ 0x67 /* 'g' */, 0x3D, 0x00 /* (to 0x003D state 1) */, + 0x70 /* 'p' */, 0x3F, 0x00 /* (to 0x0042 state 5) */, + 0x68 /* 'h' */, 0x4E, 0x00 /* (to 0x0054 state 10) */, + 0x63 /* 'c' */, 0x5A, 0x00 /* (to 0x0063 state 15) */, + 0x75 /* 'u' */, 0x7B, 0x00 /* (to 0x0087 state 26) */, + 0x6F /* 'o' */, 0x8A, 0x00 /* (to 0x0099 state 34) */, + 0x0D /* '.' */, 0x95, 0x00 /* (to 0x00A7 state 41) */, + 0x61 /* 'a' */, 0xA4, 0x00 /* (to 0x00B9 state 51) */, + 0x69 /* 'i' */, 0xC1, 0x00 /* (to 0x00D9 state 58) */, + 0x64 /* 'd' */, 0x6A, 0x01 /* (to 0x0185 state 160) */, + 0x72 /* 'r' */, 0x73, 0x01 /* (to 0x0191 state 165) */, + 0x65 /* 'e' */, 0xBF, 0x01 /* (to 0x01E0 state 229) */, + 0x66 /* 'f' */, 0xDB, 0x01 /* (to 0x01FF state 245) */, + 0x6C /* 'l' */, 0xFD, 0x01 /* (to 0x0224 state 278) */, + 0x73 /* 's' */, 0x42, 0x02 /* (to 0x026C state 321) */, + 0x74 /* 't' */, 0x60, 0x02 /* (to 0x028D state 337) */, + 0x78 /* 'x' */, 0x81, 0x02 /* (to 0x02B1 state 364) */, + 0x6D /* 'm' */, 0xF2, 0x02 /* (to 0x0325 state 456) */, + 0x76 /* 'v' */, 0x4B, 0x03 /* (to 0x0381 state 531) */, + 0x77 /* 'w' */, 0x58, 0x03 /* (to 0x0391 state 539) */, + 0x08, /* fail */ +/* pos 003d: 1 */ 0xE5 /* 'e' -> */, +/* pos 003e: 2 */ 0xF4 /* 't' -> */, +/* pos 003f: 3 */ 0xA0 /* ' ' -> */, +/* pos 0040: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, +/* pos 0042: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x004F state 6) */, + 0x72 /* 'r' */, 0xE6, 0x00 /* (to 0x012B state 106) */, + 0x61 /* 'a' */, 0x5B, 0x03 /* (to 0x03A3 state 556) */, + 0x75 /* 'u' */, 0x5D, 0x03 /* (to 0x03A8 state 560) */, + 0x08, /* fail */ +/* pos 004f: 6 */ 0xF3 /* 's' -> */, +/* pos 0050: 7 */ 0xF4 /* 't' -> */, +/* pos 0051: 8 */ 0xA0 /* ' ' -> */, +/* pos 0052: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, +/* pos 0054: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x005E state 11) */, + 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AA state 43) */, + 0x65 /* 'e' */, 0x73, 0x02 /* (to 0x02CD state 381) */, + 0x08, /* fail */ +/* pos 005e: 11 */ 0xF3 /* 's' -> */, +/* pos 005f: 12 */ 0xF4 /* 't' -> */, +/* pos 0060: 13 */ 0xBA /* ':' -> */, +/* pos 0061: 14 */ 0x00, 0x02 /* - terminal marker 2 - */, +/* pos 0063: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006A state 16) */, + 0x61 /* 'a' */, 0xD2, 0x00 /* (to 0x0138 state 112) */, + 0x08, /* fail */ +/* pos 006a: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0071 state 17) */, + 0x6F /* 'o' */, 0xE7, 0x00 /* (to 0x0154 state 138) */, + 0x08, /* fail */ +/* pos 0071: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0078 state 18) */, + 0x74 /* 't' */, 0xE6, 0x00 /* (to 0x015A state 143) */, + 0x08, /* fail */ +/* pos 0078: 18 */ 0xE5 /* 'e' -> */, +/* pos 0079: 19 */ 0xE3 /* 'c' -> */, +/* pos 007a: 20 */ 0xF4 /* 't' -> */, +/* pos 007b: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0082 state 22) */, + 0x20 /* ' ' */, 0x4D, 0x02 /* (to 0x02CB state 380) */, + 0x08, /* fail */ +/* pos 0082: 22 */ 0xEF /* 'o' -> */, +/* pos 0083: 23 */ 0xEE /* 'n' -> */, +/* pos 0084: 24 */ 0xBA /* ':' -> */, +/* pos 0085: 25 */ 0x00, 0x03 /* - terminal marker 3 - */, +/* pos 0087: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0091 state 27) */, + 0x72 /* 'r' */, 0x1C, 0x02 /* (to 0x02A6 state 355) */, + 0x73 /* 's' */, 0xE9, 0x02 /* (to 0x0376 state 521) */, + 0x08, /* fail */ +/* pos 0091: 27 */ 0xE7 /* 'g' -> */, +/* pos 0092: 28 */ 0xF2 /* 'r' -> */, +/* pos 0093: 29 */ 0xE1 /* 'a' -> */, +/* pos 0094: 30 */ 0xE4 /* 'd' -> */, +/* pos 0095: 31 */ 0xE5 /* 'e' -> */, +/* pos 0096: 32 */ 0xBA /* ':' -> */, +/* pos 0097: 33 */ 0x00, 0x04 /* - terminal marker 4 - */, +/* pos 0099: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A0 state 35) */, + 0x70 /* 'p' */, 0x42, 0x02 /* (to 0x02DE state 396) */, + 0x08, /* fail */ +/* pos 00a0: 35 */ 0xE9 /* 'i' -> */, +/* pos 00a1: 36 */ 0xE7 /* 'g' -> */, +/* pos 00a2: 37 */ 0xE9 /* 'i' -> */, +/* pos 00a3: 38 */ 0xEE /* 'n' -> */, +/* pos 00a4: 39 */ 0xBA /* ':' -> */, +/* pos 00a5: 40 */ 0x00, 0x05 /* - terminal marker 5 - */, +/* pos 00a7: 41 */ 0x8A /* '.' -> */, +/* pos 00a8: 42 */ 0x00, 0x07 /* - terminal marker 7 - */, +/* pos 00aa: 43 */ 0xF4 /* 't' -> */, +/* pos 00ab: 44 */ 0xF0 /* 'p' -> */, +/* pos 00ac: 45 */ 0xAF /* '/' -> */, +/* pos 00ad: 46 */ 0xB1 /* '1' -> */, +/* pos 00ae: 47 */ 0xAE /* '.' -> */, +/* pos 00af: 48 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x00B6 state 49) */, + 0x30 /* '0' */, 0xFC, 0x01 /* (to 0x02AE state 362) */, + 0x08, /* fail */ +/* pos 00b6: 49 */ 0xA0 /* ' ' -> */, +/* pos 00b7: 50 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 00b9: 51 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00C6 state 52) */, + 0x75 /* 'u' */, 0x8A, 0x00 /* (to 0x0146 state 125) */, + 0x67 /* 'g' */, 0xE7, 0x00 /* (to 0x01A6 state 178) */, + 0x6C /* 'l' */, 0xE8, 0x00 /* (to 0x01AA state 181) */, + 0x08, /* fail */ +/* pos 00c6: 52 */ 0xE3 /* 'c' -> */, +/* pos 00c7: 53 */ 0xE5 /* 'e' -> */, +/* pos 00c8: 54 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x00CF state 55) */, + 0x73 /* 's' */, 0x1B, 0x02 /* (to 0x02E6 state 403) */, + 0x08, /* fail */ +/* pos 00cf: 55 */ 0xF4 /* 't' -> */, +/* pos 00d0: 56 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x00D7 state 57) */, + 0x2D /* '-' */, 0x37, 0x00 /* (to 0x010A state 87) */, + 0x08, /* fail */ +/* pos 00d7: 57 */ 0x00, 0x0F /* - terminal marker 15 - */, +/* pos 00d9: 58 */ 0xE6 /* 'f' -> */, +/* pos 00da: 59 */ 0xAD /* '-' -> */, +/* pos 00db: 60 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x00E8 state 61) */, + 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x00FE state 76) */, + 0x72 /* 'r' */, 0x2A, 0x01 /* (to 0x020B state 255) */, + 0x75 /* 'u' */, 0x2E, 0x01 /* (to 0x0212 state 261) */, + 0x08, /* fail */ +/* pos 00e8: 61 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x00EF state 62) */, + 0x61 /* 'a' */, 0x1A, 0x01 /* (to 0x0205 state 250) */, + 0x08, /* fail */ +/* pos 00ef: 62 */ 0xE4 /* 'd' -> */, +/* pos 00f0: 63 */ 0xE9 /* 'i' -> */, +/* pos 00f1: 64 */ 0xE6 /* 'f' -> */, +/* pos 00f2: 65 */ 0xE9 /* 'i' -> */, +/* pos 00f3: 66 */ 0xE5 /* 'e' -> */, +/* pos 00f4: 67 */ 0xE4 /* 'd' -> */, +/* pos 00f5: 68 */ 0xAD /* '-' -> */, +/* pos 00f6: 69 */ 0xF3 /* 's' -> */, +/* pos 00f7: 70 */ 0xE9 /* 'i' -> */, +/* pos 00f8: 71 */ 0xEE /* 'n' -> */, +/* pos 00f9: 72 */ 0xE3 /* 'c' -> */, +/* pos 00fa: 73 */ 0xE5 /* 'e' -> */, +/* pos 00fb: 74 */ 0xBA /* ':' -> */, +/* pos 00fc: 75 */ 0x00, 0x10 /* - terminal marker 16 - */, +/* pos 00fe: 76 */ 0xEF /* 'o' -> */, +/* pos 00ff: 77 */ 0xEE /* 'n' -> */, +/* pos 0100: 78 */ 0xE5 /* 'e' -> */, +/* pos 0101: 79 */ 0xAD /* '-' -> */, +/* pos 0102: 80 */ 0xED /* 'm' -> */, +/* pos 0103: 81 */ 0xE1 /* 'a' -> */, +/* pos 0104: 82 */ 0xF4 /* 't' -> */, +/* pos 0105: 83 */ 0xE3 /* 'c' -> */, +/* pos 0106: 84 */ 0xE8 /* 'h' -> */, +/* pos 0107: 85 */ 0xBA /* ':' -> */, +/* pos 0108: 86 */ 0x00, 0x11 /* - terminal marker 17 - */, +/* pos 010a: 87 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x0117 state 88) */, + 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x0121 state 97) */, + 0x72 /* 'r' */, 0x8E, 0x00 /* (to 0x019E state 171) */, + 0x63 /* 'c' */, 0xFB, 0x01 /* (to 0x030E state 435) */, + 0x08, /* fail */ +/* pos 0117: 88 */ 0xEE /* 'n' -> */, +/* pos 0118: 89 */ 0xE3 /* 'c' -> */, +/* pos 0119: 90 */ 0xEF /* 'o' -> */, +/* pos 011a: 91 */ 0xE4 /* 'd' -> */, +/* pos 011b: 92 */ 0xE9 /* 'i' -> */, +/* pos 011c: 93 */ 0xEE /* 'n' -> */, +/* pos 011d: 94 */ 0xE7 /* 'g' -> */, +/* pos 011e: 95 */ 0xBA /* ':' -> */, +/* pos 011f: 96 */ 0x00, 0x12 /* - terminal marker 18 - */, +/* pos 0121: 97 */ 0xE1 /* 'a' -> */, +/* pos 0122: 98 */ 0xEE /* 'n' -> */, +/* pos 0123: 99 */ 0xE7 /* 'g' -> */, +/* pos 0124: 100 */ 0xF5 /* 'u' -> */, +/* pos 0125: 101 */ 0xE1 /* 'a' -> */, +/* pos 0126: 102 */ 0xE7 /* 'g' -> */, +/* pos 0127: 103 */ 0xE5 /* 'e' -> */, +/* pos 0128: 104 */ 0xBA /* ':' -> */, +/* pos 0129: 105 */ 0x00, 0x13 /* - terminal marker 19 - */, +/* pos 012b: 106 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0132 state 107) */, + 0x6F /* 'o' */, 0x05, 0x02 /* (to 0x0333 state 469) */, + 0x08, /* fail */ +/* pos 0132: 107 */ 0xE7 /* 'g' -> */, +/* pos 0133: 108 */ 0xED /* 'm' -> */, +/* pos 0134: 109 */ 0xE1 /* 'a' -> */, +/* pos 0135: 110 */ 0xBA /* ':' -> */, +/* pos 0136: 111 */ 0x00, 0x14 /* - terminal marker 20 - */, +/* pos 0138: 112 */ 0xE3 /* 'c' -> */, +/* pos 0139: 113 */ 0xE8 /* 'h' -> */, +/* pos 013a: 114 */ 0xE5 /* 'e' -> */, +/* pos 013b: 115 */ 0xAD /* '-' -> */, +/* pos 013c: 116 */ 0xE3 /* 'c' -> */, +/* pos 013d: 117 */ 0xEF /* 'o' -> */, +/* pos 013e: 118 */ 0xEE /* 'n' -> */, +/* pos 013f: 119 */ 0xF4 /* 't' -> */, +/* pos 0140: 120 */ 0xF2 /* 'r' -> */, +/* pos 0141: 121 */ 0xEF /* 'o' -> */, +/* pos 0142: 122 */ 0xEC /* 'l' -> */, +/* pos 0143: 123 */ 0xBA /* ':' -> */, +/* pos 0144: 124 */ 0x00, 0x15 /* - terminal marker 21 - */, +/* pos 0146: 125 */ 0xF4 /* 't' -> */, +/* pos 0147: 126 */ 0xE8 /* 'h' -> */, +/* pos 0148: 127 */ 0xEF /* 'o' -> */, +/* pos 0149: 128 */ 0xF2 /* 'r' -> */, +/* pos 014a: 129 */ 0xE9 /* 'i' -> */, +/* pos 014b: 130 */ 0xFA /* 'z' -> */, +/* pos 014c: 131 */ 0xE1 /* 'a' -> */, +/* pos 014d: 132 */ 0xF4 /* 't' -> */, +/* pos 014e: 133 */ 0xE9 /* 'i' -> */, +/* pos 014f: 134 */ 0xEF /* 'o' -> */, +/* pos 0150: 135 */ 0xEE /* 'n' -> */, +/* pos 0151: 136 */ 0xBA /* ':' -> */, +/* pos 0152: 137 */ 0x00, 0x16 /* - terminal marker 22 - */, +/* pos 0154: 138 */ 0xEB /* 'k' -> */, +/* pos 0155: 139 */ 0xE9 /* 'i' -> */, +/* pos 0156: 140 */ 0xE5 /* 'e' -> */, +/* pos 0157: 141 */ 0xBA /* ':' -> */, +/* pos 0158: 142 */ 0x00, 0x17 /* - terminal marker 23 - */, +/* pos 015a: 143 */ 0xE5 /* 'e' -> */, +/* pos 015b: 144 */ 0xEE /* 'n' -> */, +/* pos 015c: 145 */ 0xF4 /* 't' -> */, +/* pos 015d: 146 */ 0xAD /* '-' -> */, +/* pos 015e: 147 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x016E state 148) */, + 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x017F state 155) */, + 0x64 /* 'd' */, 0x4C, 0x00 /* (to 0x01B0 state 186) */, + 0x65 /* 'e' */, 0x56, 0x00 /* (to 0x01BD state 198) */, + 0x72 /* 'r' */, 0x6F, 0x00 /* (to 0x01D9 state 223) */, + 0x08, /* fail */ +/* pos 016e: 148 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0178 state 149) */, + 0x61 /* 'a' */, 0x56, 0x00 /* (to 0x01C7 state 207) */, + 0x6F /* 'o' */, 0x5C, 0x00 /* (to 0x01D0 state 215) */, + 0x08, /* fail */ +/* pos 0178: 149 */ 0xEE /* 'n' -> */, +/* pos 0179: 150 */ 0xE7 /* 'g' -> */, +/* pos 017a: 151 */ 0xF4 /* 't' -> */, +/* pos 017b: 152 */ 0xE8 /* 'h' -> */, +/* pos 017c: 153 */ 0xBA /* ':' -> */, +/* pos 017d: 154 */ 0x00, 0x18 /* - terminal marker 24 - */, +/* pos 017f: 155 */ 0xF9 /* 'y' -> */, +/* pos 0180: 156 */ 0xF0 /* 'p' -> */, +/* pos 0181: 157 */ 0xE5 /* 'e' -> */, +/* pos 0182: 158 */ 0xBA /* ':' -> */, +/* pos 0183: 159 */ 0x00, 0x19 /* - terminal marker 25 - */, +/* pos 0185: 160 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x018C state 161) */, + 0x65 /* 'e' */, 0x23, 0x02 /* (to 0x03AB state 562) */, + 0x08, /* fail */ +/* pos 018c: 161 */ 0xF4 /* 't' -> */, +/* pos 018d: 162 */ 0xE5 /* 'e' -> */, +/* pos 018e: 163 */ 0xBA /* ':' -> */, +/* pos 018f: 164 */ 0x00, 0x1A /* - terminal marker 26 - */, +/* pos 0191: 165 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0198 state 166) */, + 0x65 /* 'e' */, 0xB6, 0x00 /* (to 0x024A state 304) */, + 0x08, /* fail */ +/* pos 0198: 166 */ 0xEE /* 'n' -> */, +/* pos 0199: 167 */ 0xE7 /* 'g' -> */, +/* pos 019a: 168 */ 0xE5 /* 'e' -> */, +/* pos 019b: 169 */ 0xBA /* ':' -> */, +/* pos 019c: 170 */ 0x00, 0x1B /* - terminal marker 27 - */, +/* pos 019e: 171 */ 0xE1 /* 'a' -> */, +/* pos 019f: 172 */ 0xEE /* 'n' -> */, +/* pos 01a0: 173 */ 0xE7 /* 'g' -> */, +/* pos 01a1: 174 */ 0xE5 /* 'e' -> */, +/* pos 01a2: 175 */ 0xF3 /* 's' -> */, +/* pos 01a3: 176 */ 0xBA /* ':' -> */, +/* pos 01a4: 177 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 01a6: 178 */ 0xE5 /* 'e' -> */, +/* pos 01a7: 179 */ 0xBA /* ':' -> */, +/* pos 01a8: 180 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 01aa: 181 */ 0xEC /* 'l' -> */, +/* pos 01ab: 182 */ 0xEF /* 'o' -> */, +/* pos 01ac: 183 */ 0xF7 /* 'w' -> */, +/* pos 01ad: 184 */ 0xBA /* ':' -> */, +/* pos 01ae: 185 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* pos 01b0: 186 */ 0xE9 /* 'i' -> */, +/* pos 01b1: 187 */ 0xF3 /* 's' -> */, +/* pos 01b2: 188 */ 0xF0 /* 'p' -> */, +/* pos 01b3: 189 */ 0xEF /* 'o' -> */, +/* pos 01b4: 190 */ 0xF3 /* 's' -> */, +/* pos 01b5: 191 */ 0xE9 /* 'i' -> */, +/* pos 01b6: 192 */ 0xF4 /* 't' -> */, +/* pos 01b7: 193 */ 0xE9 /* 'i' -> */, +/* pos 01b8: 194 */ 0xEF /* 'o' -> */, +/* pos 01b9: 195 */ 0xEE /* 'n' -> */, +/* pos 01ba: 196 */ 0xBA /* ':' -> */, +/* pos 01bb: 197 */ 0x00, 0x22 /* - terminal marker 34 - */, +/* pos 01bd: 198 */ 0xEE /* 'n' -> */, +/* pos 01be: 199 */ 0xE3 /* 'c' -> */, +/* pos 01bf: 200 */ 0xEF /* 'o' -> */, +/* pos 01c0: 201 */ 0xE4 /* 'd' -> */, +/* pos 01c1: 202 */ 0xE9 /* 'i' -> */, +/* pos 01c2: 203 */ 0xEE /* 'n' -> */, +/* pos 01c3: 204 */ 0xE7 /* 'g' -> */, +/* pos 01c4: 205 */ 0xBA /* ':' -> */, +/* pos 01c5: 206 */ 0x00, 0x23 /* - terminal marker 35 - */, +/* pos 01c7: 207 */ 0xEE /* 'n' -> */, +/* pos 01c8: 208 */ 0xE7 /* 'g' -> */, +/* pos 01c9: 209 */ 0xF5 /* 'u' -> */, +/* pos 01ca: 210 */ 0xE1 /* 'a' -> */, +/* pos 01cb: 211 */ 0xE7 /* 'g' -> */, +/* pos 01cc: 212 */ 0xE5 /* 'e' -> */, +/* pos 01cd: 213 */ 0xBA /* ':' -> */, +/* pos 01ce: 214 */ 0x00, 0x24 /* - terminal marker 36 - */, +/* pos 01d0: 215 */ 0xE3 /* 'c' -> */, +/* pos 01d1: 216 */ 0xE1 /* 'a' -> */, +/* pos 01d2: 217 */ 0xF4 /* 't' -> */, +/* pos 01d3: 218 */ 0xE9 /* 'i' -> */, +/* pos 01d4: 219 */ 0xEF /* 'o' -> */, +/* pos 01d5: 220 */ 0xEE /* 'n' -> */, +/* pos 01d6: 221 */ 0xBA /* ':' -> */, +/* pos 01d7: 222 */ 0x00, 0x25 /* - terminal marker 37 - */, +/* pos 01d9: 223 */ 0xE1 /* 'a' -> */, +/* pos 01da: 224 */ 0xEE /* 'n' -> */, +/* pos 01db: 225 */ 0xE7 /* 'g' -> */, +/* pos 01dc: 226 */ 0xE5 /* 'e' -> */, +/* pos 01dd: 227 */ 0xBA /* ':' -> */, +/* pos 01de: 228 */ 0x00, 0x26 /* - terminal marker 38 - */, +/* pos 01e0: 229 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x01E7 state 230) */, + 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x01EC state 234) */, + 0x08, /* fail */ +/* pos 01e7: 230 */ 0xE1 /* 'a' -> */, +/* pos 01e8: 231 */ 0xE7 /* 'g' -> */, +/* pos 01e9: 232 */ 0xBA /* ':' -> */, +/* pos 01ea: 233 */ 0x00, 0x27 /* - terminal marker 39 - */, +/* pos 01ec: 234 */ 0xF0 /* 'p' -> */, +/* pos 01ed: 235 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01F4 state 236) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x01F9 state 240) */, + 0x08, /* fail */ +/* pos 01f4: 236 */ 0xE3 /* 'c' -> */, +/* pos 01f5: 237 */ 0xF4 /* 't' -> */, +/* pos 01f6: 238 */ 0xBA /* ':' -> */, +/* pos 01f7: 239 */ 0x00, 0x28 /* - terminal marker 40 - */, +/* pos 01f9: 240 */ 0xF2 /* 'r' -> */, +/* pos 01fa: 241 */ 0xE5 /* 'e' -> */, +/* pos 01fb: 242 */ 0xF3 /* 's' -> */, +/* pos 01fc: 243 */ 0xBA /* ':' -> */, +/* pos 01fd: 244 */ 0x00, 0x29 /* - terminal marker 41 - */, +/* pos 01ff: 245 */ 0xF2 /* 'r' -> */, +/* pos 0200: 246 */ 0xEF /* 'o' -> */, +/* pos 0201: 247 */ 0xED /* 'm' -> */, +/* pos 0202: 248 */ 0xBA /* ':' -> */, +/* pos 0203: 249 */ 0x00, 0x2A /* - terminal marker 42 - */, +/* pos 0205: 250 */ 0xF4 /* 't' -> */, +/* pos 0206: 251 */ 0xE3 /* 'c' -> */, +/* pos 0207: 252 */ 0xE8 /* 'h' -> */, +/* pos 0208: 253 */ 0xBA /* ':' -> */, +/* pos 0209: 254 */ 0x00, 0x2B /* - terminal marker 43 - */, +/* pos 020b: 255 */ 0xE1 /* 'a' -> */, +/* pos 020c: 256 */ 0xEE /* 'n' -> */, +/* pos 020d: 257 */ 0xE7 /* 'g' -> */, +/* pos 020e: 258 */ 0xE5 /* 'e' -> */, +/* pos 020f: 259 */ 0xBA /* ':' -> */, +/* pos 0210: 260 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 0212: 261 */ 0xEE /* 'n' -> */, +/* pos 0213: 262 */ 0xED /* 'm' -> */, +/* pos 0214: 263 */ 0xEF /* 'o' -> */, +/* pos 0215: 264 */ 0xE4 /* 'd' -> */, +/* pos 0216: 265 */ 0xE9 /* 'i' -> */, +/* pos 0217: 266 */ 0xE6 /* 'f' -> */, +/* pos 0218: 267 */ 0xE9 /* 'i' -> */, +/* pos 0219: 268 */ 0xE5 /* 'e' -> */, +/* pos 021a: 269 */ 0xE4 /* 'd' -> */, +/* pos 021b: 270 */ 0xAD /* '-' -> */, +/* pos 021c: 271 */ 0xF3 /* 's' -> */, +/* pos 021d: 272 */ 0xE9 /* 'i' -> */, +/* pos 021e: 273 */ 0xEE /* 'n' -> */, +/* pos 021f: 274 */ 0xE3 /* 'c' -> */, +/* pos 0220: 275 */ 0xE5 /* 'e' -> */, +/* pos 0221: 276 */ 0xBA /* ':' -> */, +/* pos 0222: 277 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 0224: 278 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x022E state 279) */, + 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x023C state 292) */, + 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0241 state 296) */, + 0x08, /* fail */ +/* pos 022e: 279 */ 0xF3 /* 's' -> */, +/* pos 022f: 280 */ 0xF4 /* 't' -> */, +/* pos 0230: 281 */ 0xAD /* '-' -> */, +/* pos 0231: 282 */ 0xED /* 'm' -> */, +/* pos 0232: 283 */ 0xEF /* 'o' -> */, +/* pos 0233: 284 */ 0xE4 /* 'd' -> */, +/* pos 0234: 285 */ 0xE9 /* 'i' -> */, +/* pos 0235: 286 */ 0xE6 /* 'f' -> */, +/* pos 0236: 287 */ 0xE9 /* 'i' -> */, +/* pos 0237: 288 */ 0xE5 /* 'e' -> */, +/* pos 0238: 289 */ 0xE4 /* 'd' -> */, +/* pos 0239: 290 */ 0xBA /* ':' -> */, +/* pos 023a: 291 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 023c: 292 */ 0xEE /* 'n' -> */, +/* pos 023d: 293 */ 0xEB /* 'k' -> */, +/* pos 023e: 294 */ 0xBA /* ':' -> */, +/* pos 023f: 295 */ 0x00, 0x2F /* - terminal marker 47 - */, +/* pos 0241: 296 */ 0xE3 /* 'c' -> */, +/* pos 0242: 297 */ 0xE1 /* 'a' -> */, +/* pos 0243: 298 */ 0xF4 /* 't' -> */, +/* pos 0244: 299 */ 0xE9 /* 'i' -> */, +/* pos 0245: 300 */ 0xEF /* 'o' -> */, +/* pos 0246: 301 */ 0xEE /* 'n' -> */, +/* pos 0247: 302 */ 0xBA /* ':' -> */, +/* pos 0248: 303 */ 0x00, 0x30 /* - terminal marker 48 - */, +/* pos 024a: 304 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x0254 state 305) */, + 0x74 /* 't' */, 0x14, 0x00 /* (to 0x0261 state 311) */, + 0x70 /* 'p' */, 0x6F, 0x01 /* (to 0x03BF state 578) */, + 0x08, /* fail */ +/* pos 0254: 305 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x025B state 306) */, + 0x65 /* 'e' */, 0xB1, 0x00 /* (to 0x0308 state 430) */, + 0x08, /* fail */ +/* pos 025b: 306 */ 0xE5 /* 'e' -> */, +/* pos 025c: 307 */ 0xF3 /* 's' -> */, +/* pos 025d: 308 */ 0xE8 /* 'h' -> */, +/* pos 025e: 309 */ 0xBA /* ':' -> */, +/* pos 025f: 310 */ 0x00, 0x31 /* - terminal marker 49 - */, +/* pos 0261: 311 */ 0xF2 /* 'r' -> */, +/* pos 0262: 312 */ 0xF9 /* 'y' -> */, +/* pos 0263: 313 */ 0xAD /* '-' -> */, +/* pos 0264: 314 */ 0xE1 /* 'a' -> */, +/* pos 0265: 315 */ 0xE6 /* 'f' -> */, +/* pos 0266: 316 */ 0xF4 /* 't' -> */, +/* pos 0267: 317 */ 0xE5 /* 'e' -> */, +/* pos 0268: 318 */ 0xF2 /* 'r' -> */, +/* pos 0269: 319 */ 0xBA /* ':' -> */, +/* pos 026a: 320 */ 0x00, 0x32 /* - terminal marker 50 - */, +/* pos 026c: 321 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0273 state 322) */, + 0x74 /* 't' */, 0xED, 0x00 /* (to 0x035C state 496) */, + 0x08, /* fail */ +/* pos 0273: 322 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x027D state 323) */, + 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x0283 state 328) */, + 0x63 /* 'c' */, 0x52, 0x01 /* (to 0x03CB state 589) */, + 0x08, /* fail */ +/* pos 027d: 323 */ 0xF6 /* 'v' -> */, +/* pos 027e: 324 */ 0xE5 /* 'e' -> */, +/* pos 027f: 325 */ 0xF2 /* 'r' -> */, +/* pos 0280: 326 */ 0xBA /* ':' -> */, +/* pos 0281: 327 */ 0x00, 0x33 /* - terminal marker 51 - */, +/* pos 0283: 328 */ 0xAD /* '-' -> */, +/* pos 0284: 329 */ 0xE3 /* 'c' -> */, +/* pos 0285: 330 */ 0xEF /* 'o' -> */, +/* pos 0286: 331 */ 0xEF /* 'o' -> */, +/* pos 0287: 332 */ 0xEB /* 'k' -> */, +/* pos 0288: 333 */ 0xE9 /* 'i' -> */, +/* pos 0289: 334 */ 0xE5 /* 'e' -> */, +/* pos 028a: 335 */ 0xBA /* ':' -> */, +/* pos 028b: 336 */ 0x00, 0x34 /* - terminal marker 52 - */, +/* pos 028d: 337 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0294 state 338) */, + 0x65 /* 'e' */, 0x2C, 0x01 /* (to 0x03BC state 576) */, + 0x08, /* fail */ +/* pos 0294: 338 */ 0xE1 /* 'a' -> */, +/* pos 0295: 339 */ 0xEE /* 'n' -> */, +/* pos 0296: 340 */ 0xF3 /* 's' -> */, +/* pos 0297: 341 */ 0xE6 /* 'f' -> */, +/* pos 0298: 342 */ 0xE5 /* 'e' -> */, +/* pos 0299: 343 */ 0xF2 /* 'r' -> */, +/* pos 029a: 344 */ 0xAD /* '-' -> */, +/* pos 029b: 345 */ 0xE5 /* 'e' -> */, +/* pos 029c: 346 */ 0xEE /* 'n' -> */, +/* pos 029d: 347 */ 0xE3 /* 'c' -> */, +/* pos 029e: 348 */ 0xEF /* 'o' -> */, +/* pos 029f: 349 */ 0xE4 /* 'd' -> */, +/* pos 02a0: 350 */ 0xE9 /* 'i' -> */, +/* pos 02a1: 351 */ 0xEE /* 'n' -> */, +/* pos 02a2: 352 */ 0xE7 /* 'g' -> */, +/* pos 02a3: 353 */ 0xBA /* ':' -> */, +/* pos 02a4: 354 */ 0x00, 0x35 /* - terminal marker 53 - */, +/* pos 02a6: 355 */ 0xE9 /* 'i' -> */, +/* pos 02a7: 356 */ 0xAD /* '-' -> */, +/* pos 02a8: 357 */ 0xE1 /* 'a' -> */, +/* pos 02a9: 358 */ 0xF2 /* 'r' -> */, +/* pos 02aa: 359 */ 0xE7 /* 'g' -> */, +/* pos 02ab: 360 */ 0xF3 /* 's' -> */, +/* pos 02ac: 361 */ 0x00, 0x36 /* - terminal marker 54 - */, +/* pos 02ae: 362 */ 0xA0 /* ' ' -> */, +/* pos 02af: 363 */ 0x00, 0x37 /* - terminal marker 55 - */, +/* pos 02b1: 364 */ 0xAD /* '-' -> */, +/* pos 02b2: 365 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02BC state 366) */, + 0x61 /* 'a' */, 0x1D, 0x00 /* (to 0x02D2 state 385) */, + 0x72 /* 'r' */, 0xFB, 0x00 /* (to 0x03B3 state 568) */, + 0x08, /* fail */ +/* pos 02bc: 366 */ 0xEF /* 'o' -> */, +/* pos 02bd: 367 */ 0xF2 /* 'r' -> */, +/* pos 02be: 368 */ 0xF7 /* 'w' -> */, +/* pos 02bf: 369 */ 0xE1 /* 'a' -> */, +/* pos 02c0: 370 */ 0xF2 /* 'r' -> */, +/* pos 02c1: 371 */ 0xE4 /* 'd' -> */, +/* pos 02c2: 372 */ 0xE5 /* 'e' -> */, +/* pos 02c3: 373 */ 0xE4 /* 'd' -> */, +/* pos 02c4: 374 */ 0xAD /* '-' -> */, +/* pos 02c5: 375 */ 0xE6 /* 'f' -> */, +/* pos 02c6: 376 */ 0xEF /* 'o' -> */, +/* pos 02c7: 377 */ 0xF2 /* 'r' -> */, +/* pos 02c8: 378 */ 0xBA /* ':' -> */, +/* pos 02c9: 379 */ 0x00, 0x38 /* - terminal marker 56 - */, +/* pos 02cb: 380 */ 0x00, 0x39 /* - terminal marker 57 - */, +/* pos 02cd: 381 */ 0xE1 /* 'a' -> */, +/* pos 02ce: 382 */ 0xE4 /* 'd' -> */, +/* pos 02cf: 383 */ 0xA0 /* ' ' -> */, +/* pos 02d0: 384 */ 0x00, 0x3A /* - terminal marker 58 - */, +/* pos 02d2: 385 */ 0xF5 /* 'u' -> */, +/* pos 02d3: 386 */ 0xF4 /* 't' -> */, +/* pos 02d4: 387 */ 0xE8 /* 'h' -> */, +/* pos 02d5: 388 */ 0xAD /* '-' -> */, +/* pos 02d6: 389 */ 0xF4 /* 't' -> */, +/* pos 02d7: 390 */ 0xEF /* 'o' -> */, +/* pos 02d8: 391 */ 0xEB /* 'k' -> */, +/* pos 02d9: 392 */ 0xE5 /* 'e' -> */, +/* pos 02da: 393 */ 0xEE /* 'n' -> */, +/* pos 02db: 394 */ 0xBA /* ':' -> */, +/* pos 02dc: 395 */ 0x00, 0x3B /* - terminal marker 59 - */, +/* pos 02de: 396 */ 0xF4 /* 't' -> */, +/* pos 02df: 397 */ 0xE9 /* 'i' -> */, +/* pos 02e0: 398 */ 0xEF /* 'o' -> */, +/* pos 02e1: 399 */ 0xEE /* 'n' -> */, +/* pos 02e2: 400 */ 0xF3 /* 's' -> */, +/* pos 02e3: 401 */ 0xA0 /* ' ' -> */, +/* pos 02e4: 402 */ 0x00, 0x02 /* - terminal marker 2 - */, +/* pos 02e6: 403 */ 0xF3 /* 's' -> */, +/* pos 02e7: 404 */ 0xAD /* '-' -> */, +/* pos 02e8: 405 */ 0xE3 /* 'c' -> */, +/* pos 02e9: 406 */ 0xEF /* 'o' -> */, +/* pos 02ea: 407 */ 0xEE /* 'n' -> */, +/* pos 02eb: 408 */ 0xF4 /* 't' -> */, +/* pos 02ec: 409 */ 0xF2 /* 'r' -> */, +/* pos 02ed: 410 */ 0xEF /* 'o' -> */, +/* pos 02ee: 411 */ 0xEC /* 'l' -> */, +/* pos 02ef: 412 */ 0xAD /* '-' -> */, +/* pos 02f0: 413 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x02F7 state 414) */, + 0x61 /* 'a' */, 0x24, 0x00 /* (to 0x0317 state 443) */, + 0x08, /* fail */ +/* pos 02f7: 414 */ 0xE5 /* 'e' -> */, +/* pos 02f8: 415 */ 0xF1 /* 'q' -> */, +/* pos 02f9: 416 */ 0xF5 /* 'u' -> */, +/* pos 02fa: 417 */ 0xE5 /* 'e' -> */, +/* pos 02fb: 418 */ 0xF3 /* 's' -> */, +/* pos 02fc: 419 */ 0xF4 /* 't' -> */, +/* pos 02fd: 420 */ 0xAD /* '-' -> */, +/* pos 02fe: 421 */ 0xE8 /* 'h' -> */, +/* pos 02ff: 422 */ 0xE5 /* 'e' -> */, +/* pos 0300: 423 */ 0xE1 /* 'a' -> */, +/* pos 0301: 424 */ 0xE4 /* 'd' -> */, +/* pos 0302: 425 */ 0xE5 /* 'e' -> */, +/* pos 0303: 426 */ 0xF2 /* 'r' -> */, +/* pos 0304: 427 */ 0xF3 /* 's' -> */, +/* pos 0305: 428 */ 0xBA /* ':' -> */, +/* pos 0306: 429 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 0308: 430 */ 0xF2 /* 'r' -> */, +/* pos 0309: 431 */ 0xE5 /* 'e' -> */, +/* pos 030a: 432 */ 0xF2 /* 'r' -> */, +/* pos 030b: 433 */ 0xBA /* ':' -> */, +/* pos 030c: 434 */ 0x00, 0x17 /* - terminal marker 23 - */, +/* pos 030e: 435 */ 0xE8 /* 'h' -> */, +/* pos 030f: 436 */ 0xE1 /* 'a' -> */, +/* pos 0310: 437 */ 0xF2 /* 'r' -> */, +/* pos 0311: 438 */ 0xF3 /* 's' -> */, +/* pos 0312: 439 */ 0xE5 /* 'e' -> */, +/* pos 0313: 440 */ 0xF4 /* 't' -> */, +/* pos 0314: 441 */ 0xBA /* ':' -> */, +/* pos 0315: 442 */ 0x00, 0x18 /* - terminal marker 24 - */, +/* pos 0317: 443 */ 0xEC /* 'l' -> */, +/* pos 0318: 444 */ 0xEC /* 'l' -> */, +/* pos 0319: 445 */ 0xEF /* 'o' -> */, +/* pos 031a: 446 */ 0xF7 /* 'w' -> */, +/* pos 031b: 447 */ 0xAD /* '-' -> */, +/* pos 031c: 448 */ 0xEF /* 'o' -> */, +/* pos 031d: 449 */ 0xF2 /* 'r' -> */, +/* pos 031e: 450 */ 0xE9 /* 'i' -> */, +/* pos 031f: 451 */ 0xE7 /* 'g' -> */, +/* pos 0320: 452 */ 0xE9 /* 'i' -> */, +/* pos 0321: 453 */ 0xEE /* 'n' -> */, +/* pos 0322: 454 */ 0xBA /* ':' -> */, +/* pos 0323: 455 */ 0x00, 0x1A /* - terminal marker 26 - */, +/* pos 0325: 456 */ 0xE1 /* 'a' -> */, +/* pos 0326: 457 */ 0xF8 /* 'x' -> */, +/* pos 0327: 458 */ 0xAD /* '-' -> */, +/* pos 0328: 459 */ 0xE6 /* 'f' -> */, +/* pos 0329: 460 */ 0xEF /* 'o' -> */, +/* pos 032a: 461 */ 0xF2 /* 'r' -> */, +/* pos 032b: 462 */ 0xF7 /* 'w' -> */, +/* pos 032c: 463 */ 0xE1 /* 'a' -> */, +/* pos 032d: 464 */ 0xF2 /* 'r' -> */, +/* pos 032e: 465 */ 0xE4 /* 'd' -> */, +/* pos 032f: 466 */ 0xF3 /* 's' -> */, +/* pos 0330: 467 */ 0xBA /* ':' -> */, +/* pos 0331: 468 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 0333: 469 */ 0xF8 /* 'x' -> */, +/* pos 0334: 470 */ 0xF9 /* 'y' -> */, +/* pos 0335: 471 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x033C state 472) */, + 0x20 /* ' ' */, 0x79, 0x00 /* (to 0x03B1 state 567) */, + 0x08, /* fail */ +/* pos 033c: 472 */ 0xE1 /* 'a' -> */, +/* pos 033d: 473 */ 0xF5 /* 'u' -> */, +/* pos 033e: 474 */ 0xF4 /* 't' -> */, +/* pos 033f: 475 */ 0xE8 /* 'h' -> */, +/* pos 0340: 476 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0347 state 477) */, + 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x0351 state 486) */, + 0x08, /* fail */ +/* pos 0347: 477 */ 0xEE /* 'n' -> */, +/* pos 0348: 478 */ 0xF4 /* 't' -> */, +/* pos 0349: 479 */ 0xE9 /* 'i' -> */, +/* pos 034a: 480 */ 0xE3 /* 'c' -> */, +/* pos 034b: 481 */ 0xE1 /* 'a' -> */, +/* pos 034c: 482 */ 0xF4 /* 't' -> */, +/* pos 034d: 483 */ 0xE5 /* 'e' -> */, +/* pos 034e: 484 */ 0xBA /* ':' -> */, +/* pos 034f: 485 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 0351: 486 */ 0xF2 /* 'r' -> */, +/* pos 0352: 487 */ 0xE9 /* 'i' -> */, +/* pos 0353: 488 */ 0xFA /* 'z' -> */, +/* pos 0354: 489 */ 0xE1 /* 'a' -> */, +/* pos 0355: 490 */ 0xF4 /* 't' -> */, +/* pos 0356: 491 */ 0xE9 /* 'i' -> */, +/* pos 0357: 492 */ 0xEF /* 'o' -> */, +/* pos 0358: 493 */ 0xEE /* 'n' -> */, +/* pos 0359: 494 */ 0xBA /* ':' -> */, +/* pos 035a: 495 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 035c: 496 */ 0xF2 /* 'r' -> */, +/* pos 035d: 497 */ 0xE9 /* 'i' -> */, +/* pos 035e: 498 */ 0xE3 /* 'c' -> */, +/* pos 035f: 499 */ 0xF4 /* 't' -> */, +/* pos 0360: 500 */ 0xAD /* '-' -> */, +/* pos 0361: 501 */ 0xF4 /* 't' -> */, +/* pos 0362: 502 */ 0xF2 /* 'r' -> */, +/* pos 0363: 503 */ 0xE1 /* 'a' -> */, +/* pos 0364: 504 */ 0xEE /* 'n' -> */, +/* pos 0365: 505 */ 0xF3 /* 's' -> */, +/* pos 0366: 506 */ 0xF0 /* 'p' -> */, +/* pos 0367: 507 */ 0xEF /* 'o' -> */, +/* pos 0368: 508 */ 0xF2 /* 'r' -> */, +/* pos 0369: 509 */ 0xF4 /* 't' -> */, +/* pos 036a: 510 */ 0xAD /* '-' -> */, +/* pos 036b: 511 */ 0xF3 /* 's' -> */, +/* pos 036c: 512 */ 0xE5 /* 'e' -> */, +/* pos 036d: 513 */ 0xE3 /* 'c' -> */, +/* pos 036e: 514 */ 0xF5 /* 'u' -> */, +/* pos 036f: 515 */ 0xF2 /* 'r' -> */, +/* pos 0370: 516 */ 0xE9 /* 'i' -> */, +/* pos 0371: 517 */ 0xF4 /* 't' -> */, +/* pos 0372: 518 */ 0xF9 /* 'y' -> */, +/* pos 0373: 519 */ 0xBA /* ':' -> */, +/* pos 0374: 520 */ 0x00, 0x33 /* - terminal marker 51 - */, +/* pos 0376: 521 */ 0xE5 /* 'e' -> */, +/* pos 0377: 522 */ 0xF2 /* 'r' -> */, +/* pos 0378: 523 */ 0xAD /* '-' -> */, +/* pos 0379: 524 */ 0xE1 /* 'a' -> */, +/* pos 037a: 525 */ 0xE7 /* 'g' -> */, +/* pos 037b: 526 */ 0xE5 /* 'e' -> */, +/* pos 037c: 527 */ 0xEE /* 'n' -> */, +/* pos 037d: 528 */ 0xF4 /* 't' -> */, +/* pos 037e: 529 */ 0xBA /* ':' -> */, +/* pos 037f: 530 */ 0x00, 0x35 /* - terminal marker 53 - */, +/* pos 0381: 531 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0388 state 532) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x038D state 536) */, + 0x08, /* fail */ +/* pos 0388: 532 */ 0xF2 /* 'r' -> */, +/* pos 0389: 533 */ 0xF9 /* 'y' -> */, +/* pos 038a: 534 */ 0xBA /* ':' -> */, +/* pos 038b: 535 */ 0x00, 0x36 /* - terminal marker 54 - */, +/* pos 038d: 536 */ 0xE1 /* 'a' -> */, +/* pos 038e: 537 */ 0xBA /* ':' -> */, +/* pos 038f: 538 */ 0x00, 0x37 /* - terminal marker 55 - */, +/* pos 0391: 539 */ 0xF7 /* 'w' -> */, +/* pos 0392: 540 */ 0xF7 /* 'w' -> */, +/* pos 0393: 541 */ 0xAD /* '-' -> */, +/* pos 0394: 542 */ 0xE1 /* 'a' -> */, +/* pos 0395: 543 */ 0xF5 /* 'u' -> */, +/* pos 0396: 544 */ 0xF4 /* 't' -> */, +/* pos 0397: 545 */ 0xE8 /* 'h' -> */, +/* pos 0398: 546 */ 0xE5 /* 'e' -> */, +/* pos 0399: 547 */ 0xEE /* 'n' -> */, +/* pos 039a: 548 */ 0xF4 /* 't' -> */, +/* pos 039b: 549 */ 0xE9 /* 'i' -> */, +/* pos 039c: 550 */ 0xE3 /* 'c' -> */, +/* pos 039d: 551 */ 0xE1 /* 'a' -> */, +/* pos 039e: 552 */ 0xF4 /* 't' -> */, +/* pos 039f: 553 */ 0xE5 /* 'e' -> */, +/* pos 03a0: 554 */ 0xBA /* ':' -> */, +/* pos 03a1: 555 */ 0x00, 0x38 /* - terminal marker 56 - */, +/* pos 03a3: 556 */ 0xF4 /* 't' -> */, +/* pos 03a4: 557 */ 0xE3 /* 'c' -> */, +/* pos 03a5: 558 */ 0xE8 /* 'h' -> */, +/* pos 03a6: 559 */ 0x00, 0x39 /* - terminal marker 57 - */, +/* pos 03a8: 560 */ 0xF4 /* 't' -> */, +/* pos 03a9: 561 */ 0x00, 0x3A /* - terminal marker 58 - */, +/* pos 03ab: 562 */ 0xEC /* 'l' -> */, +/* pos 03ac: 563 */ 0xE5 /* 'e' -> */, +/* pos 03ad: 564 */ 0xF4 /* 't' -> */, +/* pos 03ae: 565 */ 0xE5 /* 'e' -> */, +/* pos 03af: 566 */ 0x00, 0x3B /* - terminal marker 59 - */, +/* pos 03b1: 567 */ 0x00, 0x3D /* - terminal marker 61 - */, +/* pos 03b3: 568 */ 0xE5 /* 'e' -> */, +/* pos 03b4: 569 */ 0xE1 /* 'a' -> */, +/* pos 03b5: 570 */ 0xEC /* 'l' -> */, +/* pos 03b6: 571 */ 0xAD /* '-' -> */, +/* pos 03b7: 572 */ 0xE9 /* 'i' -> */, +/* pos 03b8: 573 */ 0xF0 /* 'p' -> */, +/* pos 03b9: 574 */ 0xBA /* ':' -> */, +/* pos 03ba: 575 */ 0x00, 0x3E /* - terminal marker 62 - */, +/* pos 03bc: 576 */ 0xBA /* ':' -> */, +/* pos 03bd: 577 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 03bf: 578 */ 0xEC /* 'l' -> */, +/* pos 03c0: 579 */ 0xE1 /* 'a' -> */, +/* pos 03c1: 580 */ 0xF9 /* 'y' -> */, +/* pos 03c2: 581 */ 0xAD /* '-' -> */, +/* pos 03c3: 582 */ 0xEE /* 'n' -> */, +/* pos 03c4: 583 */ 0xEF /* 'o' -> */, +/* pos 03c5: 584 */ 0xEE /* 'n' -> */, +/* pos 03c6: 585 */ 0xE3 /* 'c' -> */, +/* pos 03c7: 586 */ 0xE5 /* 'e' -> */, +/* pos 03c8: 587 */ 0xBA /* ':' -> */, +/* pos 03c9: 588 */ 0x00, 0x44 /* - terminal marker 68 - */, +/* pos 03cb: 589 */ 0xAD /* '-' -> */, +/* pos 03cc: 590 */ 0xF7 /* 'w' -> */, +/* pos 03cd: 591 */ 0xE5 /* 'e' -> */, +/* pos 03ce: 592 */ 0xE2 /* 'b' -> */, +/* pos 03cf: 593 */ 0xF3 /* 's' -> */, +/* pos 03d0: 594 */ 0xEF /* 'o' -> */, +/* pos 03d1: 595 */ 0xE3 /* 'c' -> */, +/* pos 03d2: 596 */ 0xEB /* 'k' -> */, +/* pos 03d3: 597 */ 0xE5 /* 'e' -> */, +/* pos 03d4: 598 */ 0xF4 /* 't' -> */, +/* pos 03d5: 599 */ 0xAD /* '-' -> */, +/* pos 03d6: 600 */ 0x64 /* 'd' */, 0x19, 0x00 /* (to 0x03EF state 601) */, + 0x65 /* 'e' */, 0x1D, 0x00 /* (to 0x03F6 state 607) */, + 0x6B /* 'k' */, 0x26, 0x00 /* (to 0x0402 state 618) */, + 0x70 /* 'p' */, 0x35, 0x00 /* (to 0x0414 state 625) */, + 0x61 /* 'a' */, 0x3C, 0x00 /* (to 0x041E state 634) */, + 0x6E /* 'n' */, 0x41, 0x00 /* (to 0x0426 state 641) */, + 0x76 /* 'v' */, 0x47, 0x00 /* (to 0x042F state 648) */, + 0x6F /* 'o' */, 0x4D, 0x00 /* (to 0x0438 state 656) */, + 0x08, /* fail */ +/* pos 03ef: 601 */ 0xF2 /* 'r' -> */, +/* pos 03f0: 602 */ 0xE1 /* 'a' -> */, +/* pos 03f1: 603 */ 0xE6 /* 'f' -> */, +/* pos 03f2: 604 */ 0xF4 /* 't' -> */, +/* pos 03f3: 605 */ 0xBA /* ':' -> */, +/* pos 03f4: 606 */ 0x00, 0x06 /* - terminal marker 6 - */, +/* pos 03f6: 607 */ 0xF8 /* 'x' -> */, +/* pos 03f7: 608 */ 0xF4 /* 't' -> */, +/* pos 03f8: 609 */ 0xE5 /* 'e' -> */, +/* pos 03f9: 610 */ 0xEE /* 'n' -> */, +/* pos 03fa: 611 */ 0xF3 /* 's' -> */, +/* pos 03fb: 612 */ 0xE9 /* 'i' -> */, +/* pos 03fc: 613 */ 0xEF /* 'o' -> */, +/* pos 03fd: 614 */ 0xEE /* 'n' -> */, +/* pos 03fe: 615 */ 0xF3 /* 's' -> */, +/* pos 03ff: 616 */ 0xBA /* ':' -> */, +/* pos 0400: 617 */ 0x00, 0x08 /* - terminal marker 8 - */, +/* pos 0402: 618 */ 0xE5 /* 'e' -> */, +/* pos 0403: 619 */ 0xF9 /* 'y' -> */, +/* pos 0404: 620 */ 0x31 /* '1' */, 0x0A, 0x00 /* (to 0x040E state 621) */, + 0x32 /* '2' */, 0x0A, 0x00 /* (to 0x0411 state 623) */, + 0x3A /* ':' */, 0x23, 0x00 /* (to 0x042D state 647) */, + 0x08, /* fail */ +/* pos 040e: 621 */ 0xBA /* ':' -> */, +/* pos 040f: 622 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 0411: 623 */ 0xBA /* ':' -> */, +/* pos 0412: 624 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 0414: 625 */ 0xF2 /* 'r' -> */, +/* pos 0415: 626 */ 0xEF /* 'o' -> */, +/* pos 0416: 627 */ 0xF4 /* 't' -> */, +/* pos 0417: 628 */ 0xEF /* 'o' -> */, +/* pos 0418: 629 */ 0xE3 /* 'c' -> */, +/* pos 0419: 630 */ 0xEF /* 'o' -> */, +/* pos 041a: 631 */ 0xEC /* 'l' -> */, +/* pos 041b: 632 */ 0xBA /* ':' -> */, +/* pos 041c: 633 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 041e: 634 */ 0xE3 /* 'c' -> */, +/* pos 041f: 635 */ 0xE3 /* 'c' -> */, +/* pos 0420: 636 */ 0xE5 /* 'e' -> */, +/* pos 0421: 637 */ 0xF0 /* 'p' -> */, +/* pos 0422: 638 */ 0xF4 /* 't' -> */, +/* pos 0423: 639 */ 0xBA /* ':' -> */, +/* pos 0424: 640 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 0426: 641 */ 0xEF /* 'o' -> */, +/* pos 0427: 642 */ 0xEE /* 'n' -> */, +/* pos 0428: 643 */ 0xE3 /* 'c' -> */, +/* pos 0429: 644 */ 0xE5 /* 'e' -> */, +/* pos 042a: 645 */ 0xBA /* ':' -> */, +/* pos 042b: 646 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 042d: 647 */ 0x00, 0x1C /* - terminal marker 28 - */, +/* pos 042f: 648 */ 0xE5 /* 'e' -> */, +/* pos 0430: 649 */ 0xF2 /* 'r' -> */, +/* pos 0431: 650 */ 0xF3 /* 's' -> */, +/* pos 0432: 651 */ 0xE9 /* 'i' -> */, +/* pos 0433: 652 */ 0xEF /* 'o' -> */, +/* pos 0434: 653 */ 0xEE /* 'n' -> */, +/* pos 0435: 654 */ 0xBA /* ':' -> */, +/* pos 0436: 655 */ 0x00, 0x1D /* - terminal marker 29 - */, +/* pos 0438: 656 */ 0xF2 /* 'r' -> */, +/* pos 0439: 657 */ 0xE9 /* 'i' -> */, +/* pos 043a: 658 */ 0xE7 /* 'g' -> */, +/* pos 043b: 659 */ 0xE9 /* 'i' -> */, +/* pos 043c: 660 */ 0xEE /* 'n' -> */, +/* pos 043d: 661 */ 0xBA /* ':' -> */, +/* pos 043e: 662 */ 0x00, 0x1E /* - terminal marker 30 - */, +/* total size 1088 bytes */ #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) @@ -2209,7 +2152,7 @@ /* 13: 13: sec-websocket-accept: */ /* 14: 14: sec-websocket-nonce: */ /* 15: 15: http/1.1 */ - /* 16: 16: http2-settings: */ + /* 16: 17: accept: */ /* 17: 18: access-control-request-headers: */ /* 18: 19: if-modified-since: */ /* 19: 20: if-none-match: */ @@ -2227,7 +2170,7 @@ /* 31: 32: sec-websocket-key: */ /* 32: 33: sec-websocket-version: */ /* 33: 34: sec-websocket-origin: */ - /* 34: 35: :authority */ + /* 34: 40: accept-charset: */ /* 35: 41: accept-ranges: */ /* 36: 42: access-control-allow-origin: */ /* 37: 43: age: */ @@ -2272,797 +2215,787 @@ /* 76: 82: head */ /* 77: 83: te: */ /* 78: 84: replay-nonce: */ - /* 79: 85: :protocol */ + /* 79: 86: x-auth-token: */ /* 80: 87: */ -/* pos 0000: 0 */ 0x67 /* 'g' */, 0x40, 0x00 /* (to 0x0040 state 1) */, - 0x70 /* 'p' */, 0x42, 0x00 /* (to 0x0045 state 5) */, - 0x68 /* 'h' */, 0x51, 0x00 /* (to 0x0057 state 10) */, - 0x63 /* 'c' */, 0x5D, 0x00 /* (to 0x0066 state 15) */, - 0x75 /* 'u' */, 0x7E, 0x00 /* (to 0x008A state 26) */, - 0x6F /* 'o' */, 0x8D, 0x00 /* (to 0x009C state 34) */, - 0x0D /* '.' */, 0x98, 0x00 /* (to 0x00AA state 41) */, - 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 57) */, - 0x69 /* 'i' */, 0xE2, 0x00 /* (to 0x00FA state 88) */, - 0x64 /* 'd' */, 0x74, 0x01 /* (to 0x018F state 177) */, - 0x72 /* 'r' */, 0x7D, 0x01 /* (to 0x019B state 182) */, - 0x65 /* 'e' */, 0xE2, 0x01 /* (to 0x0203 state 256) */, - 0x66 /* 'f' */, 0xFE, 0x01 /* (to 0x0222 state 272) */, - 0x6C /* 'l' */, 0x27, 0x02 /* (to 0x024E state 306) */, - 0x6D /* 'm' */, 0x4A, 0x02 /* (to 0x0274 state 332) */, - 0x73 /* 's' */, 0x60, 0x02 /* (to 0x028D state 355) */, - 0x78 /* 'x' */, 0xAE, 0x02 /* (to 0x02DE state 410) */, - 0x74 /* 't' */, 0xC9, 0x02 /* (to 0x02FC state 431) */, - 0x76 /* 'v' */, 0x5D, 0x03 /* (to 0x0393 state 527) */, - 0x77 /* 'w' */, 0x6A, 0x03 /* (to 0x03A3 state 535) */, - 0x3A /* ':' */, 0xB0, 0x03 /* (to 0x03EC state 594) */, - 0x08, /* fail */ -/* pos 0040: 1 */ 0xE5 /* 'e' -> */, -/* pos 0041: 2 */ 0xF4 /* 't' -> */, -/* pos 0042: 3 */ 0xA0 /* ' ' -> */, -/* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, -/* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */, - 0x72 /* 'r' */, 0xED, 0x00 /* (to 0x0135 state 123) */, - 0x61 /* 'a' */, 0x6A, 0x03 /* (to 0x03B5 state 552) */, - 0x75 /* 'u' */, 0x6C, 0x03 /* (to 0x03BA state 556) */, - 0x08, /* fail */ -/* pos 0052: 6 */ 0xF3 /* 's' -> */, -/* pos 0053: 7 */ 0xF4 /* 't' -> */, -/* pos 0054: 8 */ 0xA0 /* ' ' -> */, -/* pos 0055: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, -/* pos 0057: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0061 state 11) */, - 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AD state 43) */, - 0x65 /* 'e' */, 0x9A, 0x02 /* (to 0x02F7 state 427) */, - 0x08, /* fail */ -/* pos 0061: 11 */ 0xF3 /* 's' -> */, -/* pos 0062: 12 */ 0xF4 /* 't' -> */, -/* pos 0063: 13 */ 0xBA /* ':' -> */, -/* pos 0064: 14 */ 0x00, 0x03 /* - terminal marker 3 - */, -/* pos 0066: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006D state 16) */, - 0x61 /* 'a' */, 0xD9, 0x00 /* (to 0x0142 state 129) */, - 0x08, /* fail */ -/* pos 006d: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0074 state 17) */, - 0x6F /* 'o' */, 0xEE, 0x00 /* (to 0x015E state 155) */, - 0x08, /* fail */ -/* pos 0074: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x007B state 18) */, - 0x74 /* 't' */, 0xED, 0x00 /* (to 0x0164 state 160) */, - 0x08, /* fail */ -/* pos 007b: 18 */ 0xE5 /* 'e' -> */, -/* pos 007c: 19 */ 0xE3 /* 'c' -> */, -/* pos 007d: 20 */ 0xF4 /* 't' -> */, -/* pos 007e: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0085 state 22) */, - 0x20 /* ' ' */, 0x74, 0x02 /* (to 0x02F5 state 426) */, - 0x08, /* fail */ -/* pos 0085: 22 */ 0xEF /* 'o' -> */, -/* pos 0086: 23 */ 0xEE /* 'n' -> */, -/* pos 0087: 24 */ 0xBA /* ':' -> */, -/* pos 0088: 25 */ 0x00, 0x04 /* - terminal marker 4 - */, -/* pos 008a: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0094 state 27) */, - 0x73 /* 's' */, 0x3B, 0x02 /* (to 0x02C8 state 396) */, - 0x72 /* 'r' */, 0x33, 0x03 /* (to 0x03C3 state 563) */, - 0x08, /* fail */ -/* pos 0094: 27 */ 0xE7 /* 'g' -> */, -/* pos 0095: 28 */ 0xF2 /* 'r' -> */, -/* pos 0096: 29 */ 0xE1 /* 'a' -> */, -/* pos 0097: 30 */ 0xE4 /* 'd' -> */, -/* pos 0098: 31 */ 0xE5 /* 'e' -> */, -/* pos 0099: 32 */ 0xBA /* ':' -> */, -/* pos 009a: 33 */ 0x00, 0x05 /* - terminal marker 5 - */, -/* pos 009c: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A3 state 35) */, - 0x70 /* 'p' */, 0x67, 0x02 /* (to 0x0306 state 434) */, - 0x08, /* fail */ -/* pos 00a3: 35 */ 0xE9 /* 'i' -> */, -/* pos 00a4: 36 */ 0xE7 /* 'g' -> */, -/* pos 00a5: 37 */ 0xE9 /* 'i' -> */, -/* pos 00a6: 38 */ 0xEE /* 'n' -> */, -/* pos 00a7: 39 */ 0xBA /* ':' -> */, -/* pos 00a8: 40 */ 0x00, 0x06 /* - terminal marker 6 - */, -/* pos 00aa: 41 */ 0x8A /* '.' -> */, -/* pos 00ab: 42 */ 0x00, 0x08 /* - terminal marker 8 - */, -/* pos 00ad: 43 */ 0xF4 /* 't' -> */, -/* pos 00ae: 44 */ 0xF0 /* 'p' -> */, -/* pos 00af: 45 */ 0x32 /* '2' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, - 0x2F /* '/' */, 0x22, 0x03 /* (to 0x03D4 state 578) */, - 0x08, /* fail */ -/* pos 00b6: 46 */ 0xAD /* '-' -> */, -/* pos 00b7: 47 */ 0xF3 /* 's' -> */, -/* pos 00b8: 48 */ 0xE5 /* 'e' -> */, -/* pos 00b9: 49 */ 0xF4 /* 't' -> */, -/* pos 00ba: 50 */ 0xF4 /* 't' -> */, -/* pos 00bb: 51 */ 0xE9 /* 'i' -> */, -/* pos 00bc: 52 */ 0xEE /* 'n' -> */, -/* pos 00bd: 53 */ 0xE7 /* 'g' -> */, -/* pos 00be: 54 */ 0xF3 /* 's' -> */, -/* pos 00bf: 55 */ 0xBA /* ':' -> */, -/* pos 00c0: 56 */ 0x00, 0x10 /* - terminal marker 16 - */, -/* pos 00c2: 57 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 58) */, - 0x75 /* 'u' */, 0x8B, 0x00 /* (to 0x0150 state 142) */, - 0x6C /* 'l' */, 0x05, 0x01 /* (to 0x01CD state 208) */, - 0x67 /* 'g' */, 0x8C, 0x02 /* (to 0x0357 state 478) */, - 0x08, /* fail */ -/* pos 00cf: 58 */ 0xE3 /* 'c' -> */, -/* pos 00d0: 59 */ 0xE5 /* 'e' -> */, -/* pos 00d1: 60 */ 0x73 /* 's' */, 0x07, 0x00 /* (to 0x00D8 state 61) */, - 0x70 /* 'p' */, 0x41, 0x00 /* (to 0x0115 state 102) */, - 0x08, /* fail */ -/* pos 00d8: 61 */ 0xF3 /* 's' -> */, -/* pos 00d9: 62 */ 0xAD /* '-' -> */, -/* pos 00da: 63 */ 0xE3 /* 'c' -> */, -/* pos 00db: 64 */ 0xEF /* 'o' -> */, -/* pos 00dc: 65 */ 0xEE /* 'n' -> */, -/* pos 00dd: 66 */ 0xF4 /* 't' -> */, -/* pos 00de: 67 */ 0xF2 /* 'r' -> */, -/* pos 00df: 68 */ 0xEF /* 'o' -> */, -/* pos 00e0: 69 */ 0xEC /* 'l' -> */, -/* pos 00e1: 70 */ 0xAD /* '-' -> */, -/* pos 00e2: 71 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00E9 state 72) */, - 0x61 /* 'a' */, 0xDA, 0x00 /* (to 0x01BF state 195) */, - 0x08, /* fail */ -/* pos 00e9: 72 */ 0xE5 /* 'e' -> */, -/* pos 00ea: 73 */ 0xF1 /* 'q' -> */, -/* pos 00eb: 74 */ 0xF5 /* 'u' -> */, -/* pos 00ec: 75 */ 0xE5 /* 'e' -> */, -/* pos 00ed: 76 */ 0xF3 /* 's' -> */, -/* pos 00ee: 77 */ 0xF4 /* 't' -> */, -/* pos 00ef: 78 */ 0xAD /* '-' -> */, -/* pos 00f0: 79 */ 0xE8 /* 'h' -> */, -/* pos 00f1: 80 */ 0xE5 /* 'e' -> */, -/* pos 00f2: 81 */ 0xE1 /* 'a' -> */, -/* pos 00f3: 82 */ 0xE4 /* 'd' -> */, -/* pos 00f4: 83 */ 0xE5 /* 'e' -> */, -/* pos 00f5: 84 */ 0xF2 /* 'r' -> */, -/* pos 00f6: 85 */ 0xF3 /* 's' -> */, -/* pos 00f7: 86 */ 0xBA /* ':' -> */, -/* pos 00f8: 87 */ 0x00, 0x11 /* - terminal marker 17 - */, -/* pos 00fa: 88 */ 0xE6 /* 'f' -> */, -/* pos 00fb: 89 */ 0xAD /* '-' -> */, -/* pos 00fc: 90 */ 0x6E /* 'n' */, 0x0D, 0x00 /* (to 0x0109 state 91) */, - 0x6D /* 'm' */, 0x29, 0x01 /* (to 0x0228 state 277) */, - 0x72 /* 'r' */, 0x33, 0x01 /* (to 0x0235 state 283) */, - 0x75 /* 'u' */, 0x37, 0x01 /* (to 0x023C state 289) */, - 0x08, /* fail */ -/* pos 0109: 91 */ 0xEF /* 'o' -> */, -/* pos 010a: 92 */ 0xEE /* 'n' -> */, -/* pos 010b: 93 */ 0xE5 /* 'e' -> */, -/* pos 010c: 94 */ 0xAD /* '-' -> */, -/* pos 010d: 95 */ 0xED /* 'm' -> */, -/* pos 010e: 96 */ 0xE1 /* 'a' -> */, -/* pos 010f: 97 */ 0xF4 /* 't' -> */, -/* pos 0110: 98 */ 0xE3 /* 'c' -> */, -/* pos 0111: 99 */ 0xE8 /* 'h' -> */, -/* pos 0112: 100 */ 0xBA /* ':' -> */, -/* pos 0113: 101 */ 0x00, 0x13 /* - terminal marker 19 - */, -/* pos 0115: 102 */ 0xF4 /* 't' -> */, -/* pos 0116: 103 */ 0xAD /* '-' -> */, -/* pos 0117: 104 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0121 state 105) */, - 0x6C /* 'l' */, 0x11, 0x00 /* (to 0x012B state 114) */, - 0x72 /* 'r' */, 0x32, 0x02 /* (to 0x034F state 471) */, - 0x08, /* fail */ -/* pos 0121: 105 */ 0xEE /* 'n' -> */, -/* pos 0122: 106 */ 0xE3 /* 'c' -> */, -/* pos 0123: 107 */ 0xEF /* 'o' -> */, -/* pos 0124: 108 */ 0xE4 /* 'd' -> */, -/* pos 0125: 109 */ 0xE9 /* 'i' -> */, -/* pos 0126: 110 */ 0xEE /* 'n' -> */, -/* pos 0127: 111 */ 0xE7 /* 'g' -> */, -/* pos 0128: 112 */ 0xBA /* ':' -> */, -/* pos 0129: 113 */ 0x00, 0x14 /* - terminal marker 20 - */, -/* pos 012b: 114 */ 0xE1 /* 'a' -> */, -/* pos 012c: 115 */ 0xEE /* 'n' -> */, -/* pos 012d: 116 */ 0xE7 /* 'g' -> */, -/* pos 012e: 117 */ 0xF5 /* 'u' -> */, -/* pos 012f: 118 */ 0xE1 /* 'a' -> */, -/* pos 0130: 119 */ 0xE7 /* 'g' -> */, -/* pos 0131: 120 */ 0xE5 /* 'e' -> */, -/* pos 0132: 121 */ 0xBA /* ':' -> */, -/* pos 0133: 122 */ 0x00, 0x15 /* - terminal marker 21 - */, -/* pos 0135: 123 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x013C state 124) */, - 0x6F /* 'o' */, 0x9B, 0x01 /* (to 0x02D3 state 406) */, - 0x08, /* fail */ -/* pos 013c: 124 */ 0xE7 /* 'g' -> */, -/* pos 013d: 125 */ 0xED /* 'm' -> */, -/* pos 013e: 126 */ 0xE1 /* 'a' -> */, -/* pos 013f: 127 */ 0xBA /* ':' -> */, -/* pos 0140: 128 */ 0x00, 0x16 /* - terminal marker 22 - */, -/* pos 0142: 129 */ 0xE3 /* 'c' -> */, -/* pos 0143: 130 */ 0xE8 /* 'h' -> */, -/* pos 0144: 131 */ 0xE5 /* 'e' -> */, -/* pos 0145: 132 */ 0xAD /* '-' -> */, -/* pos 0146: 133 */ 0xE3 /* 'c' -> */, -/* pos 0147: 134 */ 0xEF /* 'o' -> */, -/* pos 0148: 135 */ 0xEE /* 'n' -> */, -/* pos 0149: 136 */ 0xF4 /* 't' -> */, -/* pos 014a: 137 */ 0xF2 /* 'r' -> */, -/* pos 014b: 138 */ 0xEF /* 'o' -> */, -/* pos 014c: 139 */ 0xEC /* 'l' -> */, -/* pos 014d: 140 */ 0xBA /* ':' -> */, -/* pos 014e: 141 */ 0x00, 0x17 /* - terminal marker 23 - */, -/* pos 0150: 142 */ 0xF4 /* 't' -> */, -/* pos 0151: 143 */ 0xE8 /* 'h' -> */, -/* pos 0152: 144 */ 0xEF /* 'o' -> */, -/* pos 0153: 145 */ 0xF2 /* 'r' -> */, -/* pos 0154: 146 */ 0xE9 /* 'i' -> */, -/* pos 0155: 147 */ 0xFA /* 'z' -> */, -/* pos 0156: 148 */ 0xE1 /* 'a' -> */, -/* pos 0157: 149 */ 0xF4 /* 't' -> */, -/* pos 0158: 150 */ 0xE9 /* 'i' -> */, -/* pos 0159: 151 */ 0xEF /* 'o' -> */, -/* pos 015a: 152 */ 0xEE /* 'n' -> */, -/* pos 015b: 153 */ 0xBA /* ':' -> */, -/* pos 015c: 154 */ 0x00, 0x18 /* - terminal marker 24 - */, -/* pos 015e: 155 */ 0xEB /* 'k' -> */, -/* pos 015f: 156 */ 0xE9 /* 'i' -> */, -/* pos 0160: 157 */ 0xE5 /* 'e' -> */, -/* pos 0161: 158 */ 0xBA /* ':' -> */, -/* pos 0162: 159 */ 0x00, 0x19 /* - terminal marker 25 - */, -/* pos 0164: 160 */ 0xE5 /* 'e' -> */, -/* pos 0165: 161 */ 0xEE /* 'n' -> */, -/* pos 0166: 162 */ 0xF4 /* 't' -> */, -/* pos 0167: 163 */ 0xAD /* '-' -> */, -/* pos 0168: 164 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0178 state 165) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0189 state 172) */, - 0x64 /* 'd' */, 0x65, 0x00 /* (to 0x01D3 state 213) */, - 0x65 /* 'e' */, 0x6F, 0x00 /* (to 0x01E0 state 225) */, - 0x72 /* 'r' */, 0x88, 0x00 /* (to 0x01FC state 250) */, - 0x08, /* fail */ -/* pos 0178: 165 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0182 state 166) */, - 0x61 /* 'a' */, 0x6F, 0x00 /* (to 0x01EA state 234) */, - 0x6F /* 'o' */, 0x75, 0x00 /* (to 0x01F3 state 242) */, - 0x08, /* fail */ -/* pos 0182: 166 */ 0xEE /* 'n' -> */, -/* pos 0183: 167 */ 0xE7 /* 'g' -> */, -/* pos 0184: 168 */ 0xF4 /* 't' -> */, -/* pos 0185: 169 */ 0xE8 /* 'h' -> */, -/* pos 0186: 170 */ 0xBA /* ':' -> */, -/* pos 0187: 171 */ 0x00, 0x1A /* - terminal marker 26 - */, -/* pos 0189: 172 */ 0xF9 /* 'y' -> */, -/* pos 018a: 173 */ 0xF0 /* 'p' -> */, -/* pos 018b: 174 */ 0xE5 /* 'e' -> */, -/* pos 018c: 175 */ 0xBA /* ':' -> */, -/* pos 018d: 176 */ 0x00, 0x1B /* - terminal marker 27 - */, -/* pos 018f: 177 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0196 state 178) */, - 0x65 /* 'e' */, 0x2B, 0x02 /* (to 0x03BD state 558) */, - 0x08, /* fail */ -/* pos 0196: 178 */ 0xF4 /* 't' -> */, -/* pos 0197: 179 */ 0xE5 /* 'e' -> */, -/* pos 0198: 180 */ 0xBA /* ':' -> */, -/* pos 0199: 181 */ 0x00, 0x1C /* - terminal marker 28 - */, -/* pos 019b: 182 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01A2 state 183) */, - 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x01A8 state 188) */, - 0x08, /* fail */ -/* pos 01a2: 183 */ 0xEE /* 'n' -> */, -/* pos 01a3: 184 */ 0xE7 /* 'g' -> */, -/* pos 01a4: 185 */ 0xE5 /* 'e' -> */, -/* pos 01a5: 186 */ 0xBA /* ':' -> */, -/* pos 01a6: 187 */ 0x00, 0x1D /* - terminal marker 29 - */, -/* pos 01a8: 188 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x01B2 state 189) */, - 0x74 /* 't' */, 0xD7, 0x00 /* (to 0x0282 state 345) */, - 0x70 /* 'p' */, 0x32, 0x02 /* (to 0x03E0 state 583) */, - 0x08, /* fail */ -/* pos 01b2: 189 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01B9 state 190) */, - 0x72 /* 'r' */, 0xC6, 0x01 /* (to 0x037B state 505) */, - 0x08, /* fail */ -/* pos 01b9: 190 */ 0xF2 /* 'r' -> */, -/* pos 01ba: 191 */ 0xE5 /* 'e' -> */, -/* pos 01bb: 192 */ 0xF2 /* 'r' -> */, -/* pos 01bc: 193 */ 0xBA /* ':' -> */, -/* pos 01bd: 194 */ 0x00, 0x1E /* - terminal marker 30 - */, -/* pos 01bf: 195 */ 0xEC /* 'l' -> */, -/* pos 01c0: 196 */ 0xEC /* 'l' -> */, -/* pos 01c1: 197 */ 0xEF /* 'o' -> */, -/* pos 01c2: 198 */ 0xF7 /* 'w' -> */, -/* pos 01c3: 199 */ 0xAD /* '-' -> */, -/* pos 01c4: 200 */ 0xEF /* 'o' -> */, -/* pos 01c5: 201 */ 0xF2 /* 'r' -> */, -/* pos 01c6: 202 */ 0xE9 /* 'i' -> */, -/* pos 01c7: 203 */ 0xE7 /* 'g' -> */, -/* pos 01c8: 204 */ 0xE9 /* 'i' -> */, -/* pos 01c9: 205 */ 0xEE /* 'n' -> */, -/* pos 01ca: 206 */ 0xBA /* ':' -> */, -/* pos 01cb: 207 */ 0x00, 0x24 /* - terminal marker 36 - */, -/* pos 01cd: 208 */ 0xEC /* 'l' -> */, -/* pos 01ce: 209 */ 0xEF /* 'o' -> */, -/* pos 01cf: 210 */ 0xF7 /* 'w' -> */, -/* pos 01d0: 211 */ 0xBA /* ':' -> */, -/* pos 01d1: 212 */ 0x00, 0x26 /* - terminal marker 38 - */, -/* pos 01d3: 213 */ 0xE9 /* 'i' -> */, -/* pos 01d4: 214 */ 0xF3 /* 's' -> */, -/* pos 01d5: 215 */ 0xF0 /* 'p' -> */, -/* pos 01d6: 216 */ 0xEF /* 'o' -> */, -/* pos 01d7: 217 */ 0xF3 /* 's' -> */, -/* pos 01d8: 218 */ 0xE9 /* 'i' -> */, -/* pos 01d9: 219 */ 0xF4 /* 't' -> */, -/* pos 01da: 220 */ 0xE9 /* 'i' -> */, -/* pos 01db: 221 */ 0xEF /* 'o' -> */, -/* pos 01dc: 222 */ 0xEE /* 'n' -> */, -/* pos 01dd: 223 */ 0xBA /* ':' -> */, -/* pos 01de: 224 */ 0x00, 0x27 /* - terminal marker 39 - */, -/* pos 01e0: 225 */ 0xEE /* 'n' -> */, -/* pos 01e1: 226 */ 0xE3 /* 'c' -> */, -/* pos 01e2: 227 */ 0xEF /* 'o' -> */, -/* pos 01e3: 228 */ 0xE4 /* 'd' -> */, -/* pos 01e4: 229 */ 0xE9 /* 'i' -> */, -/* pos 01e5: 230 */ 0xEE /* 'n' -> */, -/* pos 01e6: 231 */ 0xE7 /* 'g' -> */, -/* pos 01e7: 232 */ 0xBA /* ':' -> */, -/* pos 01e8: 233 */ 0x00, 0x28 /* - terminal marker 40 - */, -/* pos 01ea: 234 */ 0xEE /* 'n' -> */, -/* pos 01eb: 235 */ 0xE7 /* 'g' -> */, -/* pos 01ec: 236 */ 0xF5 /* 'u' -> */, -/* pos 01ed: 237 */ 0xE1 /* 'a' -> */, -/* pos 01ee: 238 */ 0xE7 /* 'g' -> */, -/* pos 01ef: 239 */ 0xE5 /* 'e' -> */, -/* pos 01f0: 240 */ 0xBA /* ':' -> */, -/* pos 01f1: 241 */ 0x00, 0x29 /* - terminal marker 41 - */, -/* pos 01f3: 242 */ 0xE3 /* 'c' -> */, -/* pos 01f4: 243 */ 0xE1 /* 'a' -> */, -/* pos 01f5: 244 */ 0xF4 /* 't' -> */, -/* pos 01f6: 245 */ 0xE9 /* 'i' -> */, -/* pos 01f7: 246 */ 0xEF /* 'o' -> */, -/* pos 01f8: 247 */ 0xEE /* 'n' -> */, -/* pos 01f9: 248 */ 0xBA /* ':' -> */, -/* pos 01fa: 249 */ 0x00, 0x2A /* - terminal marker 42 - */, -/* pos 01fc: 250 */ 0xE1 /* 'a' -> */, -/* pos 01fd: 251 */ 0xEE /* 'n' -> */, -/* pos 01fe: 252 */ 0xE7 /* 'g' -> */, -/* pos 01ff: 253 */ 0xE5 /* 'e' -> */, -/* pos 0200: 254 */ 0xBA /* ':' -> */, -/* pos 0201: 255 */ 0x00, 0x2B /* - terminal marker 43 - */, -/* pos 0203: 256 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x020A state 257) */, - 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x020F state 261) */, - 0x08, /* fail */ -/* pos 020a: 257 */ 0xE1 /* 'a' -> */, -/* pos 020b: 258 */ 0xE7 /* 'g' -> */, -/* pos 020c: 259 */ 0xBA /* ':' -> */, -/* pos 020d: 260 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 020f: 261 */ 0xF0 /* 'p' -> */, -/* pos 0210: 262 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0217 state 263) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x021C state 267) */, - 0x08, /* fail */ -/* pos 0217: 263 */ 0xE3 /* 'c' -> */, -/* pos 0218: 264 */ 0xF4 /* 't' -> */, -/* pos 0219: 265 */ 0xBA /* ':' -> */, -/* pos 021a: 266 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 021c: 267 */ 0xF2 /* 'r' -> */, -/* pos 021d: 268 */ 0xE5 /* 'e' -> */, -/* pos 021e: 269 */ 0xF3 /* 's' -> */, -/* pos 021f: 270 */ 0xBA /* ':' -> */, -/* pos 0220: 271 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 0222: 272 */ 0xF2 /* 'r' -> */, -/* pos 0223: 273 */ 0xEF /* 'o' -> */, -/* pos 0224: 274 */ 0xED /* 'm' -> */, -/* pos 0225: 275 */ 0xBA /* ':' -> */, -/* pos 0226: 276 */ 0x00, 0x2F /* - terminal marker 47 - */, -/* pos 0228: 277 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x022F state 278) */, - 0x6F /* 'o' */, 0xE3, 0x00 /* (to 0x030E state 441) */, - 0x08, /* fail */ -/* pos 022f: 278 */ 0xF4 /* 't' -> */, -/* pos 0230: 279 */ 0xE3 /* 'c' -> */, -/* pos 0231: 280 */ 0xE8 /* 'h' -> */, -/* pos 0232: 281 */ 0xBA /* ':' -> */, -/* pos 0233: 282 */ 0x00, 0x30 /* - terminal marker 48 - */, -/* pos 0235: 283 */ 0xE1 /* 'a' -> */, -/* pos 0236: 284 */ 0xEE /* 'n' -> */, -/* pos 0237: 285 */ 0xE7 /* 'g' -> */, -/* pos 0238: 286 */ 0xE5 /* 'e' -> */, -/* pos 0239: 287 */ 0xBA /* ':' -> */, -/* pos 023a: 288 */ 0x00, 0x31 /* - terminal marker 49 - */, -/* pos 023c: 289 */ 0xEE /* 'n' -> */, -/* pos 023d: 290 */ 0xED /* 'm' -> */, -/* pos 023e: 291 */ 0xEF /* 'o' -> */, -/* pos 023f: 292 */ 0xE4 /* 'd' -> */, -/* pos 0240: 293 */ 0xE9 /* 'i' -> */, -/* pos 0241: 294 */ 0xE6 /* 'f' -> */, -/* pos 0242: 295 */ 0xE9 /* 'i' -> */, -/* pos 0243: 296 */ 0xE5 /* 'e' -> */, -/* pos 0244: 297 */ 0xE4 /* 'd' -> */, -/* pos 0245: 298 */ 0xAD /* '-' -> */, -/* pos 0246: 299 */ 0xF3 /* 's' -> */, -/* pos 0247: 300 */ 0xE9 /* 'i' -> */, -/* pos 0248: 301 */ 0xEE /* 'n' -> */, -/* pos 0249: 302 */ 0xE3 /* 'c' -> */, -/* pos 024a: 303 */ 0xE5 /* 'e' -> */, -/* pos 024b: 304 */ 0xBA /* ':' -> */, -/* pos 024c: 305 */ 0x00, 0x32 /* - terminal marker 50 - */, -/* pos 024e: 306 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0258 state 307) */, - 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x0266 state 320) */, - 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x026B state 324) */, - 0x08, /* fail */ -/* pos 0258: 307 */ 0xF3 /* 's' -> */, -/* pos 0259: 308 */ 0xF4 /* 't' -> */, -/* pos 025a: 309 */ 0xAD /* '-' -> */, -/* pos 025b: 310 */ 0xED /* 'm' -> */, -/* pos 025c: 311 */ 0xEF /* 'o' -> */, -/* pos 025d: 312 */ 0xE4 /* 'd' -> */, -/* pos 025e: 313 */ 0xE9 /* 'i' -> */, -/* pos 025f: 314 */ 0xE6 /* 'f' -> */, -/* pos 0260: 315 */ 0xE9 /* 'i' -> */, -/* pos 0261: 316 */ 0xE5 /* 'e' -> */, -/* pos 0262: 317 */ 0xE4 /* 'd' -> */, -/* pos 0263: 318 */ 0xBA /* ':' -> */, -/* pos 0264: 319 */ 0x00, 0x33 /* - terminal marker 51 - */, -/* pos 0266: 320 */ 0xEE /* 'n' -> */, -/* pos 0267: 321 */ 0xEB /* 'k' -> */, -/* pos 0268: 322 */ 0xBA /* ':' -> */, -/* pos 0269: 323 */ 0x00, 0x34 /* - terminal marker 52 - */, -/* pos 026b: 324 */ 0xE3 /* 'c' -> */, -/* pos 026c: 325 */ 0xE1 /* 'a' -> */, -/* pos 026d: 326 */ 0xF4 /* 't' -> */, -/* pos 026e: 327 */ 0xE9 /* 'i' -> */, -/* pos 026f: 328 */ 0xEF /* 'o' -> */, -/* pos 0270: 329 */ 0xEE /* 'n' -> */, -/* pos 0271: 330 */ 0xBA /* ':' -> */, -/* pos 0272: 331 */ 0x00, 0x35 /* - terminal marker 53 - */, -/* pos 0274: 332 */ 0xE1 /* 'a' -> */, -/* pos 0275: 333 */ 0xF8 /* 'x' -> */, -/* pos 0276: 334 */ 0xAD /* '-' -> */, -/* pos 0277: 335 */ 0xE6 /* 'f' -> */, -/* pos 0278: 336 */ 0xEF /* 'o' -> */, -/* pos 0279: 337 */ 0xF2 /* 'r' -> */, -/* pos 027a: 338 */ 0xF7 /* 'w' -> */, -/* pos 027b: 339 */ 0xE1 /* 'a' -> */, -/* pos 027c: 340 */ 0xF2 /* 'r' -> */, -/* pos 027d: 341 */ 0xE4 /* 'd' -> */, -/* pos 027e: 342 */ 0xF3 /* 's' -> */, -/* pos 027f: 343 */ 0xBA /* ':' -> */, -/* pos 0280: 344 */ 0x00, 0x36 /* - terminal marker 54 - */, -/* pos 0282: 345 */ 0xF2 /* 'r' -> */, -/* pos 0283: 346 */ 0xF9 /* 'y' -> */, -/* pos 0284: 347 */ 0xAD /* '-' -> */, -/* pos 0285: 348 */ 0xE1 /* 'a' -> */, -/* pos 0286: 349 */ 0xE6 /* 'f' -> */, -/* pos 0287: 350 */ 0xF4 /* 't' -> */, -/* pos 0288: 351 */ 0xE5 /* 'e' -> */, -/* pos 0289: 352 */ 0xF2 /* 'r' -> */, -/* pos 028a: 353 */ 0xBA /* ':' -> */, -/* pos 028b: 354 */ 0x00, 0x3A /* - terminal marker 58 - */, -/* pos 028d: 355 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0294 state 356) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x02AE state 371) */, - 0x08, /* fail */ -/* pos 0294: 356 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x029E state 357) */, - 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x02A4 state 362) */, - 0x63 /* 'c' */, 0x83, 0x00 /* (to 0x031D state 455) */, - 0x08, /* fail */ -/* pos 029e: 357 */ 0xF6 /* 'v' -> */, -/* pos 029f: 358 */ 0xE5 /* 'e' -> */, -/* pos 02a0: 359 */ 0xF2 /* 'r' -> */, -/* pos 02a1: 360 */ 0xBA /* ':' -> */, -/* pos 02a2: 361 */ 0x00, 0x3B /* - terminal marker 59 - */, -/* pos 02a4: 362 */ 0xAD /* '-' -> */, -/* pos 02a5: 363 */ 0xE3 /* 'c' -> */, -/* pos 02a6: 364 */ 0xEF /* 'o' -> */, -/* pos 02a7: 365 */ 0xEF /* 'o' -> */, -/* pos 02a8: 366 */ 0xEB /* 'k' -> */, -/* pos 02a9: 367 */ 0xE9 /* 'i' -> */, -/* pos 02aa: 368 */ 0xE5 /* 'e' -> */, -/* pos 02ab: 369 */ 0xBA /* ':' -> */, -/* pos 02ac: 370 */ 0x00, 0x3C /* - terminal marker 60 - */, -/* pos 02ae: 371 */ 0xF2 /* 'r' -> */, -/* pos 02af: 372 */ 0xE9 /* 'i' -> */, -/* pos 02b0: 373 */ 0xE3 /* 'c' -> */, -/* pos 02b1: 374 */ 0xF4 /* 't' -> */, -/* pos 02b2: 375 */ 0xAD /* '-' -> */, -/* pos 02b3: 376 */ 0xF4 /* 't' -> */, -/* pos 02b4: 377 */ 0xF2 /* 'r' -> */, -/* pos 02b5: 378 */ 0xE1 /* 'a' -> */, -/* pos 02b6: 379 */ 0xEE /* 'n' -> */, -/* pos 02b7: 380 */ 0xF3 /* 's' -> */, -/* pos 02b8: 381 */ 0xF0 /* 'p' -> */, -/* pos 02b9: 382 */ 0xEF /* 'o' -> */, -/* pos 02ba: 383 */ 0xF2 /* 'r' -> */, -/* pos 02bb: 384 */ 0xF4 /* 't' -> */, -/* pos 02bc: 385 */ 0xAD /* '-' -> */, -/* pos 02bd: 386 */ 0xF3 /* 's' -> */, -/* pos 02be: 387 */ 0xE5 /* 'e' -> */, -/* pos 02bf: 388 */ 0xE3 /* 'c' -> */, -/* pos 02c0: 389 */ 0xF5 /* 'u' -> */, -/* pos 02c1: 390 */ 0xF2 /* 'r' -> */, -/* pos 02c2: 391 */ 0xE9 /* 'i' -> */, -/* pos 02c3: 392 */ 0xF4 /* 't' -> */, -/* pos 02c4: 393 */ 0xF9 /* 'y' -> */, -/* pos 02c5: 394 */ 0xBA /* ':' -> */, -/* pos 02c6: 395 */ 0x00, 0x3D /* - terminal marker 61 - */, -/* pos 02c8: 396 */ 0xE5 /* 'e' -> */, -/* pos 02c9: 397 */ 0xF2 /* 'r' -> */, -/* pos 02ca: 398 */ 0xAD /* '-' -> */, -/* pos 02cb: 399 */ 0xE1 /* 'a' -> */, -/* pos 02cc: 400 */ 0xE7 /* 'g' -> */, -/* pos 02cd: 401 */ 0xE5 /* 'e' -> */, -/* pos 02ce: 402 */ 0xEE /* 'n' -> */, -/* pos 02cf: 403 */ 0xF4 /* 't' -> */, -/* pos 02d0: 404 */ 0xBA /* ':' -> */, -/* pos 02d1: 405 */ 0x00, 0x3F /* - terminal marker 63 - */, -/* pos 02d3: 406 */ 0xF8 /* 'x' -> */, -/* pos 02d4: 407 */ 0xF9 /* 'y' -> */, -/* pos 02d5: 408 */ 0x20 /* ' ' */, 0x07, 0x00 /* (to 0x02DC state 409) */, - 0x2D /* '-' */, 0x83, 0x00 /* (to 0x035B state 481) */, - 0x08, /* fail */ -/* pos 02dc: 409 */ 0x00, 0x47 /* - terminal marker 71 - */, -/* pos 02de: 410 */ 0xAD /* '-' -> */, -/* pos 02df: 411 */ 0x66 /* 'f' */, 0x07, 0x00 /* (to 0x02E6 state 412) */, - 0x72 /* 'r' */, 0xE9, 0x00 /* (to 0x03CB state 570) */, - 0x08, /* fail */ -/* pos 02e6: 412 */ 0xEF /* 'o' -> */, -/* pos 02e7: 413 */ 0xF2 /* 'r' -> */, -/* pos 02e8: 414 */ 0xF7 /* 'w' -> */, -/* pos 02e9: 415 */ 0xE1 /* 'a' -> */, -/* pos 02ea: 416 */ 0xF2 /* 'r' -> */, -/* pos 02eb: 417 */ 0xE4 /* 'd' -> */, -/* pos 02ec: 418 */ 0xE5 /* 'e' -> */, -/* pos 02ed: 419 */ 0xE4 /* 'd' -> */, -/* pos 02ee: 420 */ 0xAD /* '-' -> */, -/* pos 02ef: 421 */ 0xE6 /* 'f' -> */, -/* pos 02f0: 422 */ 0xEF /* 'o' -> */, -/* pos 02f1: 423 */ 0xF2 /* 'r' -> */, -/* pos 02f2: 424 */ 0xBA /* ':' -> */, -/* pos 02f3: 425 */ 0x00, 0x4A /* - terminal marker 74 - */, -/* pos 02f5: 426 */ 0x00, 0x4B /* - terminal marker 75 - */, -/* pos 02f7: 427 */ 0xE1 /* 'a' -> */, -/* pos 02f8: 428 */ 0xE4 /* 'd' -> */, -/* pos 02f9: 429 */ 0xA0 /* ' ' -> */, -/* pos 02fa: 430 */ 0x00, 0x4C /* - terminal marker 76 - */, -/* pos 02fc: 431 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0303 state 432) */, - 0x72 /* 'r' */, 0x82, 0x00 /* (to 0x0381 state 510) */, - 0x08, /* fail */ -/* pos 0303: 432 */ 0xBA /* ':' -> */, -/* pos 0304: 433 */ 0x00, 0x4D /* - terminal marker 77 - */, -/* pos 0306: 434 */ 0xF4 /* 't' -> */, -/* pos 0307: 435 */ 0xE9 /* 'i' -> */, -/* pos 0308: 436 */ 0xEF /* 'o' -> */, -/* pos 0309: 437 */ 0xEE /* 'n' -> */, -/* pos 030a: 438 */ 0xF3 /* 's' -> */, -/* pos 030b: 439 */ 0xA0 /* ' ' -> */, -/* pos 030c: 440 */ 0x00, 0x02 /* - terminal marker 2 - */, -/* pos 030e: 441 */ 0xE4 /* 'd' -> */, -/* pos 030f: 442 */ 0xE9 /* 'i' -> */, -/* pos 0310: 443 */ 0xE6 /* 'f' -> */, -/* pos 0311: 444 */ 0xE9 /* 'i' -> */, -/* pos 0312: 445 */ 0xE5 /* 'e' -> */, -/* pos 0313: 446 */ 0xE4 /* 'd' -> */, -/* pos 0314: 447 */ 0xAD /* '-' -> */, -/* pos 0315: 448 */ 0xF3 /* 's' -> */, -/* pos 0316: 449 */ 0xE9 /* 'i' -> */, -/* pos 0317: 450 */ 0xEE /* 'n' -> */, -/* pos 0318: 451 */ 0xE3 /* 'c' -> */, -/* pos 0319: 452 */ 0xE5 /* 'e' -> */, -/* pos 031a: 453 */ 0xBA /* ':' -> */, -/* pos 031b: 454 */ 0x00, 0x12 /* - terminal marker 18 - */, -/* pos 031d: 455 */ 0xAD /* '-' -> */, -/* pos 031e: 456 */ 0xF7 /* 'w' -> */, -/* pos 031f: 457 */ 0xE5 /* 'e' -> */, -/* pos 0320: 458 */ 0xE2 /* 'b' -> */, -/* pos 0321: 459 */ 0xF3 /* 's' -> */, -/* pos 0322: 460 */ 0xEF /* 'o' -> */, -/* pos 0323: 461 */ 0xE3 /* 'c' -> */, -/* pos 0324: 462 */ 0xEB /* 'k' -> */, -/* pos 0325: 463 */ 0xE5 /* 'e' -> */, -/* pos 0326: 464 */ 0xF4 /* 't' -> */, -/* pos 0327: 465 */ 0xAD /* '-' -> */, -/* pos 0328: 466 */ 0x6B /* 'k' */, 0x19, 0x00 /* (to 0x0341 state 467) */, - 0x64 /* 'd' */, 0xD1, 0x00 /* (to 0x03FC state 603) */, - 0x65 /* 'e' */, 0xD5, 0x00 /* (to 0x0403 state 609) */, - 0x70 /* 'p' */, 0xE4, 0x00 /* (to 0x0415 state 624) */, - 0x61 /* 'a' */, 0xEB, 0x00 /* (to 0x041F state 633) */, - 0x6E /* 'n' */, 0xF0, 0x00 /* (to 0x0427 state 640) */, - 0x76 /* 'v' */, 0xF7, 0x00 /* (to 0x0431 state 648) */, - 0x6F /* 'o' */, 0xFD, 0x00 /* (to 0x043A state 656) */, - 0x08, /* fail */ -/* pos 0341: 467 */ 0xE5 /* 'e' -> */, -/* pos 0342: 468 */ 0xF9 /* 'y' -> */, -/* pos 0343: 469 */ 0x3A /* ':' */, 0x0A, 0x00 /* (to 0x034D state 470) */, - 0x31 /* '1' */, 0xC9, 0x00 /* (to 0x040F state 620) */, - 0x32 /* '2' */, 0xC9, 0x00 /* (to 0x0412 state 622) */, - 0x08, /* fail */ -/* pos 034d: 470 */ 0x00, 0x1F /* - terminal marker 31 - */, -/* pos 034f: 471 */ 0xE1 /* 'a' -> */, -/* pos 0350: 472 */ 0xEE /* 'n' -> */, -/* pos 0351: 473 */ 0xE7 /* 'g' -> */, -/* pos 0352: 474 */ 0xE5 /* 'e' -> */, -/* pos 0353: 475 */ 0xF3 /* 's' -> */, -/* pos 0354: 476 */ 0xBA /* ':' -> */, -/* pos 0355: 477 */ 0x00, 0x23 /* - terminal marker 35 - */, -/* pos 0357: 478 */ 0xE5 /* 'e' -> */, -/* pos 0358: 479 */ 0xBA /* ':' -> */, -/* pos 0359: 480 */ 0x00, 0x25 /* - terminal marker 37 - */, -/* pos 035b: 481 */ 0xE1 /* 'a' -> */, -/* pos 035c: 482 */ 0xF5 /* 'u' -> */, -/* pos 035d: 483 */ 0xF4 /* 't' -> */, -/* pos 035e: 484 */ 0xE8 /* 'h' -> */, -/* pos 035f: 485 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0366 state 486) */, - 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x0370 state 495) */, - 0x08, /* fail */ -/* pos 0366: 486 */ 0xEE /* 'n' -> */, -/* pos 0367: 487 */ 0xF4 /* 't' -> */, -/* pos 0368: 488 */ 0xE9 /* 'i' -> */, -/* pos 0369: 489 */ 0xE3 /* 'c' -> */, -/* pos 036a: 490 */ 0xE1 /* 'a' -> */, -/* pos 036b: 491 */ 0xF4 /* 't' -> */, -/* pos 036c: 492 */ 0xE5 /* 'e' -> */, -/* pos 036d: 493 */ 0xBA /* ':' -> */, -/* pos 036e: 494 */ 0x00, 0x37 /* - terminal marker 55 - */, -/* pos 0370: 495 */ 0xF2 /* 'r' -> */, -/* pos 0371: 496 */ 0xE9 /* 'i' -> */, -/* pos 0372: 497 */ 0xFA /* 'z' -> */, -/* pos 0373: 498 */ 0xE1 /* 'a' -> */, -/* pos 0374: 499 */ 0xF4 /* 't' -> */, -/* pos 0375: 500 */ 0xE9 /* 'i' -> */, -/* pos 0376: 501 */ 0xEF /* 'o' -> */, -/* pos 0377: 502 */ 0xEE /* 'n' -> */, -/* pos 0378: 503 */ 0xBA /* ':' -> */, -/* pos 0379: 504 */ 0x00, 0x38 /* - terminal marker 56 - */, -/* pos 037b: 505 */ 0xE5 /* 'e' -> */, -/* pos 037c: 506 */ 0xF3 /* 's' -> */, -/* pos 037d: 507 */ 0xE8 /* 'h' -> */, -/* pos 037e: 508 */ 0xBA /* ':' -> */, -/* pos 037f: 509 */ 0x00, 0x39 /* - terminal marker 57 - */, -/* pos 0381: 510 */ 0xE1 /* 'a' -> */, -/* pos 0382: 511 */ 0xEE /* 'n' -> */, -/* pos 0383: 512 */ 0xF3 /* 's' -> */, -/* pos 0384: 513 */ 0xE6 /* 'f' -> */, -/* pos 0385: 514 */ 0xE5 /* 'e' -> */, -/* pos 0386: 515 */ 0xF2 /* 'r' -> */, -/* pos 0387: 516 */ 0xAD /* '-' -> */, -/* pos 0388: 517 */ 0xE5 /* 'e' -> */, -/* pos 0389: 518 */ 0xEE /* 'n' -> */, -/* pos 038a: 519 */ 0xE3 /* 'c' -> */, -/* pos 038b: 520 */ 0xEF /* 'o' -> */, -/* pos 038c: 521 */ 0xE4 /* 'd' -> */, -/* pos 038d: 522 */ 0xE9 /* 'i' -> */, -/* pos 038e: 523 */ 0xEE /* 'n' -> */, -/* pos 038f: 524 */ 0xE7 /* 'g' -> */, -/* pos 0390: 525 */ 0xBA /* ':' -> */, -/* pos 0391: 526 */ 0x00, 0x3E /* - terminal marker 62 - */, -/* pos 0393: 527 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x039A state 528) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x039F state 532) */, - 0x08, /* fail */ -/* pos 039a: 528 */ 0xF2 /* 'r' -> */, -/* pos 039b: 529 */ 0xF9 /* 'y' -> */, -/* pos 039c: 530 */ 0xBA /* ':' -> */, -/* pos 039d: 531 */ 0x00, 0x40 /* - terminal marker 64 - */, -/* pos 039f: 532 */ 0xE1 /* 'a' -> */, -/* pos 03a0: 533 */ 0xBA /* ':' -> */, -/* pos 03a1: 534 */ 0x00, 0x41 /* - terminal marker 65 - */, -/* pos 03a3: 535 */ 0xF7 /* 'w' -> */, -/* pos 03a4: 536 */ 0xF7 /* 'w' -> */, -/* pos 03a5: 537 */ 0xAD /* '-' -> */, -/* pos 03a6: 538 */ 0xE1 /* 'a' -> */, -/* pos 03a7: 539 */ 0xF5 /* 'u' -> */, -/* pos 03a8: 540 */ 0xF4 /* 't' -> */, -/* pos 03a9: 541 */ 0xE8 /* 'h' -> */, -/* pos 03aa: 542 */ 0xE5 /* 'e' -> */, -/* pos 03ab: 543 */ 0xEE /* 'n' -> */, -/* pos 03ac: 544 */ 0xF4 /* 't' -> */, -/* pos 03ad: 545 */ 0xE9 /* 'i' -> */, -/* pos 03ae: 546 */ 0xE3 /* 'c' -> */, -/* pos 03af: 547 */ 0xE1 /* 'a' -> */, -/* pos 03b0: 548 */ 0xF4 /* 't' -> */, -/* pos 03b1: 549 */ 0xE5 /* 'e' -> */, -/* pos 03b2: 550 */ 0xBA /* ':' -> */, -/* pos 03b3: 551 */ 0x00, 0x42 /* - terminal marker 66 - */, -/* pos 03b5: 552 */ 0xF4 /* 't' -> */, -/* pos 03b6: 553 */ 0xE3 /* 'c' -> */, -/* pos 03b7: 554 */ 0xE8 /* 'h' -> */, -/* pos 03b8: 555 */ 0x00, 0x43 /* - terminal marker 67 - */, -/* pos 03ba: 556 */ 0xF4 /* 't' -> */, -/* pos 03bb: 557 */ 0x00, 0x44 /* - terminal marker 68 - */, -/* pos 03bd: 558 */ 0xEC /* 'l' -> */, -/* pos 03be: 559 */ 0xE5 /* 'e' -> */, -/* pos 03bf: 560 */ 0xF4 /* 't' -> */, -/* pos 03c0: 561 */ 0xE5 /* 'e' -> */, -/* pos 03c1: 562 */ 0x00, 0x45 /* - terminal marker 69 - */, -/* pos 03c3: 563 */ 0xE9 /* 'i' -> */, -/* pos 03c4: 564 */ 0xAD /* '-' -> */, -/* pos 03c5: 565 */ 0xE1 /* 'a' -> */, -/* pos 03c6: 566 */ 0xF2 /* 'r' -> */, -/* pos 03c7: 567 */ 0xE7 /* 'g' -> */, -/* pos 03c8: 568 */ 0xF3 /* 's' -> */, -/* pos 03c9: 569 */ 0x00, 0x46 /* - terminal marker 70 - */, -/* pos 03cb: 570 */ 0xE5 /* 'e' -> */, -/* pos 03cc: 571 */ 0xE1 /* 'a' -> */, -/* pos 03cd: 572 */ 0xEC /* 'l' -> */, -/* pos 03ce: 573 */ 0xAD /* '-' -> */, -/* pos 03cf: 574 */ 0xE9 /* 'i' -> */, -/* pos 03d0: 575 */ 0xF0 /* 'p' -> */, -/* pos 03d1: 576 */ 0xBA /* ':' -> */, -/* pos 03d2: 577 */ 0x00, 0x48 /* - terminal marker 72 - */, -/* pos 03d4: 578 */ 0xB1 /* '1' -> */, -/* pos 03d5: 579 */ 0xAE /* '.' -> */, -/* pos 03d6: 580 */ 0x30 /* '0' */, 0x07, 0x00 /* (to 0x03DD state 581) */, - 0x31 /* '1' */, 0x55, 0x00 /* (to 0x042E state 646) */, - 0x08, /* fail */ -/* pos 03dd: 581 */ 0xA0 /* ' ' -> */, -/* pos 03de: 582 */ 0x00, 0x49 /* - terminal marker 73 - */, -/* pos 03e0: 583 */ 0xEC /* 'l' -> */, -/* pos 03e1: 584 */ 0xE1 /* 'a' -> */, -/* pos 03e2: 585 */ 0xF9 /* 'y' -> */, -/* pos 03e3: 586 */ 0xAD /* '-' -> */, -/* pos 03e4: 587 */ 0xEE /* 'n' -> */, -/* pos 03e5: 588 */ 0xEF /* 'o' -> */, -/* pos 03e6: 589 */ 0xEE /* 'n' -> */, -/* pos 03e7: 590 */ 0xE3 /* 'c' -> */, -/* pos 03e8: 591 */ 0xE5 /* 'e' -> */, -/* pos 03e9: 592 */ 0xBA /* ':' -> */, -/* pos 03ea: 593 */ 0x00, 0x4E /* - terminal marker 78 - */, -/* pos 03ec: 594 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x03F3 state 595) */, - 0x61 /* 'a' */, 0x53, 0x00 /* (to 0x0442 state 663) */, - 0x08, /* fail */ -/* pos 03f3: 595 */ 0xF2 /* 'r' -> */, -/* pos 03f4: 596 */ 0xEF /* 'o' -> */, -/* pos 03f5: 597 */ 0xF4 /* 't' -> */, -/* pos 03f6: 598 */ 0xEF /* 'o' -> */, -/* pos 03f7: 599 */ 0xE3 /* 'c' -> */, -/* pos 03f8: 600 */ 0xEF /* 'o' -> */, -/* pos 03f9: 601 */ 0xEC /* 'l' -> */, -/* pos 03fa: 602 */ 0x00, 0x4F /* - terminal marker 79 - */, -/* pos 03fc: 603 */ 0xF2 /* 'r' -> */, -/* pos 03fd: 604 */ 0xE1 /* 'a' -> */, -/* pos 03fe: 605 */ 0xE6 /* 'f' -> */, -/* pos 03ff: 606 */ 0xF4 /* 't' -> */, -/* pos 0400: 607 */ 0xBA /* ':' -> */, -/* pos 0401: 608 */ 0x00, 0x07 /* - terminal marker 7 - */, -/* pos 0403: 609 */ 0xF8 /* 'x' -> */, -/* pos 0404: 610 */ 0xF4 /* 't' -> */, -/* pos 0405: 611 */ 0xE5 /* 'e' -> */, -/* pos 0406: 612 */ 0xEE /* 'n' -> */, -/* pos 0407: 613 */ 0xF3 /* 's' -> */, -/* pos 0408: 614 */ 0xE9 /* 'i' -> */, -/* pos 0409: 615 */ 0xEF /* 'o' -> */, -/* pos 040a: 616 */ 0xEE /* 'n' -> */, -/* pos 040b: 617 */ 0xF3 /* 's' -> */, -/* pos 040c: 618 */ 0xBA /* ':' -> */, -/* pos 040d: 619 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 040f: 620 */ 0xBA /* ':' -> */, -/* pos 0410: 621 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 0412: 622 */ 0xBA /* ':' -> */, -/* pos 0413: 623 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 0415: 624 */ 0xF2 /* 'r' -> */, -/* pos 0416: 625 */ 0xEF /* 'o' -> */, -/* pos 0417: 626 */ 0xF4 /* 't' -> */, -/* pos 0418: 627 */ 0xEF /* 'o' -> */, -/* pos 0419: 628 */ 0xE3 /* 'c' -> */, -/* pos 041a: 629 */ 0xEF /* 'o' -> */, -/* pos 041b: 630 */ 0xEC /* 'l' -> */, -/* pos 041c: 631 */ 0xBA /* ':' -> */, -/* pos 041d: 632 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 041f: 633 */ 0xE3 /* 'c' -> */, -/* pos 0420: 634 */ 0xE3 /* 'c' -> */, -/* pos 0421: 635 */ 0xE5 /* 'e' -> */, -/* pos 0422: 636 */ 0xF0 /* 'p' -> */, -/* pos 0423: 637 */ 0xF4 /* 't' -> */, -/* pos 0424: 638 */ 0xBA /* ':' -> */, -/* pos 0425: 639 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 0427: 640 */ 0xEF /* 'o' -> */, -/* pos 0428: 641 */ 0xEE /* 'n' -> */, -/* pos 0429: 642 */ 0xE3 /* 'c' -> */, -/* pos 042a: 643 */ 0xE5 /* 'e' -> */, -/* pos 042b: 644 */ 0xBA /* ':' -> */, -/* pos 042c: 645 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 042e: 646 */ 0xA0 /* ' ' -> */, -/* pos 042f: 647 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 0431: 648 */ 0xE5 /* 'e' -> */, -/* pos 0432: 649 */ 0xF2 /* 'r' -> */, -/* pos 0433: 650 */ 0xF3 /* 's' -> */, -/* pos 0434: 651 */ 0xE9 /* 'i' -> */, -/* pos 0435: 652 */ 0xEF /* 'o' -> */, -/* pos 0436: 653 */ 0xEE /* 'n' -> */, -/* pos 0437: 654 */ 0xBA /* ':' -> */, -/* pos 0438: 655 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 043a: 656 */ 0xF2 /* 'r' -> */, -/* pos 043b: 657 */ 0xE9 /* 'i' -> */, -/* pos 043c: 658 */ 0xE7 /* 'g' -> */, -/* pos 043d: 659 */ 0xE9 /* 'i' -> */, -/* pos 043e: 660 */ 0xEE /* 'n' -> */, -/* pos 043f: 661 */ 0xBA /* ':' -> */, -/* pos 0440: 662 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 0442: 663 */ 0xF5 /* 'u' -> */, -/* pos 0443: 664 */ 0xF4 /* 't' -> */, -/* pos 0444: 665 */ 0xE8 /* 'h' -> */, -/* pos 0445: 666 */ 0xEF /* 'o' -> */, -/* pos 0446: 667 */ 0xF2 /* 'r' -> */, -/* pos 0447: 668 */ 0xE9 /* 'i' -> */, -/* pos 0448: 669 */ 0xF4 /* 't' -> */, -/* pos 0449: 670 */ 0xF9 /* 'y' -> */, -/* pos 044a: 671 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* total size 1100 bytes */ +/* pos 0000: 0 */ 0x67 /* 'g' */, 0x3D, 0x00 /* (to 0x003D state 1) */, + 0x70 /* 'p' */, 0x3F, 0x00 /* (to 0x0042 state 5) */, + 0x68 /* 'h' */, 0x4E, 0x00 /* (to 0x0054 state 10) */, + 0x63 /* 'c' */, 0x5A, 0x00 /* (to 0x0063 state 15) */, + 0x75 /* 'u' */, 0x7B, 0x00 /* (to 0x0087 state 26) */, + 0x6F /* 'o' */, 0x8A, 0x00 /* (to 0x0099 state 34) */, + 0x0D /* '.' */, 0x95, 0x00 /* (to 0x00A7 state 41) */, + 0x61 /* 'a' */, 0xA4, 0x00 /* (to 0x00B9 state 51) */, + 0x69 /* 'i' */, 0xC1, 0x00 /* (to 0x00D9 state 58) */, + 0x64 /* 'd' */, 0x6A, 0x01 /* (to 0x0185 state 160) */, + 0x72 /* 'r' */, 0x73, 0x01 /* (to 0x0191 state 165) */, + 0x65 /* 'e' */, 0xBF, 0x01 /* (to 0x01E0 state 229) */, + 0x66 /* 'f' */, 0xDB, 0x01 /* (to 0x01FF state 245) */, + 0x6C /* 'l' */, 0xFD, 0x01 /* (to 0x0224 state 278) */, + 0x73 /* 's' */, 0x42, 0x02 /* (to 0x026C state 321) */, + 0x74 /* 't' */, 0x60, 0x02 /* (to 0x028D state 337) */, + 0x78 /* 'x' */, 0x81, 0x02 /* (to 0x02B1 state 364) */, + 0x6D /* 'm' */, 0xF2, 0x02 /* (to 0x0325 state 456) */, + 0x76 /* 'v' */, 0x4B, 0x03 /* (to 0x0381 state 531) */, + 0x77 /* 'w' */, 0x58, 0x03 /* (to 0x0391 state 539) */, + 0x08, /* fail */ +/* pos 003d: 1 */ 0xE5 /* 'e' -> */, +/* pos 003e: 2 */ 0xF4 /* 't' -> */, +/* pos 003f: 3 */ 0xA0 /* ' ' -> */, +/* pos 0040: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, +/* pos 0042: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x004F state 6) */, + 0x72 /* 'r' */, 0xE6, 0x00 /* (to 0x012B state 106) */, + 0x61 /* 'a' */, 0x5B, 0x03 /* (to 0x03A3 state 556) */, + 0x75 /* 'u' */, 0x5D, 0x03 /* (to 0x03A8 state 560) */, + 0x08, /* fail */ +/* pos 004f: 6 */ 0xF3 /* 's' -> */, +/* pos 0050: 7 */ 0xF4 /* 't' -> */, +/* pos 0051: 8 */ 0xA0 /* ' ' -> */, +/* pos 0052: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, +/* pos 0054: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x005E state 11) */, + 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AA state 43) */, + 0x65 /* 'e' */, 0x73, 0x02 /* (to 0x02CD state 381) */, + 0x08, /* fail */ +/* pos 005e: 11 */ 0xF3 /* 's' -> */, +/* pos 005f: 12 */ 0xF4 /* 't' -> */, +/* pos 0060: 13 */ 0xBA /* ':' -> */, +/* pos 0061: 14 */ 0x00, 0x03 /* - terminal marker 3 - */, +/* pos 0063: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006A state 16) */, + 0x61 /* 'a' */, 0xD2, 0x00 /* (to 0x0138 state 112) */, + 0x08, /* fail */ +/* pos 006a: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0071 state 17) */, + 0x6F /* 'o' */, 0xE7, 0x00 /* (to 0x0154 state 138) */, + 0x08, /* fail */ +/* pos 0071: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0078 state 18) */, + 0x74 /* 't' */, 0xE6, 0x00 /* (to 0x015A state 143) */, + 0x08, /* fail */ +/* pos 0078: 18 */ 0xE5 /* 'e' -> */, +/* pos 0079: 19 */ 0xE3 /* 'c' -> */, +/* pos 007a: 20 */ 0xF4 /* 't' -> */, +/* pos 007b: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0082 state 22) */, + 0x20 /* ' ' */, 0x4D, 0x02 /* (to 0x02CB state 380) */, + 0x08, /* fail */ +/* pos 0082: 22 */ 0xEF /* 'o' -> */, +/* pos 0083: 23 */ 0xEE /* 'n' -> */, +/* pos 0084: 24 */ 0xBA /* ':' -> */, +/* pos 0085: 25 */ 0x00, 0x04 /* - terminal marker 4 - */, +/* pos 0087: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0091 state 27) */, + 0x72 /* 'r' */, 0x1C, 0x02 /* (to 0x02A6 state 355) */, + 0x73 /* 's' */, 0xE9, 0x02 /* (to 0x0376 state 521) */, + 0x08, /* fail */ +/* pos 0091: 27 */ 0xE7 /* 'g' -> */, +/* pos 0092: 28 */ 0xF2 /* 'r' -> */, +/* pos 0093: 29 */ 0xE1 /* 'a' -> */, +/* pos 0094: 30 */ 0xE4 /* 'd' -> */, +/* pos 0095: 31 */ 0xE5 /* 'e' -> */, +/* pos 0096: 32 */ 0xBA /* ':' -> */, +/* pos 0097: 33 */ 0x00, 0x05 /* - terminal marker 5 - */, +/* pos 0099: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A0 state 35) */, + 0x70 /* 'p' */, 0x42, 0x02 /* (to 0x02DE state 396) */, + 0x08, /* fail */ +/* pos 00a0: 35 */ 0xE9 /* 'i' -> */, +/* pos 00a1: 36 */ 0xE7 /* 'g' -> */, +/* pos 00a2: 37 */ 0xE9 /* 'i' -> */, +/* pos 00a3: 38 */ 0xEE /* 'n' -> */, +/* pos 00a4: 39 */ 0xBA /* ':' -> */, +/* pos 00a5: 40 */ 0x00, 0x06 /* - terminal marker 6 - */, +/* pos 00a7: 41 */ 0x8A /* '.' -> */, +/* pos 00a8: 42 */ 0x00, 0x08 /* - terminal marker 8 - */, +/* pos 00aa: 43 */ 0xF4 /* 't' -> */, +/* pos 00ab: 44 */ 0xF0 /* 'p' -> */, +/* pos 00ac: 45 */ 0xAF /* '/' -> */, +/* pos 00ad: 46 */ 0xB1 /* '1' -> */, +/* pos 00ae: 47 */ 0xAE /* '.' -> */, +/* pos 00af: 48 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x00B6 state 49) */, + 0x30 /* '0' */, 0xFC, 0x01 /* (to 0x02AE state 362) */, + 0x08, /* fail */ +/* pos 00b6: 49 */ 0xA0 /* ' ' -> */, +/* pos 00b7: 50 */ 0x00, 0x0F /* - terminal marker 15 - */, +/* pos 00b9: 51 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00C6 state 52) */, + 0x75 /* 'u' */, 0x8A, 0x00 /* (to 0x0146 state 125) */, + 0x67 /* 'g' */, 0xE7, 0x00 /* (to 0x01A6 state 178) */, + 0x6C /* 'l' */, 0xE8, 0x00 /* (to 0x01AA state 181) */, + 0x08, /* fail */ +/* pos 00c6: 52 */ 0xE3 /* 'c' -> */, +/* pos 00c7: 53 */ 0xE5 /* 'e' -> */, +/* pos 00c8: 54 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x00CF state 55) */, + 0x73 /* 's' */, 0x1B, 0x02 /* (to 0x02E6 state 403) */, + 0x08, /* fail */ +/* pos 00cf: 55 */ 0xF4 /* 't' -> */, +/* pos 00d0: 56 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x00D7 state 57) */, + 0x2D /* '-' */, 0x37, 0x00 /* (to 0x010A state 87) */, + 0x08, /* fail */ +/* pos 00d7: 57 */ 0x00, 0x10 /* - terminal marker 16 - */, +/* pos 00d9: 58 */ 0xE6 /* 'f' -> */, +/* pos 00da: 59 */ 0xAD /* '-' -> */, +/* pos 00db: 60 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x00E8 state 61) */, + 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x00FE state 76) */, + 0x72 /* 'r' */, 0x2A, 0x01 /* (to 0x020B state 255) */, + 0x75 /* 'u' */, 0x2E, 0x01 /* (to 0x0212 state 261) */, + 0x08, /* fail */ +/* pos 00e8: 61 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x00EF state 62) */, + 0x61 /* 'a' */, 0x1A, 0x01 /* (to 0x0205 state 250) */, + 0x08, /* fail */ +/* pos 00ef: 62 */ 0xE4 /* 'd' -> */, +/* pos 00f0: 63 */ 0xE9 /* 'i' -> */, +/* pos 00f1: 64 */ 0xE6 /* 'f' -> */, +/* pos 00f2: 65 */ 0xE9 /* 'i' -> */, +/* pos 00f3: 66 */ 0xE5 /* 'e' -> */, +/* pos 00f4: 67 */ 0xE4 /* 'd' -> */, +/* pos 00f5: 68 */ 0xAD /* '-' -> */, +/* pos 00f6: 69 */ 0xF3 /* 's' -> */, +/* pos 00f7: 70 */ 0xE9 /* 'i' -> */, +/* pos 00f8: 71 */ 0xEE /* 'n' -> */, +/* pos 00f9: 72 */ 0xE3 /* 'c' -> */, +/* pos 00fa: 73 */ 0xE5 /* 'e' -> */, +/* pos 00fb: 74 */ 0xBA /* ':' -> */, +/* pos 00fc: 75 */ 0x00, 0x12 /* - terminal marker 18 - */, +/* pos 00fe: 76 */ 0xEF /* 'o' -> */, +/* pos 00ff: 77 */ 0xEE /* 'n' -> */, +/* pos 0100: 78 */ 0xE5 /* 'e' -> */, +/* pos 0101: 79 */ 0xAD /* '-' -> */, +/* pos 0102: 80 */ 0xED /* 'm' -> */, +/* pos 0103: 81 */ 0xE1 /* 'a' -> */, +/* pos 0104: 82 */ 0xF4 /* 't' -> */, +/* pos 0105: 83 */ 0xE3 /* 'c' -> */, +/* pos 0106: 84 */ 0xE8 /* 'h' -> */, +/* pos 0107: 85 */ 0xBA /* ':' -> */, +/* pos 0108: 86 */ 0x00, 0x13 /* - terminal marker 19 - */, +/* pos 010a: 87 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x0117 state 88) */, + 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x0121 state 97) */, + 0x72 /* 'r' */, 0x8E, 0x00 /* (to 0x019E state 171) */, + 0x63 /* 'c' */, 0xFB, 0x01 /* (to 0x030E state 435) */, + 0x08, /* fail */ +/* pos 0117: 88 */ 0xEE /* 'n' -> */, +/* pos 0118: 89 */ 0xE3 /* 'c' -> */, +/* pos 0119: 90 */ 0xEF /* 'o' -> */, +/* pos 011a: 91 */ 0xE4 /* 'd' -> */, +/* pos 011b: 92 */ 0xE9 /* 'i' -> */, +/* pos 011c: 93 */ 0xEE /* 'n' -> */, +/* pos 011d: 94 */ 0xE7 /* 'g' -> */, +/* pos 011e: 95 */ 0xBA /* ':' -> */, +/* pos 011f: 96 */ 0x00, 0x14 /* - terminal marker 20 - */, +/* pos 0121: 97 */ 0xE1 /* 'a' -> */, +/* pos 0122: 98 */ 0xEE /* 'n' -> */, +/* pos 0123: 99 */ 0xE7 /* 'g' -> */, +/* pos 0124: 100 */ 0xF5 /* 'u' -> */, +/* pos 0125: 101 */ 0xE1 /* 'a' -> */, +/* pos 0126: 102 */ 0xE7 /* 'g' -> */, +/* pos 0127: 103 */ 0xE5 /* 'e' -> */, +/* pos 0128: 104 */ 0xBA /* ':' -> */, +/* pos 0129: 105 */ 0x00, 0x15 /* - terminal marker 21 - */, +/* pos 012b: 106 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0132 state 107) */, + 0x6F /* 'o' */, 0x05, 0x02 /* (to 0x0333 state 469) */, + 0x08, /* fail */ +/* pos 0132: 107 */ 0xE7 /* 'g' -> */, +/* pos 0133: 108 */ 0xED /* 'm' -> */, +/* pos 0134: 109 */ 0xE1 /* 'a' -> */, +/* pos 0135: 110 */ 0xBA /* ':' -> */, +/* pos 0136: 111 */ 0x00, 0x16 /* - terminal marker 22 - */, +/* pos 0138: 112 */ 0xE3 /* 'c' -> */, +/* pos 0139: 113 */ 0xE8 /* 'h' -> */, +/* pos 013a: 114 */ 0xE5 /* 'e' -> */, +/* pos 013b: 115 */ 0xAD /* '-' -> */, +/* pos 013c: 116 */ 0xE3 /* 'c' -> */, +/* pos 013d: 117 */ 0xEF /* 'o' -> */, +/* pos 013e: 118 */ 0xEE /* 'n' -> */, +/* pos 013f: 119 */ 0xF4 /* 't' -> */, +/* pos 0140: 120 */ 0xF2 /* 'r' -> */, +/* pos 0141: 121 */ 0xEF /* 'o' -> */, +/* pos 0142: 122 */ 0xEC /* 'l' -> */, +/* pos 0143: 123 */ 0xBA /* ':' -> */, +/* pos 0144: 124 */ 0x00, 0x17 /* - terminal marker 23 - */, +/* pos 0146: 125 */ 0xF4 /* 't' -> */, +/* pos 0147: 126 */ 0xE8 /* 'h' -> */, +/* pos 0148: 127 */ 0xEF /* 'o' -> */, +/* pos 0149: 128 */ 0xF2 /* 'r' -> */, +/* pos 014a: 129 */ 0xE9 /* 'i' -> */, +/* pos 014b: 130 */ 0xFA /* 'z' -> */, +/* pos 014c: 131 */ 0xE1 /* 'a' -> */, +/* pos 014d: 132 */ 0xF4 /* 't' -> */, +/* pos 014e: 133 */ 0xE9 /* 'i' -> */, +/* pos 014f: 134 */ 0xEF /* 'o' -> */, +/* pos 0150: 135 */ 0xEE /* 'n' -> */, +/* pos 0151: 136 */ 0xBA /* ':' -> */, +/* pos 0152: 137 */ 0x00, 0x18 /* - terminal marker 24 - */, +/* pos 0154: 138 */ 0xEB /* 'k' -> */, +/* pos 0155: 139 */ 0xE9 /* 'i' -> */, +/* pos 0156: 140 */ 0xE5 /* 'e' -> */, +/* pos 0157: 141 */ 0xBA /* ':' -> */, +/* pos 0158: 142 */ 0x00, 0x19 /* - terminal marker 25 - */, +/* pos 015a: 143 */ 0xE5 /* 'e' -> */, +/* pos 015b: 144 */ 0xEE /* 'n' -> */, +/* pos 015c: 145 */ 0xF4 /* 't' -> */, +/* pos 015d: 146 */ 0xAD /* '-' -> */, +/* pos 015e: 147 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x016E state 148) */, + 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x017F state 155) */, + 0x64 /* 'd' */, 0x4C, 0x00 /* (to 0x01B0 state 186) */, + 0x65 /* 'e' */, 0x56, 0x00 /* (to 0x01BD state 198) */, + 0x72 /* 'r' */, 0x6F, 0x00 /* (to 0x01D9 state 223) */, + 0x08, /* fail */ +/* pos 016e: 148 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0178 state 149) */, + 0x61 /* 'a' */, 0x56, 0x00 /* (to 0x01C7 state 207) */, + 0x6F /* 'o' */, 0x5C, 0x00 /* (to 0x01D0 state 215) */, + 0x08, /* fail */ +/* pos 0178: 149 */ 0xEE /* 'n' -> */, +/* pos 0179: 150 */ 0xE7 /* 'g' -> */, +/* pos 017a: 151 */ 0xF4 /* 't' -> */, +/* pos 017b: 152 */ 0xE8 /* 'h' -> */, +/* pos 017c: 153 */ 0xBA /* ':' -> */, +/* pos 017d: 154 */ 0x00, 0x1A /* - terminal marker 26 - */, +/* pos 017f: 155 */ 0xF9 /* 'y' -> */, +/* pos 0180: 156 */ 0xF0 /* 'p' -> */, +/* pos 0181: 157 */ 0xE5 /* 'e' -> */, +/* pos 0182: 158 */ 0xBA /* ':' -> */, +/* pos 0183: 159 */ 0x00, 0x1B /* - terminal marker 27 - */, +/* pos 0185: 160 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x018C state 161) */, + 0x65 /* 'e' */, 0x23, 0x02 /* (to 0x03AB state 562) */, + 0x08, /* fail */ +/* pos 018c: 161 */ 0xF4 /* 't' -> */, +/* pos 018d: 162 */ 0xE5 /* 'e' -> */, +/* pos 018e: 163 */ 0xBA /* ':' -> */, +/* pos 018f: 164 */ 0x00, 0x1C /* - terminal marker 28 - */, +/* pos 0191: 165 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0198 state 166) */, + 0x65 /* 'e' */, 0xB6, 0x00 /* (to 0x024A state 304) */, + 0x08, /* fail */ +/* pos 0198: 166 */ 0xEE /* 'n' -> */, +/* pos 0199: 167 */ 0xE7 /* 'g' -> */, +/* pos 019a: 168 */ 0xE5 /* 'e' -> */, +/* pos 019b: 169 */ 0xBA /* ':' -> */, +/* pos 019c: 170 */ 0x00, 0x1D /* - terminal marker 29 - */, +/* pos 019e: 171 */ 0xE1 /* 'a' -> */, +/* pos 019f: 172 */ 0xEE /* 'n' -> */, +/* pos 01a0: 173 */ 0xE7 /* 'g' -> */, +/* pos 01a1: 174 */ 0xE5 /* 'e' -> */, +/* pos 01a2: 175 */ 0xF3 /* 's' -> */, +/* pos 01a3: 176 */ 0xBA /* ':' -> */, +/* pos 01a4: 177 */ 0x00, 0x23 /* - terminal marker 35 - */, +/* pos 01a6: 178 */ 0xE5 /* 'e' -> */, +/* pos 01a7: 179 */ 0xBA /* ':' -> */, +/* pos 01a8: 180 */ 0x00, 0x25 /* - terminal marker 37 - */, +/* pos 01aa: 181 */ 0xEC /* 'l' -> */, +/* pos 01ab: 182 */ 0xEF /* 'o' -> */, +/* pos 01ac: 183 */ 0xF7 /* 'w' -> */, +/* pos 01ad: 184 */ 0xBA /* ':' -> */, +/* pos 01ae: 185 */ 0x00, 0x26 /* - terminal marker 38 - */, +/* pos 01b0: 186 */ 0xE9 /* 'i' -> */, +/* pos 01b1: 187 */ 0xF3 /* 's' -> */, +/* pos 01b2: 188 */ 0xF0 /* 'p' -> */, +/* pos 01b3: 189 */ 0xEF /* 'o' -> */, +/* pos 01b4: 190 */ 0xF3 /* 's' -> */, +/* pos 01b5: 191 */ 0xE9 /* 'i' -> */, +/* pos 01b6: 192 */ 0xF4 /* 't' -> */, +/* pos 01b7: 193 */ 0xE9 /* 'i' -> */, +/* pos 01b8: 194 */ 0xEF /* 'o' -> */, +/* pos 01b9: 195 */ 0xEE /* 'n' -> */, +/* pos 01ba: 196 */ 0xBA /* ':' -> */, +/* pos 01bb: 197 */ 0x00, 0x27 /* - terminal marker 39 - */, +/* pos 01bd: 198 */ 0xEE /* 'n' -> */, +/* pos 01be: 199 */ 0xE3 /* 'c' -> */, +/* pos 01bf: 200 */ 0xEF /* 'o' -> */, +/* pos 01c0: 201 */ 0xE4 /* 'd' -> */, +/* pos 01c1: 202 */ 0xE9 /* 'i' -> */, +/* pos 01c2: 203 */ 0xEE /* 'n' -> */, +/* pos 01c3: 204 */ 0xE7 /* 'g' -> */, +/* pos 01c4: 205 */ 0xBA /* ':' -> */, +/* pos 01c5: 206 */ 0x00, 0x28 /* - terminal marker 40 - */, +/* pos 01c7: 207 */ 0xEE /* 'n' -> */, +/* pos 01c8: 208 */ 0xE7 /* 'g' -> */, +/* pos 01c9: 209 */ 0xF5 /* 'u' -> */, +/* pos 01ca: 210 */ 0xE1 /* 'a' -> */, +/* pos 01cb: 211 */ 0xE7 /* 'g' -> */, +/* pos 01cc: 212 */ 0xE5 /* 'e' -> */, +/* pos 01cd: 213 */ 0xBA /* ':' -> */, +/* pos 01ce: 214 */ 0x00, 0x29 /* - terminal marker 41 - */, +/* pos 01d0: 215 */ 0xE3 /* 'c' -> */, +/* pos 01d1: 216 */ 0xE1 /* 'a' -> */, +/* pos 01d2: 217 */ 0xF4 /* 't' -> */, +/* pos 01d3: 218 */ 0xE9 /* 'i' -> */, +/* pos 01d4: 219 */ 0xEF /* 'o' -> */, +/* pos 01d5: 220 */ 0xEE /* 'n' -> */, +/* pos 01d6: 221 */ 0xBA /* ':' -> */, +/* pos 01d7: 222 */ 0x00, 0x2A /* - terminal marker 42 - */, +/* pos 01d9: 223 */ 0xE1 /* 'a' -> */, +/* pos 01da: 224 */ 0xEE /* 'n' -> */, +/* pos 01db: 225 */ 0xE7 /* 'g' -> */, +/* pos 01dc: 226 */ 0xE5 /* 'e' -> */, +/* pos 01dd: 227 */ 0xBA /* ':' -> */, +/* pos 01de: 228 */ 0x00, 0x2B /* - terminal marker 43 - */, +/* pos 01e0: 229 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x01E7 state 230) */, + 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x01EC state 234) */, + 0x08, /* fail */ +/* pos 01e7: 230 */ 0xE1 /* 'a' -> */, +/* pos 01e8: 231 */ 0xE7 /* 'g' -> */, +/* pos 01e9: 232 */ 0xBA /* ':' -> */, +/* pos 01ea: 233 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 01ec: 234 */ 0xF0 /* 'p' -> */, +/* pos 01ed: 235 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01F4 state 236) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x01F9 state 240) */, + 0x08, /* fail */ +/* pos 01f4: 236 */ 0xE3 /* 'c' -> */, +/* pos 01f5: 237 */ 0xF4 /* 't' -> */, +/* pos 01f6: 238 */ 0xBA /* ':' -> */, +/* pos 01f7: 239 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 01f9: 240 */ 0xF2 /* 'r' -> */, +/* pos 01fa: 241 */ 0xE5 /* 'e' -> */, +/* pos 01fb: 242 */ 0xF3 /* 's' -> */, +/* pos 01fc: 243 */ 0xBA /* ':' -> */, +/* pos 01fd: 244 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 01ff: 245 */ 0xF2 /* 'r' -> */, +/* pos 0200: 246 */ 0xEF /* 'o' -> */, +/* pos 0201: 247 */ 0xED /* 'm' -> */, +/* pos 0202: 248 */ 0xBA /* ':' -> */, +/* pos 0203: 249 */ 0x00, 0x2F /* - terminal marker 47 - */, +/* pos 0205: 250 */ 0xF4 /* 't' -> */, +/* pos 0206: 251 */ 0xE3 /* 'c' -> */, +/* pos 0207: 252 */ 0xE8 /* 'h' -> */, +/* pos 0208: 253 */ 0xBA /* ':' -> */, +/* pos 0209: 254 */ 0x00, 0x30 /* - terminal marker 48 - */, +/* pos 020b: 255 */ 0xE1 /* 'a' -> */, +/* pos 020c: 256 */ 0xEE /* 'n' -> */, +/* pos 020d: 257 */ 0xE7 /* 'g' -> */, +/* pos 020e: 258 */ 0xE5 /* 'e' -> */, +/* pos 020f: 259 */ 0xBA /* ':' -> */, +/* pos 0210: 260 */ 0x00, 0x31 /* - terminal marker 49 - */, +/* pos 0212: 261 */ 0xEE /* 'n' -> */, +/* pos 0213: 262 */ 0xED /* 'm' -> */, +/* pos 0214: 263 */ 0xEF /* 'o' -> */, +/* pos 0215: 264 */ 0xE4 /* 'd' -> */, +/* pos 0216: 265 */ 0xE9 /* 'i' -> */, +/* pos 0217: 266 */ 0xE6 /* 'f' -> */, +/* pos 0218: 267 */ 0xE9 /* 'i' -> */, +/* pos 0219: 268 */ 0xE5 /* 'e' -> */, +/* pos 021a: 269 */ 0xE4 /* 'd' -> */, +/* pos 021b: 270 */ 0xAD /* '-' -> */, +/* pos 021c: 271 */ 0xF3 /* 's' -> */, +/* pos 021d: 272 */ 0xE9 /* 'i' -> */, +/* pos 021e: 273 */ 0xEE /* 'n' -> */, +/* pos 021f: 274 */ 0xE3 /* 'c' -> */, +/* pos 0220: 275 */ 0xE5 /* 'e' -> */, +/* pos 0221: 276 */ 0xBA /* ':' -> */, +/* pos 0222: 277 */ 0x00, 0x32 /* - terminal marker 50 - */, +/* pos 0224: 278 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x022E state 279) */, + 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x023C state 292) */, + 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0241 state 296) */, + 0x08, /* fail */ +/* pos 022e: 279 */ 0xF3 /* 's' -> */, +/* pos 022f: 280 */ 0xF4 /* 't' -> */, +/* pos 0230: 281 */ 0xAD /* '-' -> */, +/* pos 0231: 282 */ 0xED /* 'm' -> */, +/* pos 0232: 283 */ 0xEF /* 'o' -> */, +/* pos 0233: 284 */ 0xE4 /* 'd' -> */, +/* pos 0234: 285 */ 0xE9 /* 'i' -> */, +/* pos 0235: 286 */ 0xE6 /* 'f' -> */, +/* pos 0236: 287 */ 0xE9 /* 'i' -> */, +/* pos 0237: 288 */ 0xE5 /* 'e' -> */, +/* pos 0238: 289 */ 0xE4 /* 'd' -> */, +/* pos 0239: 290 */ 0xBA /* ':' -> */, +/* pos 023a: 291 */ 0x00, 0x33 /* - terminal marker 51 - */, +/* pos 023c: 292 */ 0xEE /* 'n' -> */, +/* pos 023d: 293 */ 0xEB /* 'k' -> */, +/* pos 023e: 294 */ 0xBA /* ':' -> */, +/* pos 023f: 295 */ 0x00, 0x34 /* - terminal marker 52 - */, +/* pos 0241: 296 */ 0xE3 /* 'c' -> */, +/* pos 0242: 297 */ 0xE1 /* 'a' -> */, +/* pos 0243: 298 */ 0xF4 /* 't' -> */, +/* pos 0244: 299 */ 0xE9 /* 'i' -> */, +/* pos 0245: 300 */ 0xEF /* 'o' -> */, +/* pos 0246: 301 */ 0xEE /* 'n' -> */, +/* pos 0247: 302 */ 0xBA /* ':' -> */, +/* pos 0248: 303 */ 0x00, 0x35 /* - terminal marker 53 - */, +/* pos 024a: 304 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x0254 state 305) */, + 0x74 /* 't' */, 0x14, 0x00 /* (to 0x0261 state 311) */, + 0x70 /* 'p' */, 0x6F, 0x01 /* (to 0x03BF state 578) */, + 0x08, /* fail */ +/* pos 0254: 305 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x025B state 306) */, + 0x65 /* 'e' */, 0xB1, 0x00 /* (to 0x0308 state 430) */, + 0x08, /* fail */ +/* pos 025b: 306 */ 0xE5 /* 'e' -> */, +/* pos 025c: 307 */ 0xF3 /* 's' -> */, +/* pos 025d: 308 */ 0xE8 /* 'h' -> */, +/* pos 025e: 309 */ 0xBA /* ':' -> */, +/* pos 025f: 310 */ 0x00, 0x39 /* - terminal marker 57 - */, +/* pos 0261: 311 */ 0xF2 /* 'r' -> */, +/* pos 0262: 312 */ 0xF9 /* 'y' -> */, +/* pos 0263: 313 */ 0xAD /* '-' -> */, +/* pos 0264: 314 */ 0xE1 /* 'a' -> */, +/* pos 0265: 315 */ 0xE6 /* 'f' -> */, +/* pos 0266: 316 */ 0xF4 /* 't' -> */, +/* pos 0267: 317 */ 0xE5 /* 'e' -> */, +/* pos 0268: 318 */ 0xF2 /* 'r' -> */, +/* pos 0269: 319 */ 0xBA /* ':' -> */, +/* pos 026a: 320 */ 0x00, 0x3A /* - terminal marker 58 - */, +/* pos 026c: 321 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0273 state 322) */, + 0x74 /* 't' */, 0xED, 0x00 /* (to 0x035C state 496) */, + 0x08, /* fail */ +/* pos 0273: 322 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x027D state 323) */, + 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x0283 state 328) */, + 0x63 /* 'c' */, 0x52, 0x01 /* (to 0x03CB state 589) */, + 0x08, /* fail */ +/* pos 027d: 323 */ 0xF6 /* 'v' -> */, +/* pos 027e: 324 */ 0xE5 /* 'e' -> */, +/* pos 027f: 325 */ 0xF2 /* 'r' -> */, +/* pos 0280: 326 */ 0xBA /* ':' -> */, +/* pos 0281: 327 */ 0x00, 0x3B /* - terminal marker 59 - */, +/* pos 0283: 328 */ 0xAD /* '-' -> */, +/* pos 0284: 329 */ 0xE3 /* 'c' -> */, +/* pos 0285: 330 */ 0xEF /* 'o' -> */, +/* pos 0286: 331 */ 0xEF /* 'o' -> */, +/* pos 0287: 332 */ 0xEB /* 'k' -> */, +/* pos 0288: 333 */ 0xE9 /* 'i' -> */, +/* pos 0289: 334 */ 0xE5 /* 'e' -> */, +/* pos 028a: 335 */ 0xBA /* ':' -> */, +/* pos 028b: 336 */ 0x00, 0x3C /* - terminal marker 60 - */, +/* pos 028d: 337 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0294 state 338) */, + 0x65 /* 'e' */, 0x2C, 0x01 /* (to 0x03BC state 576) */, + 0x08, /* fail */ +/* pos 0294: 338 */ 0xE1 /* 'a' -> */, +/* pos 0295: 339 */ 0xEE /* 'n' -> */, +/* pos 0296: 340 */ 0xF3 /* 's' -> */, +/* pos 0297: 341 */ 0xE6 /* 'f' -> */, +/* pos 0298: 342 */ 0xE5 /* 'e' -> */, +/* pos 0299: 343 */ 0xF2 /* 'r' -> */, +/* pos 029a: 344 */ 0xAD /* '-' -> */, +/* pos 029b: 345 */ 0xE5 /* 'e' -> */, +/* pos 029c: 346 */ 0xEE /* 'n' -> */, +/* pos 029d: 347 */ 0xE3 /* 'c' -> */, +/* pos 029e: 348 */ 0xEF /* 'o' -> */, +/* pos 029f: 349 */ 0xE4 /* 'd' -> */, +/* pos 02a0: 350 */ 0xE9 /* 'i' -> */, +/* pos 02a1: 351 */ 0xEE /* 'n' -> */, +/* pos 02a2: 352 */ 0xE7 /* 'g' -> */, +/* pos 02a3: 353 */ 0xBA /* ':' -> */, +/* pos 02a4: 354 */ 0x00, 0x3E /* - terminal marker 62 - */, +/* pos 02a6: 355 */ 0xE9 /* 'i' -> */, +/* pos 02a7: 356 */ 0xAD /* '-' -> */, +/* pos 02a8: 357 */ 0xE1 /* 'a' -> */, +/* pos 02a9: 358 */ 0xF2 /* 'r' -> */, +/* pos 02aa: 359 */ 0xE7 /* 'g' -> */, +/* pos 02ab: 360 */ 0xF3 /* 's' -> */, +/* pos 02ac: 361 */ 0x00, 0x46 /* - terminal marker 70 - */, +/* pos 02ae: 362 */ 0xA0 /* ' ' -> */, +/* pos 02af: 363 */ 0x00, 0x49 /* - terminal marker 73 - */, +/* pos 02b1: 364 */ 0xAD /* '-' -> */, +/* pos 02b2: 365 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02BC state 366) */, + 0x61 /* 'a' */, 0x1D, 0x00 /* (to 0x02D2 state 385) */, + 0x72 /* 'r' */, 0xFB, 0x00 /* (to 0x03B3 state 568) */, + 0x08, /* fail */ +/* pos 02bc: 366 */ 0xEF /* 'o' -> */, +/* pos 02bd: 367 */ 0xF2 /* 'r' -> */, +/* pos 02be: 368 */ 0xF7 /* 'w' -> */, +/* pos 02bf: 369 */ 0xE1 /* 'a' -> */, +/* pos 02c0: 370 */ 0xF2 /* 'r' -> */, +/* pos 02c1: 371 */ 0xE4 /* 'd' -> */, +/* pos 02c2: 372 */ 0xE5 /* 'e' -> */, +/* pos 02c3: 373 */ 0xE4 /* 'd' -> */, +/* pos 02c4: 374 */ 0xAD /* '-' -> */, +/* pos 02c5: 375 */ 0xE6 /* 'f' -> */, +/* pos 02c6: 376 */ 0xEF /* 'o' -> */, +/* pos 02c7: 377 */ 0xF2 /* 'r' -> */, +/* pos 02c8: 378 */ 0xBA /* ':' -> */, +/* pos 02c9: 379 */ 0x00, 0x4A /* - terminal marker 74 - */, +/* pos 02cb: 380 */ 0x00, 0x4B /* - terminal marker 75 - */, +/* pos 02cd: 381 */ 0xE1 /* 'a' -> */, +/* pos 02ce: 382 */ 0xE4 /* 'd' -> */, +/* pos 02cf: 383 */ 0xA0 /* ' ' -> */, +/* pos 02d0: 384 */ 0x00, 0x4C /* - terminal marker 76 - */, +/* pos 02d2: 385 */ 0xF5 /* 'u' -> */, +/* pos 02d3: 386 */ 0xF4 /* 't' -> */, +/* pos 02d4: 387 */ 0xE8 /* 'h' -> */, +/* pos 02d5: 388 */ 0xAD /* '-' -> */, +/* pos 02d6: 389 */ 0xF4 /* 't' -> */, +/* pos 02d7: 390 */ 0xEF /* 'o' -> */, +/* pos 02d8: 391 */ 0xEB /* 'k' -> */, +/* pos 02d9: 392 */ 0xE5 /* 'e' -> */, +/* pos 02da: 393 */ 0xEE /* 'n' -> */, +/* pos 02db: 394 */ 0xBA /* ':' -> */, +/* pos 02dc: 395 */ 0x00, 0x4F /* - terminal marker 79 - */, +/* pos 02de: 396 */ 0xF4 /* 't' -> */, +/* pos 02df: 397 */ 0xE9 /* 'i' -> */, +/* pos 02e0: 398 */ 0xEF /* 'o' -> */, +/* pos 02e1: 399 */ 0xEE /* 'n' -> */, +/* pos 02e2: 400 */ 0xF3 /* 's' -> */, +/* pos 02e3: 401 */ 0xA0 /* ' ' -> */, +/* pos 02e4: 402 */ 0x00, 0x02 /* - terminal marker 2 - */, +/* pos 02e6: 403 */ 0xF3 /* 's' -> */, +/* pos 02e7: 404 */ 0xAD /* '-' -> */, +/* pos 02e8: 405 */ 0xE3 /* 'c' -> */, +/* pos 02e9: 406 */ 0xEF /* 'o' -> */, +/* pos 02ea: 407 */ 0xEE /* 'n' -> */, +/* pos 02eb: 408 */ 0xF4 /* 't' -> */, +/* pos 02ec: 409 */ 0xF2 /* 'r' -> */, +/* pos 02ed: 410 */ 0xEF /* 'o' -> */, +/* pos 02ee: 411 */ 0xEC /* 'l' -> */, +/* pos 02ef: 412 */ 0xAD /* '-' -> */, +/* pos 02f0: 413 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x02F7 state 414) */, + 0x61 /* 'a' */, 0x24, 0x00 /* (to 0x0317 state 443) */, + 0x08, /* fail */ +/* pos 02f7: 414 */ 0xE5 /* 'e' -> */, +/* pos 02f8: 415 */ 0xF1 /* 'q' -> */, +/* pos 02f9: 416 */ 0xF5 /* 'u' -> */, +/* pos 02fa: 417 */ 0xE5 /* 'e' -> */, +/* pos 02fb: 418 */ 0xF3 /* 's' -> */, +/* pos 02fc: 419 */ 0xF4 /* 't' -> */, +/* pos 02fd: 420 */ 0xAD /* '-' -> */, +/* pos 02fe: 421 */ 0xE8 /* 'h' -> */, +/* pos 02ff: 422 */ 0xE5 /* 'e' -> */, +/* pos 0300: 423 */ 0xE1 /* 'a' -> */, +/* pos 0301: 424 */ 0xE4 /* 'd' -> */, +/* pos 0302: 425 */ 0xE5 /* 'e' -> */, +/* pos 0303: 426 */ 0xF2 /* 'r' -> */, +/* pos 0304: 427 */ 0xF3 /* 's' -> */, +/* pos 0305: 428 */ 0xBA /* ':' -> */, +/* pos 0306: 429 */ 0x00, 0x11 /* - terminal marker 17 - */, +/* pos 0308: 430 */ 0xF2 /* 'r' -> */, +/* pos 0309: 431 */ 0xE5 /* 'e' -> */, +/* pos 030a: 432 */ 0xF2 /* 'r' -> */, +/* pos 030b: 433 */ 0xBA /* ':' -> */, +/* pos 030c: 434 */ 0x00, 0x1E /* - terminal marker 30 - */, +/* pos 030e: 435 */ 0xE8 /* 'h' -> */, +/* pos 030f: 436 */ 0xE1 /* 'a' -> */, +/* pos 0310: 437 */ 0xF2 /* 'r' -> */, +/* pos 0311: 438 */ 0xF3 /* 's' -> */, +/* pos 0312: 439 */ 0xE5 /* 'e' -> */, +/* pos 0313: 440 */ 0xF4 /* 't' -> */, +/* pos 0314: 441 */ 0xBA /* ':' -> */, +/* pos 0315: 442 */ 0x00, 0x22 /* - terminal marker 34 - */, +/* pos 0317: 443 */ 0xEC /* 'l' -> */, +/* pos 0318: 444 */ 0xEC /* 'l' -> */, +/* pos 0319: 445 */ 0xEF /* 'o' -> */, +/* pos 031a: 446 */ 0xF7 /* 'w' -> */, +/* pos 031b: 447 */ 0xAD /* '-' -> */, +/* pos 031c: 448 */ 0xEF /* 'o' -> */, +/* pos 031d: 449 */ 0xF2 /* 'r' -> */, +/* pos 031e: 450 */ 0xE9 /* 'i' -> */, +/* pos 031f: 451 */ 0xE7 /* 'g' -> */, +/* pos 0320: 452 */ 0xE9 /* 'i' -> */, +/* pos 0321: 453 */ 0xEE /* 'n' -> */, +/* pos 0322: 454 */ 0xBA /* ':' -> */, +/* pos 0323: 455 */ 0x00, 0x24 /* - terminal marker 36 - */, +/* pos 0325: 456 */ 0xE1 /* 'a' -> */, +/* pos 0326: 457 */ 0xF8 /* 'x' -> */, +/* pos 0327: 458 */ 0xAD /* '-' -> */, +/* pos 0328: 459 */ 0xE6 /* 'f' -> */, +/* pos 0329: 460 */ 0xEF /* 'o' -> */, +/* pos 032a: 461 */ 0xF2 /* 'r' -> */, +/* pos 032b: 462 */ 0xF7 /* 'w' -> */, +/* pos 032c: 463 */ 0xE1 /* 'a' -> */, +/* pos 032d: 464 */ 0xF2 /* 'r' -> */, +/* pos 032e: 465 */ 0xE4 /* 'd' -> */, +/* pos 032f: 466 */ 0xF3 /* 's' -> */, +/* pos 0330: 467 */ 0xBA /* ':' -> */, +/* pos 0331: 468 */ 0x00, 0x36 /* - terminal marker 54 - */, +/* pos 0333: 469 */ 0xF8 /* 'x' -> */, +/* pos 0334: 470 */ 0xF9 /* 'y' -> */, +/* pos 0335: 471 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x033C state 472) */, + 0x20 /* ' ' */, 0x79, 0x00 /* (to 0x03B1 state 567) */, + 0x08, /* fail */ +/* pos 033c: 472 */ 0xE1 /* 'a' -> */, +/* pos 033d: 473 */ 0xF5 /* 'u' -> */, +/* pos 033e: 474 */ 0xF4 /* 't' -> */, +/* pos 033f: 475 */ 0xE8 /* 'h' -> */, +/* pos 0340: 476 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0347 state 477) */, + 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x0351 state 486) */, + 0x08, /* fail */ +/* pos 0347: 477 */ 0xEE /* 'n' -> */, +/* pos 0348: 478 */ 0xF4 /* 't' -> */, +/* pos 0349: 479 */ 0xE9 /* 'i' -> */, +/* pos 034a: 480 */ 0xE3 /* 'c' -> */, +/* pos 034b: 481 */ 0xE1 /* 'a' -> */, +/* pos 034c: 482 */ 0xF4 /* 't' -> */, +/* pos 034d: 483 */ 0xE5 /* 'e' -> */, +/* pos 034e: 484 */ 0xBA /* ':' -> */, +/* pos 034f: 485 */ 0x00, 0x37 /* - terminal marker 55 - */, +/* pos 0351: 486 */ 0xF2 /* 'r' -> */, +/* pos 0352: 487 */ 0xE9 /* 'i' -> */, +/* pos 0353: 488 */ 0xFA /* 'z' -> */, +/* pos 0354: 489 */ 0xE1 /* 'a' -> */, +/* pos 0355: 490 */ 0xF4 /* 't' -> */, +/* pos 0356: 491 */ 0xE9 /* 'i' -> */, +/* pos 0357: 492 */ 0xEF /* 'o' -> */, +/* pos 0358: 493 */ 0xEE /* 'n' -> */, +/* pos 0359: 494 */ 0xBA /* ':' -> */, +/* pos 035a: 495 */ 0x00, 0x38 /* - terminal marker 56 - */, +/* pos 035c: 496 */ 0xF2 /* 'r' -> */, +/* pos 035d: 497 */ 0xE9 /* 'i' -> */, +/* pos 035e: 498 */ 0xE3 /* 'c' -> */, +/* pos 035f: 499 */ 0xF4 /* 't' -> */, +/* pos 0360: 500 */ 0xAD /* '-' -> */, +/* pos 0361: 501 */ 0xF4 /* 't' -> */, +/* pos 0362: 502 */ 0xF2 /* 'r' -> */, +/* pos 0363: 503 */ 0xE1 /* 'a' -> */, +/* pos 0364: 504 */ 0xEE /* 'n' -> */, +/* pos 0365: 505 */ 0xF3 /* 's' -> */, +/* pos 0366: 506 */ 0xF0 /* 'p' -> */, +/* pos 0367: 507 */ 0xEF /* 'o' -> */, +/* pos 0368: 508 */ 0xF2 /* 'r' -> */, +/* pos 0369: 509 */ 0xF4 /* 't' -> */, +/* pos 036a: 510 */ 0xAD /* '-' -> */, +/* pos 036b: 511 */ 0xF3 /* 's' -> */, +/* pos 036c: 512 */ 0xE5 /* 'e' -> */, +/* pos 036d: 513 */ 0xE3 /* 'c' -> */, +/* pos 036e: 514 */ 0xF5 /* 'u' -> */, +/* pos 036f: 515 */ 0xF2 /* 'r' -> */, +/* pos 0370: 516 */ 0xE9 /* 'i' -> */, +/* pos 0371: 517 */ 0xF4 /* 't' -> */, +/* pos 0372: 518 */ 0xF9 /* 'y' -> */, +/* pos 0373: 519 */ 0xBA /* ':' -> */, +/* pos 0374: 520 */ 0x00, 0x3D /* - terminal marker 61 - */, +/* pos 0376: 521 */ 0xE5 /* 'e' -> */, +/* pos 0377: 522 */ 0xF2 /* 'r' -> */, +/* pos 0378: 523 */ 0xAD /* '-' -> */, +/* pos 0379: 524 */ 0xE1 /* 'a' -> */, +/* pos 037a: 525 */ 0xE7 /* 'g' -> */, +/* pos 037b: 526 */ 0xE5 /* 'e' -> */, +/* pos 037c: 527 */ 0xEE /* 'n' -> */, +/* pos 037d: 528 */ 0xF4 /* 't' -> */, +/* pos 037e: 529 */ 0xBA /* ':' -> */, +/* pos 037f: 530 */ 0x00, 0x3F /* - terminal marker 63 - */, +/* pos 0381: 531 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0388 state 532) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x038D state 536) */, + 0x08, /* fail */ +/* pos 0388: 532 */ 0xF2 /* 'r' -> */, +/* pos 0389: 533 */ 0xF9 /* 'y' -> */, +/* pos 038a: 534 */ 0xBA /* ':' -> */, +/* pos 038b: 535 */ 0x00, 0x40 /* - terminal marker 64 - */, +/* pos 038d: 536 */ 0xE1 /* 'a' -> */, +/* pos 038e: 537 */ 0xBA /* ':' -> */, +/* pos 038f: 538 */ 0x00, 0x41 /* - terminal marker 65 - */, +/* pos 0391: 539 */ 0xF7 /* 'w' -> */, +/* pos 0392: 540 */ 0xF7 /* 'w' -> */, +/* pos 0393: 541 */ 0xAD /* '-' -> */, +/* pos 0394: 542 */ 0xE1 /* 'a' -> */, +/* pos 0395: 543 */ 0xF5 /* 'u' -> */, +/* pos 0396: 544 */ 0xF4 /* 't' -> */, +/* pos 0397: 545 */ 0xE8 /* 'h' -> */, +/* pos 0398: 546 */ 0xE5 /* 'e' -> */, +/* pos 0399: 547 */ 0xEE /* 'n' -> */, +/* pos 039a: 548 */ 0xF4 /* 't' -> */, +/* pos 039b: 549 */ 0xE9 /* 'i' -> */, +/* pos 039c: 550 */ 0xE3 /* 'c' -> */, +/* pos 039d: 551 */ 0xE1 /* 'a' -> */, +/* pos 039e: 552 */ 0xF4 /* 't' -> */, +/* pos 039f: 553 */ 0xE5 /* 'e' -> */, +/* pos 03a0: 554 */ 0xBA /* ':' -> */, +/* pos 03a1: 555 */ 0x00, 0x42 /* - terminal marker 66 - */, +/* pos 03a3: 556 */ 0xF4 /* 't' -> */, +/* pos 03a4: 557 */ 0xE3 /* 'c' -> */, +/* pos 03a5: 558 */ 0xE8 /* 'h' -> */, +/* pos 03a6: 559 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 03a8: 560 */ 0xF4 /* 't' -> */, +/* pos 03a9: 561 */ 0x00, 0x44 /* - terminal marker 68 - */, +/* pos 03ab: 562 */ 0xEC /* 'l' -> */, +/* pos 03ac: 563 */ 0xE5 /* 'e' -> */, +/* pos 03ad: 564 */ 0xF4 /* 't' -> */, +/* pos 03ae: 565 */ 0xE5 /* 'e' -> */, +/* pos 03af: 566 */ 0x00, 0x45 /* - terminal marker 69 - */, +/* pos 03b1: 567 */ 0x00, 0x47 /* - terminal marker 71 - */, +/* pos 03b3: 568 */ 0xE5 /* 'e' -> */, +/* pos 03b4: 569 */ 0xE1 /* 'a' -> */, +/* pos 03b5: 570 */ 0xEC /* 'l' -> */, +/* pos 03b6: 571 */ 0xAD /* '-' -> */, +/* pos 03b7: 572 */ 0xE9 /* 'i' -> */, +/* pos 03b8: 573 */ 0xF0 /* 'p' -> */, +/* pos 03b9: 574 */ 0xBA /* ':' -> */, +/* pos 03ba: 575 */ 0x00, 0x48 /* - terminal marker 72 - */, +/* pos 03bc: 576 */ 0xBA /* ':' -> */, +/* pos 03bd: 577 */ 0x00, 0x4D /* - terminal marker 77 - */, +/* pos 03bf: 578 */ 0xEC /* 'l' -> */, +/* pos 03c0: 579 */ 0xE1 /* 'a' -> */, +/* pos 03c1: 580 */ 0xF9 /* 'y' -> */, +/* pos 03c2: 581 */ 0xAD /* '-' -> */, +/* pos 03c3: 582 */ 0xEE /* 'n' -> */, +/* pos 03c4: 583 */ 0xEF /* 'o' -> */, +/* pos 03c5: 584 */ 0xEE /* 'n' -> */, +/* pos 03c6: 585 */ 0xE3 /* 'c' -> */, +/* pos 03c7: 586 */ 0xE5 /* 'e' -> */, +/* pos 03c8: 587 */ 0xBA /* ':' -> */, +/* pos 03c9: 588 */ 0x00, 0x4E /* - terminal marker 78 - */, +/* pos 03cb: 589 */ 0xAD /* '-' -> */, +/* pos 03cc: 590 */ 0xF7 /* 'w' -> */, +/* pos 03cd: 591 */ 0xE5 /* 'e' -> */, +/* pos 03ce: 592 */ 0xE2 /* 'b' -> */, +/* pos 03cf: 593 */ 0xF3 /* 's' -> */, +/* pos 03d0: 594 */ 0xEF /* 'o' -> */, +/* pos 03d1: 595 */ 0xE3 /* 'c' -> */, +/* pos 03d2: 596 */ 0xEB /* 'k' -> */, +/* pos 03d3: 597 */ 0xE5 /* 'e' -> */, +/* pos 03d4: 598 */ 0xF4 /* 't' -> */, +/* pos 03d5: 599 */ 0xAD /* '-' -> */, +/* pos 03d6: 600 */ 0x64 /* 'd' */, 0x19, 0x00 /* (to 0x03EF state 601) */, + 0x65 /* 'e' */, 0x1D, 0x00 /* (to 0x03F6 state 607) */, + 0x6B /* 'k' */, 0x26, 0x00 /* (to 0x0402 state 618) */, + 0x70 /* 'p' */, 0x35, 0x00 /* (to 0x0414 state 625) */, + 0x61 /* 'a' */, 0x3C, 0x00 /* (to 0x041E state 634) */, + 0x6E /* 'n' */, 0x41, 0x00 /* (to 0x0426 state 641) */, + 0x76 /* 'v' */, 0x47, 0x00 /* (to 0x042F state 648) */, + 0x6F /* 'o' */, 0x4D, 0x00 /* (to 0x0438 state 656) */, + 0x08, /* fail */ +/* pos 03ef: 601 */ 0xF2 /* 'r' -> */, +/* pos 03f0: 602 */ 0xE1 /* 'a' -> */, +/* pos 03f1: 603 */ 0xE6 /* 'f' -> */, +/* pos 03f2: 604 */ 0xF4 /* 't' -> */, +/* pos 03f3: 605 */ 0xBA /* ':' -> */, +/* pos 03f4: 606 */ 0x00, 0x07 /* - terminal marker 7 - */, +/* pos 03f6: 607 */ 0xF8 /* 'x' -> */, +/* pos 03f7: 608 */ 0xF4 /* 't' -> */, +/* pos 03f8: 609 */ 0xE5 /* 'e' -> */, +/* pos 03f9: 610 */ 0xEE /* 'n' -> */, +/* pos 03fa: 611 */ 0xF3 /* 's' -> */, +/* pos 03fb: 612 */ 0xE9 /* 'i' -> */, +/* pos 03fc: 613 */ 0xEF /* 'o' -> */, +/* pos 03fd: 614 */ 0xEE /* 'n' -> */, +/* pos 03fe: 615 */ 0xF3 /* 's' -> */, +/* pos 03ff: 616 */ 0xBA /* ':' -> */, +/* pos 0400: 617 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 0402: 618 */ 0xE5 /* 'e' -> */, +/* pos 0403: 619 */ 0xF9 /* 'y' -> */, +/* pos 0404: 620 */ 0x31 /* '1' */, 0x0A, 0x00 /* (to 0x040E state 621) */, + 0x32 /* '2' */, 0x0A, 0x00 /* (to 0x0411 state 623) */, + 0x3A /* ':' */, 0x23, 0x00 /* (to 0x042D state 647) */, + 0x08, /* fail */ +/* pos 040e: 621 */ 0xBA /* ':' -> */, +/* pos 040f: 622 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 0411: 623 */ 0xBA /* ':' -> */, +/* pos 0412: 624 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 0414: 625 */ 0xF2 /* 'r' -> */, +/* pos 0415: 626 */ 0xEF /* 'o' -> */, +/* pos 0416: 627 */ 0xF4 /* 't' -> */, +/* pos 0417: 628 */ 0xEF /* 'o' -> */, +/* pos 0418: 629 */ 0xE3 /* 'c' -> */, +/* pos 0419: 630 */ 0xEF /* 'o' -> */, +/* pos 041a: 631 */ 0xEC /* 'l' -> */, +/* pos 041b: 632 */ 0xBA /* ':' -> */, +/* pos 041c: 633 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 041e: 634 */ 0xE3 /* 'c' -> */, +/* pos 041f: 635 */ 0xE3 /* 'c' -> */, +/* pos 0420: 636 */ 0xE5 /* 'e' -> */, +/* pos 0421: 637 */ 0xF0 /* 'p' -> */, +/* pos 0422: 638 */ 0xF4 /* 't' -> */, +/* pos 0423: 639 */ 0xBA /* ':' -> */, +/* pos 0424: 640 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 0426: 641 */ 0xEF /* 'o' -> */, +/* pos 0427: 642 */ 0xEE /* 'n' -> */, +/* pos 0428: 643 */ 0xE3 /* 'c' -> */, +/* pos 0429: 644 */ 0xE5 /* 'e' -> */, +/* pos 042a: 645 */ 0xBA /* ':' -> */, +/* pos 042b: 646 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 042d: 647 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 042f: 648 */ 0xE5 /* 'e' -> */, +/* pos 0430: 649 */ 0xF2 /* 'r' -> */, +/* pos 0431: 650 */ 0xF3 /* 's' -> */, +/* pos 0432: 651 */ 0xE9 /* 'i' -> */, +/* pos 0433: 652 */ 0xEF /* 'o' -> */, +/* pos 0434: 653 */ 0xEE /* 'n' -> */, +/* pos 0435: 654 */ 0xBA /* ':' -> */, +/* pos 0436: 655 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 0438: 656 */ 0xF2 /* 'r' -> */, +/* pos 0439: 657 */ 0xE9 /* 'i' -> */, +/* pos 043a: 658 */ 0xE7 /* 'g' -> */, +/* pos 043b: 659 */ 0xE9 /* 'i' -> */, +/* pos 043c: 660 */ 0xEE /* 'n' -> */, +/* pos 043d: 661 */ 0xBA /* ':' -> */, +/* pos 043e: 662 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* total size 1088 bytes */ #endif #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) @@ -3074,69 +3007,70 @@ /* 5: 6: origin: */ /* 6: 8: */ - /* 7: 16: http2-settings: */ - /* 8: 17: accept: */ - /* 9: 18: access-control-request-headers: */ - /* 10: 20: if-none-match: */ - /* 11: 21: accept-encoding: */ - /* 12: 22: accept-language: */ - /* 13: 23: pragma: */ - /* 14: 24: cache-control: */ - /* 15: 25: authorization: */ - /* 16: 26: cookie: */ - /* 17: 27: content-length: */ - /* 18: 28: content-type: */ - /* 19: 29: date: */ - /* 20: 30: range: */ - /* 21: 31: referer: */ - /* 22: 32: sec-websocket-key: */ - /* 23: 36: :method */ - /* 24: 37: :path */ - /* 25: 38: :scheme */ - /* 26: 39: :status */ - /* 27: 40: accept-charset: */ - /* 28: 41: accept-ranges: */ - /* 29: 42: access-control-allow-origin: */ - /* 30: 43: age: */ - /* 31: 44: allow: */ - /* 32: 45: content-disposition: */ - /* 33: 46: content-encoding: */ - /* 34: 47: content-language: */ - /* 35: 48: content-location: */ - /* 36: 49: content-range: */ - /* 37: 50: etag: */ - /* 38: 51: expect: */ - /* 39: 52: expires: */ - /* 40: 53: from: */ - /* 41: 54: if-match: */ - /* 42: 55: if-range: */ - /* 43: 56: if-unmodified-since: */ - /* 44: 57: last-modified: */ - /* 45: 58: link: */ - /* 46: 59: location: */ - /* 47: 60: max-forwards: */ - /* 48: 61: proxy-authenticate: */ - /* 49: 62: proxy-authorization: */ - /* 50: 63: refresh: */ - /* 51: 64: retry-after: */ - /* 52: 65: server: */ - /* 53: 66: set-cookie: */ - /* 54: 67: strict-transport-security: */ - /* 55: 68: transfer-encoding: */ - /* 56: 69: user-agent: */ - /* 57: 70: vary: */ - /* 58: 71: via: */ - /* 59: 72: www-authenticate: */ - /* 60: 73: patch */ - /* 61: 77: proxy */ - /* 62: 80: x-forwarded-for: */ - /* 63: 81: connect */ - /* 64: 82: head */ - /* 65: 83: te: */ - /* 66: 84: replay-nonce: */ - /* 67: 85: :protocol */ - /* 68: 86: x-auth-token: */ - /* 69: 87: */ + /* 7: 15: http/1.1 */ + /* 8: 16: http2-settings: */ + /* 9: 17: accept: */ + /* 10: 19: if-modified-since: */ + /* 11: 20: if-none-match: */ + /* 12: 21: accept-encoding: */ + /* 13: 22: accept-language: */ + /* 14: 23: pragma: */ + /* 15: 24: cache-control: */ + /* 16: 25: authorization: */ + /* 17: 26: cookie: */ + /* 18: 27: content-length: */ + /* 19: 28: content-type: */ + /* 20: 29: date: */ + /* 21: 30: range: */ + /* 22: 31: referer: */ + /* 23: 35: :authority */ + /* 24: 36: :method */ + /* 25: 37: :path */ + /* 26: 38: :scheme */ + /* 27: 39: :status */ + /* 28: 40: accept-charset: */ + /* 29: 41: accept-ranges: */ + /* 30: 42: access-control-allow-origin: */ + /* 31: 43: age: */ + /* 32: 44: allow: */ + /* 33: 45: content-disposition: */ + /* 34: 46: content-encoding: */ + /* 35: 47: content-language: */ + /* 36: 48: content-location: */ + /* 37: 49: content-range: */ + /* 38: 50: etag: */ + /* 39: 51: expect: */ + /* 40: 52: expires: */ + /* 41: 53: from: */ + /* 42: 54: if-match: */ + /* 43: 55: if-range: */ + /* 44: 56: if-unmodified-since: */ + /* 45: 57: last-modified: */ + /* 46: 58: link: */ + /* 47: 59: location: */ + /* 48: 60: max-forwards: */ + /* 49: 61: proxy-authenticate: */ + /* 50: 62: proxy-authorization: */ + /* 51: 63: refresh: */ + /* 52: 64: retry-after: */ + /* 53: 65: server: */ + /* 54: 66: set-cookie: */ + /* 55: 67: strict-transport-security: */ + /* 56: 68: transfer-encoding: */ + /* 57: 69: user-agent: */ + /* 58: 70: vary: */ + /* 59: 71: via: */ + /* 60: 72: www-authenticate: */ + /* 61: 76: uri-args */ + /* 62: 79: http/1.0 */ + /* 63: 80: x-forwarded-for: */ + /* 64: 81: connect */ + /* 65: 82: head */ + /* 66: 83: te: */ + /* 67: 84: replay-nonce: */ + /* 68: 85: :protocol */ + /* 69: 86: x-auth-token: */ + /* 70: 87: */ /* pos 0000: 0 */ 0x67 /* 'g' */, 0x40, 0x00 /* (to 0x0040 state 1) */, 0x70 /* 'p' */, 0x42, 0x00 /* (to 0x0045 state 5) */, 0x68 /* 'h' */, 0x51, 0x00 /* (to 0x0057 state 10) */, @@ -3144,29 +3078,29 @@ 0x75 /* 'u' */, 0x7E, 0x00 /* (to 0x008A state 26) */, 0x6F /* 'o' */, 0x8D, 0x00 /* (to 0x009C state 34) */, 0x0D /* '.' */, 0x98, 0x00 /* (to 0x00AA state 41) */, - 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 57) */, - 0x69 /* 'i' */, 0xE2, 0x00 /* (to 0x00FA state 88) */, - 0x64 /* 'd' */, 0x7D, 0x01 /* (to 0x0198 state 177) */, - 0x72 /* 'r' */, 0x86, 0x01 /* (to 0x01A4 state 182) */, - 0x65 /* 'e' */, 0xEB, 0x01 /* (to 0x020C state 256) */, - 0x66 /* 'f' */, 0x07, 0x02 /* (to 0x022B state 272) */, - 0x6C /* 'l' */, 0x30, 0x02 /* (to 0x0257 state 306) */, - 0x6D /* 'm' */, 0x53, 0x02 /* (to 0x027D state 332) */, - 0x73 /* 's' */, 0x69, 0x02 /* (to 0x0296 state 355) */, - 0x78 /* 'x' */, 0xB7, 0x02 /* (to 0x02E7 state 410) */, - 0x74 /* 't' */, 0xD5, 0x02 /* (to 0x0308 state 431) */, - 0x76 /* 'v' */, 0x69, 0x03 /* (to 0x039F state 527) */, - 0x77 /* 'w' */, 0x76, 0x03 /* (to 0x03AF state 535) */, - 0x3A /* ':' */, 0xBC, 0x03 /* (to 0x03F8 state 594) */, + 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 51) */, + 0x69 /* 'i' */, 0xCA, 0x00 /* (to 0x00E2 state 58) */, + 0x64 /* 'd' */, 0x73, 0x01 /* (to 0x018E state 160) */, + 0x72 /* 'r' */, 0x7C, 0x01 /* (to 0x019A state 165) */, + 0x65 /* 'e' */, 0xC8, 0x01 /* (to 0x01E9 state 229) */, + 0x66 /* 'f' */, 0xE4, 0x01 /* (to 0x0208 state 245) */, + 0x6C /* 'l' */, 0x06, 0x02 /* (to 0x022D state 278) */, + 0x73 /* 's' */, 0x4B, 0x02 /* (to 0x0275 state 321) */, + 0x74 /* 't' */, 0x69, 0x02 /* (to 0x0296 state 337) */, + 0x78 /* 'x' */, 0x8A, 0x02 /* (to 0x02BA state 364) */, + 0x6D /* 'm' */, 0xFB, 0x02 /* (to 0x032E state 456) */, + 0x76 /* 'v' */, 0x54, 0x03 /* (to 0x038A state 531) */, + 0x77 /* 'w' */, 0x61, 0x03 /* (to 0x039A state 539) */, + 0x3A /* ':' */, 0x19, 0x04 /* (to 0x0455 state 674) */, 0x08, /* fail */ /* pos 0040: 1 */ 0xE5 /* 'e' -> */, /* pos 0041: 2 */ 0xF4 /* 't' -> */, /* pos 0042: 3 */ 0xA0 /* ' ' -> */, /* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, /* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */, - 0x72 /* 'r' */, 0xF6, 0x00 /* (to 0x013E state 123) */, - 0x61 /* 'a' */, 0x76, 0x03 /* (to 0x03C1 state 552) */, - 0x75 /* 'u' */, 0x78, 0x03 /* (to 0x03C6 state 556) */, + 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x0134 state 106) */, + 0x61 /* 'a' */, 0x61, 0x03 /* (to 0x03AC state 556) */, + 0x75 /* 'u' */, 0x63, 0x03 /* (to 0x03B1 state 560) */, 0x08, /* fail */ /* pos 0052: 6 */ 0xF3 /* 's' -> */, /* pos 0053: 7 */ 0xF4 /* 't' -> */, @@ -3174,34 +3108,34 @@ /* pos 0055: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, /* pos 0057: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0061 state 11) */, 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AD state 43) */, - 0x65 /* 'e' */, 0xA6, 0x02 /* (to 0x0303 state 427) */, + 0x65 /* 'e' */, 0x79, 0x02 /* (to 0x02D6 state 381) */, 0x08, /* fail */ /* pos 0061: 11 */ 0xF3 /* 's' -> */, /* pos 0062: 12 */ 0xF4 /* 't' -> */, /* pos 0063: 13 */ 0xBA /* ':' -> */, /* pos 0064: 14 */ 0x00, 0x02 /* - terminal marker 2 - */, /* pos 0066: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006D state 16) */, - 0x61 /* 'a' */, 0xE2, 0x00 /* (to 0x014B state 129) */, + 0x61 /* 'a' */, 0xD8, 0x00 /* (to 0x0141 state 112) */, 0x08, /* fail */ /* pos 006d: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0074 state 17) */, - 0x6F /* 'o' */, 0xF7, 0x00 /* (to 0x0167 state 155) */, + 0x6F /* 'o' */, 0xED, 0x00 /* (to 0x015D state 138) */, 0x08, /* fail */ /* pos 0074: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x007B state 18) */, - 0x74 /* 't' */, 0xF6, 0x00 /* (to 0x016D state 160) */, + 0x74 /* 't' */, 0xEC, 0x00 /* (to 0x0163 state 143) */, 0x08, /* fail */ /* pos 007b: 18 */ 0xE5 /* 'e' -> */, /* pos 007c: 19 */ 0xE3 /* 'c' -> */, /* pos 007d: 20 */ 0xF4 /* 't' -> */, /* pos 007e: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0085 state 22) */, - 0x20 /* ' ' */, 0x80, 0x02 /* (to 0x0301 state 426) */, + 0x20 /* ' ' */, 0x53, 0x02 /* (to 0x02D4 state 380) */, 0x08, /* fail */ /* pos 0085: 22 */ 0xEF /* 'o' -> */, /* pos 0086: 23 */ 0xEE /* 'n' -> */, /* pos 0087: 24 */ 0xBA /* ':' -> */, /* pos 0088: 25 */ 0x00, 0x03 /* - terminal marker 3 - */, /* pos 008a: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0094 state 27) */, - 0x73 /* 's' */, 0x44, 0x02 /* (to 0x02D1 state 396) */, - 0x72 /* 'r' */, 0x3F, 0x03 /* (to 0x03CF state 563) */, + 0x72 /* 'r' */, 0x22, 0x02 /* (to 0x02AF state 355) */, + 0x73 /* 's' */, 0xEF, 0x02 /* (to 0x037F state 521) */, 0x08, /* fail */ /* pos 0094: 27 */ 0xE7 /* 'g' -> */, /* pos 0095: 28 */ 0xF2 /* 'r' -> */, @@ -3211,7 +3145,7 @@ /* pos 0099: 32 */ 0xBA /* ':' -> */, /* pos 009a: 33 */ 0x00, 0x04 /* - terminal marker 4 - */, /* pos 009c: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A3 state 35) */, - 0x70 /* 'p' */, 0x73, 0x02 /* (to 0x0312 state 434) */, + 0x70 /* 'p' */, 0x48, 0x02 /* (to 0x02E7 state 396) */, 0x08, /* fail */ /* pos 00a3: 35 */ 0xE9 /* 'i' -> */, /* pos 00a4: 36 */ 0xE7 /* 'g' -> */, @@ -3223,757 +3157,757 @@ /* pos 00ab: 42 */ 0x00, 0x06 /* - terminal marker 6 - */, /* pos 00ad: 43 */ 0xF4 /* 't' -> */, /* pos 00ae: 44 */ 0xF0 /* 'p' -> */, -/* pos 00af: 45 */ 0x32 /* '2' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, - 0x2F /* '/' */, 0x2E, 0x03 /* (to 0x03E0 state 578) */, - 0x08, /* fail */ -/* pos 00b6: 46 */ 0xAD /* '-' -> */, -/* pos 00b7: 47 */ 0xF3 /* 's' -> */, -/* pos 00b8: 48 */ 0xE5 /* 'e' -> */, -/* pos 00b9: 49 */ 0xF4 /* 't' -> */, -/* pos 00ba: 50 */ 0xF4 /* 't' -> */, -/* pos 00bb: 51 */ 0xE9 /* 'i' -> */, -/* pos 00bc: 52 */ 0xEE /* 'n' -> */, -/* pos 00bd: 53 */ 0xE7 /* 'g' -> */, -/* pos 00be: 54 */ 0xF3 /* 's' -> */, -/* pos 00bf: 55 */ 0xBA /* ':' -> */, -/* pos 00c0: 56 */ 0x00, 0x07 /* - terminal marker 7 - */, -/* pos 00c2: 57 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 58) */, - 0x75 /* 'u' */, 0x94, 0x00 /* (to 0x0159 state 142) */, - 0x6C /* 'l' */, 0x0E, 0x01 /* (to 0x01D6 state 208) */, - 0x67 /* 'g' */, 0x98, 0x02 /* (to 0x0363 state 478) */, - 0x08, /* fail */ -/* pos 00cf: 58 */ 0xE3 /* 'c' -> */, -/* pos 00d0: 59 */ 0xE5 /* 'e' -> */, -/* pos 00d1: 60 */ 0x73 /* 's' */, 0x07, 0x00 /* (to 0x00D8 state 61) */, - 0x70 /* 'p' */, 0x41, 0x00 /* (to 0x0115 state 102) */, - 0x08, /* fail */ -/* pos 00d8: 61 */ 0xF3 /* 's' -> */, -/* pos 00d9: 62 */ 0xAD /* '-' -> */, -/* pos 00da: 63 */ 0xE3 /* 'c' -> */, -/* pos 00db: 64 */ 0xEF /* 'o' -> */, -/* pos 00dc: 65 */ 0xEE /* 'n' -> */, -/* pos 00dd: 66 */ 0xF4 /* 't' -> */, -/* pos 00de: 67 */ 0xF2 /* 'r' -> */, -/* pos 00df: 68 */ 0xEF /* 'o' -> */, -/* pos 00e0: 69 */ 0xEC /* 'l' -> */, -/* pos 00e1: 70 */ 0xAD /* '-' -> */, -/* pos 00e2: 71 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00E9 state 72) */, - 0x61 /* 'a' */, 0xE3, 0x00 /* (to 0x01C8 state 195) */, - 0x08, /* fail */ -/* pos 00e9: 72 */ 0xE5 /* 'e' -> */, -/* pos 00ea: 73 */ 0xF1 /* 'q' -> */, -/* pos 00eb: 74 */ 0xF5 /* 'u' -> */, -/* pos 00ec: 75 */ 0xE5 /* 'e' -> */, -/* pos 00ed: 76 */ 0xF3 /* 's' -> */, -/* pos 00ee: 77 */ 0xF4 /* 't' -> */, -/* pos 00ef: 78 */ 0xAD /* '-' -> */, -/* pos 00f0: 79 */ 0xE8 /* 'h' -> */, -/* pos 00f1: 80 */ 0xE5 /* 'e' -> */, -/* pos 00f2: 81 */ 0xE1 /* 'a' -> */, -/* pos 00f3: 82 */ 0xE4 /* 'd' -> */, -/* pos 00f4: 83 */ 0xE5 /* 'e' -> */, -/* pos 00f5: 84 */ 0xF2 /* 'r' -> */, -/* pos 00f6: 85 */ 0xF3 /* 's' -> */, -/* pos 00f7: 86 */ 0xBA /* ':' -> */, -/* pos 00f8: 87 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 00fa: 88 */ 0xE6 /* 'f' -> */, -/* pos 00fb: 89 */ 0xAD /* '-' -> */, -/* pos 00fc: 90 */ 0x6E /* 'n' */, 0x0D, 0x00 /* (to 0x0109 state 91) */, - 0x6D /* 'm' */, 0x32, 0x01 /* (to 0x0231 state 277) */, - 0x72 /* 'r' */, 0x3C, 0x01 /* (to 0x023E state 283) */, - 0x75 /* 'u' */, 0x40, 0x01 /* (to 0x0245 state 289) */, - 0x08, /* fail */ -/* pos 0109: 91 */ 0xEF /* 'o' -> */, -/* pos 010a: 92 */ 0xEE /* 'n' -> */, -/* pos 010b: 93 */ 0xE5 /* 'e' -> */, -/* pos 010c: 94 */ 0xAD /* '-' -> */, -/* pos 010d: 95 */ 0xED /* 'm' -> */, -/* pos 010e: 96 */ 0xE1 /* 'a' -> */, -/* pos 010f: 97 */ 0xF4 /* 't' -> */, -/* pos 0110: 98 */ 0xE3 /* 'c' -> */, -/* pos 0111: 99 */ 0xE8 /* 'h' -> */, -/* pos 0112: 100 */ 0xBA /* ':' -> */, -/* pos 0113: 101 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 0115: 102 */ 0xF4 /* 't' -> */, -/* pos 0116: 103 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x011D state 104) */, - 0x3A /* ':' */, 0x4B, 0x03 /* (to 0x0464 state 672) */, - 0x08, /* fail */ -/* pos 011d: 104 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x012A state 105) */, - 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x0134 state 114) */, - 0x72 /* 'r' */, 0x38, 0x02 /* (to 0x035B state 471) */, - 0x63 /* 'c' */, 0x5E, 0x03 /* (to 0x0484 state 693) */, - 0x08, /* fail */ -/* pos 012a: 105 */ 0xEE /* 'n' -> */, -/* pos 012b: 106 */ 0xE3 /* 'c' -> */, -/* pos 012c: 107 */ 0xEF /* 'o' -> */, -/* pos 012d: 108 */ 0xE4 /* 'd' -> */, -/* pos 012e: 109 */ 0xE9 /* 'i' -> */, -/* pos 012f: 110 */ 0xEE /* 'n' -> */, -/* pos 0130: 111 */ 0xE7 /* 'g' -> */, -/* pos 0131: 112 */ 0xBA /* ':' -> */, -/* pos 0132: 113 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 0134: 114 */ 0xE1 /* 'a' -> */, -/* pos 0135: 115 */ 0xEE /* 'n' -> */, -/* pos 0136: 116 */ 0xE7 /* 'g' -> */, -/* pos 0137: 117 */ 0xF5 /* 'u' -> */, -/* pos 0138: 118 */ 0xE1 /* 'a' -> */, -/* pos 0139: 119 */ 0xE7 /* 'g' -> */, -/* pos 013a: 120 */ 0xE5 /* 'e' -> */, -/* pos 013b: 121 */ 0xBA /* ':' -> */, -/* pos 013c: 122 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 013e: 123 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0145 state 124) */, - 0x6F /* 'o' */, 0x9B, 0x01 /* (to 0x02DC state 406) */, - 0x08, /* fail */ -/* pos 0145: 124 */ 0xE7 /* 'g' -> */, -/* pos 0146: 125 */ 0xED /* 'm' -> */, -/* pos 0147: 126 */ 0xE1 /* 'a' -> */, -/* pos 0148: 127 */ 0xBA /* ':' -> */, -/* pos 0149: 128 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 014b: 129 */ 0xE3 /* 'c' -> */, -/* pos 014c: 130 */ 0xE8 /* 'h' -> */, -/* pos 014d: 131 */ 0xE5 /* 'e' -> */, -/* pos 014e: 132 */ 0xAD /* '-' -> */, -/* pos 014f: 133 */ 0xE3 /* 'c' -> */, -/* pos 0150: 134 */ 0xEF /* 'o' -> */, -/* pos 0151: 135 */ 0xEE /* 'n' -> */, -/* pos 0152: 136 */ 0xF4 /* 't' -> */, -/* pos 0153: 137 */ 0xF2 /* 'r' -> */, -/* pos 0154: 138 */ 0xEF /* 'o' -> */, -/* pos 0155: 139 */ 0xEC /* 'l' -> */, -/* pos 0156: 140 */ 0xBA /* ':' -> */, -/* pos 0157: 141 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 0159: 142 */ 0xF4 /* 't' -> */, -/* pos 015a: 143 */ 0xE8 /* 'h' -> */, -/* pos 015b: 144 */ 0xEF /* 'o' -> */, -/* pos 015c: 145 */ 0xF2 /* 'r' -> */, -/* pos 015d: 146 */ 0xE9 /* 'i' -> */, -/* pos 015e: 147 */ 0xFA /* 'z' -> */, -/* pos 015f: 148 */ 0xE1 /* 'a' -> */, -/* pos 0160: 149 */ 0xF4 /* 't' -> */, -/* pos 0161: 150 */ 0xE9 /* 'i' -> */, -/* pos 0162: 151 */ 0xEF /* 'o' -> */, -/* pos 0163: 152 */ 0xEE /* 'n' -> */, -/* pos 0164: 153 */ 0xBA /* ':' -> */, -/* pos 0165: 154 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 0167: 155 */ 0xEB /* 'k' -> */, -/* pos 0168: 156 */ 0xE9 /* 'i' -> */, -/* pos 0169: 157 */ 0xE5 /* 'e' -> */, -/* pos 016a: 158 */ 0xBA /* ':' -> */, -/* pos 016b: 159 */ 0x00, 0x10 /* - terminal marker 16 - */, -/* pos 016d: 160 */ 0xE5 /* 'e' -> */, -/* pos 016e: 161 */ 0xEE /* 'n' -> */, -/* pos 016f: 162 */ 0xF4 /* 't' -> */, -/* pos 0170: 163 */ 0xAD /* '-' -> */, -/* pos 0171: 164 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0181 state 165) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0192 state 172) */, - 0x64 /* 'd' */, 0x65, 0x00 /* (to 0x01DC state 213) */, - 0x65 /* 'e' */, 0x6F, 0x00 /* (to 0x01E9 state 225) */, - 0x72 /* 'r' */, 0x88, 0x00 /* (to 0x0205 state 250) */, - 0x08, /* fail */ -/* pos 0181: 165 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x018B state 166) */, - 0x61 /* 'a' */, 0x6F, 0x00 /* (to 0x01F3 state 234) */, - 0x6F /* 'o' */, 0x75, 0x00 /* (to 0x01FC state 242) */, - 0x08, /* fail */ -/* pos 018b: 166 */ 0xEE /* 'n' -> */, -/* pos 018c: 167 */ 0xE7 /* 'g' -> */, -/* pos 018d: 168 */ 0xF4 /* 't' -> */, -/* pos 018e: 169 */ 0xE8 /* 'h' -> */, -/* pos 018f: 170 */ 0xBA /* ':' -> */, -/* pos 0190: 171 */ 0x00, 0x11 /* - terminal marker 17 - */, -/* pos 0192: 172 */ 0xF9 /* 'y' -> */, -/* pos 0193: 173 */ 0xF0 /* 'p' -> */, -/* pos 0194: 174 */ 0xE5 /* 'e' -> */, -/* pos 0195: 175 */ 0xBA /* ':' -> */, -/* pos 0196: 176 */ 0x00, 0x12 /* - terminal marker 18 - */, -/* pos 0198: 177 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x019F state 178) */, - 0x65 /* 'e' */, 0x2E, 0x02 /* (to 0x03C9 state 558) */, - 0x08, /* fail */ -/* pos 019f: 178 */ 0xF4 /* 't' -> */, -/* pos 01a0: 179 */ 0xE5 /* 'e' -> */, -/* pos 01a1: 180 */ 0xBA /* ':' -> */, -/* pos 01a2: 181 */ 0x00, 0x13 /* - terminal marker 19 - */, -/* pos 01a4: 182 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01AB state 183) */, - 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x01B1 state 188) */, - 0x08, /* fail */ -/* pos 01ab: 183 */ 0xEE /* 'n' -> */, -/* pos 01ac: 184 */ 0xE7 /* 'g' -> */, -/* pos 01ad: 185 */ 0xE5 /* 'e' -> */, -/* pos 01ae: 186 */ 0xBA /* ':' -> */, -/* pos 01af: 187 */ 0x00, 0x14 /* - terminal marker 20 - */, -/* pos 01b1: 188 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x01BB state 189) */, - 0x74 /* 't' */, 0xD7, 0x00 /* (to 0x028B state 345) */, - 0x70 /* 'p' */, 0x35, 0x02 /* (to 0x03EC state 583) */, - 0x08, /* fail */ -/* pos 01bb: 189 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01C2 state 190) */, - 0x72 /* 'r' */, 0xC9, 0x01 /* (to 0x0387 state 505) */, - 0x08, /* fail */ -/* pos 01c2: 190 */ 0xF2 /* 'r' -> */, -/* pos 01c3: 191 */ 0xE5 /* 'e' -> */, -/* pos 01c4: 192 */ 0xF2 /* 'r' -> */, -/* pos 01c5: 193 */ 0xBA /* ':' -> */, -/* pos 01c6: 194 */ 0x00, 0x15 /* - terminal marker 21 - */, -/* pos 01c8: 195 */ 0xEC /* 'l' -> */, -/* pos 01c9: 196 */ 0xEC /* 'l' -> */, -/* pos 01ca: 197 */ 0xEF /* 'o' -> */, -/* pos 01cb: 198 */ 0xF7 /* 'w' -> */, -/* pos 01cc: 199 */ 0xAD /* '-' -> */, -/* pos 01cd: 200 */ 0xEF /* 'o' -> */, -/* pos 01ce: 201 */ 0xF2 /* 'r' -> */, -/* pos 01cf: 202 */ 0xE9 /* 'i' -> */, -/* pos 01d0: 203 */ 0xE7 /* 'g' -> */, -/* pos 01d1: 204 */ 0xE9 /* 'i' -> */, -/* pos 01d2: 205 */ 0xEE /* 'n' -> */, -/* pos 01d3: 206 */ 0xBA /* ':' -> */, -/* pos 01d4: 207 */ 0x00, 0x1D /* - terminal marker 29 - */, -/* pos 01d6: 208 */ 0xEC /* 'l' -> */, -/* pos 01d7: 209 */ 0xEF /* 'o' -> */, -/* pos 01d8: 210 */ 0xF7 /* 'w' -> */, -/* pos 01d9: 211 */ 0xBA /* ':' -> */, -/* pos 01da: 212 */ 0x00, 0x1F /* - terminal marker 31 - */, -/* pos 01dc: 213 */ 0xE9 /* 'i' -> */, -/* pos 01dd: 214 */ 0xF3 /* 's' -> */, -/* pos 01de: 215 */ 0xF0 /* 'p' -> */, -/* pos 01df: 216 */ 0xEF /* 'o' -> */, -/* pos 01e0: 217 */ 0xF3 /* 's' -> */, -/* pos 01e1: 218 */ 0xE9 /* 'i' -> */, -/* pos 01e2: 219 */ 0xF4 /* 't' -> */, -/* pos 01e3: 220 */ 0xE9 /* 'i' -> */, -/* pos 01e4: 221 */ 0xEF /* 'o' -> */, -/* pos 01e5: 222 */ 0xEE /* 'n' -> */, -/* pos 01e6: 223 */ 0xBA /* ':' -> */, -/* pos 01e7: 224 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 01e9: 225 */ 0xEE /* 'n' -> */, -/* pos 01ea: 226 */ 0xE3 /* 'c' -> */, -/* pos 01eb: 227 */ 0xEF /* 'o' -> */, -/* pos 01ec: 228 */ 0xE4 /* 'd' -> */, -/* pos 01ed: 229 */ 0xE9 /* 'i' -> */, -/* pos 01ee: 230 */ 0xEE /* 'n' -> */, -/* pos 01ef: 231 */ 0xE7 /* 'g' -> */, -/* pos 01f0: 232 */ 0xBA /* ':' -> */, -/* pos 01f1: 233 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 01f3: 234 */ 0xEE /* 'n' -> */, -/* pos 01f4: 235 */ 0xE7 /* 'g' -> */, -/* pos 01f5: 236 */ 0xF5 /* 'u' -> */, -/* pos 01f6: 237 */ 0xE1 /* 'a' -> */, -/* pos 01f7: 238 */ 0xE7 /* 'g' -> */, -/* pos 01f8: 239 */ 0xE5 /* 'e' -> */, -/* pos 01f9: 240 */ 0xBA /* ':' -> */, -/* pos 01fa: 241 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* pos 01fc: 242 */ 0xE3 /* 'c' -> */, -/* pos 01fd: 243 */ 0xE1 /* 'a' -> */, -/* pos 01fe: 244 */ 0xF4 /* 't' -> */, -/* pos 01ff: 245 */ 0xE9 /* 'i' -> */, -/* pos 0200: 246 */ 0xEF /* 'o' -> */, -/* pos 0201: 247 */ 0xEE /* 'n' -> */, -/* pos 0202: 248 */ 0xBA /* ':' -> */, -/* pos 0203: 249 */ 0x00, 0x23 /* - terminal marker 35 - */, -/* pos 0205: 250 */ 0xE1 /* 'a' -> */, -/* pos 0206: 251 */ 0xEE /* 'n' -> */, -/* pos 0207: 252 */ 0xE7 /* 'g' -> */, -/* pos 0208: 253 */ 0xE5 /* 'e' -> */, -/* pos 0209: 254 */ 0xBA /* ':' -> */, -/* pos 020a: 255 */ 0x00, 0x24 /* - terminal marker 36 - */, -/* pos 020c: 256 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x0213 state 257) */, - 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x0218 state 261) */, - 0x08, /* fail */ -/* pos 0213: 257 */ 0xE1 /* 'a' -> */, -/* pos 0214: 258 */ 0xE7 /* 'g' -> */, -/* pos 0215: 259 */ 0xBA /* ':' -> */, -/* pos 0216: 260 */ 0x00, 0x25 /* - terminal marker 37 - */, -/* pos 0218: 261 */ 0xF0 /* 'p' -> */, -/* pos 0219: 262 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0220 state 263) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0225 state 267) */, - 0x08, /* fail */ -/* pos 0220: 263 */ 0xE3 /* 'c' -> */, -/* pos 0221: 264 */ 0xF4 /* 't' -> */, -/* pos 0222: 265 */ 0xBA /* ':' -> */, -/* pos 0223: 266 */ 0x00, 0x26 /* - terminal marker 38 - */, -/* pos 0225: 267 */ 0xF2 /* 'r' -> */, -/* pos 0226: 268 */ 0xE5 /* 'e' -> */, -/* pos 0227: 269 */ 0xF3 /* 's' -> */, -/* pos 0228: 270 */ 0xBA /* ':' -> */, -/* pos 0229: 271 */ 0x00, 0x27 /* - terminal marker 39 - */, -/* pos 022b: 272 */ 0xF2 /* 'r' -> */, -/* pos 022c: 273 */ 0xEF /* 'o' -> */, -/* pos 022d: 274 */ 0xED /* 'm' -> */, -/* pos 022e: 275 */ 0xBA /* ':' -> */, -/* pos 022f: 276 */ 0x00, 0x28 /* - terminal marker 40 - */, -/* pos 0231: 277 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0238 state 278) */, - 0x6F /* 'o' */, 0xE6, 0x00 /* (to 0x031A state 441) */, - 0x08, /* fail */ -/* pos 0238: 278 */ 0xF4 /* 't' -> */, -/* pos 0239: 279 */ 0xE3 /* 'c' -> */, -/* pos 023a: 280 */ 0xE8 /* 'h' -> */, -/* pos 023b: 281 */ 0xBA /* ':' -> */, -/* pos 023c: 282 */ 0x00, 0x29 /* - terminal marker 41 - */, -/* pos 023e: 283 */ 0xE1 /* 'a' -> */, -/* pos 023f: 284 */ 0xEE /* 'n' -> */, -/* pos 0240: 285 */ 0xE7 /* 'g' -> */, -/* pos 0241: 286 */ 0xE5 /* 'e' -> */, -/* pos 0242: 287 */ 0xBA /* ':' -> */, -/* pos 0243: 288 */ 0x00, 0x2A /* - terminal marker 42 - */, -/* pos 0245: 289 */ 0xEE /* 'n' -> */, -/* pos 0246: 290 */ 0xED /* 'm' -> */, -/* pos 0247: 291 */ 0xEF /* 'o' -> */, -/* pos 0248: 292 */ 0xE4 /* 'd' -> */, -/* pos 0249: 293 */ 0xE9 /* 'i' -> */, -/* pos 024a: 294 */ 0xE6 /* 'f' -> */, -/* pos 024b: 295 */ 0xE9 /* 'i' -> */, -/* pos 024c: 296 */ 0xE5 /* 'e' -> */, -/* pos 024d: 297 */ 0xE4 /* 'd' -> */, -/* pos 024e: 298 */ 0xAD /* '-' -> */, -/* pos 024f: 299 */ 0xF3 /* 's' -> */, -/* pos 0250: 300 */ 0xE9 /* 'i' -> */, -/* pos 0251: 301 */ 0xEE /* 'n' -> */, -/* pos 0252: 302 */ 0xE3 /* 'c' -> */, -/* pos 0253: 303 */ 0xE5 /* 'e' -> */, -/* pos 0254: 304 */ 0xBA /* ':' -> */, -/* pos 0255: 305 */ 0x00, 0x2B /* - terminal marker 43 - */, -/* pos 0257: 306 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0261 state 307) */, - 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x026F state 320) */, - 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0274 state 324) */, - 0x08, /* fail */ -/* pos 0261: 307 */ 0xF3 /* 's' -> */, -/* pos 0262: 308 */ 0xF4 /* 't' -> */, -/* pos 0263: 309 */ 0xAD /* '-' -> */, -/* pos 0264: 310 */ 0xED /* 'm' -> */, -/* pos 0265: 311 */ 0xEF /* 'o' -> */, -/* pos 0266: 312 */ 0xE4 /* 'd' -> */, -/* pos 0267: 313 */ 0xE9 /* 'i' -> */, -/* pos 0268: 314 */ 0xE6 /* 'f' -> */, -/* pos 0269: 315 */ 0xE9 /* 'i' -> */, -/* pos 026a: 316 */ 0xE5 /* 'e' -> */, -/* pos 026b: 317 */ 0xE4 /* 'd' -> */, -/* pos 026c: 318 */ 0xBA /* ':' -> */, -/* pos 026d: 319 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 026f: 320 */ 0xEE /* 'n' -> */, -/* pos 0270: 321 */ 0xEB /* 'k' -> */, -/* pos 0271: 322 */ 0xBA /* ':' -> */, -/* pos 0272: 323 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 0274: 324 */ 0xE3 /* 'c' -> */, -/* pos 0275: 325 */ 0xE1 /* 'a' -> */, -/* pos 0276: 326 */ 0xF4 /* 't' -> */, -/* pos 0277: 327 */ 0xE9 /* 'i' -> */, -/* pos 0278: 328 */ 0xEF /* 'o' -> */, -/* pos 0279: 329 */ 0xEE /* 'n' -> */, -/* pos 027a: 330 */ 0xBA /* ':' -> */, -/* pos 027b: 331 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 027d: 332 */ 0xE1 /* 'a' -> */, -/* pos 027e: 333 */ 0xF8 /* 'x' -> */, -/* pos 027f: 334 */ 0xAD /* '-' -> */, -/* pos 0280: 335 */ 0xE6 /* 'f' -> */, -/* pos 0281: 336 */ 0xEF /* 'o' -> */, -/* pos 0282: 337 */ 0xF2 /* 'r' -> */, -/* pos 0283: 338 */ 0xF7 /* 'w' -> */, -/* pos 0284: 339 */ 0xE1 /* 'a' -> */, -/* pos 0285: 340 */ 0xF2 /* 'r' -> */, -/* pos 0286: 341 */ 0xE4 /* 'd' -> */, -/* pos 0287: 342 */ 0xF3 /* 's' -> */, -/* pos 0288: 343 */ 0xBA /* ':' -> */, -/* pos 0289: 344 */ 0x00, 0x2F /* - terminal marker 47 - */, -/* pos 028b: 345 */ 0xF2 /* 'r' -> */, -/* pos 028c: 346 */ 0xF9 /* 'y' -> */, -/* pos 028d: 347 */ 0xAD /* '-' -> */, -/* pos 028e: 348 */ 0xE1 /* 'a' -> */, -/* pos 028f: 349 */ 0xE6 /* 'f' -> */, -/* pos 0290: 350 */ 0xF4 /* 't' -> */, -/* pos 0291: 351 */ 0xE5 /* 'e' -> */, -/* pos 0292: 352 */ 0xF2 /* 'r' -> */, -/* pos 0293: 353 */ 0xBA /* ':' -> */, -/* pos 0294: 354 */ 0x00, 0x33 /* - terminal marker 51 - */, -/* pos 0296: 355 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x029D state 356) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x02B7 state 371) */, - 0x08, /* fail */ -/* pos 029d: 356 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x02A7 state 357) */, - 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x02AD state 362) */, - 0x63 /* 'c' */, 0x86, 0x00 /* (to 0x0329 state 455) */, - 0x08, /* fail */ -/* pos 02a7: 357 */ 0xF6 /* 'v' -> */, -/* pos 02a8: 358 */ 0xE5 /* 'e' -> */, -/* pos 02a9: 359 */ 0xF2 /* 'r' -> */, -/* pos 02aa: 360 */ 0xBA /* ':' -> */, -/* pos 02ab: 361 */ 0x00, 0x34 /* - terminal marker 52 - */, -/* pos 02ad: 362 */ 0xAD /* '-' -> */, -/* pos 02ae: 363 */ 0xE3 /* 'c' -> */, -/* pos 02af: 364 */ 0xEF /* 'o' -> */, -/* pos 02b0: 365 */ 0xEF /* 'o' -> */, -/* pos 02b1: 366 */ 0xEB /* 'k' -> */, -/* pos 02b2: 367 */ 0xE9 /* 'i' -> */, -/* pos 02b3: 368 */ 0xE5 /* 'e' -> */, -/* pos 02b4: 369 */ 0xBA /* ':' -> */, -/* pos 02b5: 370 */ 0x00, 0x35 /* - terminal marker 53 - */, -/* pos 02b7: 371 */ 0xF2 /* 'r' -> */, -/* pos 02b8: 372 */ 0xE9 /* 'i' -> */, -/* pos 02b9: 373 */ 0xE3 /* 'c' -> */, -/* pos 02ba: 374 */ 0xF4 /* 't' -> */, -/* pos 02bb: 375 */ 0xAD /* '-' -> */, -/* pos 02bc: 376 */ 0xF4 /* 't' -> */, -/* pos 02bd: 377 */ 0xF2 /* 'r' -> */, -/* pos 02be: 378 */ 0xE1 /* 'a' -> */, -/* pos 02bf: 379 */ 0xEE /* 'n' -> */, -/* pos 02c0: 380 */ 0xF3 /* 's' -> */, -/* pos 02c1: 381 */ 0xF0 /* 'p' -> */, -/* pos 02c2: 382 */ 0xEF /* 'o' -> */, -/* pos 02c3: 383 */ 0xF2 /* 'r' -> */, -/* pos 02c4: 384 */ 0xF4 /* 't' -> */, -/* pos 02c5: 385 */ 0xAD /* '-' -> */, -/* pos 02c6: 386 */ 0xF3 /* 's' -> */, -/* pos 02c7: 387 */ 0xE5 /* 'e' -> */, -/* pos 02c8: 388 */ 0xE3 /* 'c' -> */, -/* pos 02c9: 389 */ 0xF5 /* 'u' -> */, -/* pos 02ca: 390 */ 0xF2 /* 'r' -> */, -/* pos 02cb: 391 */ 0xE9 /* 'i' -> */, -/* pos 02cc: 392 */ 0xF4 /* 't' -> */, -/* pos 02cd: 393 */ 0xF9 /* 'y' -> */, -/* pos 02ce: 394 */ 0xBA /* ':' -> */, -/* pos 02cf: 395 */ 0x00, 0x36 /* - terminal marker 54 - */, -/* pos 02d1: 396 */ 0xE5 /* 'e' -> */, -/* pos 02d2: 397 */ 0xF2 /* 'r' -> */, -/* pos 02d3: 398 */ 0xAD /* '-' -> */, -/* pos 02d4: 399 */ 0xE1 /* 'a' -> */, -/* pos 02d5: 400 */ 0xE7 /* 'g' -> */, -/* pos 02d6: 401 */ 0xE5 /* 'e' -> */, -/* pos 02d7: 402 */ 0xEE /* 'n' -> */, -/* pos 02d8: 403 */ 0xF4 /* 't' -> */, -/* pos 02d9: 404 */ 0xBA /* ':' -> */, -/* pos 02da: 405 */ 0x00, 0x38 /* - terminal marker 56 - */, -/* pos 02dc: 406 */ 0xF8 /* 'x' -> */, -/* pos 02dd: 407 */ 0xF9 /* 'y' -> */, -/* pos 02de: 408 */ 0x20 /* ' ' */, 0x07, 0x00 /* (to 0x02E5 state 409) */, - 0x2D /* '-' */, 0x86, 0x00 /* (to 0x0367 state 481) */, - 0x08, /* fail */ -/* pos 02e5: 409 */ 0x00, 0x3D /* - terminal marker 61 - */, -/* pos 02e7: 410 */ 0xAD /* '-' -> */, -/* pos 02e8: 411 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02F2 state 412) */, - 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x03D7 state 570) */, - 0x61 /* 'a' */, 0x9F, 0x01 /* (to 0x048D state 701) */, - 0x08, /* fail */ -/* pos 02f2: 412 */ 0xEF /* 'o' -> */, -/* pos 02f3: 413 */ 0xF2 /* 'r' -> */, -/* pos 02f4: 414 */ 0xF7 /* 'w' -> */, -/* pos 02f5: 415 */ 0xE1 /* 'a' -> */, -/* pos 02f6: 416 */ 0xF2 /* 'r' -> */, -/* pos 02f7: 417 */ 0xE4 /* 'd' -> */, -/* pos 02f8: 418 */ 0xE5 /* 'e' -> */, -/* pos 02f9: 419 */ 0xE4 /* 'd' -> */, -/* pos 02fa: 420 */ 0xAD /* '-' -> */, -/* pos 02fb: 421 */ 0xE6 /* 'f' -> */, -/* pos 02fc: 422 */ 0xEF /* 'o' -> */, -/* pos 02fd: 423 */ 0xF2 /* 'r' -> */, -/* pos 02fe: 424 */ 0xBA /* ':' -> */, -/* pos 02ff: 425 */ 0x00, 0x3E /* - terminal marker 62 - */, -/* pos 0301: 426 */ 0x00, 0x3F /* - terminal marker 63 - */, -/* pos 0303: 427 */ 0xE1 /* 'a' -> */, -/* pos 0304: 428 */ 0xE4 /* 'd' -> */, -/* pos 0305: 429 */ 0xA0 /* ' ' -> */, -/* pos 0306: 430 */ 0x00, 0x40 /* - terminal marker 64 - */, -/* pos 0308: 431 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x030F state 432) */, - 0x72 /* 'r' */, 0x82, 0x00 /* (to 0x038D state 510) */, - 0x08, /* fail */ -/* pos 030f: 432 */ 0xBA /* ':' -> */, -/* pos 0310: 433 */ 0x00, 0x41 /* - terminal marker 65 - */, -/* pos 0312: 434 */ 0xF4 /* 't' -> */, -/* pos 0313: 435 */ 0xE9 /* 'i' -> */, -/* pos 0314: 436 */ 0xEF /* 'o' -> */, -/* pos 0315: 437 */ 0xEE /* 'n' -> */, -/* pos 0316: 438 */ 0xF3 /* 's' -> */, -/* pos 0317: 439 */ 0xA0 /* ' ' -> */, -/* pos 0318: 440 */ 0x00, 0x02 /* - terminal marker 2 - */, -/* pos 031a: 441 */ 0xE4 /* 'd' -> */, -/* pos 031b: 442 */ 0xE9 /* 'i' -> */, -/* pos 031c: 443 */ 0xE6 /* 'f' -> */, -/* pos 031d: 444 */ 0xE9 /* 'i' -> */, -/* pos 031e: 445 */ 0xE5 /* 'e' -> */, -/* pos 031f: 446 */ 0xE4 /* 'd' -> */, -/* pos 0320: 447 */ 0xAD /* '-' -> */, -/* pos 0321: 448 */ 0xF3 /* 's' -> */, -/* pos 0322: 449 */ 0xE9 /* 'i' -> */, -/* pos 0323: 450 */ 0xEE /* 'n' -> */, -/* pos 0324: 451 */ 0xE3 /* 'c' -> */, -/* pos 0325: 452 */ 0xE5 /* 'e' -> */, -/* pos 0326: 453 */ 0xBA /* ':' -> */, -/* pos 0327: 454 */ 0x00, 0x12 /* - terminal marker 18 - */, -/* pos 0329: 455 */ 0xAD /* '-' -> */, -/* pos 032a: 456 */ 0xF7 /* 'w' -> */, -/* pos 032b: 457 */ 0xE5 /* 'e' -> */, -/* pos 032c: 458 */ 0xE2 /* 'b' -> */, -/* pos 032d: 459 */ 0xF3 /* 's' -> */, -/* pos 032e: 460 */ 0xEF /* 'o' -> */, -/* pos 032f: 461 */ 0xE3 /* 'c' -> */, -/* pos 0330: 462 */ 0xEB /* 'k' -> */, -/* pos 0331: 463 */ 0xE5 /* 'e' -> */, -/* pos 0332: 464 */ 0xF4 /* 't' -> */, -/* pos 0333: 465 */ 0xAD /* '-' -> */, -/* pos 0334: 466 */ 0x6B /* 'k' */, 0x19, 0x00 /* (to 0x034D state 467) */, - 0x64 /* 'd' */, 0xDD, 0x00 /* (to 0x0414 state 603) */, - 0x65 /* 'e' */, 0xE1, 0x00 /* (to 0x041B state 609) */, - 0x70 /* 'p' */, 0xF0, 0x00 /* (to 0x042D state 624) */, - 0x61 /* 'a' */, 0xF7, 0x00 /* (to 0x0437 state 633) */, - 0x6E /* 'n' */, 0xFC, 0x00 /* (to 0x043F state 640) */, - 0x76 /* 'v' */, 0x03, 0x01 /* (to 0x0449 state 648) */, - 0x6F /* 'o' */, 0x09, 0x01 /* (to 0x0452 state 656) */, - 0x08, /* fail */ -/* pos 034d: 467 */ 0xE5 /* 'e' -> */, -/* pos 034e: 468 */ 0xF9 /* 'y' -> */, -/* pos 034f: 469 */ 0x3A /* ':' */, 0x0A, 0x00 /* (to 0x0359 state 470) */, - 0x31 /* '1' */, 0xD5, 0x00 /* (to 0x0427 state 620) */, - 0x32 /* '2' */, 0xD5, 0x00 /* (to 0x042A state 622) */, - 0x08, /* fail */ -/* pos 0359: 470 */ 0x00, 0x16 /* - terminal marker 22 - */, -/* pos 035b: 471 */ 0xE1 /* 'a' -> */, -/* pos 035c: 472 */ 0xEE /* 'n' -> */, -/* pos 035d: 473 */ 0xE7 /* 'g' -> */, -/* pos 035e: 474 */ 0xE5 /* 'e' -> */, -/* pos 035f: 475 */ 0xF3 /* 's' -> */, -/* pos 0360: 476 */ 0xBA /* ':' -> */, -/* pos 0361: 477 */ 0x00, 0x1C /* - terminal marker 28 - */, -/* pos 0363: 478 */ 0xE5 /* 'e' -> */, -/* pos 0364: 479 */ 0xBA /* ':' -> */, -/* pos 0365: 480 */ 0x00, 0x1E /* - terminal marker 30 - */, -/* pos 0367: 481 */ 0xE1 /* 'a' -> */, -/* pos 0368: 482 */ 0xF5 /* 'u' -> */, -/* pos 0369: 483 */ 0xF4 /* 't' -> */, -/* pos 036a: 484 */ 0xE8 /* 'h' -> */, -/* pos 036b: 485 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0372 state 486) */, - 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x037C state 495) */, - 0x08, /* fail */ -/* pos 0372: 486 */ 0xEE /* 'n' -> */, -/* pos 0373: 487 */ 0xF4 /* 't' -> */, -/* pos 0374: 488 */ 0xE9 /* 'i' -> */, -/* pos 0375: 489 */ 0xE3 /* 'c' -> */, -/* pos 0376: 490 */ 0xE1 /* 'a' -> */, -/* pos 0377: 491 */ 0xF4 /* 't' -> */, -/* pos 0378: 492 */ 0xE5 /* 'e' -> */, -/* pos 0379: 493 */ 0xBA /* ':' -> */, -/* pos 037a: 494 */ 0x00, 0x30 /* - terminal marker 48 - */, -/* pos 037c: 495 */ 0xF2 /* 'r' -> */, -/* pos 037d: 496 */ 0xE9 /* 'i' -> */, -/* pos 037e: 497 */ 0xFA /* 'z' -> */, -/* pos 037f: 498 */ 0xE1 /* 'a' -> */, -/* pos 0380: 499 */ 0xF4 /* 't' -> */, -/* pos 0381: 500 */ 0xE9 /* 'i' -> */, -/* pos 0382: 501 */ 0xEF /* 'o' -> */, -/* pos 0383: 502 */ 0xEE /* 'n' -> */, -/* pos 0384: 503 */ 0xBA /* ':' -> */, -/* pos 0385: 504 */ 0x00, 0x31 /* - terminal marker 49 - */, -/* pos 0387: 505 */ 0xE5 /* 'e' -> */, -/* pos 0388: 506 */ 0xF3 /* 's' -> */, -/* pos 0389: 507 */ 0xE8 /* 'h' -> */, -/* pos 038a: 508 */ 0xBA /* ':' -> */, -/* pos 038b: 509 */ 0x00, 0x32 /* - terminal marker 50 - */, -/* pos 038d: 510 */ 0xE1 /* 'a' -> */, -/* pos 038e: 511 */ 0xEE /* 'n' -> */, -/* pos 038f: 512 */ 0xF3 /* 's' -> */, -/* pos 0390: 513 */ 0xE6 /* 'f' -> */, -/* pos 0391: 514 */ 0xE5 /* 'e' -> */, -/* pos 0392: 515 */ 0xF2 /* 'r' -> */, -/* pos 0393: 516 */ 0xAD /* '-' -> */, -/* pos 0394: 517 */ 0xE5 /* 'e' -> */, -/* pos 0395: 518 */ 0xEE /* 'n' -> */, -/* pos 0396: 519 */ 0xE3 /* 'c' -> */, -/* pos 0397: 520 */ 0xEF /* 'o' -> */, -/* pos 0398: 521 */ 0xE4 /* 'd' -> */, -/* pos 0399: 522 */ 0xE9 /* 'i' -> */, -/* pos 039a: 523 */ 0xEE /* 'n' -> */, -/* pos 039b: 524 */ 0xE7 /* 'g' -> */, -/* pos 039c: 525 */ 0xBA /* ':' -> */, -/* pos 039d: 526 */ 0x00, 0x37 /* - terminal marker 55 - */, -/* pos 039f: 527 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x03A6 state 528) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x03AB state 532) */, - 0x08, /* fail */ -/* pos 03a6: 528 */ 0xF2 /* 'r' -> */, -/* pos 03a7: 529 */ 0xF9 /* 'y' -> */, -/* pos 03a8: 530 */ 0xBA /* ':' -> */, -/* pos 03a9: 531 */ 0x00, 0x39 /* - terminal marker 57 - */, -/* pos 03ab: 532 */ 0xE1 /* 'a' -> */, -/* pos 03ac: 533 */ 0xBA /* ':' -> */, -/* pos 03ad: 534 */ 0x00, 0x3A /* - terminal marker 58 - */, -/* pos 03af: 535 */ 0xF7 /* 'w' -> */, -/* pos 03b0: 536 */ 0xF7 /* 'w' -> */, -/* pos 03b1: 537 */ 0xAD /* '-' -> */, -/* pos 03b2: 538 */ 0xE1 /* 'a' -> */, -/* pos 03b3: 539 */ 0xF5 /* 'u' -> */, -/* pos 03b4: 540 */ 0xF4 /* 't' -> */, -/* pos 03b5: 541 */ 0xE8 /* 'h' -> */, -/* pos 03b6: 542 */ 0xE5 /* 'e' -> */, -/* pos 03b7: 543 */ 0xEE /* 'n' -> */, -/* pos 03b8: 544 */ 0xF4 /* 't' -> */, -/* pos 03b9: 545 */ 0xE9 /* 'i' -> */, -/* pos 03ba: 546 */ 0xE3 /* 'c' -> */, -/* pos 03bb: 547 */ 0xE1 /* 'a' -> */, -/* pos 03bc: 548 */ 0xF4 /* 't' -> */, -/* pos 03bd: 549 */ 0xE5 /* 'e' -> */, -/* pos 03be: 550 */ 0xBA /* ':' -> */, -/* pos 03bf: 551 */ 0x00, 0x3B /* - terminal marker 59 - */, -/* pos 03c1: 552 */ 0xF4 /* 't' -> */, -/* pos 03c2: 553 */ 0xE3 /* 'c' -> */, -/* pos 03c3: 554 */ 0xE8 /* 'h' -> */, -/* pos 03c4: 555 */ 0x00, 0x3C /* - terminal marker 60 - */, -/* pos 03c6: 556 */ 0xF4 /* 't' -> */, -/* pos 03c7: 557 */ 0x00, 0x44 /* - terminal marker 68 - */, -/* pos 03c9: 558 */ 0xEC /* 'l' -> */, -/* pos 03ca: 559 */ 0xE5 /* 'e' -> */, -/* pos 03cb: 560 */ 0xF4 /* 't' -> */, -/* pos 03cc: 561 */ 0xE5 /* 'e' -> */, -/* pos 03cd: 562 */ 0x00, 0x45 /* - terminal marker 69 - */, -/* pos 03cf: 563 */ 0xE9 /* 'i' -> */, -/* pos 03d0: 564 */ 0xAD /* '-' -> */, -/* pos 03d1: 565 */ 0xE1 /* 'a' -> */, -/* pos 03d2: 566 */ 0xF2 /* 'r' -> */, -/* pos 03d3: 567 */ 0xE7 /* 'g' -> */, -/* pos 03d4: 568 */ 0xF3 /* 's' -> */, -/* pos 03d5: 569 */ 0x00, 0x46 /* - terminal marker 70 - */, -/* pos 03d7: 570 */ 0xE5 /* 'e' -> */, -/* pos 03d8: 571 */ 0xE1 /* 'a' -> */, -/* pos 03d9: 572 */ 0xEC /* 'l' -> */, -/* pos 03da: 573 */ 0xAD /* '-' -> */, -/* pos 03db: 574 */ 0xE9 /* 'i' -> */, -/* pos 03dc: 575 */ 0xF0 /* 'p' -> */, -/* pos 03dd: 576 */ 0xBA /* ':' -> */, -/* pos 03de: 577 */ 0x00, 0x48 /* - terminal marker 72 - */, -/* pos 03e0: 578 */ 0xB1 /* '1' -> */, -/* pos 03e1: 579 */ 0xAE /* '.' -> */, -/* pos 03e2: 580 */ 0x30 /* '0' */, 0x07, 0x00 /* (to 0x03E9 state 581) */, - 0x31 /* '1' */, 0x61, 0x00 /* (to 0x0446 state 646) */, - 0x08, /* fail */ -/* pos 03e9: 581 */ 0xA0 /* ' ' -> */, -/* pos 03ea: 582 */ 0x00, 0x49 /* - terminal marker 73 - */, -/* pos 03ec: 583 */ 0xEC /* 'l' -> */, -/* pos 03ed: 584 */ 0xE1 /* 'a' -> */, -/* pos 03ee: 585 */ 0xF9 /* 'y' -> */, -/* pos 03ef: 586 */ 0xAD /* '-' -> */, -/* pos 03f0: 587 */ 0xEE /* 'n' -> */, -/* pos 03f1: 588 */ 0xEF /* 'o' -> */, -/* pos 03f2: 589 */ 0xEE /* 'n' -> */, -/* pos 03f3: 590 */ 0xE3 /* 'c' -> */, -/* pos 03f4: 591 */ 0xE5 /* 'e' -> */, -/* pos 03f5: 592 */ 0xBA /* ':' -> */, -/* pos 03f6: 593 */ 0x00, 0x42 /* - terminal marker 66 - */, -/* pos 03f8: 594 */ 0x70 /* 'p' */, 0x0D, 0x00 /* (to 0x0405 state 595) */, - 0x61 /* 'a' */, 0x5F, 0x00 /* (to 0x045A state 663) */, - 0x6D /* 'm' */, 0x68, 0x00 /* (to 0x0466 state 673) */, - 0x73 /* 's' */, 0x70, 0x00 /* (to 0x0471 state 682) */, - 0x08, /* fail */ -/* pos 0405: 595 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x040C state 596) */, - 0x61 /* 'a' */, 0x65, 0x00 /* (to 0x046D state 679) */, - 0x08, /* fail */ -/* pos 040c: 596 */ 0xEF /* 'o' -> */, -/* pos 040d: 597 */ 0xF4 /* 't' -> */, -/* pos 040e: 598 */ 0xEF /* 'o' -> */, -/* pos 040f: 599 */ 0xE3 /* 'c' -> */, -/* pos 0410: 600 */ 0xEF /* 'o' -> */, -/* pos 0411: 601 */ 0xEC /* 'l' -> */, -/* pos 0412: 602 */ 0x00, 0x43 /* - terminal marker 67 - */, -/* pos 0414: 603 */ 0xF2 /* 'r' -> */, -/* pos 0415: 604 */ 0xE1 /* 'a' -> */, -/* pos 0416: 605 */ 0xE6 /* 'f' -> */, -/* pos 0417: 606 */ 0xF4 /* 't' -> */, -/* pos 0418: 607 */ 0xBA /* ':' -> */, -/* pos 0419: 608 */ 0x00, 0x07 /* - terminal marker 7 - */, -/* pos 041b: 609 */ 0xF8 /* 'x' -> */, -/* pos 041c: 610 */ 0xF4 /* 't' -> */, -/* pos 041d: 611 */ 0xE5 /* 'e' -> */, -/* pos 041e: 612 */ 0xEE /* 'n' -> */, -/* pos 041f: 613 */ 0xF3 /* 's' -> */, -/* pos 0420: 614 */ 0xE9 /* 'i' -> */, -/* pos 0421: 615 */ 0xEF /* 'o' -> */, -/* pos 0422: 616 */ 0xEE /* 'n' -> */, -/* pos 0423: 617 */ 0xF3 /* 's' -> */, -/* pos 0424: 618 */ 0xBA /* ':' -> */, -/* pos 0425: 619 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 0427: 620 */ 0xBA /* ':' -> */, -/* pos 0428: 621 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 042a: 622 */ 0xBA /* ':' -> */, -/* pos 042b: 623 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 042d: 624 */ 0xF2 /* 'r' -> */, -/* pos 042e: 625 */ 0xEF /* 'o' -> */, -/* pos 042f: 626 */ 0xF4 /* 't' -> */, -/* pos 0430: 627 */ 0xEF /* 'o' -> */, -/* pos 0431: 628 */ 0xE3 /* 'c' -> */, -/* pos 0432: 629 */ 0xEF /* 'o' -> */, -/* pos 0433: 630 */ 0xEC /* 'l' -> */, -/* pos 0434: 631 */ 0xBA /* ':' -> */, -/* pos 0435: 632 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 0437: 633 */ 0xE3 /* 'c' -> */, -/* pos 0438: 634 */ 0xE3 /* 'c' -> */, -/* pos 0439: 635 */ 0xE5 /* 'e' -> */, -/* pos 043a: 636 */ 0xF0 /* 'p' -> */, -/* pos 043b: 637 */ 0xF4 /* 't' -> */, -/* pos 043c: 638 */ 0xBA /* ':' -> */, -/* pos 043d: 639 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 043f: 640 */ 0xEF /* 'o' -> */, -/* pos 0440: 641 */ 0xEE /* 'n' -> */, -/* pos 0441: 642 */ 0xE3 /* 'c' -> */, -/* pos 0442: 643 */ 0xE5 /* 'e' -> */, -/* pos 0443: 644 */ 0xBA /* ':' -> */, -/* pos 0444: 645 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 0446: 646 */ 0xA0 /* ' ' -> */, -/* pos 0447: 647 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 0449: 648 */ 0xE5 /* 'e' -> */, -/* pos 044a: 649 */ 0xF2 /* 'r' -> */, -/* pos 044b: 650 */ 0xF3 /* 's' -> */, -/* pos 044c: 651 */ 0xE9 /* 'i' -> */, -/* pos 044d: 652 */ 0xEF /* 'o' -> */, -/* pos 044e: 653 */ 0xEE /* 'n' -> */, -/* pos 044f: 654 */ 0xBA /* ':' -> */, -/* pos 0450: 655 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 0452: 656 */ 0xF2 /* 'r' -> */, -/* pos 0453: 657 */ 0xE9 /* 'i' -> */, -/* pos 0454: 658 */ 0xE7 /* 'g' -> */, -/* pos 0455: 659 */ 0xE9 /* 'i' -> */, -/* pos 0456: 660 */ 0xEE /* 'n' -> */, -/* pos 0457: 661 */ 0xBA /* ':' -> */, -/* pos 0458: 662 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 045a: 663 */ 0xF5 /* 'u' -> */, -/* pos 045b: 664 */ 0xF4 /* 't' -> */, -/* pos 045c: 665 */ 0xE8 /* 'h' -> */, -/* pos 045d: 666 */ 0xEF /* 'o' -> */, -/* pos 045e: 667 */ 0xF2 /* 'r' -> */, -/* pos 045f: 668 */ 0xE9 /* 'i' -> */, -/* pos 0460: 669 */ 0xF4 /* 't' -> */, -/* pos 0461: 670 */ 0xF9 /* 'y' -> */, -/* pos 0462: 671 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* pos 0464: 672 */ 0x00, 0x08 /* - terminal marker 8 - */, -/* pos 0466: 673 */ 0xE5 /* 'e' -> */, -/* pos 0467: 674 */ 0xF4 /* 't' -> */, -/* pos 0468: 675 */ 0xE8 /* 'h' -> */, -/* pos 0469: 676 */ 0xEF /* 'o' -> */, -/* pos 046a: 677 */ 0xE4 /* 'd' -> */, -/* pos 046b: 678 */ 0x00, 0x17 /* - terminal marker 23 - */, -/* pos 046d: 679 */ 0xF4 /* 't' -> */, -/* pos 046e: 680 */ 0xE8 /* 'h' -> */, -/* pos 046f: 681 */ 0x00, 0x18 /* - terminal marker 24 - */, -/* pos 0471: 682 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x0478 state 683) */, - 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x047E state 688) */, - 0x08, /* fail */ -/* pos 0478: 683 */ 0xE8 /* 'h' -> */, -/* pos 0479: 684 */ 0xE5 /* 'e' -> */, -/* pos 047a: 685 */ 0xED /* 'm' -> */, -/* pos 047b: 686 */ 0xE5 /* 'e' -> */, -/* pos 047c: 687 */ 0x00, 0x19 /* - terminal marker 25 - */, -/* pos 047e: 688 */ 0xE1 /* 'a' -> */, -/* pos 047f: 689 */ 0xF4 /* 't' -> */, -/* pos 0480: 690 */ 0xF5 /* 'u' -> */, -/* pos 0481: 691 */ 0xF3 /* 's' -> */, -/* pos 0482: 692 */ 0x00, 0x1A /* - terminal marker 26 - */, -/* pos 0484: 693 */ 0xE8 /* 'h' -> */, -/* pos 0485: 694 */ 0xE1 /* 'a' -> */, -/* pos 0486: 695 */ 0xF2 /* 'r' -> */, -/* pos 0487: 696 */ 0xF3 /* 's' -> */, -/* pos 0488: 697 */ 0xE5 /* 'e' -> */, -/* pos 0489: 698 */ 0xF4 /* 't' -> */, -/* pos 048a: 699 */ 0xBA /* ':' -> */, -/* pos 048b: 700 */ 0x00, 0x1B /* - terminal marker 27 - */, -/* pos 048d: 701 */ 0xF5 /* 'u' -> */, -/* pos 048e: 702 */ 0xF4 /* 't' -> */, -/* pos 048f: 703 */ 0xE8 /* 'h' -> */, -/* pos 0490: 704 */ 0xAD /* '-' -> */, -/* pos 0491: 705 */ 0xF4 /* 't' -> */, -/* pos 0492: 706 */ 0xEF /* 'o' -> */, -/* pos 0493: 707 */ 0xEB /* 'k' -> */, -/* pos 0494: 708 */ 0xE5 /* 'e' -> */, -/* pos 0495: 709 */ 0xEE /* 'n' -> */, -/* pos 0496: 710 */ 0xBA /* ':' -> */, +/* pos 00af: 45 */ 0x2F /* '/' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, + 0x32 /* '2' */, 0x97, 0x03 /* (to 0x0449 state 663) */, + 0x08, /* fail */ +/* pos 00b6: 46 */ 0xB1 /* '1' -> */, +/* pos 00b7: 47 */ 0xAE /* '.' -> */, +/* pos 00b8: 48 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x00BF state 49) */, + 0x30 /* '0' */, 0xFC, 0x01 /* (to 0x02B7 state 362) */, + 0x08, /* fail */ +/* pos 00bf: 49 */ 0xA0 /* ' ' -> */, +/* pos 00c0: 50 */ 0x00, 0x07 /* - terminal marker 7 - */, +/* pos 00c2: 51 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 52) */, + 0x75 /* 'u' */, 0x8A, 0x00 /* (to 0x014F state 125) */, + 0x67 /* 'g' */, 0xE7, 0x00 /* (to 0x01AF state 178) */, + 0x6C /* 'l' */, 0xE8, 0x00 /* (to 0x01B3 state 181) */, + 0x08, /* fail */ +/* pos 00cf: 52 */ 0xE3 /* 'c' -> */, +/* pos 00d0: 53 */ 0xE5 /* 'e' -> */, +/* pos 00d1: 54 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x00D8 state 55) */, + 0x73 /* 's' */, 0x1B, 0x02 /* (to 0x02EF state 403) */, + 0x08, /* fail */ +/* pos 00d8: 55 */ 0xF4 /* 't' -> */, +/* pos 00d9: 56 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x00E0 state 57) */, + 0x2D /* '-' */, 0x37, 0x00 /* (to 0x0113 state 87) */, + 0x08, /* fail */ +/* pos 00e0: 57 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 00e2: 58 */ 0xE6 /* 'f' -> */, +/* pos 00e3: 59 */ 0xAD /* '-' -> */, +/* pos 00e4: 60 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x00F1 state 61) */, + 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x0107 state 76) */, + 0x72 /* 'r' */, 0x2A, 0x01 /* (to 0x0214 state 255) */, + 0x75 /* 'u' */, 0x2E, 0x01 /* (to 0x021B state 261) */, + 0x08, /* fail */ +/* pos 00f1: 61 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x00F8 state 62) */, + 0x61 /* 'a' */, 0x1A, 0x01 /* (to 0x020E state 250) */, + 0x08, /* fail */ +/* pos 00f8: 62 */ 0xE4 /* 'd' -> */, +/* pos 00f9: 63 */ 0xE9 /* 'i' -> */, +/* pos 00fa: 64 */ 0xE6 /* 'f' -> */, +/* pos 00fb: 65 */ 0xE9 /* 'i' -> */, +/* pos 00fc: 66 */ 0xE5 /* 'e' -> */, +/* pos 00fd: 67 */ 0xE4 /* 'd' -> */, +/* pos 00fe: 68 */ 0xAD /* '-' -> */, +/* pos 00ff: 69 */ 0xF3 /* 's' -> */, +/* pos 0100: 70 */ 0xE9 /* 'i' -> */, +/* pos 0101: 71 */ 0xEE /* 'n' -> */, +/* pos 0102: 72 */ 0xE3 /* 'c' -> */, +/* pos 0103: 73 */ 0xE5 /* 'e' -> */, +/* pos 0104: 74 */ 0xBA /* ':' -> */, +/* pos 0105: 75 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 0107: 76 */ 0xEF /* 'o' -> */, +/* pos 0108: 77 */ 0xEE /* 'n' -> */, +/* pos 0109: 78 */ 0xE5 /* 'e' -> */, +/* pos 010a: 79 */ 0xAD /* '-' -> */, +/* pos 010b: 80 */ 0xED /* 'm' -> */, +/* pos 010c: 81 */ 0xE1 /* 'a' -> */, +/* pos 010d: 82 */ 0xF4 /* 't' -> */, +/* pos 010e: 83 */ 0xE3 /* 'c' -> */, +/* pos 010f: 84 */ 0xE8 /* 'h' -> */, +/* pos 0110: 85 */ 0xBA /* ':' -> */, +/* pos 0111: 86 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 0113: 87 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x0120 state 88) */, + 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x012A state 97) */, + 0x72 /* 'r' */, 0x8E, 0x00 /* (to 0x01A7 state 171) */, + 0x63 /* 'c' */, 0xFB, 0x01 /* (to 0x0317 state 435) */, + 0x08, /* fail */ +/* pos 0120: 88 */ 0xEE /* 'n' -> */, +/* pos 0121: 89 */ 0xE3 /* 'c' -> */, +/* pos 0122: 90 */ 0xEF /* 'o' -> */, +/* pos 0123: 91 */ 0xE4 /* 'd' -> */, +/* pos 0124: 92 */ 0xE9 /* 'i' -> */, +/* pos 0125: 93 */ 0xEE /* 'n' -> */, +/* pos 0126: 94 */ 0xE7 /* 'g' -> */, +/* pos 0127: 95 */ 0xBA /* ':' -> */, +/* pos 0128: 96 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 012a: 97 */ 0xE1 /* 'a' -> */, +/* pos 012b: 98 */ 0xEE /* 'n' -> */, +/* pos 012c: 99 */ 0xE7 /* 'g' -> */, +/* pos 012d: 100 */ 0xF5 /* 'u' -> */, +/* pos 012e: 101 */ 0xE1 /* 'a' -> */, +/* pos 012f: 102 */ 0xE7 /* 'g' -> */, +/* pos 0130: 103 */ 0xE5 /* 'e' -> */, +/* pos 0131: 104 */ 0xBA /* ':' -> */, +/* pos 0132: 105 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 0134: 106 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x013B state 107) */, + 0x6F /* 'o' */, 0x05, 0x02 /* (to 0x033C state 469) */, + 0x08, /* fail */ +/* pos 013b: 107 */ 0xE7 /* 'g' -> */, +/* pos 013c: 108 */ 0xED /* 'm' -> */, +/* pos 013d: 109 */ 0xE1 /* 'a' -> */, +/* pos 013e: 110 */ 0xBA /* ':' -> */, +/* pos 013f: 111 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 0141: 112 */ 0xE3 /* 'c' -> */, +/* pos 0142: 113 */ 0xE8 /* 'h' -> */, +/* pos 0143: 114 */ 0xE5 /* 'e' -> */, +/* pos 0144: 115 */ 0xAD /* '-' -> */, +/* pos 0145: 116 */ 0xE3 /* 'c' -> */, +/* pos 0146: 117 */ 0xEF /* 'o' -> */, +/* pos 0147: 118 */ 0xEE /* 'n' -> */, +/* pos 0148: 119 */ 0xF4 /* 't' -> */, +/* pos 0149: 120 */ 0xF2 /* 'r' -> */, +/* pos 014a: 121 */ 0xEF /* 'o' -> */, +/* pos 014b: 122 */ 0xEC /* 'l' -> */, +/* pos 014c: 123 */ 0xBA /* ':' -> */, +/* pos 014d: 124 */ 0x00, 0x0F /* - terminal marker 15 - */, +/* pos 014f: 125 */ 0xF4 /* 't' -> */, +/* pos 0150: 126 */ 0xE8 /* 'h' -> */, +/* pos 0151: 127 */ 0xEF /* 'o' -> */, +/* pos 0152: 128 */ 0xF2 /* 'r' -> */, +/* pos 0153: 129 */ 0xE9 /* 'i' -> */, +/* pos 0154: 130 */ 0xFA /* 'z' -> */, +/* pos 0155: 131 */ 0xE1 /* 'a' -> */, +/* pos 0156: 132 */ 0xF4 /* 't' -> */, +/* pos 0157: 133 */ 0xE9 /* 'i' -> */, +/* pos 0158: 134 */ 0xEF /* 'o' -> */, +/* pos 0159: 135 */ 0xEE /* 'n' -> */, +/* pos 015a: 136 */ 0xBA /* ':' -> */, +/* pos 015b: 137 */ 0x00, 0x10 /* - terminal marker 16 - */, +/* pos 015d: 138 */ 0xEB /* 'k' -> */, +/* pos 015e: 139 */ 0xE9 /* 'i' -> */, +/* pos 015f: 140 */ 0xE5 /* 'e' -> */, +/* pos 0160: 141 */ 0xBA /* ':' -> */, +/* pos 0161: 142 */ 0x00, 0x11 /* - terminal marker 17 - */, +/* pos 0163: 143 */ 0xE5 /* 'e' -> */, +/* pos 0164: 144 */ 0xEE /* 'n' -> */, +/* pos 0165: 145 */ 0xF4 /* 't' -> */, +/* pos 0166: 146 */ 0xAD /* '-' -> */, +/* pos 0167: 147 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0177 state 148) */, + 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0188 state 155) */, + 0x64 /* 'd' */, 0x4C, 0x00 /* (to 0x01B9 state 186) */, + 0x65 /* 'e' */, 0x56, 0x00 /* (to 0x01C6 state 198) */, + 0x72 /* 'r' */, 0x6F, 0x00 /* (to 0x01E2 state 223) */, + 0x08, /* fail */ +/* pos 0177: 148 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0181 state 149) */, + 0x61 /* 'a' */, 0x56, 0x00 /* (to 0x01D0 state 207) */, + 0x6F /* 'o' */, 0x5C, 0x00 /* (to 0x01D9 state 215) */, + 0x08, /* fail */ +/* pos 0181: 149 */ 0xEE /* 'n' -> */, +/* pos 0182: 150 */ 0xE7 /* 'g' -> */, +/* pos 0183: 151 */ 0xF4 /* 't' -> */, +/* pos 0184: 152 */ 0xE8 /* 'h' -> */, +/* pos 0185: 153 */ 0xBA /* ':' -> */, +/* pos 0186: 154 */ 0x00, 0x12 /* - terminal marker 18 - */, +/* pos 0188: 155 */ 0xF9 /* 'y' -> */, +/* pos 0189: 156 */ 0xF0 /* 'p' -> */, +/* pos 018a: 157 */ 0xE5 /* 'e' -> */, +/* pos 018b: 158 */ 0xBA /* ':' -> */, +/* pos 018c: 159 */ 0x00, 0x13 /* - terminal marker 19 - */, +/* pos 018e: 160 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0195 state 161) */, + 0x65 /* 'e' */, 0x23, 0x02 /* (to 0x03B4 state 562) */, + 0x08, /* fail */ +/* pos 0195: 161 */ 0xF4 /* 't' -> */, +/* pos 0196: 162 */ 0xE5 /* 'e' -> */, +/* pos 0197: 163 */ 0xBA /* ':' -> */, +/* pos 0198: 164 */ 0x00, 0x14 /* - terminal marker 20 - */, +/* pos 019a: 165 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01A1 state 166) */, + 0x65 /* 'e' */, 0xB6, 0x00 /* (to 0x0253 state 304) */, + 0x08, /* fail */ +/* pos 01a1: 166 */ 0xEE /* 'n' -> */, +/* pos 01a2: 167 */ 0xE7 /* 'g' -> */, +/* pos 01a3: 168 */ 0xE5 /* 'e' -> */, +/* pos 01a4: 169 */ 0xBA /* ':' -> */, +/* pos 01a5: 170 */ 0x00, 0x15 /* - terminal marker 21 - */, +/* pos 01a7: 171 */ 0xE1 /* 'a' -> */, +/* pos 01a8: 172 */ 0xEE /* 'n' -> */, +/* pos 01a9: 173 */ 0xE7 /* 'g' -> */, +/* pos 01aa: 174 */ 0xE5 /* 'e' -> */, +/* pos 01ab: 175 */ 0xF3 /* 's' -> */, +/* pos 01ac: 176 */ 0xBA /* ':' -> */, +/* pos 01ad: 177 */ 0x00, 0x1D /* - terminal marker 29 - */, +/* pos 01af: 178 */ 0xE5 /* 'e' -> */, +/* pos 01b0: 179 */ 0xBA /* ':' -> */, +/* pos 01b1: 180 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 01b3: 181 */ 0xEC /* 'l' -> */, +/* pos 01b4: 182 */ 0xEF /* 'o' -> */, +/* pos 01b5: 183 */ 0xF7 /* 'w' -> */, +/* pos 01b6: 184 */ 0xBA /* ':' -> */, +/* pos 01b7: 185 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 01b9: 186 */ 0xE9 /* 'i' -> */, +/* pos 01ba: 187 */ 0xF3 /* 's' -> */, +/* pos 01bb: 188 */ 0xF0 /* 'p' -> */, +/* pos 01bc: 189 */ 0xEF /* 'o' -> */, +/* pos 01bd: 190 */ 0xF3 /* 's' -> */, +/* pos 01be: 191 */ 0xE9 /* 'i' -> */, +/* pos 01bf: 192 */ 0xF4 /* 't' -> */, +/* pos 01c0: 193 */ 0xE9 /* 'i' -> */, +/* pos 01c1: 194 */ 0xEF /* 'o' -> */, +/* pos 01c2: 195 */ 0xEE /* 'n' -> */, +/* pos 01c3: 196 */ 0xBA /* ':' -> */, +/* pos 01c4: 197 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* pos 01c6: 198 */ 0xEE /* 'n' -> */, +/* pos 01c7: 199 */ 0xE3 /* 'c' -> */, +/* pos 01c8: 200 */ 0xEF /* 'o' -> */, +/* pos 01c9: 201 */ 0xE4 /* 'd' -> */, +/* pos 01ca: 202 */ 0xE9 /* 'i' -> */, +/* pos 01cb: 203 */ 0xEE /* 'n' -> */, +/* pos 01cc: 204 */ 0xE7 /* 'g' -> */, +/* pos 01cd: 205 */ 0xBA /* ':' -> */, +/* pos 01ce: 206 */ 0x00, 0x22 /* - terminal marker 34 - */, +/* pos 01d0: 207 */ 0xEE /* 'n' -> */, +/* pos 01d1: 208 */ 0xE7 /* 'g' -> */, +/* pos 01d2: 209 */ 0xF5 /* 'u' -> */, +/* pos 01d3: 210 */ 0xE1 /* 'a' -> */, +/* pos 01d4: 211 */ 0xE7 /* 'g' -> */, +/* pos 01d5: 212 */ 0xE5 /* 'e' -> */, +/* pos 01d6: 213 */ 0xBA /* ':' -> */, +/* pos 01d7: 214 */ 0x00, 0x23 /* - terminal marker 35 - */, +/* pos 01d9: 215 */ 0xE3 /* 'c' -> */, +/* pos 01da: 216 */ 0xE1 /* 'a' -> */, +/* pos 01db: 217 */ 0xF4 /* 't' -> */, +/* pos 01dc: 218 */ 0xE9 /* 'i' -> */, +/* pos 01dd: 219 */ 0xEF /* 'o' -> */, +/* pos 01de: 220 */ 0xEE /* 'n' -> */, +/* pos 01df: 221 */ 0xBA /* ':' -> */, +/* pos 01e0: 222 */ 0x00, 0x24 /* - terminal marker 36 - */, +/* pos 01e2: 223 */ 0xE1 /* 'a' -> */, +/* pos 01e3: 224 */ 0xEE /* 'n' -> */, +/* pos 01e4: 225 */ 0xE7 /* 'g' -> */, +/* pos 01e5: 226 */ 0xE5 /* 'e' -> */, +/* pos 01e6: 227 */ 0xBA /* ':' -> */, +/* pos 01e7: 228 */ 0x00, 0x25 /* - terminal marker 37 - */, +/* pos 01e9: 229 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x01F0 state 230) */, + 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x01F5 state 234) */, + 0x08, /* fail */ +/* pos 01f0: 230 */ 0xE1 /* 'a' -> */, +/* pos 01f1: 231 */ 0xE7 /* 'g' -> */, +/* pos 01f2: 232 */ 0xBA /* ':' -> */, +/* pos 01f3: 233 */ 0x00, 0x26 /* - terminal marker 38 - */, +/* pos 01f5: 234 */ 0xF0 /* 'p' -> */, +/* pos 01f6: 235 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01FD state 236) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0202 state 240) */, + 0x08, /* fail */ +/* pos 01fd: 236 */ 0xE3 /* 'c' -> */, +/* pos 01fe: 237 */ 0xF4 /* 't' -> */, +/* pos 01ff: 238 */ 0xBA /* ':' -> */, +/* pos 0200: 239 */ 0x00, 0x27 /* - terminal marker 39 - */, +/* pos 0202: 240 */ 0xF2 /* 'r' -> */, +/* pos 0203: 241 */ 0xE5 /* 'e' -> */, +/* pos 0204: 242 */ 0xF3 /* 's' -> */, +/* pos 0205: 243 */ 0xBA /* ':' -> */, +/* pos 0206: 244 */ 0x00, 0x28 /* - terminal marker 40 - */, +/* pos 0208: 245 */ 0xF2 /* 'r' -> */, +/* pos 0209: 246 */ 0xEF /* 'o' -> */, +/* pos 020a: 247 */ 0xED /* 'm' -> */, +/* pos 020b: 248 */ 0xBA /* ':' -> */, +/* pos 020c: 249 */ 0x00, 0x29 /* - terminal marker 41 - */, +/* pos 020e: 250 */ 0xF4 /* 't' -> */, +/* pos 020f: 251 */ 0xE3 /* 'c' -> */, +/* pos 0210: 252 */ 0xE8 /* 'h' -> */, +/* pos 0211: 253 */ 0xBA /* ':' -> */, +/* pos 0212: 254 */ 0x00, 0x2A /* - terminal marker 42 - */, +/* pos 0214: 255 */ 0xE1 /* 'a' -> */, +/* pos 0215: 256 */ 0xEE /* 'n' -> */, +/* pos 0216: 257 */ 0xE7 /* 'g' -> */, +/* pos 0217: 258 */ 0xE5 /* 'e' -> */, +/* pos 0218: 259 */ 0xBA /* ':' -> */, +/* pos 0219: 260 */ 0x00, 0x2B /* - terminal marker 43 - */, +/* pos 021b: 261 */ 0xEE /* 'n' -> */, +/* pos 021c: 262 */ 0xED /* 'm' -> */, +/* pos 021d: 263 */ 0xEF /* 'o' -> */, +/* pos 021e: 264 */ 0xE4 /* 'd' -> */, +/* pos 021f: 265 */ 0xE9 /* 'i' -> */, +/* pos 0220: 266 */ 0xE6 /* 'f' -> */, +/* pos 0221: 267 */ 0xE9 /* 'i' -> */, +/* pos 0222: 268 */ 0xE5 /* 'e' -> */, +/* pos 0223: 269 */ 0xE4 /* 'd' -> */, +/* pos 0224: 270 */ 0xAD /* '-' -> */, +/* pos 0225: 271 */ 0xF3 /* 's' -> */, +/* pos 0226: 272 */ 0xE9 /* 'i' -> */, +/* pos 0227: 273 */ 0xEE /* 'n' -> */, +/* pos 0228: 274 */ 0xE3 /* 'c' -> */, +/* pos 0229: 275 */ 0xE5 /* 'e' -> */, +/* pos 022a: 276 */ 0xBA /* ':' -> */, +/* pos 022b: 277 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 022d: 278 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0237 state 279) */, + 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x0245 state 292) */, + 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x024A state 296) */, + 0x08, /* fail */ +/* pos 0237: 279 */ 0xF3 /* 's' -> */, +/* pos 0238: 280 */ 0xF4 /* 't' -> */, +/* pos 0239: 281 */ 0xAD /* '-' -> */, +/* pos 023a: 282 */ 0xED /* 'm' -> */, +/* pos 023b: 283 */ 0xEF /* 'o' -> */, +/* pos 023c: 284 */ 0xE4 /* 'd' -> */, +/* pos 023d: 285 */ 0xE9 /* 'i' -> */, +/* pos 023e: 286 */ 0xE6 /* 'f' -> */, +/* pos 023f: 287 */ 0xE9 /* 'i' -> */, +/* pos 0240: 288 */ 0xE5 /* 'e' -> */, +/* pos 0241: 289 */ 0xE4 /* 'd' -> */, +/* pos 0242: 290 */ 0xBA /* ':' -> */, +/* pos 0243: 291 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 0245: 292 */ 0xEE /* 'n' -> */, +/* pos 0246: 293 */ 0xEB /* 'k' -> */, +/* pos 0247: 294 */ 0xBA /* ':' -> */, +/* pos 0248: 295 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 024a: 296 */ 0xE3 /* 'c' -> */, +/* pos 024b: 297 */ 0xE1 /* 'a' -> */, +/* pos 024c: 298 */ 0xF4 /* 't' -> */, +/* pos 024d: 299 */ 0xE9 /* 'i' -> */, +/* pos 024e: 300 */ 0xEF /* 'o' -> */, +/* pos 024f: 301 */ 0xEE /* 'n' -> */, +/* pos 0250: 302 */ 0xBA /* ':' -> */, +/* pos 0251: 303 */ 0x00, 0x2F /* - terminal marker 47 - */, +/* pos 0253: 304 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x025D state 305) */, + 0x74 /* 't' */, 0x14, 0x00 /* (to 0x026A state 311) */, + 0x70 /* 'p' */, 0x6F, 0x01 /* (to 0x03C8 state 578) */, + 0x08, /* fail */ +/* pos 025d: 305 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0264 state 306) */, + 0x65 /* 'e' */, 0xB1, 0x00 /* (to 0x0311 state 430) */, + 0x08, /* fail */ +/* pos 0264: 306 */ 0xE5 /* 'e' -> */, +/* pos 0265: 307 */ 0xF3 /* 's' -> */, +/* pos 0266: 308 */ 0xE8 /* 'h' -> */, +/* pos 0267: 309 */ 0xBA /* ':' -> */, +/* pos 0268: 310 */ 0x00, 0x33 /* - terminal marker 51 - */, +/* pos 026a: 311 */ 0xF2 /* 'r' -> */, +/* pos 026b: 312 */ 0xF9 /* 'y' -> */, +/* pos 026c: 313 */ 0xAD /* '-' -> */, +/* pos 026d: 314 */ 0xE1 /* 'a' -> */, +/* pos 026e: 315 */ 0xE6 /* 'f' -> */, +/* pos 026f: 316 */ 0xF4 /* 't' -> */, +/* pos 0270: 317 */ 0xE5 /* 'e' -> */, +/* pos 0271: 318 */ 0xF2 /* 'r' -> */, +/* pos 0272: 319 */ 0xBA /* ':' -> */, +/* pos 0273: 320 */ 0x00, 0x34 /* - terminal marker 52 - */, +/* pos 0275: 321 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x027C state 322) */, + 0x74 /* 't' */, 0xED, 0x00 /* (to 0x0365 state 496) */, + 0x08, /* fail */ +/* pos 027c: 322 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x0286 state 323) */, + 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x028C state 328) */, + 0x63 /* 'c' */, 0x52, 0x01 /* (to 0x03D4 state 589) */, + 0x08, /* fail */ +/* pos 0286: 323 */ 0xF6 /* 'v' -> */, +/* pos 0287: 324 */ 0xE5 /* 'e' -> */, +/* pos 0288: 325 */ 0xF2 /* 'r' -> */, +/* pos 0289: 326 */ 0xBA /* ':' -> */, +/* pos 028a: 327 */ 0x00, 0x35 /* - terminal marker 53 - */, +/* pos 028c: 328 */ 0xAD /* '-' -> */, +/* pos 028d: 329 */ 0xE3 /* 'c' -> */, +/* pos 028e: 330 */ 0xEF /* 'o' -> */, +/* pos 028f: 331 */ 0xEF /* 'o' -> */, +/* pos 0290: 332 */ 0xEB /* 'k' -> */, +/* pos 0291: 333 */ 0xE9 /* 'i' -> */, +/* pos 0292: 334 */ 0xE5 /* 'e' -> */, +/* pos 0293: 335 */ 0xBA /* ':' -> */, +/* pos 0294: 336 */ 0x00, 0x36 /* - terminal marker 54 - */, +/* pos 0296: 337 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x029D state 338) */, + 0x65 /* 'e' */, 0x2C, 0x01 /* (to 0x03C5 state 576) */, + 0x08, /* fail */ +/* pos 029d: 338 */ 0xE1 /* 'a' -> */, +/* pos 029e: 339 */ 0xEE /* 'n' -> */, +/* pos 029f: 340 */ 0xF3 /* 's' -> */, +/* pos 02a0: 341 */ 0xE6 /* 'f' -> */, +/* pos 02a1: 342 */ 0xE5 /* 'e' -> */, +/* pos 02a2: 343 */ 0xF2 /* 'r' -> */, +/* pos 02a3: 344 */ 0xAD /* '-' -> */, +/* pos 02a4: 345 */ 0xE5 /* 'e' -> */, +/* pos 02a5: 346 */ 0xEE /* 'n' -> */, +/* pos 02a6: 347 */ 0xE3 /* 'c' -> */, +/* pos 02a7: 348 */ 0xEF /* 'o' -> */, +/* pos 02a8: 349 */ 0xE4 /* 'd' -> */, +/* pos 02a9: 350 */ 0xE9 /* 'i' -> */, +/* pos 02aa: 351 */ 0xEE /* 'n' -> */, +/* pos 02ab: 352 */ 0xE7 /* 'g' -> */, +/* pos 02ac: 353 */ 0xBA /* ':' -> */, +/* pos 02ad: 354 */ 0x00, 0x38 /* - terminal marker 56 - */, +/* pos 02af: 355 */ 0xE9 /* 'i' -> */, +/* pos 02b0: 356 */ 0xAD /* '-' -> */, +/* pos 02b1: 357 */ 0xE1 /* 'a' -> */, +/* pos 02b2: 358 */ 0xF2 /* 'r' -> */, +/* pos 02b3: 359 */ 0xE7 /* 'g' -> */, +/* pos 02b4: 360 */ 0xF3 /* 's' -> */, +/* pos 02b5: 361 */ 0x00, 0x3D /* - terminal marker 61 - */, +/* pos 02b7: 362 */ 0xA0 /* ' ' -> */, +/* pos 02b8: 363 */ 0x00, 0x3E /* - terminal marker 62 - */, +/* pos 02ba: 364 */ 0xAD /* '-' -> */, +/* pos 02bb: 365 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02C5 state 366) */, + 0x61 /* 'a' */, 0x1D, 0x00 /* (to 0x02DB state 385) */, + 0x72 /* 'r' */, 0xFB, 0x00 /* (to 0x03BC state 568) */, + 0x08, /* fail */ +/* pos 02c5: 366 */ 0xEF /* 'o' -> */, +/* pos 02c6: 367 */ 0xF2 /* 'r' -> */, +/* pos 02c7: 368 */ 0xF7 /* 'w' -> */, +/* pos 02c8: 369 */ 0xE1 /* 'a' -> */, +/* pos 02c9: 370 */ 0xF2 /* 'r' -> */, +/* pos 02ca: 371 */ 0xE4 /* 'd' -> */, +/* pos 02cb: 372 */ 0xE5 /* 'e' -> */, +/* pos 02cc: 373 */ 0xE4 /* 'd' -> */, +/* pos 02cd: 374 */ 0xAD /* '-' -> */, +/* pos 02ce: 375 */ 0xE6 /* 'f' -> */, +/* pos 02cf: 376 */ 0xEF /* 'o' -> */, +/* pos 02d0: 377 */ 0xF2 /* 'r' -> */, +/* pos 02d1: 378 */ 0xBA /* ':' -> */, +/* pos 02d2: 379 */ 0x00, 0x3F /* - terminal marker 63 - */, +/* pos 02d4: 380 */ 0x00, 0x40 /* - terminal marker 64 - */, +/* pos 02d6: 381 */ 0xE1 /* 'a' -> */, +/* pos 02d7: 382 */ 0xE4 /* 'd' -> */, +/* pos 02d8: 383 */ 0xA0 /* ' ' -> */, +/* pos 02d9: 384 */ 0x00, 0x41 /* - terminal marker 65 - */, +/* pos 02db: 385 */ 0xF5 /* 'u' -> */, +/* pos 02dc: 386 */ 0xF4 /* 't' -> */, +/* pos 02dd: 387 */ 0xE8 /* 'h' -> */, +/* pos 02de: 388 */ 0xAD /* '-' -> */, +/* pos 02df: 389 */ 0xF4 /* 't' -> */, +/* pos 02e0: 390 */ 0xEF /* 'o' -> */, +/* pos 02e1: 391 */ 0xEB /* 'k' -> */, +/* pos 02e2: 392 */ 0xE5 /* 'e' -> */, +/* pos 02e3: 393 */ 0xEE /* 'n' -> */, +/* pos 02e4: 394 */ 0xBA /* ':' -> */, +/* pos 02e5: 395 */ 0x00, 0x45 /* - terminal marker 69 - */, +/* pos 02e7: 396 */ 0xF4 /* 't' -> */, +/* pos 02e8: 397 */ 0xE9 /* 'i' -> */, +/* pos 02e9: 398 */ 0xEF /* 'o' -> */, +/* pos 02ea: 399 */ 0xEE /* 'n' -> */, +/* pos 02eb: 400 */ 0xF3 /* 's' -> */, +/* pos 02ec: 401 */ 0xA0 /* ' ' -> */, +/* pos 02ed: 402 */ 0x00, 0x02 /* - terminal marker 2 - */, +/* pos 02ef: 403 */ 0xF3 /* 's' -> */, +/* pos 02f0: 404 */ 0xAD /* '-' -> */, +/* pos 02f1: 405 */ 0xE3 /* 'c' -> */, +/* pos 02f2: 406 */ 0xEF /* 'o' -> */, +/* pos 02f3: 407 */ 0xEE /* 'n' -> */, +/* pos 02f4: 408 */ 0xF4 /* 't' -> */, +/* pos 02f5: 409 */ 0xF2 /* 'r' -> */, +/* pos 02f6: 410 */ 0xEF /* 'o' -> */, +/* pos 02f7: 411 */ 0xEC /* 'l' -> */, +/* pos 02f8: 412 */ 0xAD /* '-' -> */, +/* pos 02f9: 413 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0300 state 414) */, + 0x61 /* 'a' */, 0x24, 0x00 /* (to 0x0320 state 443) */, + 0x08, /* fail */ +/* pos 0300: 414 */ 0xE5 /* 'e' -> */, +/* pos 0301: 415 */ 0xF1 /* 'q' -> */, +/* pos 0302: 416 */ 0xF5 /* 'u' -> */, +/* pos 0303: 417 */ 0xE5 /* 'e' -> */, +/* pos 0304: 418 */ 0xF3 /* 's' -> */, +/* pos 0305: 419 */ 0xF4 /* 't' -> */, +/* pos 0306: 420 */ 0xAD /* '-' -> */, +/* pos 0307: 421 */ 0xE8 /* 'h' -> */, +/* pos 0308: 422 */ 0xE5 /* 'e' -> */, +/* pos 0309: 423 */ 0xE1 /* 'a' -> */, +/* pos 030a: 424 */ 0xE4 /* 'd' -> */, +/* pos 030b: 425 */ 0xE5 /* 'e' -> */, +/* pos 030c: 426 */ 0xF2 /* 'r' -> */, +/* pos 030d: 427 */ 0xF3 /* 's' -> */, +/* pos 030e: 428 */ 0xBA /* ':' -> */, +/* pos 030f: 429 */ 0x00, 0x11 /* - terminal marker 17 - */, +/* pos 0311: 430 */ 0xF2 /* 'r' -> */, +/* pos 0312: 431 */ 0xE5 /* 'e' -> */, +/* pos 0313: 432 */ 0xF2 /* 'r' -> */, +/* pos 0314: 433 */ 0xBA /* ':' -> */, +/* pos 0315: 434 */ 0x00, 0x16 /* - terminal marker 22 - */, +/* pos 0317: 435 */ 0xE8 /* 'h' -> */, +/* pos 0318: 436 */ 0xE1 /* 'a' -> */, +/* pos 0319: 437 */ 0xF2 /* 'r' -> */, +/* pos 031a: 438 */ 0xF3 /* 's' -> */, +/* pos 031b: 439 */ 0xE5 /* 'e' -> */, +/* pos 031c: 440 */ 0xF4 /* 't' -> */, +/* pos 031d: 441 */ 0xBA /* ':' -> */, +/* pos 031e: 442 */ 0x00, 0x1C /* - terminal marker 28 - */, +/* pos 0320: 443 */ 0xEC /* 'l' -> */, +/* pos 0321: 444 */ 0xEC /* 'l' -> */, +/* pos 0322: 445 */ 0xEF /* 'o' -> */, +/* pos 0323: 446 */ 0xF7 /* 'w' -> */, +/* pos 0324: 447 */ 0xAD /* '-' -> */, +/* pos 0325: 448 */ 0xEF /* 'o' -> */, +/* pos 0326: 449 */ 0xF2 /* 'r' -> */, +/* pos 0327: 450 */ 0xE9 /* 'i' -> */, +/* pos 0328: 451 */ 0xE7 /* 'g' -> */, +/* pos 0329: 452 */ 0xE9 /* 'i' -> */, +/* pos 032a: 453 */ 0xEE /* 'n' -> */, +/* pos 032b: 454 */ 0xBA /* ':' -> */, +/* pos 032c: 455 */ 0x00, 0x1E /* - terminal marker 30 - */, +/* pos 032e: 456 */ 0xE1 /* 'a' -> */, +/* pos 032f: 457 */ 0xF8 /* 'x' -> */, +/* pos 0330: 458 */ 0xAD /* '-' -> */, +/* pos 0331: 459 */ 0xE6 /* 'f' -> */, +/* pos 0332: 460 */ 0xEF /* 'o' -> */, +/* pos 0333: 461 */ 0xF2 /* 'r' -> */, +/* pos 0334: 462 */ 0xF7 /* 'w' -> */, +/* pos 0335: 463 */ 0xE1 /* 'a' -> */, +/* pos 0336: 464 */ 0xF2 /* 'r' -> */, +/* pos 0337: 465 */ 0xE4 /* 'd' -> */, +/* pos 0338: 466 */ 0xF3 /* 's' -> */, +/* pos 0339: 467 */ 0xBA /* ':' -> */, +/* pos 033a: 468 */ 0x00, 0x30 /* - terminal marker 48 - */, +/* pos 033c: 469 */ 0xF8 /* 'x' -> */, +/* pos 033d: 470 */ 0xF9 /* 'y' -> */, +/* pos 033e: 471 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x0345 state 472) */, + 0x20 /* ' ' */, 0x79, 0x00 /* (to 0x03BA state 567) */, + 0x08, /* fail */ +/* pos 0345: 472 */ 0xE1 /* 'a' -> */, +/* pos 0346: 473 */ 0xF5 /* 'u' -> */, +/* pos 0347: 474 */ 0xF4 /* 't' -> */, +/* pos 0348: 475 */ 0xE8 /* 'h' -> */, +/* pos 0349: 476 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0350 state 477) */, + 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x035A state 486) */, + 0x08, /* fail */ +/* pos 0350: 477 */ 0xEE /* 'n' -> */, +/* pos 0351: 478 */ 0xF4 /* 't' -> */, +/* pos 0352: 479 */ 0xE9 /* 'i' -> */, +/* pos 0353: 480 */ 0xE3 /* 'c' -> */, +/* pos 0354: 481 */ 0xE1 /* 'a' -> */, +/* pos 0355: 482 */ 0xF4 /* 't' -> */, +/* pos 0356: 483 */ 0xE5 /* 'e' -> */, +/* pos 0357: 484 */ 0xBA /* ':' -> */, +/* pos 0358: 485 */ 0x00, 0x31 /* - terminal marker 49 - */, +/* pos 035a: 486 */ 0xF2 /* 'r' -> */, +/* pos 035b: 487 */ 0xE9 /* 'i' -> */, +/* pos 035c: 488 */ 0xFA /* 'z' -> */, +/* pos 035d: 489 */ 0xE1 /* 'a' -> */, +/* pos 035e: 490 */ 0xF4 /* 't' -> */, +/* pos 035f: 491 */ 0xE9 /* 'i' -> */, +/* pos 0360: 492 */ 0xEF /* 'o' -> */, +/* pos 0361: 493 */ 0xEE /* 'n' -> */, +/* pos 0362: 494 */ 0xBA /* ':' -> */, +/* pos 0363: 495 */ 0x00, 0x32 /* - terminal marker 50 - */, +/* pos 0365: 496 */ 0xF2 /* 'r' -> */, +/* pos 0366: 497 */ 0xE9 /* 'i' -> */, +/* pos 0367: 498 */ 0xE3 /* 'c' -> */, +/* pos 0368: 499 */ 0xF4 /* 't' -> */, +/* pos 0369: 500 */ 0xAD /* '-' -> */, +/* pos 036a: 501 */ 0xF4 /* 't' -> */, +/* pos 036b: 502 */ 0xF2 /* 'r' -> */, +/* pos 036c: 503 */ 0xE1 /* 'a' -> */, +/* pos 036d: 504 */ 0xEE /* 'n' -> */, +/* pos 036e: 505 */ 0xF3 /* 's' -> */, +/* pos 036f: 506 */ 0xF0 /* 'p' -> */, +/* pos 0370: 507 */ 0xEF /* 'o' -> */, +/* pos 0371: 508 */ 0xF2 /* 'r' -> */, +/* pos 0372: 509 */ 0xF4 /* 't' -> */, +/* pos 0373: 510 */ 0xAD /* '-' -> */, +/* pos 0374: 511 */ 0xF3 /* 's' -> */, +/* pos 0375: 512 */ 0xE5 /* 'e' -> */, +/* pos 0376: 513 */ 0xE3 /* 'c' -> */, +/* pos 0377: 514 */ 0xF5 /* 'u' -> */, +/* pos 0378: 515 */ 0xF2 /* 'r' -> */, +/* pos 0379: 516 */ 0xE9 /* 'i' -> */, +/* pos 037a: 517 */ 0xF4 /* 't' -> */, +/* pos 037b: 518 */ 0xF9 /* 'y' -> */, +/* pos 037c: 519 */ 0xBA /* ':' -> */, +/* pos 037d: 520 */ 0x00, 0x37 /* - terminal marker 55 - */, +/* pos 037f: 521 */ 0xE5 /* 'e' -> */, +/* pos 0380: 522 */ 0xF2 /* 'r' -> */, +/* pos 0381: 523 */ 0xAD /* '-' -> */, +/* pos 0382: 524 */ 0xE1 /* 'a' -> */, +/* pos 0383: 525 */ 0xE7 /* 'g' -> */, +/* pos 0384: 526 */ 0xE5 /* 'e' -> */, +/* pos 0385: 527 */ 0xEE /* 'n' -> */, +/* pos 0386: 528 */ 0xF4 /* 't' -> */, +/* pos 0387: 529 */ 0xBA /* ':' -> */, +/* pos 0388: 530 */ 0x00, 0x39 /* - terminal marker 57 - */, +/* pos 038a: 531 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0391 state 532) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0396 state 536) */, + 0x08, /* fail */ +/* pos 0391: 532 */ 0xF2 /* 'r' -> */, +/* pos 0392: 533 */ 0xF9 /* 'y' -> */, +/* pos 0393: 534 */ 0xBA /* ':' -> */, +/* pos 0394: 535 */ 0x00, 0x3A /* - terminal marker 58 - */, +/* pos 0396: 536 */ 0xE1 /* 'a' -> */, +/* pos 0397: 537 */ 0xBA /* ':' -> */, +/* pos 0398: 538 */ 0x00, 0x3B /* - terminal marker 59 - */, +/* pos 039a: 539 */ 0xF7 /* 'w' -> */, +/* pos 039b: 540 */ 0xF7 /* 'w' -> */, +/* pos 039c: 541 */ 0xAD /* '-' -> */, +/* pos 039d: 542 */ 0xE1 /* 'a' -> */, +/* pos 039e: 543 */ 0xF5 /* 'u' -> */, +/* pos 039f: 544 */ 0xF4 /* 't' -> */, +/* pos 03a0: 545 */ 0xE8 /* 'h' -> */, +/* pos 03a1: 546 */ 0xE5 /* 'e' -> */, +/* pos 03a2: 547 */ 0xEE /* 'n' -> */, +/* pos 03a3: 548 */ 0xF4 /* 't' -> */, +/* pos 03a4: 549 */ 0xE9 /* 'i' -> */, +/* pos 03a5: 550 */ 0xE3 /* 'c' -> */, +/* pos 03a6: 551 */ 0xE1 /* 'a' -> */, +/* pos 03a7: 552 */ 0xF4 /* 't' -> */, +/* pos 03a8: 553 */ 0xE5 /* 'e' -> */, +/* pos 03a9: 554 */ 0xBA /* ':' -> */, +/* pos 03aa: 555 */ 0x00, 0x3C /* - terminal marker 60 - */, +/* pos 03ac: 556 */ 0xF4 /* 't' -> */, +/* pos 03ad: 557 */ 0xE3 /* 'c' -> */, +/* pos 03ae: 558 */ 0xE8 /* 'h' -> */, +/* pos 03af: 559 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 03b1: 560 */ 0xF4 /* 't' -> */, +/* pos 03b2: 561 */ 0x00, 0x44 /* - terminal marker 68 - */, +/* pos 03b4: 562 */ 0xEC /* 'l' -> */, +/* pos 03b5: 563 */ 0xE5 /* 'e' -> */, +/* pos 03b6: 564 */ 0xF4 /* 't' -> */, +/* pos 03b7: 565 */ 0xE5 /* 'e' -> */, +/* pos 03b8: 566 */ 0x00, 0x45 /* - terminal marker 69 - */, +/* pos 03ba: 567 */ 0x00, 0x47 /* - terminal marker 71 - */, +/* pos 03bc: 568 */ 0xE5 /* 'e' -> */, +/* pos 03bd: 569 */ 0xE1 /* 'a' -> */, +/* pos 03be: 570 */ 0xEC /* 'l' -> */, +/* pos 03bf: 571 */ 0xAD /* '-' -> */, +/* pos 03c0: 572 */ 0xE9 /* 'i' -> */, +/* pos 03c1: 573 */ 0xF0 /* 'p' -> */, +/* pos 03c2: 574 */ 0xBA /* ':' -> */, +/* pos 03c3: 575 */ 0x00, 0x48 /* - terminal marker 72 - */, +/* pos 03c5: 576 */ 0xBA /* ':' -> */, +/* pos 03c6: 577 */ 0x00, 0x42 /* - terminal marker 66 - */, +/* pos 03c8: 578 */ 0xEC /* 'l' -> */, +/* pos 03c9: 579 */ 0xE1 /* 'a' -> */, +/* pos 03ca: 580 */ 0xF9 /* 'y' -> */, +/* pos 03cb: 581 */ 0xAD /* '-' -> */, +/* pos 03cc: 582 */ 0xEE /* 'n' -> */, +/* pos 03cd: 583 */ 0xEF /* 'o' -> */, +/* pos 03ce: 584 */ 0xEE /* 'n' -> */, +/* pos 03cf: 585 */ 0xE3 /* 'c' -> */, +/* pos 03d0: 586 */ 0xE5 /* 'e' -> */, +/* pos 03d1: 587 */ 0xBA /* ':' -> */, +/* pos 03d2: 588 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 03d4: 589 */ 0xAD /* '-' -> */, +/* pos 03d5: 590 */ 0xF7 /* 'w' -> */, +/* pos 03d6: 591 */ 0xE5 /* 'e' -> */, +/* pos 03d7: 592 */ 0xE2 /* 'b' -> */, +/* pos 03d8: 593 */ 0xF3 /* 's' -> */, +/* pos 03d9: 594 */ 0xEF /* 'o' -> */, +/* pos 03da: 595 */ 0xE3 /* 'c' -> */, +/* pos 03db: 596 */ 0xEB /* 'k' -> */, +/* pos 03dc: 597 */ 0xE5 /* 'e' -> */, +/* pos 03dd: 598 */ 0xF4 /* 't' -> */, +/* pos 03de: 599 */ 0xAD /* '-' -> */, +/* pos 03df: 600 */ 0x64 /* 'd' */, 0x19, 0x00 /* (to 0x03F8 state 601) */, + 0x65 /* 'e' */, 0x1D, 0x00 /* (to 0x03FF state 607) */, + 0x6B /* 'k' */, 0x26, 0x00 /* (to 0x040B state 618) */, + 0x70 /* 'p' */, 0x35, 0x00 /* (to 0x041D state 625) */, + 0x61 /* 'a' */, 0x3C, 0x00 /* (to 0x0427 state 634) */, + 0x6E /* 'n' */, 0x41, 0x00 /* (to 0x042F state 641) */, + 0x76 /* 'v' */, 0x47, 0x00 /* (to 0x0438 state 648) */, + 0x6F /* 'o' */, 0x4D, 0x00 /* (to 0x0441 state 656) */, + 0x08, /* fail */ +/* pos 03f8: 601 */ 0xF2 /* 'r' -> */, +/* pos 03f9: 602 */ 0xE1 /* 'a' -> */, +/* pos 03fa: 603 */ 0xE6 /* 'f' -> */, +/* pos 03fb: 604 */ 0xF4 /* 't' -> */, +/* pos 03fc: 605 */ 0xBA /* ':' -> */, +/* pos 03fd: 606 */ 0x00, 0x07 /* - terminal marker 7 - */, +/* pos 03ff: 607 */ 0xF8 /* 'x' -> */, +/* pos 0400: 608 */ 0xF4 /* 't' -> */, +/* pos 0401: 609 */ 0xE5 /* 'e' -> */, +/* pos 0402: 610 */ 0xEE /* 'n' -> */, +/* pos 0403: 611 */ 0xF3 /* 's' -> */, +/* pos 0404: 612 */ 0xE9 /* 'i' -> */, +/* pos 0405: 613 */ 0xEF /* 'o' -> */, +/* pos 0406: 614 */ 0xEE /* 'n' -> */, +/* pos 0407: 615 */ 0xF3 /* 's' -> */, +/* pos 0408: 616 */ 0xBA /* ':' -> */, +/* pos 0409: 617 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 040b: 618 */ 0xE5 /* 'e' -> */, +/* pos 040c: 619 */ 0xF9 /* 'y' -> */, +/* pos 040d: 620 */ 0x31 /* '1' */, 0x0A, 0x00 /* (to 0x0417 state 621) */, + 0x32 /* '2' */, 0x0A, 0x00 /* (to 0x041A state 623) */, + 0x3A /* ':' */, 0x23, 0x00 /* (to 0x0436 state 647) */, + 0x08, /* fail */ +/* pos 0417: 621 */ 0xBA /* ':' -> */, +/* pos 0418: 622 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 041a: 623 */ 0xBA /* ':' -> */, +/* pos 041b: 624 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 041d: 625 */ 0xF2 /* 'r' -> */, +/* pos 041e: 626 */ 0xEF /* 'o' -> */, +/* pos 041f: 627 */ 0xF4 /* 't' -> */, +/* pos 0420: 628 */ 0xEF /* 'o' -> */, +/* pos 0421: 629 */ 0xE3 /* 'c' -> */, +/* pos 0422: 630 */ 0xEF /* 'o' -> */, +/* pos 0423: 631 */ 0xEC /* 'l' -> */, +/* pos 0424: 632 */ 0xBA /* ':' -> */, +/* pos 0425: 633 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 0427: 634 */ 0xE3 /* 'c' -> */, +/* pos 0428: 635 */ 0xE3 /* 'c' -> */, +/* pos 0429: 636 */ 0xE5 /* 'e' -> */, +/* pos 042a: 637 */ 0xF0 /* 'p' -> */, +/* pos 042b: 638 */ 0xF4 /* 't' -> */, +/* pos 042c: 639 */ 0xBA /* ':' -> */, +/* pos 042d: 640 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 042f: 641 */ 0xEF /* 'o' -> */, +/* pos 0430: 642 */ 0xEE /* 'n' -> */, +/* pos 0431: 643 */ 0xE3 /* 'c' -> */, +/* pos 0432: 644 */ 0xE5 /* 'e' -> */, +/* pos 0433: 645 */ 0xBA /* ':' -> */, +/* pos 0434: 646 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 0436: 647 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 0438: 648 */ 0xE5 /* 'e' -> */, +/* pos 0439: 649 */ 0xF2 /* 'r' -> */, +/* pos 043a: 650 */ 0xF3 /* 's' -> */, +/* pos 043b: 651 */ 0xE9 /* 'i' -> */, +/* pos 043c: 652 */ 0xEF /* 'o' -> */, +/* pos 043d: 653 */ 0xEE /* 'n' -> */, +/* pos 043e: 654 */ 0xBA /* ':' -> */, +/* pos 043f: 655 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 0441: 656 */ 0xF2 /* 'r' -> */, +/* pos 0442: 657 */ 0xE9 /* 'i' -> */, +/* pos 0443: 658 */ 0xE7 /* 'g' -> */, +/* pos 0444: 659 */ 0xE9 /* 'i' -> */, +/* pos 0445: 660 */ 0xEE /* 'n' -> */, +/* pos 0446: 661 */ 0xBA /* ':' -> */, +/* pos 0447: 662 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* pos 0449: 663 */ 0xAD /* '-' -> */, +/* pos 044a: 664 */ 0xF3 /* 's' -> */, +/* pos 044b: 665 */ 0xE5 /* 'e' -> */, +/* pos 044c: 666 */ 0xF4 /* 't' -> */, +/* pos 044d: 667 */ 0xF4 /* 't' -> */, +/* pos 044e: 668 */ 0xE9 /* 'i' -> */, +/* pos 044f: 669 */ 0xEE /* 'n' -> */, +/* pos 0450: 670 */ 0xE7 /* 'g' -> */, +/* pos 0451: 671 */ 0xF3 /* 's' -> */, +/* pos 0452: 672 */ 0xBA /* ':' -> */, +/* pos 0453: 673 */ 0x00, 0x08 /* - terminal marker 8 - */, +/* pos 0455: 674 */ 0x61 /* 'a' */, 0x0D, 0x00 /* (to 0x0462 state 675) */, + 0x6D /* 'm' */, 0x14, 0x00 /* (to 0x046C state 684) */, + 0x70 /* 'p' */, 0x18, 0x00 /* (to 0x0473 state 690) */, + 0x73 /* 's' */, 0x20, 0x00 /* (to 0x047E state 694) */, + 0x08, /* fail */ +/* pos 0462: 675 */ 0xF5 /* 'u' -> */, +/* pos 0463: 676 */ 0xF4 /* 't' -> */, +/* pos 0464: 677 */ 0xE8 /* 'h' -> */, +/* pos 0465: 678 */ 0xEF /* 'o' -> */, +/* pos 0466: 679 */ 0xF2 /* 'r' -> */, +/* pos 0467: 680 */ 0xE9 /* 'i' -> */, +/* pos 0468: 681 */ 0xF4 /* 't' -> */, +/* pos 0469: 682 */ 0xF9 /* 'y' -> */, +/* pos 046a: 683 */ 0x00, 0x17 /* - terminal marker 23 - */, +/* pos 046c: 684 */ 0xE5 /* 'e' -> */, +/* pos 046d: 685 */ 0xF4 /* 't' -> */, +/* pos 046e: 686 */ 0xE8 /* 'h' -> */, +/* pos 046f: 687 */ 0xEF /* 'o' -> */, +/* pos 0470: 688 */ 0xE4 /* 'd' -> */, +/* pos 0471: 689 */ 0x00, 0x18 /* - terminal marker 24 - */, +/* pos 0473: 690 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x047A state 691) */, + 0x72 /* 'r' */, 0x1B, 0x00 /* (to 0x0491 state 705) */, + 0x08, /* fail */ +/* pos 047a: 691 */ 0xF4 /* 't' -> */, +/* pos 047b: 692 */ 0xE8 /* 'h' -> */, +/* pos 047c: 693 */ 0x00, 0x19 /* - terminal marker 25 - */, +/* pos 047e: 694 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x0485 state 695) */, + 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x048B state 700) */, + 0x08, /* fail */ +/* pos 0485: 695 */ 0xE8 /* 'h' -> */, +/* pos 0486: 696 */ 0xE5 /* 'e' -> */, +/* pos 0487: 697 */ 0xED /* 'm' -> */, +/* pos 0488: 698 */ 0xE5 /* 'e' -> */, +/* pos 0489: 699 */ 0x00, 0x1A /* - terminal marker 26 - */, +/* pos 048b: 700 */ 0xE1 /* 'a' -> */, +/* pos 048c: 701 */ 0xF4 /* 't' -> */, +/* pos 048d: 702 */ 0xF5 /* 'u' -> */, +/* pos 048e: 703 */ 0xF3 /* 's' -> */, +/* pos 048f: 704 */ 0x00, 0x1B /* - terminal marker 27 - */, +/* pos 0491: 705 */ 0xEF /* 'o' -> */, +/* pos 0492: 706 */ 0xF4 /* 't' -> */, +/* pos 0493: 707 */ 0xEF /* 'o' -> */, +/* pos 0494: 708 */ 0xE3 /* 'c' -> */, +/* pos 0495: 709 */ 0xEF /* 'o' -> */, +/* pos 0496: 710 */ 0xEC /* 'l' -> */, /* pos 0497: 711 */ 0x00, 0x44 /* - terminal marker 68 - */, /* total size 1177 bytes */ #endif @@ -3988,75 +3922,76 @@ /* 6: 6: origin: */ /* 7: 8: */ - /* 8: 16: http2-settings: */ - /* 9: 17: accept: */ - /* 10: 18: access-control-request-headers: */ - /* 11: 19: if-modified-since: */ - /* 12: 20: if-none-match: */ - /* 13: 21: accept-encoding: */ - /* 14: 22: accept-language: */ - /* 15: 23: pragma: */ - /* 16: 24: cache-control: */ - /* 17: 25: authorization: */ - /* 18: 26: cookie: */ - /* 19: 27: content-length: */ - /* 20: 28: content-type: */ - /* 21: 29: date: */ - /* 22: 30: range: */ - /* 23: 31: referer: */ - /* 24: 32: sec-websocket-key: */ - /* 25: 36: :method */ - /* 26: 37: :path */ - /* 27: 38: :scheme */ - /* 28: 39: :status */ - /* 29: 40: accept-charset: */ - /* 30: 41: accept-ranges: */ - /* 31: 42: access-control-allow-origin: */ - /* 32: 43: age: */ - /* 33: 44: allow: */ - /* 34: 45: content-disposition: */ - /* 35: 46: content-encoding: */ - /* 36: 47: content-language: */ - /* 37: 48: content-location: */ - /* 38: 49: content-range: */ - /* 39: 50: etag: */ - /* 40: 51: expect: */ - /* 41: 52: expires: */ - /* 42: 53: from: */ - /* 43: 54: if-match: */ - /* 44: 55: if-range: */ - /* 45: 56: if-unmodified-since: */ - /* 46: 57: last-modified: */ - /* 47: 58: link: */ - /* 48: 59: location: */ - /* 49: 60: max-forwards: */ - /* 50: 61: proxy-authenticate: */ - /* 51: 62: proxy-authorization: */ - /* 52: 63: refresh: */ - /* 53: 64: retry-after: */ - /* 54: 65: server: */ - /* 55: 66: set-cookie: */ - /* 56: 67: strict-transport-security: */ - /* 57: 68: transfer-encoding: */ - /* 58: 69: user-agent: */ - /* 59: 70: vary: */ - /* 60: 71: via: */ - /* 61: 72: www-authenticate: */ - /* 62: 73: patch */ - /* 63: 74: put */ - /* 64: 75: delete */ - /* 65: 76: uri-args */ - /* 66: 77: proxy */ - /* 67: 78: x-real-ip: */ - /* 68: 79: http/1.0 */ - /* 69: 80: x-forwarded-for: */ - /* 70: 81: connect */ - /* 71: 82: head */ - /* 72: 83: te: */ - /* 73: 84: replay-nonce: */ - /* 74: 85: :protocol */ - /* 75: 86: x-auth-token: */ - /* 76: 87: */ + /* 8: 15: http/1.1 */ + /* 9: 16: http2-settings: */ + /* 10: 17: accept: */ + /* 11: 18: access-control-request-headers: */ + /* 12: 19: if-modified-since: */ + /* 13: 20: if-none-match: */ + /* 14: 21: accept-encoding: */ + /* 15: 22: accept-language: */ + /* 16: 23: pragma: */ + /* 17: 24: cache-control: */ + /* 18: 25: authorization: */ + /* 19: 26: cookie: */ + /* 20: 27: content-length: */ + /* 21: 28: content-type: */ + /* 22: 29: date: */ + /* 23: 30: range: */ + /* 24: 31: referer: */ + /* 25: 35: :authority */ + /* 26: 36: :method */ + /* 27: 37: :path */ + /* 28: 38: :scheme */ + /* 29: 39: :status */ + /* 30: 40: accept-charset: */ + /* 31: 41: accept-ranges: */ + /* 32: 42: access-control-allow-origin: */ + /* 33: 43: age: */ + /* 34: 44: allow: */ + /* 35: 45: content-disposition: */ + /* 36: 46: content-encoding: */ + /* 37: 47: content-language: */ + /* 38: 48: content-location: */ + /* 39: 49: content-range: */ + /* 40: 50: etag: */ + /* 41: 51: expect: */ + /* 42: 52: expires: */ + /* 43: 53: from: */ + /* 44: 54: if-match: */ + /* 45: 55: if-range: */ + /* 46: 56: if-unmodified-since: */ + /* 47: 57: last-modified: */ + /* 48: 58: link: */ + /* 49: 59: location: */ + /* 50: 60: max-forwards: */ + /* 51: 61: proxy-authenticate: */ + /* 52: 62: proxy-authorization: */ + /* 53: 63: refresh: */ + /* 54: 64: retry-after: */ + /* 55: 65: server: */ + /* 56: 66: set-cookie: */ + /* 57: 67: strict-transport-security: */ + /* 58: 68: transfer-encoding: */ + /* 59: 69: user-agent: */ + /* 60: 70: vary: */ + /* 61: 71: via: */ + /* 62: 72: www-authenticate: */ + /* 63: 73: patch */ + /* 64: 74: put */ + /* 65: 75: delete */ + /* 66: 76: uri-args */ + /* 67: 77: proxy */ + /* 68: 78: x-real-ip: */ + /* 69: 79: http/1.0 */ + /* 70: 80: x-forwarded-for: */ + /* 71: 81: connect */ + /* 72: 82: head */ + /* 73: 83: te: */ + /* 74: 84: replay-nonce: */ + /* 75: 85: :protocol */ + /* 76: 86: x-auth-token: */ + /* 77: 87: */ /* pos 0000: 0 */ 0x67 /* 'g' */, 0x40, 0x00 /* (to 0x0040 state 1) */, 0x70 /* 'p' */, 0x42, 0x00 /* (to 0x0045 state 5) */, 0x68 /* 'h' */, 0x51, 0x00 /* (to 0x0057 state 10) */, @@ -4064,29 +3999,29 @@ 0x75 /* 'u' */, 0x7E, 0x00 /* (to 0x008A state 26) */, 0x6F /* 'o' */, 0x8D, 0x00 /* (to 0x009C state 34) */, 0x0D /* '.' */, 0x98, 0x00 /* (to 0x00AA state 41) */, - 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 57) */, - 0x69 /* 'i' */, 0xE2, 0x00 /* (to 0x00FA state 88) */, - 0x64 /* 'd' */, 0x7D, 0x01 /* (to 0x0198 state 177) */, - 0x72 /* 'r' */, 0x86, 0x01 /* (to 0x01A4 state 182) */, - 0x65 /* 'e' */, 0xEB, 0x01 /* (to 0x020C state 256) */, - 0x66 /* 'f' */, 0x07, 0x02 /* (to 0x022B state 272) */, - 0x6C /* 'l' */, 0x30, 0x02 /* (to 0x0257 state 306) */, - 0x6D /* 'm' */, 0x53, 0x02 /* (to 0x027D state 332) */, - 0x73 /* 's' */, 0x69, 0x02 /* (to 0x0296 state 355) */, - 0x78 /* 'x' */, 0xB7, 0x02 /* (to 0x02E7 state 410) */, - 0x74 /* 't' */, 0xD5, 0x02 /* (to 0x0308 state 431) */, - 0x76 /* 'v' */, 0x69, 0x03 /* (to 0x039F state 527) */, - 0x77 /* 'w' */, 0x76, 0x03 /* (to 0x03AF state 535) */, - 0x3A /* ':' */, 0xBC, 0x03 /* (to 0x03F8 state 594) */, + 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 51) */, + 0x69 /* 'i' */, 0xCA, 0x00 /* (to 0x00E2 state 58) */, + 0x64 /* 'd' */, 0x73, 0x01 /* (to 0x018E state 160) */, + 0x72 /* 'r' */, 0x7C, 0x01 /* (to 0x019A state 165) */, + 0x65 /* 'e' */, 0xC8, 0x01 /* (to 0x01E9 state 229) */, + 0x66 /* 'f' */, 0xE4, 0x01 /* (to 0x0208 state 245) */, + 0x6C /* 'l' */, 0x06, 0x02 /* (to 0x022D state 278) */, + 0x73 /* 's' */, 0x4B, 0x02 /* (to 0x0275 state 321) */, + 0x74 /* 't' */, 0x69, 0x02 /* (to 0x0296 state 337) */, + 0x78 /* 'x' */, 0x8A, 0x02 /* (to 0x02BA state 364) */, + 0x6D /* 'm' */, 0xFB, 0x02 /* (to 0x032E state 456) */, + 0x76 /* 'v' */, 0x54, 0x03 /* (to 0x038A state 531) */, + 0x77 /* 'w' */, 0x61, 0x03 /* (to 0x039A state 539) */, + 0x3A /* ':' */, 0x19, 0x04 /* (to 0x0455 state 674) */, 0x08, /* fail */ /* pos 0040: 1 */ 0xE5 /* 'e' -> */, /* pos 0041: 2 */ 0xF4 /* 't' -> */, /* pos 0042: 3 */ 0xA0 /* ' ' -> */, /* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, /* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */, - 0x72 /* 'r' */, 0xF6, 0x00 /* (to 0x013E state 123) */, - 0x61 /* 'a' */, 0x76, 0x03 /* (to 0x03C1 state 552) */, - 0x75 /* 'u' */, 0x78, 0x03 /* (to 0x03C6 state 556) */, + 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x0134 state 106) */, + 0x61 /* 'a' */, 0x61, 0x03 /* (to 0x03AC state 556) */, + 0x75 /* 'u' */, 0x63, 0x03 /* (to 0x03B1 state 560) */, 0x08, /* fail */ /* pos 0052: 6 */ 0xF3 /* 's' -> */, /* pos 0053: 7 */ 0xF4 /* 't' -> */, @@ -4094,34 +4029,34 @@ /* pos 0055: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, /* pos 0057: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0061 state 11) */, 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AD state 43) */, - 0x65 /* 'e' */, 0xA6, 0x02 /* (to 0x0303 state 427) */, + 0x65 /* 'e' */, 0x79, 0x02 /* (to 0x02D6 state 381) */, 0x08, /* fail */ /* pos 0061: 11 */ 0xF3 /* 's' -> */, /* pos 0062: 12 */ 0xF4 /* 't' -> */, /* pos 0063: 13 */ 0xBA /* ':' -> */, /* pos 0064: 14 */ 0x00, 0x03 /* - terminal marker 3 - */, /* pos 0066: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006D state 16) */, - 0x61 /* 'a' */, 0xE2, 0x00 /* (to 0x014B state 129) */, + 0x61 /* 'a' */, 0xD8, 0x00 /* (to 0x0141 state 112) */, 0x08, /* fail */ /* pos 006d: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0074 state 17) */, - 0x6F /* 'o' */, 0xF7, 0x00 /* (to 0x0167 state 155) */, + 0x6F /* 'o' */, 0xED, 0x00 /* (to 0x015D state 138) */, 0x08, /* fail */ /* pos 0074: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x007B state 18) */, - 0x74 /* 't' */, 0xF6, 0x00 /* (to 0x016D state 160) */, + 0x74 /* 't' */, 0xEC, 0x00 /* (to 0x0163 state 143) */, 0x08, /* fail */ /* pos 007b: 18 */ 0xE5 /* 'e' -> */, /* pos 007c: 19 */ 0xE3 /* 'c' -> */, /* pos 007d: 20 */ 0xF4 /* 't' -> */, /* pos 007e: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0085 state 22) */, - 0x20 /* ' ' */, 0x80, 0x02 /* (to 0x0301 state 426) */, + 0x20 /* ' ' */, 0x53, 0x02 /* (to 0x02D4 state 380) */, 0x08, /* fail */ /* pos 0085: 22 */ 0xEF /* 'o' -> */, /* pos 0086: 23 */ 0xEE /* 'n' -> */, /* pos 0087: 24 */ 0xBA /* ':' -> */, /* pos 0088: 25 */ 0x00, 0x04 /* - terminal marker 4 - */, /* pos 008a: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0094 state 27) */, - 0x73 /* 's' */, 0x44, 0x02 /* (to 0x02D1 state 396) */, - 0x72 /* 'r' */, 0x3F, 0x03 /* (to 0x03CF state 563) */, + 0x72 /* 'r' */, 0x22, 0x02 /* (to 0x02AF state 355) */, + 0x73 /* 's' */, 0xEF, 0x02 /* (to 0x037F state 521) */, 0x08, /* fail */ /* pos 0094: 27 */ 0xE7 /* 'g' -> */, /* pos 0095: 28 */ 0xF2 /* 'r' -> */, @@ -4131,7 +4066,7 @@ /* pos 0099: 32 */ 0xBA /* ':' -> */, /* pos 009a: 33 */ 0x00, 0x05 /* - terminal marker 5 - */, /* pos 009c: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A3 state 35) */, - 0x70 /* 'p' */, 0x73, 0x02 /* (to 0x0312 state 434) */, + 0x70 /* 'p' */, 0x48, 0x02 /* (to 0x02E7 state 396) */, 0x08, /* fail */ /* pos 00a3: 35 */ 0xE9 /* 'i' -> */, /* pos 00a4: 36 */ 0xE7 /* 'g' -> */, @@ -4143,757 +4078,757 @@ /* pos 00ab: 42 */ 0x00, 0x07 /* - terminal marker 7 - */, /* pos 00ad: 43 */ 0xF4 /* 't' -> */, /* pos 00ae: 44 */ 0xF0 /* 'p' -> */, -/* pos 00af: 45 */ 0x32 /* '2' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, - 0x2F /* '/' */, 0x2E, 0x03 /* (to 0x03E0 state 578) */, - 0x08, /* fail */ -/* pos 00b6: 46 */ 0xAD /* '-' -> */, -/* pos 00b7: 47 */ 0xF3 /* 's' -> */, -/* pos 00b8: 48 */ 0xE5 /* 'e' -> */, -/* pos 00b9: 49 */ 0xF4 /* 't' -> */, -/* pos 00ba: 50 */ 0xF4 /* 't' -> */, -/* pos 00bb: 51 */ 0xE9 /* 'i' -> */, -/* pos 00bc: 52 */ 0xEE /* 'n' -> */, -/* pos 00bd: 53 */ 0xE7 /* 'g' -> */, -/* pos 00be: 54 */ 0xF3 /* 's' -> */, -/* pos 00bf: 55 */ 0xBA /* ':' -> */, -/* pos 00c0: 56 */ 0x00, 0x08 /* - terminal marker 8 - */, -/* pos 00c2: 57 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 58) */, - 0x75 /* 'u' */, 0x94, 0x00 /* (to 0x0159 state 142) */, - 0x6C /* 'l' */, 0x0E, 0x01 /* (to 0x01D6 state 208) */, - 0x67 /* 'g' */, 0x98, 0x02 /* (to 0x0363 state 478) */, - 0x08, /* fail */ -/* pos 00cf: 58 */ 0xE3 /* 'c' -> */, -/* pos 00d0: 59 */ 0xE5 /* 'e' -> */, -/* pos 00d1: 60 */ 0x73 /* 's' */, 0x07, 0x00 /* (to 0x00D8 state 61) */, - 0x70 /* 'p' */, 0x41, 0x00 /* (to 0x0115 state 102) */, - 0x08, /* fail */ -/* pos 00d8: 61 */ 0xF3 /* 's' -> */, -/* pos 00d9: 62 */ 0xAD /* '-' -> */, -/* pos 00da: 63 */ 0xE3 /* 'c' -> */, -/* pos 00db: 64 */ 0xEF /* 'o' -> */, -/* pos 00dc: 65 */ 0xEE /* 'n' -> */, -/* pos 00dd: 66 */ 0xF4 /* 't' -> */, -/* pos 00de: 67 */ 0xF2 /* 'r' -> */, -/* pos 00df: 68 */ 0xEF /* 'o' -> */, -/* pos 00e0: 69 */ 0xEC /* 'l' -> */, -/* pos 00e1: 70 */ 0xAD /* '-' -> */, -/* pos 00e2: 71 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00E9 state 72) */, - 0x61 /* 'a' */, 0xE3, 0x00 /* (to 0x01C8 state 195) */, - 0x08, /* fail */ -/* pos 00e9: 72 */ 0xE5 /* 'e' -> */, -/* pos 00ea: 73 */ 0xF1 /* 'q' -> */, -/* pos 00eb: 74 */ 0xF5 /* 'u' -> */, -/* pos 00ec: 75 */ 0xE5 /* 'e' -> */, -/* pos 00ed: 76 */ 0xF3 /* 's' -> */, -/* pos 00ee: 77 */ 0xF4 /* 't' -> */, -/* pos 00ef: 78 */ 0xAD /* '-' -> */, -/* pos 00f0: 79 */ 0xE8 /* 'h' -> */, -/* pos 00f1: 80 */ 0xE5 /* 'e' -> */, -/* pos 00f2: 81 */ 0xE1 /* 'a' -> */, -/* pos 00f3: 82 */ 0xE4 /* 'd' -> */, -/* pos 00f4: 83 */ 0xE5 /* 'e' -> */, -/* pos 00f5: 84 */ 0xF2 /* 'r' -> */, -/* pos 00f6: 85 */ 0xF3 /* 's' -> */, -/* pos 00f7: 86 */ 0xBA /* ':' -> */, -/* pos 00f8: 87 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 00fa: 88 */ 0xE6 /* 'f' -> */, -/* pos 00fb: 89 */ 0xAD /* '-' -> */, -/* pos 00fc: 90 */ 0x6E /* 'n' */, 0x0D, 0x00 /* (to 0x0109 state 91) */, - 0x6D /* 'm' */, 0x32, 0x01 /* (to 0x0231 state 277) */, - 0x72 /* 'r' */, 0x3C, 0x01 /* (to 0x023E state 283) */, - 0x75 /* 'u' */, 0x40, 0x01 /* (to 0x0245 state 289) */, - 0x08, /* fail */ -/* pos 0109: 91 */ 0xEF /* 'o' -> */, -/* pos 010a: 92 */ 0xEE /* 'n' -> */, -/* pos 010b: 93 */ 0xE5 /* 'e' -> */, -/* pos 010c: 94 */ 0xAD /* '-' -> */, -/* pos 010d: 95 */ 0xED /* 'm' -> */, -/* pos 010e: 96 */ 0xE1 /* 'a' -> */, -/* pos 010f: 97 */ 0xF4 /* 't' -> */, -/* pos 0110: 98 */ 0xE3 /* 'c' -> */, -/* pos 0111: 99 */ 0xE8 /* 'h' -> */, -/* pos 0112: 100 */ 0xBA /* ':' -> */, -/* pos 0113: 101 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 0115: 102 */ 0xF4 /* 't' -> */, -/* pos 0116: 103 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x011D state 104) */, - 0x3A /* ':' */, 0x4B, 0x03 /* (to 0x0464 state 672) */, - 0x08, /* fail */ -/* pos 011d: 104 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x012A state 105) */, - 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x0134 state 114) */, - 0x72 /* 'r' */, 0x38, 0x02 /* (to 0x035B state 471) */, - 0x63 /* 'c' */, 0x5E, 0x03 /* (to 0x0484 state 693) */, - 0x08, /* fail */ -/* pos 012a: 105 */ 0xEE /* 'n' -> */, -/* pos 012b: 106 */ 0xE3 /* 'c' -> */, -/* pos 012c: 107 */ 0xEF /* 'o' -> */, -/* pos 012d: 108 */ 0xE4 /* 'd' -> */, -/* pos 012e: 109 */ 0xE9 /* 'i' -> */, -/* pos 012f: 110 */ 0xEE /* 'n' -> */, -/* pos 0130: 111 */ 0xE7 /* 'g' -> */, -/* pos 0131: 112 */ 0xBA /* ':' -> */, -/* pos 0132: 113 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 0134: 114 */ 0xE1 /* 'a' -> */, -/* pos 0135: 115 */ 0xEE /* 'n' -> */, -/* pos 0136: 116 */ 0xE7 /* 'g' -> */, -/* pos 0137: 117 */ 0xF5 /* 'u' -> */, -/* pos 0138: 118 */ 0xE1 /* 'a' -> */, -/* pos 0139: 119 */ 0xE7 /* 'g' -> */, -/* pos 013a: 120 */ 0xE5 /* 'e' -> */, -/* pos 013b: 121 */ 0xBA /* ':' -> */, -/* pos 013c: 122 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 013e: 123 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0145 state 124) */, - 0x6F /* 'o' */, 0x9B, 0x01 /* (to 0x02DC state 406) */, - 0x08, /* fail */ -/* pos 0145: 124 */ 0xE7 /* 'g' -> */, -/* pos 0146: 125 */ 0xED /* 'm' -> */, -/* pos 0147: 126 */ 0xE1 /* 'a' -> */, -/* pos 0148: 127 */ 0xBA /* ':' -> */, -/* pos 0149: 128 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 014b: 129 */ 0xE3 /* 'c' -> */, -/* pos 014c: 130 */ 0xE8 /* 'h' -> */, -/* pos 014d: 131 */ 0xE5 /* 'e' -> */, -/* pos 014e: 132 */ 0xAD /* '-' -> */, -/* pos 014f: 133 */ 0xE3 /* 'c' -> */, -/* pos 0150: 134 */ 0xEF /* 'o' -> */, -/* pos 0151: 135 */ 0xEE /* 'n' -> */, -/* pos 0152: 136 */ 0xF4 /* 't' -> */, -/* pos 0153: 137 */ 0xF2 /* 'r' -> */, -/* pos 0154: 138 */ 0xEF /* 'o' -> */, -/* pos 0155: 139 */ 0xEC /* 'l' -> */, -/* pos 0156: 140 */ 0xBA /* ':' -> */, -/* pos 0157: 141 */ 0x00, 0x10 /* - terminal marker 16 - */, -/* pos 0159: 142 */ 0xF4 /* 't' -> */, -/* pos 015a: 143 */ 0xE8 /* 'h' -> */, -/* pos 015b: 144 */ 0xEF /* 'o' -> */, -/* pos 015c: 145 */ 0xF2 /* 'r' -> */, -/* pos 015d: 146 */ 0xE9 /* 'i' -> */, -/* pos 015e: 147 */ 0xFA /* 'z' -> */, -/* pos 015f: 148 */ 0xE1 /* 'a' -> */, -/* pos 0160: 149 */ 0xF4 /* 't' -> */, -/* pos 0161: 150 */ 0xE9 /* 'i' -> */, -/* pos 0162: 151 */ 0xEF /* 'o' -> */, -/* pos 0163: 152 */ 0xEE /* 'n' -> */, -/* pos 0164: 153 */ 0xBA /* ':' -> */, -/* pos 0165: 154 */ 0x00, 0x11 /* - terminal marker 17 - */, -/* pos 0167: 155 */ 0xEB /* 'k' -> */, -/* pos 0168: 156 */ 0xE9 /* 'i' -> */, -/* pos 0169: 157 */ 0xE5 /* 'e' -> */, -/* pos 016a: 158 */ 0xBA /* ':' -> */, -/* pos 016b: 159 */ 0x00, 0x12 /* - terminal marker 18 - */, -/* pos 016d: 160 */ 0xE5 /* 'e' -> */, -/* pos 016e: 161 */ 0xEE /* 'n' -> */, -/* pos 016f: 162 */ 0xF4 /* 't' -> */, -/* pos 0170: 163 */ 0xAD /* '-' -> */, -/* pos 0171: 164 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0181 state 165) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0192 state 172) */, - 0x64 /* 'd' */, 0x65, 0x00 /* (to 0x01DC state 213) */, - 0x65 /* 'e' */, 0x6F, 0x00 /* (to 0x01E9 state 225) */, - 0x72 /* 'r' */, 0x88, 0x00 /* (to 0x0205 state 250) */, - 0x08, /* fail */ -/* pos 0181: 165 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x018B state 166) */, - 0x61 /* 'a' */, 0x6F, 0x00 /* (to 0x01F3 state 234) */, - 0x6F /* 'o' */, 0x75, 0x00 /* (to 0x01FC state 242) */, - 0x08, /* fail */ -/* pos 018b: 166 */ 0xEE /* 'n' -> */, -/* pos 018c: 167 */ 0xE7 /* 'g' -> */, -/* pos 018d: 168 */ 0xF4 /* 't' -> */, -/* pos 018e: 169 */ 0xE8 /* 'h' -> */, -/* pos 018f: 170 */ 0xBA /* ':' -> */, -/* pos 0190: 171 */ 0x00, 0x13 /* - terminal marker 19 - */, -/* pos 0192: 172 */ 0xF9 /* 'y' -> */, -/* pos 0193: 173 */ 0xF0 /* 'p' -> */, -/* pos 0194: 174 */ 0xE5 /* 'e' -> */, -/* pos 0195: 175 */ 0xBA /* ':' -> */, -/* pos 0196: 176 */ 0x00, 0x14 /* - terminal marker 20 - */, -/* pos 0198: 177 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x019F state 178) */, - 0x65 /* 'e' */, 0x2E, 0x02 /* (to 0x03C9 state 558) */, - 0x08, /* fail */ -/* pos 019f: 178 */ 0xF4 /* 't' -> */, -/* pos 01a0: 179 */ 0xE5 /* 'e' -> */, -/* pos 01a1: 180 */ 0xBA /* ':' -> */, -/* pos 01a2: 181 */ 0x00, 0x15 /* - terminal marker 21 - */, -/* pos 01a4: 182 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01AB state 183) */, - 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x01B1 state 188) */, - 0x08, /* fail */ -/* pos 01ab: 183 */ 0xEE /* 'n' -> */, -/* pos 01ac: 184 */ 0xE7 /* 'g' -> */, -/* pos 01ad: 185 */ 0xE5 /* 'e' -> */, -/* pos 01ae: 186 */ 0xBA /* ':' -> */, -/* pos 01af: 187 */ 0x00, 0x16 /* - terminal marker 22 - */, -/* pos 01b1: 188 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x01BB state 189) */, - 0x74 /* 't' */, 0xD7, 0x00 /* (to 0x028B state 345) */, - 0x70 /* 'p' */, 0x35, 0x02 /* (to 0x03EC state 583) */, - 0x08, /* fail */ -/* pos 01bb: 189 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01C2 state 190) */, - 0x72 /* 'r' */, 0xC9, 0x01 /* (to 0x0387 state 505) */, - 0x08, /* fail */ -/* pos 01c2: 190 */ 0xF2 /* 'r' -> */, -/* pos 01c3: 191 */ 0xE5 /* 'e' -> */, -/* pos 01c4: 192 */ 0xF2 /* 'r' -> */, -/* pos 01c5: 193 */ 0xBA /* ':' -> */, -/* pos 01c6: 194 */ 0x00, 0x17 /* - terminal marker 23 - */, -/* pos 01c8: 195 */ 0xEC /* 'l' -> */, -/* pos 01c9: 196 */ 0xEC /* 'l' -> */, -/* pos 01ca: 197 */ 0xEF /* 'o' -> */, -/* pos 01cb: 198 */ 0xF7 /* 'w' -> */, -/* pos 01cc: 199 */ 0xAD /* '-' -> */, -/* pos 01cd: 200 */ 0xEF /* 'o' -> */, -/* pos 01ce: 201 */ 0xF2 /* 'r' -> */, -/* pos 01cf: 202 */ 0xE9 /* 'i' -> */, -/* pos 01d0: 203 */ 0xE7 /* 'g' -> */, -/* pos 01d1: 204 */ 0xE9 /* 'i' -> */, -/* pos 01d2: 205 */ 0xEE /* 'n' -> */, -/* pos 01d3: 206 */ 0xBA /* ':' -> */, -/* pos 01d4: 207 */ 0x00, 0x1F /* - terminal marker 31 - */, -/* pos 01d6: 208 */ 0xEC /* 'l' -> */, -/* pos 01d7: 209 */ 0xEF /* 'o' -> */, -/* pos 01d8: 210 */ 0xF7 /* 'w' -> */, -/* pos 01d9: 211 */ 0xBA /* ':' -> */, -/* pos 01da: 212 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 01dc: 213 */ 0xE9 /* 'i' -> */, -/* pos 01dd: 214 */ 0xF3 /* 's' -> */, -/* pos 01de: 215 */ 0xF0 /* 'p' -> */, -/* pos 01df: 216 */ 0xEF /* 'o' -> */, -/* pos 01e0: 217 */ 0xF3 /* 's' -> */, -/* pos 01e1: 218 */ 0xE9 /* 'i' -> */, -/* pos 01e2: 219 */ 0xF4 /* 't' -> */, -/* pos 01e3: 220 */ 0xE9 /* 'i' -> */, -/* pos 01e4: 221 */ 0xEF /* 'o' -> */, -/* pos 01e5: 222 */ 0xEE /* 'n' -> */, -/* pos 01e6: 223 */ 0xBA /* ':' -> */, -/* pos 01e7: 224 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* pos 01e9: 225 */ 0xEE /* 'n' -> */, -/* pos 01ea: 226 */ 0xE3 /* 'c' -> */, -/* pos 01eb: 227 */ 0xEF /* 'o' -> */, -/* pos 01ec: 228 */ 0xE4 /* 'd' -> */, -/* pos 01ed: 229 */ 0xE9 /* 'i' -> */, -/* pos 01ee: 230 */ 0xEE /* 'n' -> */, -/* pos 01ef: 231 */ 0xE7 /* 'g' -> */, -/* pos 01f0: 232 */ 0xBA /* ':' -> */, -/* pos 01f1: 233 */ 0x00, 0x23 /* - terminal marker 35 - */, -/* pos 01f3: 234 */ 0xEE /* 'n' -> */, -/* pos 01f4: 235 */ 0xE7 /* 'g' -> */, -/* pos 01f5: 236 */ 0xF5 /* 'u' -> */, -/* pos 01f6: 237 */ 0xE1 /* 'a' -> */, -/* pos 01f7: 238 */ 0xE7 /* 'g' -> */, -/* pos 01f8: 239 */ 0xE5 /* 'e' -> */, -/* pos 01f9: 240 */ 0xBA /* ':' -> */, -/* pos 01fa: 241 */ 0x00, 0x24 /* - terminal marker 36 - */, -/* pos 01fc: 242 */ 0xE3 /* 'c' -> */, -/* pos 01fd: 243 */ 0xE1 /* 'a' -> */, -/* pos 01fe: 244 */ 0xF4 /* 't' -> */, -/* pos 01ff: 245 */ 0xE9 /* 'i' -> */, -/* pos 0200: 246 */ 0xEF /* 'o' -> */, -/* pos 0201: 247 */ 0xEE /* 'n' -> */, -/* pos 0202: 248 */ 0xBA /* ':' -> */, -/* pos 0203: 249 */ 0x00, 0x25 /* - terminal marker 37 - */, -/* pos 0205: 250 */ 0xE1 /* 'a' -> */, -/* pos 0206: 251 */ 0xEE /* 'n' -> */, -/* pos 0207: 252 */ 0xE7 /* 'g' -> */, -/* pos 0208: 253 */ 0xE5 /* 'e' -> */, -/* pos 0209: 254 */ 0xBA /* ':' -> */, -/* pos 020a: 255 */ 0x00, 0x26 /* - terminal marker 38 - */, -/* pos 020c: 256 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x0213 state 257) */, - 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x0218 state 261) */, - 0x08, /* fail */ -/* pos 0213: 257 */ 0xE1 /* 'a' -> */, -/* pos 0214: 258 */ 0xE7 /* 'g' -> */, -/* pos 0215: 259 */ 0xBA /* ':' -> */, -/* pos 0216: 260 */ 0x00, 0x27 /* - terminal marker 39 - */, -/* pos 0218: 261 */ 0xF0 /* 'p' -> */, -/* pos 0219: 262 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0220 state 263) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0225 state 267) */, - 0x08, /* fail */ -/* pos 0220: 263 */ 0xE3 /* 'c' -> */, -/* pos 0221: 264 */ 0xF4 /* 't' -> */, -/* pos 0222: 265 */ 0xBA /* ':' -> */, -/* pos 0223: 266 */ 0x00, 0x28 /* - terminal marker 40 - */, -/* pos 0225: 267 */ 0xF2 /* 'r' -> */, -/* pos 0226: 268 */ 0xE5 /* 'e' -> */, -/* pos 0227: 269 */ 0xF3 /* 's' -> */, -/* pos 0228: 270 */ 0xBA /* ':' -> */, -/* pos 0229: 271 */ 0x00, 0x29 /* - terminal marker 41 - */, -/* pos 022b: 272 */ 0xF2 /* 'r' -> */, -/* pos 022c: 273 */ 0xEF /* 'o' -> */, -/* pos 022d: 274 */ 0xED /* 'm' -> */, -/* pos 022e: 275 */ 0xBA /* ':' -> */, -/* pos 022f: 276 */ 0x00, 0x2A /* - terminal marker 42 - */, -/* pos 0231: 277 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0238 state 278) */, - 0x6F /* 'o' */, 0xE6, 0x00 /* (to 0x031A state 441) */, - 0x08, /* fail */ -/* pos 0238: 278 */ 0xF4 /* 't' -> */, -/* pos 0239: 279 */ 0xE3 /* 'c' -> */, -/* pos 023a: 280 */ 0xE8 /* 'h' -> */, -/* pos 023b: 281 */ 0xBA /* ':' -> */, -/* pos 023c: 282 */ 0x00, 0x2B /* - terminal marker 43 - */, -/* pos 023e: 283 */ 0xE1 /* 'a' -> */, -/* pos 023f: 284 */ 0xEE /* 'n' -> */, -/* pos 0240: 285 */ 0xE7 /* 'g' -> */, -/* pos 0241: 286 */ 0xE5 /* 'e' -> */, -/* pos 0242: 287 */ 0xBA /* ':' -> */, -/* pos 0243: 288 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 0245: 289 */ 0xEE /* 'n' -> */, -/* pos 0246: 290 */ 0xED /* 'm' -> */, -/* pos 0247: 291 */ 0xEF /* 'o' -> */, -/* pos 0248: 292 */ 0xE4 /* 'd' -> */, -/* pos 0249: 293 */ 0xE9 /* 'i' -> */, -/* pos 024a: 294 */ 0xE6 /* 'f' -> */, -/* pos 024b: 295 */ 0xE9 /* 'i' -> */, -/* pos 024c: 296 */ 0xE5 /* 'e' -> */, -/* pos 024d: 297 */ 0xE4 /* 'd' -> */, -/* pos 024e: 298 */ 0xAD /* '-' -> */, -/* pos 024f: 299 */ 0xF3 /* 's' -> */, -/* pos 0250: 300 */ 0xE9 /* 'i' -> */, -/* pos 0251: 301 */ 0xEE /* 'n' -> */, -/* pos 0252: 302 */ 0xE3 /* 'c' -> */, -/* pos 0253: 303 */ 0xE5 /* 'e' -> */, -/* pos 0254: 304 */ 0xBA /* ':' -> */, -/* pos 0255: 305 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 0257: 306 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0261 state 307) */, - 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x026F state 320) */, - 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0274 state 324) */, - 0x08, /* fail */ -/* pos 0261: 307 */ 0xF3 /* 's' -> */, -/* pos 0262: 308 */ 0xF4 /* 't' -> */, -/* pos 0263: 309 */ 0xAD /* '-' -> */, -/* pos 0264: 310 */ 0xED /* 'm' -> */, -/* pos 0265: 311 */ 0xEF /* 'o' -> */, -/* pos 0266: 312 */ 0xE4 /* 'd' -> */, -/* pos 0267: 313 */ 0xE9 /* 'i' -> */, -/* pos 0268: 314 */ 0xE6 /* 'f' -> */, -/* pos 0269: 315 */ 0xE9 /* 'i' -> */, -/* pos 026a: 316 */ 0xE5 /* 'e' -> */, -/* pos 026b: 317 */ 0xE4 /* 'd' -> */, -/* pos 026c: 318 */ 0xBA /* ':' -> */, -/* pos 026d: 319 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 026f: 320 */ 0xEE /* 'n' -> */, -/* pos 0270: 321 */ 0xEB /* 'k' -> */, -/* pos 0271: 322 */ 0xBA /* ':' -> */, -/* pos 0272: 323 */ 0x00, 0x2F /* - terminal marker 47 - */, -/* pos 0274: 324 */ 0xE3 /* 'c' -> */, -/* pos 0275: 325 */ 0xE1 /* 'a' -> */, -/* pos 0276: 326 */ 0xF4 /* 't' -> */, -/* pos 0277: 327 */ 0xE9 /* 'i' -> */, -/* pos 0278: 328 */ 0xEF /* 'o' -> */, -/* pos 0279: 329 */ 0xEE /* 'n' -> */, -/* pos 027a: 330 */ 0xBA /* ':' -> */, -/* pos 027b: 331 */ 0x00, 0x30 /* - terminal marker 48 - */, -/* pos 027d: 332 */ 0xE1 /* 'a' -> */, -/* pos 027e: 333 */ 0xF8 /* 'x' -> */, -/* pos 027f: 334 */ 0xAD /* '-' -> */, -/* pos 0280: 335 */ 0xE6 /* 'f' -> */, -/* pos 0281: 336 */ 0xEF /* 'o' -> */, -/* pos 0282: 337 */ 0xF2 /* 'r' -> */, -/* pos 0283: 338 */ 0xF7 /* 'w' -> */, -/* pos 0284: 339 */ 0xE1 /* 'a' -> */, -/* pos 0285: 340 */ 0xF2 /* 'r' -> */, -/* pos 0286: 341 */ 0xE4 /* 'd' -> */, -/* pos 0287: 342 */ 0xF3 /* 's' -> */, -/* pos 0288: 343 */ 0xBA /* ':' -> */, -/* pos 0289: 344 */ 0x00, 0x31 /* - terminal marker 49 - */, -/* pos 028b: 345 */ 0xF2 /* 'r' -> */, -/* pos 028c: 346 */ 0xF9 /* 'y' -> */, -/* pos 028d: 347 */ 0xAD /* '-' -> */, -/* pos 028e: 348 */ 0xE1 /* 'a' -> */, -/* pos 028f: 349 */ 0xE6 /* 'f' -> */, -/* pos 0290: 350 */ 0xF4 /* 't' -> */, -/* pos 0291: 351 */ 0xE5 /* 'e' -> */, -/* pos 0292: 352 */ 0xF2 /* 'r' -> */, -/* pos 0293: 353 */ 0xBA /* ':' -> */, -/* pos 0294: 354 */ 0x00, 0x35 /* - terminal marker 53 - */, -/* pos 0296: 355 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x029D state 356) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x02B7 state 371) */, - 0x08, /* fail */ -/* pos 029d: 356 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x02A7 state 357) */, - 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x02AD state 362) */, - 0x63 /* 'c' */, 0x86, 0x00 /* (to 0x0329 state 455) */, - 0x08, /* fail */ -/* pos 02a7: 357 */ 0xF6 /* 'v' -> */, -/* pos 02a8: 358 */ 0xE5 /* 'e' -> */, -/* pos 02a9: 359 */ 0xF2 /* 'r' -> */, -/* pos 02aa: 360 */ 0xBA /* ':' -> */, -/* pos 02ab: 361 */ 0x00, 0x36 /* - terminal marker 54 - */, -/* pos 02ad: 362 */ 0xAD /* '-' -> */, -/* pos 02ae: 363 */ 0xE3 /* 'c' -> */, -/* pos 02af: 364 */ 0xEF /* 'o' -> */, -/* pos 02b0: 365 */ 0xEF /* 'o' -> */, -/* pos 02b1: 366 */ 0xEB /* 'k' -> */, -/* pos 02b2: 367 */ 0xE9 /* 'i' -> */, -/* pos 02b3: 368 */ 0xE5 /* 'e' -> */, -/* pos 02b4: 369 */ 0xBA /* ':' -> */, -/* pos 02b5: 370 */ 0x00, 0x37 /* - terminal marker 55 - */, -/* pos 02b7: 371 */ 0xF2 /* 'r' -> */, -/* pos 02b8: 372 */ 0xE9 /* 'i' -> */, -/* pos 02b9: 373 */ 0xE3 /* 'c' -> */, -/* pos 02ba: 374 */ 0xF4 /* 't' -> */, -/* pos 02bb: 375 */ 0xAD /* '-' -> */, -/* pos 02bc: 376 */ 0xF4 /* 't' -> */, -/* pos 02bd: 377 */ 0xF2 /* 'r' -> */, -/* pos 02be: 378 */ 0xE1 /* 'a' -> */, -/* pos 02bf: 379 */ 0xEE /* 'n' -> */, -/* pos 02c0: 380 */ 0xF3 /* 's' -> */, -/* pos 02c1: 381 */ 0xF0 /* 'p' -> */, -/* pos 02c2: 382 */ 0xEF /* 'o' -> */, -/* pos 02c3: 383 */ 0xF2 /* 'r' -> */, -/* pos 02c4: 384 */ 0xF4 /* 't' -> */, -/* pos 02c5: 385 */ 0xAD /* '-' -> */, -/* pos 02c6: 386 */ 0xF3 /* 's' -> */, -/* pos 02c7: 387 */ 0xE5 /* 'e' -> */, -/* pos 02c8: 388 */ 0xE3 /* 'c' -> */, -/* pos 02c9: 389 */ 0xF5 /* 'u' -> */, -/* pos 02ca: 390 */ 0xF2 /* 'r' -> */, -/* pos 02cb: 391 */ 0xE9 /* 'i' -> */, -/* pos 02cc: 392 */ 0xF4 /* 't' -> */, -/* pos 02cd: 393 */ 0xF9 /* 'y' -> */, -/* pos 02ce: 394 */ 0xBA /* ':' -> */, -/* pos 02cf: 395 */ 0x00, 0x38 /* - terminal marker 56 - */, -/* pos 02d1: 396 */ 0xE5 /* 'e' -> */, -/* pos 02d2: 397 */ 0xF2 /* 'r' -> */, -/* pos 02d3: 398 */ 0xAD /* '-' -> */, -/* pos 02d4: 399 */ 0xE1 /* 'a' -> */, -/* pos 02d5: 400 */ 0xE7 /* 'g' -> */, -/* pos 02d6: 401 */ 0xE5 /* 'e' -> */, -/* pos 02d7: 402 */ 0xEE /* 'n' -> */, -/* pos 02d8: 403 */ 0xF4 /* 't' -> */, -/* pos 02d9: 404 */ 0xBA /* ':' -> */, -/* pos 02da: 405 */ 0x00, 0x3A /* - terminal marker 58 - */, -/* pos 02dc: 406 */ 0xF8 /* 'x' -> */, -/* pos 02dd: 407 */ 0xF9 /* 'y' -> */, -/* pos 02de: 408 */ 0x20 /* ' ' */, 0x07, 0x00 /* (to 0x02E5 state 409) */, - 0x2D /* '-' */, 0x86, 0x00 /* (to 0x0367 state 481) */, - 0x08, /* fail */ -/* pos 02e5: 409 */ 0x00, 0x42 /* - terminal marker 66 - */, -/* pos 02e7: 410 */ 0xAD /* '-' -> */, -/* pos 02e8: 411 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02F2 state 412) */, - 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x03D7 state 570) */, - 0x61 /* 'a' */, 0x9F, 0x01 /* (to 0x048D state 701) */, - 0x08, /* fail */ -/* pos 02f2: 412 */ 0xEF /* 'o' -> */, -/* pos 02f3: 413 */ 0xF2 /* 'r' -> */, -/* pos 02f4: 414 */ 0xF7 /* 'w' -> */, -/* pos 02f5: 415 */ 0xE1 /* 'a' -> */, -/* pos 02f6: 416 */ 0xF2 /* 'r' -> */, -/* pos 02f7: 417 */ 0xE4 /* 'd' -> */, -/* pos 02f8: 418 */ 0xE5 /* 'e' -> */, -/* pos 02f9: 419 */ 0xE4 /* 'd' -> */, -/* pos 02fa: 420 */ 0xAD /* '-' -> */, -/* pos 02fb: 421 */ 0xE6 /* 'f' -> */, -/* pos 02fc: 422 */ 0xEF /* 'o' -> */, -/* pos 02fd: 423 */ 0xF2 /* 'r' -> */, -/* pos 02fe: 424 */ 0xBA /* ':' -> */, -/* pos 02ff: 425 */ 0x00, 0x45 /* - terminal marker 69 - */, -/* pos 0301: 426 */ 0x00, 0x46 /* - terminal marker 70 - */, -/* pos 0303: 427 */ 0xE1 /* 'a' -> */, -/* pos 0304: 428 */ 0xE4 /* 'd' -> */, -/* pos 0305: 429 */ 0xA0 /* ' ' -> */, -/* pos 0306: 430 */ 0x00, 0x47 /* - terminal marker 71 - */, -/* pos 0308: 431 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x030F state 432) */, - 0x72 /* 'r' */, 0x82, 0x00 /* (to 0x038D state 510) */, - 0x08, /* fail */ -/* pos 030f: 432 */ 0xBA /* ':' -> */, -/* pos 0310: 433 */ 0x00, 0x48 /* - terminal marker 72 - */, -/* pos 0312: 434 */ 0xF4 /* 't' -> */, -/* pos 0313: 435 */ 0xE9 /* 'i' -> */, -/* pos 0314: 436 */ 0xEF /* 'o' -> */, -/* pos 0315: 437 */ 0xEE /* 'n' -> */, -/* pos 0316: 438 */ 0xF3 /* 's' -> */, -/* pos 0317: 439 */ 0xA0 /* ' ' -> */, -/* pos 0318: 440 */ 0x00, 0x02 /* - terminal marker 2 - */, -/* pos 031a: 441 */ 0xE4 /* 'd' -> */, -/* pos 031b: 442 */ 0xE9 /* 'i' -> */, -/* pos 031c: 443 */ 0xE6 /* 'f' -> */, -/* pos 031d: 444 */ 0xE9 /* 'i' -> */, -/* pos 031e: 445 */ 0xE5 /* 'e' -> */, -/* pos 031f: 446 */ 0xE4 /* 'd' -> */, -/* pos 0320: 447 */ 0xAD /* '-' -> */, -/* pos 0321: 448 */ 0xF3 /* 's' -> */, -/* pos 0322: 449 */ 0xE9 /* 'i' -> */, -/* pos 0323: 450 */ 0xEE /* 'n' -> */, -/* pos 0324: 451 */ 0xE3 /* 'c' -> */, -/* pos 0325: 452 */ 0xE5 /* 'e' -> */, -/* pos 0326: 453 */ 0xBA /* ':' -> */, -/* pos 0327: 454 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 0329: 455 */ 0xAD /* '-' -> */, -/* pos 032a: 456 */ 0xF7 /* 'w' -> */, -/* pos 032b: 457 */ 0xE5 /* 'e' -> */, -/* pos 032c: 458 */ 0xE2 /* 'b' -> */, -/* pos 032d: 459 */ 0xF3 /* 's' -> */, -/* pos 032e: 460 */ 0xEF /* 'o' -> */, -/* pos 032f: 461 */ 0xE3 /* 'c' -> */, -/* pos 0330: 462 */ 0xEB /* 'k' -> */, -/* pos 0331: 463 */ 0xE5 /* 'e' -> */, -/* pos 0332: 464 */ 0xF4 /* 't' -> */, -/* pos 0333: 465 */ 0xAD /* '-' -> */, -/* pos 0334: 466 */ 0x6B /* 'k' */, 0x19, 0x00 /* (to 0x034D state 467) */, - 0x64 /* 'd' */, 0xDD, 0x00 /* (to 0x0414 state 603) */, - 0x65 /* 'e' */, 0xE1, 0x00 /* (to 0x041B state 609) */, - 0x70 /* 'p' */, 0xF0, 0x00 /* (to 0x042D state 624) */, - 0x61 /* 'a' */, 0xF7, 0x00 /* (to 0x0437 state 633) */, - 0x6E /* 'n' */, 0xFC, 0x00 /* (to 0x043F state 640) */, - 0x76 /* 'v' */, 0x03, 0x01 /* (to 0x0449 state 648) */, - 0x6F /* 'o' */, 0x09, 0x01 /* (to 0x0452 state 656) */, - 0x08, /* fail */ -/* pos 034d: 467 */ 0xE5 /* 'e' -> */, -/* pos 034e: 468 */ 0xF9 /* 'y' -> */, -/* pos 034f: 469 */ 0x3A /* ':' */, 0x0A, 0x00 /* (to 0x0359 state 470) */, - 0x31 /* '1' */, 0xD5, 0x00 /* (to 0x0427 state 620) */, - 0x32 /* '2' */, 0xD5, 0x00 /* (to 0x042A state 622) */, - 0x08, /* fail */ -/* pos 0359: 470 */ 0x00, 0x18 /* - terminal marker 24 - */, -/* pos 035b: 471 */ 0xE1 /* 'a' -> */, -/* pos 035c: 472 */ 0xEE /* 'n' -> */, -/* pos 035d: 473 */ 0xE7 /* 'g' -> */, -/* pos 035e: 474 */ 0xE5 /* 'e' -> */, -/* pos 035f: 475 */ 0xF3 /* 's' -> */, -/* pos 0360: 476 */ 0xBA /* ':' -> */, -/* pos 0361: 477 */ 0x00, 0x1E /* - terminal marker 30 - */, -/* pos 0363: 478 */ 0xE5 /* 'e' -> */, -/* pos 0364: 479 */ 0xBA /* ':' -> */, -/* pos 0365: 480 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 0367: 481 */ 0xE1 /* 'a' -> */, -/* pos 0368: 482 */ 0xF5 /* 'u' -> */, -/* pos 0369: 483 */ 0xF4 /* 't' -> */, -/* pos 036a: 484 */ 0xE8 /* 'h' -> */, -/* pos 036b: 485 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0372 state 486) */, - 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x037C state 495) */, - 0x08, /* fail */ -/* pos 0372: 486 */ 0xEE /* 'n' -> */, -/* pos 0373: 487 */ 0xF4 /* 't' -> */, -/* pos 0374: 488 */ 0xE9 /* 'i' -> */, -/* pos 0375: 489 */ 0xE3 /* 'c' -> */, -/* pos 0376: 490 */ 0xE1 /* 'a' -> */, -/* pos 0377: 491 */ 0xF4 /* 't' -> */, -/* pos 0378: 492 */ 0xE5 /* 'e' -> */, -/* pos 0379: 493 */ 0xBA /* ':' -> */, -/* pos 037a: 494 */ 0x00, 0x32 /* - terminal marker 50 - */, -/* pos 037c: 495 */ 0xF2 /* 'r' -> */, -/* pos 037d: 496 */ 0xE9 /* 'i' -> */, -/* pos 037e: 497 */ 0xFA /* 'z' -> */, -/* pos 037f: 498 */ 0xE1 /* 'a' -> */, -/* pos 0380: 499 */ 0xF4 /* 't' -> */, -/* pos 0381: 500 */ 0xE9 /* 'i' -> */, -/* pos 0382: 501 */ 0xEF /* 'o' -> */, -/* pos 0383: 502 */ 0xEE /* 'n' -> */, -/* pos 0384: 503 */ 0xBA /* ':' -> */, -/* pos 0385: 504 */ 0x00, 0x33 /* - terminal marker 51 - */, -/* pos 0387: 505 */ 0xE5 /* 'e' -> */, -/* pos 0388: 506 */ 0xF3 /* 's' -> */, -/* pos 0389: 507 */ 0xE8 /* 'h' -> */, -/* pos 038a: 508 */ 0xBA /* ':' -> */, -/* pos 038b: 509 */ 0x00, 0x34 /* - terminal marker 52 - */, -/* pos 038d: 510 */ 0xE1 /* 'a' -> */, -/* pos 038e: 511 */ 0xEE /* 'n' -> */, -/* pos 038f: 512 */ 0xF3 /* 's' -> */, -/* pos 0390: 513 */ 0xE6 /* 'f' -> */, -/* pos 0391: 514 */ 0xE5 /* 'e' -> */, -/* pos 0392: 515 */ 0xF2 /* 'r' -> */, -/* pos 0393: 516 */ 0xAD /* '-' -> */, -/* pos 0394: 517 */ 0xE5 /* 'e' -> */, -/* pos 0395: 518 */ 0xEE /* 'n' -> */, -/* pos 0396: 519 */ 0xE3 /* 'c' -> */, -/* pos 0397: 520 */ 0xEF /* 'o' -> */, -/* pos 0398: 521 */ 0xE4 /* 'd' -> */, -/* pos 0399: 522 */ 0xE9 /* 'i' -> */, -/* pos 039a: 523 */ 0xEE /* 'n' -> */, -/* pos 039b: 524 */ 0xE7 /* 'g' -> */, -/* pos 039c: 525 */ 0xBA /* ':' -> */, -/* pos 039d: 526 */ 0x00, 0x39 /* - terminal marker 57 - */, -/* pos 039f: 527 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x03A6 state 528) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x03AB state 532) */, - 0x08, /* fail */ -/* pos 03a6: 528 */ 0xF2 /* 'r' -> */, -/* pos 03a7: 529 */ 0xF9 /* 'y' -> */, -/* pos 03a8: 530 */ 0xBA /* ':' -> */, -/* pos 03a9: 531 */ 0x00, 0x3B /* - terminal marker 59 - */, -/* pos 03ab: 532 */ 0xE1 /* 'a' -> */, -/* pos 03ac: 533 */ 0xBA /* ':' -> */, -/* pos 03ad: 534 */ 0x00, 0x3C /* - terminal marker 60 - */, -/* pos 03af: 535 */ 0xF7 /* 'w' -> */, -/* pos 03b0: 536 */ 0xF7 /* 'w' -> */, -/* pos 03b1: 537 */ 0xAD /* '-' -> */, -/* pos 03b2: 538 */ 0xE1 /* 'a' -> */, -/* pos 03b3: 539 */ 0xF5 /* 'u' -> */, -/* pos 03b4: 540 */ 0xF4 /* 't' -> */, -/* pos 03b5: 541 */ 0xE8 /* 'h' -> */, -/* pos 03b6: 542 */ 0xE5 /* 'e' -> */, -/* pos 03b7: 543 */ 0xEE /* 'n' -> */, -/* pos 03b8: 544 */ 0xF4 /* 't' -> */, -/* pos 03b9: 545 */ 0xE9 /* 'i' -> */, -/* pos 03ba: 546 */ 0xE3 /* 'c' -> */, -/* pos 03bb: 547 */ 0xE1 /* 'a' -> */, -/* pos 03bc: 548 */ 0xF4 /* 't' -> */, -/* pos 03bd: 549 */ 0xE5 /* 'e' -> */, -/* pos 03be: 550 */ 0xBA /* ':' -> */, -/* pos 03bf: 551 */ 0x00, 0x3D /* - terminal marker 61 - */, -/* pos 03c1: 552 */ 0xF4 /* 't' -> */, -/* pos 03c2: 553 */ 0xE3 /* 'c' -> */, -/* pos 03c3: 554 */ 0xE8 /* 'h' -> */, -/* pos 03c4: 555 */ 0x00, 0x3E /* - terminal marker 62 - */, -/* pos 03c6: 556 */ 0xF4 /* 't' -> */, -/* pos 03c7: 557 */ 0x00, 0x3F /* - terminal marker 63 - */, -/* pos 03c9: 558 */ 0xEC /* 'l' -> */, -/* pos 03ca: 559 */ 0xE5 /* 'e' -> */, -/* pos 03cb: 560 */ 0xF4 /* 't' -> */, -/* pos 03cc: 561 */ 0xE5 /* 'e' -> */, -/* pos 03cd: 562 */ 0x00, 0x40 /* - terminal marker 64 - */, -/* pos 03cf: 563 */ 0xE9 /* 'i' -> */, -/* pos 03d0: 564 */ 0xAD /* '-' -> */, -/* pos 03d1: 565 */ 0xE1 /* 'a' -> */, -/* pos 03d2: 566 */ 0xF2 /* 'r' -> */, -/* pos 03d3: 567 */ 0xE7 /* 'g' -> */, -/* pos 03d4: 568 */ 0xF3 /* 's' -> */, -/* pos 03d5: 569 */ 0x00, 0x41 /* - terminal marker 65 - */, -/* pos 03d7: 570 */ 0xE5 /* 'e' -> */, -/* pos 03d8: 571 */ 0xE1 /* 'a' -> */, -/* pos 03d9: 572 */ 0xEC /* 'l' -> */, -/* pos 03da: 573 */ 0xAD /* '-' -> */, -/* pos 03db: 574 */ 0xE9 /* 'i' -> */, -/* pos 03dc: 575 */ 0xF0 /* 'p' -> */, -/* pos 03dd: 576 */ 0xBA /* ':' -> */, -/* pos 03de: 577 */ 0x00, 0x43 /* - terminal marker 67 - */, -/* pos 03e0: 578 */ 0xB1 /* '1' -> */, -/* pos 03e1: 579 */ 0xAE /* '.' -> */, -/* pos 03e2: 580 */ 0x30 /* '0' */, 0x07, 0x00 /* (to 0x03E9 state 581) */, - 0x31 /* '1' */, 0x61, 0x00 /* (to 0x0446 state 646) */, - 0x08, /* fail */ -/* pos 03e9: 581 */ 0xA0 /* ' ' -> */, -/* pos 03ea: 582 */ 0x00, 0x44 /* - terminal marker 68 - */, -/* pos 03ec: 583 */ 0xEC /* 'l' -> */, -/* pos 03ed: 584 */ 0xE1 /* 'a' -> */, -/* pos 03ee: 585 */ 0xF9 /* 'y' -> */, -/* pos 03ef: 586 */ 0xAD /* '-' -> */, -/* pos 03f0: 587 */ 0xEE /* 'n' -> */, -/* pos 03f1: 588 */ 0xEF /* 'o' -> */, -/* pos 03f2: 589 */ 0xEE /* 'n' -> */, -/* pos 03f3: 590 */ 0xE3 /* 'c' -> */, -/* pos 03f4: 591 */ 0xE5 /* 'e' -> */, -/* pos 03f5: 592 */ 0xBA /* ':' -> */, -/* pos 03f6: 593 */ 0x00, 0x49 /* - terminal marker 73 - */, -/* pos 03f8: 594 */ 0x70 /* 'p' */, 0x0D, 0x00 /* (to 0x0405 state 595) */, - 0x61 /* 'a' */, 0x5F, 0x00 /* (to 0x045A state 663) */, - 0x6D /* 'm' */, 0x68, 0x00 /* (to 0x0466 state 673) */, - 0x73 /* 's' */, 0x70, 0x00 /* (to 0x0471 state 682) */, - 0x08, /* fail */ -/* pos 0405: 595 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x040C state 596) */, - 0x61 /* 'a' */, 0x65, 0x00 /* (to 0x046D state 679) */, - 0x08, /* fail */ -/* pos 040c: 596 */ 0xEF /* 'o' -> */, -/* pos 040d: 597 */ 0xF4 /* 't' -> */, -/* pos 040e: 598 */ 0xEF /* 'o' -> */, -/* pos 040f: 599 */ 0xE3 /* 'c' -> */, -/* pos 0410: 600 */ 0xEF /* 'o' -> */, -/* pos 0411: 601 */ 0xEC /* 'l' -> */, -/* pos 0412: 602 */ 0x00, 0x4A /* - terminal marker 74 - */, -/* pos 0414: 603 */ 0xF2 /* 'r' -> */, -/* pos 0415: 604 */ 0xE1 /* 'a' -> */, -/* pos 0416: 605 */ 0xE6 /* 'f' -> */, -/* pos 0417: 606 */ 0xF4 /* 't' -> */, -/* pos 0418: 607 */ 0xBA /* ':' -> */, -/* pos 0419: 608 */ 0x00, 0x07 /* - terminal marker 7 - */, -/* pos 041b: 609 */ 0xF8 /* 'x' -> */, -/* pos 041c: 610 */ 0xF4 /* 't' -> */, -/* pos 041d: 611 */ 0xE5 /* 'e' -> */, -/* pos 041e: 612 */ 0xEE /* 'n' -> */, -/* pos 041f: 613 */ 0xF3 /* 's' -> */, -/* pos 0420: 614 */ 0xE9 /* 'i' -> */, -/* pos 0421: 615 */ 0xEF /* 'o' -> */, -/* pos 0422: 616 */ 0xEE /* 'n' -> */, -/* pos 0423: 617 */ 0xF3 /* 's' -> */, -/* pos 0424: 618 */ 0xBA /* ':' -> */, -/* pos 0425: 619 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 0427: 620 */ 0xBA /* ':' -> */, -/* pos 0428: 621 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 042a: 622 */ 0xBA /* ':' -> */, -/* pos 042b: 623 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 042d: 624 */ 0xF2 /* 'r' -> */, -/* pos 042e: 625 */ 0xEF /* 'o' -> */, -/* pos 042f: 626 */ 0xF4 /* 't' -> */, -/* pos 0430: 627 */ 0xEF /* 'o' -> */, -/* pos 0431: 628 */ 0xE3 /* 'c' -> */, -/* pos 0432: 629 */ 0xEF /* 'o' -> */, -/* pos 0433: 630 */ 0xEC /* 'l' -> */, -/* pos 0434: 631 */ 0xBA /* ':' -> */, -/* pos 0435: 632 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 0437: 633 */ 0xE3 /* 'c' -> */, -/* pos 0438: 634 */ 0xE3 /* 'c' -> */, -/* pos 0439: 635 */ 0xE5 /* 'e' -> */, -/* pos 043a: 636 */ 0xF0 /* 'p' -> */, -/* pos 043b: 637 */ 0xF4 /* 't' -> */, -/* pos 043c: 638 */ 0xBA /* ':' -> */, -/* pos 043d: 639 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 043f: 640 */ 0xEF /* 'o' -> */, -/* pos 0440: 641 */ 0xEE /* 'n' -> */, -/* pos 0441: 642 */ 0xE3 /* 'c' -> */, -/* pos 0442: 643 */ 0xE5 /* 'e' -> */, -/* pos 0443: 644 */ 0xBA /* ':' -> */, -/* pos 0444: 645 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 0446: 646 */ 0xA0 /* ' ' -> */, -/* pos 0447: 647 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 0449: 648 */ 0xE5 /* 'e' -> */, -/* pos 044a: 649 */ 0xF2 /* 'r' -> */, -/* pos 044b: 650 */ 0xF3 /* 's' -> */, -/* pos 044c: 651 */ 0xE9 /* 'i' -> */, -/* pos 044d: 652 */ 0xEF /* 'o' -> */, -/* pos 044e: 653 */ 0xEE /* 'n' -> */, -/* pos 044f: 654 */ 0xBA /* ':' -> */, -/* pos 0450: 655 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 0452: 656 */ 0xF2 /* 'r' -> */, -/* pos 0453: 657 */ 0xE9 /* 'i' -> */, -/* pos 0454: 658 */ 0xE7 /* 'g' -> */, -/* pos 0455: 659 */ 0xE9 /* 'i' -> */, -/* pos 0456: 660 */ 0xEE /* 'n' -> */, -/* pos 0457: 661 */ 0xBA /* ':' -> */, -/* pos 0458: 662 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 045a: 663 */ 0xF5 /* 'u' -> */, -/* pos 045b: 664 */ 0xF4 /* 't' -> */, -/* pos 045c: 665 */ 0xE8 /* 'h' -> */, -/* pos 045d: 666 */ 0xEF /* 'o' -> */, -/* pos 045e: 667 */ 0xF2 /* 'r' -> */, -/* pos 045f: 668 */ 0xE9 /* 'i' -> */, -/* pos 0460: 669 */ 0xF4 /* 't' -> */, -/* pos 0461: 670 */ 0xF9 /* 'y' -> */, -/* pos 0462: 671 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* pos 0464: 672 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 0466: 673 */ 0xE5 /* 'e' -> */, -/* pos 0467: 674 */ 0xF4 /* 't' -> */, -/* pos 0468: 675 */ 0xE8 /* 'h' -> */, -/* pos 0469: 676 */ 0xEF /* 'o' -> */, -/* pos 046a: 677 */ 0xE4 /* 'd' -> */, -/* pos 046b: 678 */ 0x00, 0x19 /* - terminal marker 25 - */, -/* pos 046d: 679 */ 0xF4 /* 't' -> */, -/* pos 046e: 680 */ 0xE8 /* 'h' -> */, -/* pos 046f: 681 */ 0x00, 0x1A /* - terminal marker 26 - */, -/* pos 0471: 682 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x0478 state 683) */, - 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x047E state 688) */, - 0x08, /* fail */ -/* pos 0478: 683 */ 0xE8 /* 'h' -> */, -/* pos 0479: 684 */ 0xE5 /* 'e' -> */, -/* pos 047a: 685 */ 0xED /* 'm' -> */, -/* pos 047b: 686 */ 0xE5 /* 'e' -> */, -/* pos 047c: 687 */ 0x00, 0x1B /* - terminal marker 27 - */, -/* pos 047e: 688 */ 0xE1 /* 'a' -> */, -/* pos 047f: 689 */ 0xF4 /* 't' -> */, -/* pos 0480: 690 */ 0xF5 /* 'u' -> */, -/* pos 0481: 691 */ 0xF3 /* 's' -> */, -/* pos 0482: 692 */ 0x00, 0x1C /* - terminal marker 28 - */, -/* pos 0484: 693 */ 0xE8 /* 'h' -> */, -/* pos 0485: 694 */ 0xE1 /* 'a' -> */, -/* pos 0486: 695 */ 0xF2 /* 'r' -> */, -/* pos 0487: 696 */ 0xF3 /* 's' -> */, -/* pos 0488: 697 */ 0xE5 /* 'e' -> */, -/* pos 0489: 698 */ 0xF4 /* 't' -> */, -/* pos 048a: 699 */ 0xBA /* ':' -> */, -/* pos 048b: 700 */ 0x00, 0x1D /* - terminal marker 29 - */, -/* pos 048d: 701 */ 0xF5 /* 'u' -> */, -/* pos 048e: 702 */ 0xF4 /* 't' -> */, -/* pos 048f: 703 */ 0xE8 /* 'h' -> */, -/* pos 0490: 704 */ 0xAD /* '-' -> */, -/* pos 0491: 705 */ 0xF4 /* 't' -> */, -/* pos 0492: 706 */ 0xEF /* 'o' -> */, -/* pos 0493: 707 */ 0xEB /* 'k' -> */, -/* pos 0494: 708 */ 0xE5 /* 'e' -> */, -/* pos 0495: 709 */ 0xEE /* 'n' -> */, -/* pos 0496: 710 */ 0xBA /* ':' -> */, +/* pos 00af: 45 */ 0x2F /* '/' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, + 0x32 /* '2' */, 0x97, 0x03 /* (to 0x0449 state 663) */, + 0x08, /* fail */ +/* pos 00b6: 46 */ 0xB1 /* '1' -> */, +/* pos 00b7: 47 */ 0xAE /* '.' -> */, +/* pos 00b8: 48 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x00BF state 49) */, + 0x30 /* '0' */, 0xFC, 0x01 /* (to 0x02B7 state 362) */, + 0x08, /* fail */ +/* pos 00bf: 49 */ 0xA0 /* ' ' -> */, +/* pos 00c0: 50 */ 0x00, 0x08 /* - terminal marker 8 - */, +/* pos 00c2: 51 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 52) */, + 0x75 /* 'u' */, 0x8A, 0x00 /* (to 0x014F state 125) */, + 0x67 /* 'g' */, 0xE7, 0x00 /* (to 0x01AF state 178) */, + 0x6C /* 'l' */, 0xE8, 0x00 /* (to 0x01B3 state 181) */, + 0x08, /* fail */ +/* pos 00cf: 52 */ 0xE3 /* 'c' -> */, +/* pos 00d0: 53 */ 0xE5 /* 'e' -> */, +/* pos 00d1: 54 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x00D8 state 55) */, + 0x73 /* 's' */, 0x1B, 0x02 /* (to 0x02EF state 403) */, + 0x08, /* fail */ +/* pos 00d8: 55 */ 0xF4 /* 't' -> */, +/* pos 00d9: 56 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x00E0 state 57) */, + 0x2D /* '-' */, 0x37, 0x00 /* (to 0x0113 state 87) */, + 0x08, /* fail */ +/* pos 00e0: 57 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 00e2: 58 */ 0xE6 /* 'f' -> */, +/* pos 00e3: 59 */ 0xAD /* '-' -> */, +/* pos 00e4: 60 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x00F1 state 61) */, + 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x0107 state 76) */, + 0x72 /* 'r' */, 0x2A, 0x01 /* (to 0x0214 state 255) */, + 0x75 /* 'u' */, 0x2E, 0x01 /* (to 0x021B state 261) */, + 0x08, /* fail */ +/* pos 00f1: 61 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x00F8 state 62) */, + 0x61 /* 'a' */, 0x1A, 0x01 /* (to 0x020E state 250) */, + 0x08, /* fail */ +/* pos 00f8: 62 */ 0xE4 /* 'd' -> */, +/* pos 00f9: 63 */ 0xE9 /* 'i' -> */, +/* pos 00fa: 64 */ 0xE6 /* 'f' -> */, +/* pos 00fb: 65 */ 0xE9 /* 'i' -> */, +/* pos 00fc: 66 */ 0xE5 /* 'e' -> */, +/* pos 00fd: 67 */ 0xE4 /* 'd' -> */, +/* pos 00fe: 68 */ 0xAD /* '-' -> */, +/* pos 00ff: 69 */ 0xF3 /* 's' -> */, +/* pos 0100: 70 */ 0xE9 /* 'i' -> */, +/* pos 0101: 71 */ 0xEE /* 'n' -> */, +/* pos 0102: 72 */ 0xE3 /* 'c' -> */, +/* pos 0103: 73 */ 0xE5 /* 'e' -> */, +/* pos 0104: 74 */ 0xBA /* ':' -> */, +/* pos 0105: 75 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 0107: 76 */ 0xEF /* 'o' -> */, +/* pos 0108: 77 */ 0xEE /* 'n' -> */, +/* pos 0109: 78 */ 0xE5 /* 'e' -> */, +/* pos 010a: 79 */ 0xAD /* '-' -> */, +/* pos 010b: 80 */ 0xED /* 'm' -> */, +/* pos 010c: 81 */ 0xE1 /* 'a' -> */, +/* pos 010d: 82 */ 0xF4 /* 't' -> */, +/* pos 010e: 83 */ 0xE3 /* 'c' -> */, +/* pos 010f: 84 */ 0xE8 /* 'h' -> */, +/* pos 0110: 85 */ 0xBA /* ':' -> */, +/* pos 0111: 86 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 0113: 87 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x0120 state 88) */, + 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x012A state 97) */, + 0x72 /* 'r' */, 0x8E, 0x00 /* (to 0x01A7 state 171) */, + 0x63 /* 'c' */, 0xFB, 0x01 /* (to 0x0317 state 435) */, + 0x08, /* fail */ +/* pos 0120: 88 */ 0xEE /* 'n' -> */, +/* pos 0121: 89 */ 0xE3 /* 'c' -> */, +/* pos 0122: 90 */ 0xEF /* 'o' -> */, +/* pos 0123: 91 */ 0xE4 /* 'd' -> */, +/* pos 0124: 92 */ 0xE9 /* 'i' -> */, +/* pos 0125: 93 */ 0xEE /* 'n' -> */, +/* pos 0126: 94 */ 0xE7 /* 'g' -> */, +/* pos 0127: 95 */ 0xBA /* ':' -> */, +/* pos 0128: 96 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 012a: 97 */ 0xE1 /* 'a' -> */, +/* pos 012b: 98 */ 0xEE /* 'n' -> */, +/* pos 012c: 99 */ 0xE7 /* 'g' -> */, +/* pos 012d: 100 */ 0xF5 /* 'u' -> */, +/* pos 012e: 101 */ 0xE1 /* 'a' -> */, +/* pos 012f: 102 */ 0xE7 /* 'g' -> */, +/* pos 0130: 103 */ 0xE5 /* 'e' -> */, +/* pos 0131: 104 */ 0xBA /* ':' -> */, +/* pos 0132: 105 */ 0x00, 0x0F /* - terminal marker 15 - */, +/* pos 0134: 106 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x013B state 107) */, + 0x6F /* 'o' */, 0x05, 0x02 /* (to 0x033C state 469) */, + 0x08, /* fail */ +/* pos 013b: 107 */ 0xE7 /* 'g' -> */, +/* pos 013c: 108 */ 0xED /* 'm' -> */, +/* pos 013d: 109 */ 0xE1 /* 'a' -> */, +/* pos 013e: 110 */ 0xBA /* ':' -> */, +/* pos 013f: 111 */ 0x00, 0x10 /* - terminal marker 16 - */, +/* pos 0141: 112 */ 0xE3 /* 'c' -> */, +/* pos 0142: 113 */ 0xE8 /* 'h' -> */, +/* pos 0143: 114 */ 0xE5 /* 'e' -> */, +/* pos 0144: 115 */ 0xAD /* '-' -> */, +/* pos 0145: 116 */ 0xE3 /* 'c' -> */, +/* pos 0146: 117 */ 0xEF /* 'o' -> */, +/* pos 0147: 118 */ 0xEE /* 'n' -> */, +/* pos 0148: 119 */ 0xF4 /* 't' -> */, +/* pos 0149: 120 */ 0xF2 /* 'r' -> */, +/* pos 014a: 121 */ 0xEF /* 'o' -> */, +/* pos 014b: 122 */ 0xEC /* 'l' -> */, +/* pos 014c: 123 */ 0xBA /* ':' -> */, +/* pos 014d: 124 */ 0x00, 0x11 /* - terminal marker 17 - */, +/* pos 014f: 125 */ 0xF4 /* 't' -> */, +/* pos 0150: 126 */ 0xE8 /* 'h' -> */, +/* pos 0151: 127 */ 0xEF /* 'o' -> */, +/* pos 0152: 128 */ 0xF2 /* 'r' -> */, +/* pos 0153: 129 */ 0xE9 /* 'i' -> */, +/* pos 0154: 130 */ 0xFA /* 'z' -> */, +/* pos 0155: 131 */ 0xE1 /* 'a' -> */, +/* pos 0156: 132 */ 0xF4 /* 't' -> */, +/* pos 0157: 133 */ 0xE9 /* 'i' -> */, +/* pos 0158: 134 */ 0xEF /* 'o' -> */, +/* pos 0159: 135 */ 0xEE /* 'n' -> */, +/* pos 015a: 136 */ 0xBA /* ':' -> */, +/* pos 015b: 137 */ 0x00, 0x12 /* - terminal marker 18 - */, +/* pos 015d: 138 */ 0xEB /* 'k' -> */, +/* pos 015e: 139 */ 0xE9 /* 'i' -> */, +/* pos 015f: 140 */ 0xE5 /* 'e' -> */, +/* pos 0160: 141 */ 0xBA /* ':' -> */, +/* pos 0161: 142 */ 0x00, 0x13 /* - terminal marker 19 - */, +/* pos 0163: 143 */ 0xE5 /* 'e' -> */, +/* pos 0164: 144 */ 0xEE /* 'n' -> */, +/* pos 0165: 145 */ 0xF4 /* 't' -> */, +/* pos 0166: 146 */ 0xAD /* '-' -> */, +/* pos 0167: 147 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0177 state 148) */, + 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0188 state 155) */, + 0x64 /* 'd' */, 0x4C, 0x00 /* (to 0x01B9 state 186) */, + 0x65 /* 'e' */, 0x56, 0x00 /* (to 0x01C6 state 198) */, + 0x72 /* 'r' */, 0x6F, 0x00 /* (to 0x01E2 state 223) */, + 0x08, /* fail */ +/* pos 0177: 148 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0181 state 149) */, + 0x61 /* 'a' */, 0x56, 0x00 /* (to 0x01D0 state 207) */, + 0x6F /* 'o' */, 0x5C, 0x00 /* (to 0x01D9 state 215) */, + 0x08, /* fail */ +/* pos 0181: 149 */ 0xEE /* 'n' -> */, +/* pos 0182: 150 */ 0xE7 /* 'g' -> */, +/* pos 0183: 151 */ 0xF4 /* 't' -> */, +/* pos 0184: 152 */ 0xE8 /* 'h' -> */, +/* pos 0185: 153 */ 0xBA /* ':' -> */, +/* pos 0186: 154 */ 0x00, 0x14 /* - terminal marker 20 - */, +/* pos 0188: 155 */ 0xF9 /* 'y' -> */, +/* pos 0189: 156 */ 0xF0 /* 'p' -> */, +/* pos 018a: 157 */ 0xE5 /* 'e' -> */, +/* pos 018b: 158 */ 0xBA /* ':' -> */, +/* pos 018c: 159 */ 0x00, 0x15 /* - terminal marker 21 - */, +/* pos 018e: 160 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0195 state 161) */, + 0x65 /* 'e' */, 0x23, 0x02 /* (to 0x03B4 state 562) */, + 0x08, /* fail */ +/* pos 0195: 161 */ 0xF4 /* 't' -> */, +/* pos 0196: 162 */ 0xE5 /* 'e' -> */, +/* pos 0197: 163 */ 0xBA /* ':' -> */, +/* pos 0198: 164 */ 0x00, 0x16 /* - terminal marker 22 - */, +/* pos 019a: 165 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01A1 state 166) */, + 0x65 /* 'e' */, 0xB6, 0x00 /* (to 0x0253 state 304) */, + 0x08, /* fail */ +/* pos 01a1: 166 */ 0xEE /* 'n' -> */, +/* pos 01a2: 167 */ 0xE7 /* 'g' -> */, +/* pos 01a3: 168 */ 0xE5 /* 'e' -> */, +/* pos 01a4: 169 */ 0xBA /* ':' -> */, +/* pos 01a5: 170 */ 0x00, 0x17 /* - terminal marker 23 - */, +/* pos 01a7: 171 */ 0xE1 /* 'a' -> */, +/* pos 01a8: 172 */ 0xEE /* 'n' -> */, +/* pos 01a9: 173 */ 0xE7 /* 'g' -> */, +/* pos 01aa: 174 */ 0xE5 /* 'e' -> */, +/* pos 01ab: 175 */ 0xF3 /* 's' -> */, +/* pos 01ac: 176 */ 0xBA /* ':' -> */, +/* pos 01ad: 177 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 01af: 178 */ 0xE5 /* 'e' -> */, +/* pos 01b0: 179 */ 0xBA /* ':' -> */, +/* pos 01b1: 180 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* pos 01b3: 181 */ 0xEC /* 'l' -> */, +/* pos 01b4: 182 */ 0xEF /* 'o' -> */, +/* pos 01b5: 183 */ 0xF7 /* 'w' -> */, +/* pos 01b6: 184 */ 0xBA /* ':' -> */, +/* pos 01b7: 185 */ 0x00, 0x22 /* - terminal marker 34 - */, +/* pos 01b9: 186 */ 0xE9 /* 'i' -> */, +/* pos 01ba: 187 */ 0xF3 /* 's' -> */, +/* pos 01bb: 188 */ 0xF0 /* 'p' -> */, +/* pos 01bc: 189 */ 0xEF /* 'o' -> */, +/* pos 01bd: 190 */ 0xF3 /* 's' -> */, +/* pos 01be: 191 */ 0xE9 /* 'i' -> */, +/* pos 01bf: 192 */ 0xF4 /* 't' -> */, +/* pos 01c0: 193 */ 0xE9 /* 'i' -> */, +/* pos 01c1: 194 */ 0xEF /* 'o' -> */, +/* pos 01c2: 195 */ 0xEE /* 'n' -> */, +/* pos 01c3: 196 */ 0xBA /* ':' -> */, +/* pos 01c4: 197 */ 0x00, 0x23 /* - terminal marker 35 - */, +/* pos 01c6: 198 */ 0xEE /* 'n' -> */, +/* pos 01c7: 199 */ 0xE3 /* 'c' -> */, +/* pos 01c8: 200 */ 0xEF /* 'o' -> */, +/* pos 01c9: 201 */ 0xE4 /* 'd' -> */, +/* pos 01ca: 202 */ 0xE9 /* 'i' -> */, +/* pos 01cb: 203 */ 0xEE /* 'n' -> */, +/* pos 01cc: 204 */ 0xE7 /* 'g' -> */, +/* pos 01cd: 205 */ 0xBA /* ':' -> */, +/* pos 01ce: 206 */ 0x00, 0x24 /* - terminal marker 36 - */, +/* pos 01d0: 207 */ 0xEE /* 'n' -> */, +/* pos 01d1: 208 */ 0xE7 /* 'g' -> */, +/* pos 01d2: 209 */ 0xF5 /* 'u' -> */, +/* pos 01d3: 210 */ 0xE1 /* 'a' -> */, +/* pos 01d4: 211 */ 0xE7 /* 'g' -> */, +/* pos 01d5: 212 */ 0xE5 /* 'e' -> */, +/* pos 01d6: 213 */ 0xBA /* ':' -> */, +/* pos 01d7: 214 */ 0x00, 0x25 /* - terminal marker 37 - */, +/* pos 01d9: 215 */ 0xE3 /* 'c' -> */, +/* pos 01da: 216 */ 0xE1 /* 'a' -> */, +/* pos 01db: 217 */ 0xF4 /* 't' -> */, +/* pos 01dc: 218 */ 0xE9 /* 'i' -> */, +/* pos 01dd: 219 */ 0xEF /* 'o' -> */, +/* pos 01de: 220 */ 0xEE /* 'n' -> */, +/* pos 01df: 221 */ 0xBA /* ':' -> */, +/* pos 01e0: 222 */ 0x00, 0x26 /* - terminal marker 38 - */, +/* pos 01e2: 223 */ 0xE1 /* 'a' -> */, +/* pos 01e3: 224 */ 0xEE /* 'n' -> */, +/* pos 01e4: 225 */ 0xE7 /* 'g' -> */, +/* pos 01e5: 226 */ 0xE5 /* 'e' -> */, +/* pos 01e6: 227 */ 0xBA /* ':' -> */, +/* pos 01e7: 228 */ 0x00, 0x27 /* - terminal marker 39 - */, +/* pos 01e9: 229 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x01F0 state 230) */, + 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x01F5 state 234) */, + 0x08, /* fail */ +/* pos 01f0: 230 */ 0xE1 /* 'a' -> */, +/* pos 01f1: 231 */ 0xE7 /* 'g' -> */, +/* pos 01f2: 232 */ 0xBA /* ':' -> */, +/* pos 01f3: 233 */ 0x00, 0x28 /* - terminal marker 40 - */, +/* pos 01f5: 234 */ 0xF0 /* 'p' -> */, +/* pos 01f6: 235 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01FD state 236) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0202 state 240) */, + 0x08, /* fail */ +/* pos 01fd: 236 */ 0xE3 /* 'c' -> */, +/* pos 01fe: 237 */ 0xF4 /* 't' -> */, +/* pos 01ff: 238 */ 0xBA /* ':' -> */, +/* pos 0200: 239 */ 0x00, 0x29 /* - terminal marker 41 - */, +/* pos 0202: 240 */ 0xF2 /* 'r' -> */, +/* pos 0203: 241 */ 0xE5 /* 'e' -> */, +/* pos 0204: 242 */ 0xF3 /* 's' -> */, +/* pos 0205: 243 */ 0xBA /* ':' -> */, +/* pos 0206: 244 */ 0x00, 0x2A /* - terminal marker 42 - */, +/* pos 0208: 245 */ 0xF2 /* 'r' -> */, +/* pos 0209: 246 */ 0xEF /* 'o' -> */, +/* pos 020a: 247 */ 0xED /* 'm' -> */, +/* pos 020b: 248 */ 0xBA /* ':' -> */, +/* pos 020c: 249 */ 0x00, 0x2B /* - terminal marker 43 - */, +/* pos 020e: 250 */ 0xF4 /* 't' -> */, +/* pos 020f: 251 */ 0xE3 /* 'c' -> */, +/* pos 0210: 252 */ 0xE8 /* 'h' -> */, +/* pos 0211: 253 */ 0xBA /* ':' -> */, +/* pos 0212: 254 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 0214: 255 */ 0xE1 /* 'a' -> */, +/* pos 0215: 256 */ 0xEE /* 'n' -> */, +/* pos 0216: 257 */ 0xE7 /* 'g' -> */, +/* pos 0217: 258 */ 0xE5 /* 'e' -> */, +/* pos 0218: 259 */ 0xBA /* ':' -> */, +/* pos 0219: 260 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 021b: 261 */ 0xEE /* 'n' -> */, +/* pos 021c: 262 */ 0xED /* 'm' -> */, +/* pos 021d: 263 */ 0xEF /* 'o' -> */, +/* pos 021e: 264 */ 0xE4 /* 'd' -> */, +/* pos 021f: 265 */ 0xE9 /* 'i' -> */, +/* pos 0220: 266 */ 0xE6 /* 'f' -> */, +/* pos 0221: 267 */ 0xE9 /* 'i' -> */, +/* pos 0222: 268 */ 0xE5 /* 'e' -> */, +/* pos 0223: 269 */ 0xE4 /* 'd' -> */, +/* pos 0224: 270 */ 0xAD /* '-' -> */, +/* pos 0225: 271 */ 0xF3 /* 's' -> */, +/* pos 0226: 272 */ 0xE9 /* 'i' -> */, +/* pos 0227: 273 */ 0xEE /* 'n' -> */, +/* pos 0228: 274 */ 0xE3 /* 'c' -> */, +/* pos 0229: 275 */ 0xE5 /* 'e' -> */, +/* pos 022a: 276 */ 0xBA /* ':' -> */, +/* pos 022b: 277 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 022d: 278 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0237 state 279) */, + 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x0245 state 292) */, + 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x024A state 296) */, + 0x08, /* fail */ +/* pos 0237: 279 */ 0xF3 /* 's' -> */, +/* pos 0238: 280 */ 0xF4 /* 't' -> */, +/* pos 0239: 281 */ 0xAD /* '-' -> */, +/* pos 023a: 282 */ 0xED /* 'm' -> */, +/* pos 023b: 283 */ 0xEF /* 'o' -> */, +/* pos 023c: 284 */ 0xE4 /* 'd' -> */, +/* pos 023d: 285 */ 0xE9 /* 'i' -> */, +/* pos 023e: 286 */ 0xE6 /* 'f' -> */, +/* pos 023f: 287 */ 0xE9 /* 'i' -> */, +/* pos 0240: 288 */ 0xE5 /* 'e' -> */, +/* pos 0241: 289 */ 0xE4 /* 'd' -> */, +/* pos 0242: 290 */ 0xBA /* ':' -> */, +/* pos 0243: 291 */ 0x00, 0x2F /* - terminal marker 47 - */, +/* pos 0245: 292 */ 0xEE /* 'n' -> */, +/* pos 0246: 293 */ 0xEB /* 'k' -> */, +/* pos 0247: 294 */ 0xBA /* ':' -> */, +/* pos 0248: 295 */ 0x00, 0x30 /* - terminal marker 48 - */, +/* pos 024a: 296 */ 0xE3 /* 'c' -> */, +/* pos 024b: 297 */ 0xE1 /* 'a' -> */, +/* pos 024c: 298 */ 0xF4 /* 't' -> */, +/* pos 024d: 299 */ 0xE9 /* 'i' -> */, +/* pos 024e: 300 */ 0xEF /* 'o' -> */, +/* pos 024f: 301 */ 0xEE /* 'n' -> */, +/* pos 0250: 302 */ 0xBA /* ':' -> */, +/* pos 0251: 303 */ 0x00, 0x31 /* - terminal marker 49 - */, +/* pos 0253: 304 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x025D state 305) */, + 0x74 /* 't' */, 0x14, 0x00 /* (to 0x026A state 311) */, + 0x70 /* 'p' */, 0x6F, 0x01 /* (to 0x03C8 state 578) */, + 0x08, /* fail */ +/* pos 025d: 305 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0264 state 306) */, + 0x65 /* 'e' */, 0xB1, 0x00 /* (to 0x0311 state 430) */, + 0x08, /* fail */ +/* pos 0264: 306 */ 0xE5 /* 'e' -> */, +/* pos 0265: 307 */ 0xF3 /* 's' -> */, +/* pos 0266: 308 */ 0xE8 /* 'h' -> */, +/* pos 0267: 309 */ 0xBA /* ':' -> */, +/* pos 0268: 310 */ 0x00, 0x35 /* - terminal marker 53 - */, +/* pos 026a: 311 */ 0xF2 /* 'r' -> */, +/* pos 026b: 312 */ 0xF9 /* 'y' -> */, +/* pos 026c: 313 */ 0xAD /* '-' -> */, +/* pos 026d: 314 */ 0xE1 /* 'a' -> */, +/* pos 026e: 315 */ 0xE6 /* 'f' -> */, +/* pos 026f: 316 */ 0xF4 /* 't' -> */, +/* pos 0270: 317 */ 0xE5 /* 'e' -> */, +/* pos 0271: 318 */ 0xF2 /* 'r' -> */, +/* pos 0272: 319 */ 0xBA /* ':' -> */, +/* pos 0273: 320 */ 0x00, 0x36 /* - terminal marker 54 - */, +/* pos 0275: 321 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x027C state 322) */, + 0x74 /* 't' */, 0xED, 0x00 /* (to 0x0365 state 496) */, + 0x08, /* fail */ +/* pos 027c: 322 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x0286 state 323) */, + 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x028C state 328) */, + 0x63 /* 'c' */, 0x52, 0x01 /* (to 0x03D4 state 589) */, + 0x08, /* fail */ +/* pos 0286: 323 */ 0xF6 /* 'v' -> */, +/* pos 0287: 324 */ 0xE5 /* 'e' -> */, +/* pos 0288: 325 */ 0xF2 /* 'r' -> */, +/* pos 0289: 326 */ 0xBA /* ':' -> */, +/* pos 028a: 327 */ 0x00, 0x37 /* - terminal marker 55 - */, +/* pos 028c: 328 */ 0xAD /* '-' -> */, +/* pos 028d: 329 */ 0xE3 /* 'c' -> */, +/* pos 028e: 330 */ 0xEF /* 'o' -> */, +/* pos 028f: 331 */ 0xEF /* 'o' -> */, +/* pos 0290: 332 */ 0xEB /* 'k' -> */, +/* pos 0291: 333 */ 0xE9 /* 'i' -> */, +/* pos 0292: 334 */ 0xE5 /* 'e' -> */, +/* pos 0293: 335 */ 0xBA /* ':' -> */, +/* pos 0294: 336 */ 0x00, 0x38 /* - terminal marker 56 - */, +/* pos 0296: 337 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x029D state 338) */, + 0x65 /* 'e' */, 0x2C, 0x01 /* (to 0x03C5 state 576) */, + 0x08, /* fail */ +/* pos 029d: 338 */ 0xE1 /* 'a' -> */, +/* pos 029e: 339 */ 0xEE /* 'n' -> */, +/* pos 029f: 340 */ 0xF3 /* 's' -> */, +/* pos 02a0: 341 */ 0xE6 /* 'f' -> */, +/* pos 02a1: 342 */ 0xE5 /* 'e' -> */, +/* pos 02a2: 343 */ 0xF2 /* 'r' -> */, +/* pos 02a3: 344 */ 0xAD /* '-' -> */, +/* pos 02a4: 345 */ 0xE5 /* 'e' -> */, +/* pos 02a5: 346 */ 0xEE /* 'n' -> */, +/* pos 02a6: 347 */ 0xE3 /* 'c' -> */, +/* pos 02a7: 348 */ 0xEF /* 'o' -> */, +/* pos 02a8: 349 */ 0xE4 /* 'd' -> */, +/* pos 02a9: 350 */ 0xE9 /* 'i' -> */, +/* pos 02aa: 351 */ 0xEE /* 'n' -> */, +/* pos 02ab: 352 */ 0xE7 /* 'g' -> */, +/* pos 02ac: 353 */ 0xBA /* ':' -> */, +/* pos 02ad: 354 */ 0x00, 0x3A /* - terminal marker 58 - */, +/* pos 02af: 355 */ 0xE9 /* 'i' -> */, +/* pos 02b0: 356 */ 0xAD /* '-' -> */, +/* pos 02b1: 357 */ 0xE1 /* 'a' -> */, +/* pos 02b2: 358 */ 0xF2 /* 'r' -> */, +/* pos 02b3: 359 */ 0xE7 /* 'g' -> */, +/* pos 02b4: 360 */ 0xF3 /* 's' -> */, +/* pos 02b5: 361 */ 0x00, 0x42 /* - terminal marker 66 - */, +/* pos 02b7: 362 */ 0xA0 /* ' ' -> */, +/* pos 02b8: 363 */ 0x00, 0x45 /* - terminal marker 69 - */, +/* pos 02ba: 364 */ 0xAD /* '-' -> */, +/* pos 02bb: 365 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02C5 state 366) */, + 0x61 /* 'a' */, 0x1D, 0x00 /* (to 0x02DB state 385) */, + 0x72 /* 'r' */, 0xFB, 0x00 /* (to 0x03BC state 568) */, + 0x08, /* fail */ +/* pos 02c5: 366 */ 0xEF /* 'o' -> */, +/* pos 02c6: 367 */ 0xF2 /* 'r' -> */, +/* pos 02c7: 368 */ 0xF7 /* 'w' -> */, +/* pos 02c8: 369 */ 0xE1 /* 'a' -> */, +/* pos 02c9: 370 */ 0xF2 /* 'r' -> */, +/* pos 02ca: 371 */ 0xE4 /* 'd' -> */, +/* pos 02cb: 372 */ 0xE5 /* 'e' -> */, +/* pos 02cc: 373 */ 0xE4 /* 'd' -> */, +/* pos 02cd: 374 */ 0xAD /* '-' -> */, +/* pos 02ce: 375 */ 0xE6 /* 'f' -> */, +/* pos 02cf: 376 */ 0xEF /* 'o' -> */, +/* pos 02d0: 377 */ 0xF2 /* 'r' -> */, +/* pos 02d1: 378 */ 0xBA /* ':' -> */, +/* pos 02d2: 379 */ 0x00, 0x46 /* - terminal marker 70 - */, +/* pos 02d4: 380 */ 0x00, 0x47 /* - terminal marker 71 - */, +/* pos 02d6: 381 */ 0xE1 /* 'a' -> */, +/* pos 02d7: 382 */ 0xE4 /* 'd' -> */, +/* pos 02d8: 383 */ 0xA0 /* ' ' -> */, +/* pos 02d9: 384 */ 0x00, 0x48 /* - terminal marker 72 - */, +/* pos 02db: 385 */ 0xF5 /* 'u' -> */, +/* pos 02dc: 386 */ 0xF4 /* 't' -> */, +/* pos 02dd: 387 */ 0xE8 /* 'h' -> */, +/* pos 02de: 388 */ 0xAD /* '-' -> */, +/* pos 02df: 389 */ 0xF4 /* 't' -> */, +/* pos 02e0: 390 */ 0xEF /* 'o' -> */, +/* pos 02e1: 391 */ 0xEB /* 'k' -> */, +/* pos 02e2: 392 */ 0xE5 /* 'e' -> */, +/* pos 02e3: 393 */ 0xEE /* 'n' -> */, +/* pos 02e4: 394 */ 0xBA /* ':' -> */, +/* pos 02e5: 395 */ 0x00, 0x4C /* - terminal marker 76 - */, +/* pos 02e7: 396 */ 0xF4 /* 't' -> */, +/* pos 02e8: 397 */ 0xE9 /* 'i' -> */, +/* pos 02e9: 398 */ 0xEF /* 'o' -> */, +/* pos 02ea: 399 */ 0xEE /* 'n' -> */, +/* pos 02eb: 400 */ 0xF3 /* 's' -> */, +/* pos 02ec: 401 */ 0xA0 /* ' ' -> */, +/* pos 02ed: 402 */ 0x00, 0x02 /* - terminal marker 2 - */, +/* pos 02ef: 403 */ 0xF3 /* 's' -> */, +/* pos 02f0: 404 */ 0xAD /* '-' -> */, +/* pos 02f1: 405 */ 0xE3 /* 'c' -> */, +/* pos 02f2: 406 */ 0xEF /* 'o' -> */, +/* pos 02f3: 407 */ 0xEE /* 'n' -> */, +/* pos 02f4: 408 */ 0xF4 /* 't' -> */, +/* pos 02f5: 409 */ 0xF2 /* 'r' -> */, +/* pos 02f6: 410 */ 0xEF /* 'o' -> */, +/* pos 02f7: 411 */ 0xEC /* 'l' -> */, +/* pos 02f8: 412 */ 0xAD /* '-' -> */, +/* pos 02f9: 413 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0300 state 414) */, + 0x61 /* 'a' */, 0x24, 0x00 /* (to 0x0320 state 443) */, + 0x08, /* fail */ +/* pos 0300: 414 */ 0xE5 /* 'e' -> */, +/* pos 0301: 415 */ 0xF1 /* 'q' -> */, +/* pos 0302: 416 */ 0xF5 /* 'u' -> */, +/* pos 0303: 417 */ 0xE5 /* 'e' -> */, +/* pos 0304: 418 */ 0xF3 /* 's' -> */, +/* pos 0305: 419 */ 0xF4 /* 't' -> */, +/* pos 0306: 420 */ 0xAD /* '-' -> */, +/* pos 0307: 421 */ 0xE8 /* 'h' -> */, +/* pos 0308: 422 */ 0xE5 /* 'e' -> */, +/* pos 0309: 423 */ 0xE1 /* 'a' -> */, +/* pos 030a: 424 */ 0xE4 /* 'd' -> */, +/* pos 030b: 425 */ 0xE5 /* 'e' -> */, +/* pos 030c: 426 */ 0xF2 /* 'r' -> */, +/* pos 030d: 427 */ 0xF3 /* 's' -> */, +/* pos 030e: 428 */ 0xBA /* ':' -> */, +/* pos 030f: 429 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 0311: 430 */ 0xF2 /* 'r' -> */, +/* pos 0312: 431 */ 0xE5 /* 'e' -> */, +/* pos 0313: 432 */ 0xF2 /* 'r' -> */, +/* pos 0314: 433 */ 0xBA /* ':' -> */, +/* pos 0315: 434 */ 0x00, 0x18 /* - terminal marker 24 - */, +/* pos 0317: 435 */ 0xE8 /* 'h' -> */, +/* pos 0318: 436 */ 0xE1 /* 'a' -> */, +/* pos 0319: 437 */ 0xF2 /* 'r' -> */, +/* pos 031a: 438 */ 0xF3 /* 's' -> */, +/* pos 031b: 439 */ 0xE5 /* 'e' -> */, +/* pos 031c: 440 */ 0xF4 /* 't' -> */, +/* pos 031d: 441 */ 0xBA /* ':' -> */, +/* pos 031e: 442 */ 0x00, 0x1E /* - terminal marker 30 - */, +/* pos 0320: 443 */ 0xEC /* 'l' -> */, +/* pos 0321: 444 */ 0xEC /* 'l' -> */, +/* pos 0322: 445 */ 0xEF /* 'o' -> */, +/* pos 0323: 446 */ 0xF7 /* 'w' -> */, +/* pos 0324: 447 */ 0xAD /* '-' -> */, +/* pos 0325: 448 */ 0xEF /* 'o' -> */, +/* pos 0326: 449 */ 0xF2 /* 'r' -> */, +/* pos 0327: 450 */ 0xE9 /* 'i' -> */, +/* pos 0328: 451 */ 0xE7 /* 'g' -> */, +/* pos 0329: 452 */ 0xE9 /* 'i' -> */, +/* pos 032a: 453 */ 0xEE /* 'n' -> */, +/* pos 032b: 454 */ 0xBA /* ':' -> */, +/* pos 032c: 455 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 032e: 456 */ 0xE1 /* 'a' -> */, +/* pos 032f: 457 */ 0xF8 /* 'x' -> */, +/* pos 0330: 458 */ 0xAD /* '-' -> */, +/* pos 0331: 459 */ 0xE6 /* 'f' -> */, +/* pos 0332: 460 */ 0xEF /* 'o' -> */, +/* pos 0333: 461 */ 0xF2 /* 'r' -> */, +/* pos 0334: 462 */ 0xF7 /* 'w' -> */, +/* pos 0335: 463 */ 0xE1 /* 'a' -> */, +/* pos 0336: 464 */ 0xF2 /* 'r' -> */, +/* pos 0337: 465 */ 0xE4 /* 'd' -> */, +/* pos 0338: 466 */ 0xF3 /* 's' -> */, +/* pos 0339: 467 */ 0xBA /* ':' -> */, +/* pos 033a: 468 */ 0x00, 0x32 /* - terminal marker 50 - */, +/* pos 033c: 469 */ 0xF8 /* 'x' -> */, +/* pos 033d: 470 */ 0xF9 /* 'y' -> */, +/* pos 033e: 471 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x0345 state 472) */, + 0x20 /* ' ' */, 0x79, 0x00 /* (to 0x03BA state 567) */, + 0x08, /* fail */ +/* pos 0345: 472 */ 0xE1 /* 'a' -> */, +/* pos 0346: 473 */ 0xF5 /* 'u' -> */, +/* pos 0347: 474 */ 0xF4 /* 't' -> */, +/* pos 0348: 475 */ 0xE8 /* 'h' -> */, +/* pos 0349: 476 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0350 state 477) */, + 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x035A state 486) */, + 0x08, /* fail */ +/* pos 0350: 477 */ 0xEE /* 'n' -> */, +/* pos 0351: 478 */ 0xF4 /* 't' -> */, +/* pos 0352: 479 */ 0xE9 /* 'i' -> */, +/* pos 0353: 480 */ 0xE3 /* 'c' -> */, +/* pos 0354: 481 */ 0xE1 /* 'a' -> */, +/* pos 0355: 482 */ 0xF4 /* 't' -> */, +/* pos 0356: 483 */ 0xE5 /* 'e' -> */, +/* pos 0357: 484 */ 0xBA /* ':' -> */, +/* pos 0358: 485 */ 0x00, 0x33 /* - terminal marker 51 - */, +/* pos 035a: 486 */ 0xF2 /* 'r' -> */, +/* pos 035b: 487 */ 0xE9 /* 'i' -> */, +/* pos 035c: 488 */ 0xFA /* 'z' -> */, +/* pos 035d: 489 */ 0xE1 /* 'a' -> */, +/* pos 035e: 490 */ 0xF4 /* 't' -> */, +/* pos 035f: 491 */ 0xE9 /* 'i' -> */, +/* pos 0360: 492 */ 0xEF /* 'o' -> */, +/* pos 0361: 493 */ 0xEE /* 'n' -> */, +/* pos 0362: 494 */ 0xBA /* ':' -> */, +/* pos 0363: 495 */ 0x00, 0x34 /* - terminal marker 52 - */, +/* pos 0365: 496 */ 0xF2 /* 'r' -> */, +/* pos 0366: 497 */ 0xE9 /* 'i' -> */, +/* pos 0367: 498 */ 0xE3 /* 'c' -> */, +/* pos 0368: 499 */ 0xF4 /* 't' -> */, +/* pos 0369: 500 */ 0xAD /* '-' -> */, +/* pos 036a: 501 */ 0xF4 /* 't' -> */, +/* pos 036b: 502 */ 0xF2 /* 'r' -> */, +/* pos 036c: 503 */ 0xE1 /* 'a' -> */, +/* pos 036d: 504 */ 0xEE /* 'n' -> */, +/* pos 036e: 505 */ 0xF3 /* 's' -> */, +/* pos 036f: 506 */ 0xF0 /* 'p' -> */, +/* pos 0370: 507 */ 0xEF /* 'o' -> */, +/* pos 0371: 508 */ 0xF2 /* 'r' -> */, +/* pos 0372: 509 */ 0xF4 /* 't' -> */, +/* pos 0373: 510 */ 0xAD /* '-' -> */, +/* pos 0374: 511 */ 0xF3 /* 's' -> */, +/* pos 0375: 512 */ 0xE5 /* 'e' -> */, +/* pos 0376: 513 */ 0xE3 /* 'c' -> */, +/* pos 0377: 514 */ 0xF5 /* 'u' -> */, +/* pos 0378: 515 */ 0xF2 /* 'r' -> */, +/* pos 0379: 516 */ 0xE9 /* 'i' -> */, +/* pos 037a: 517 */ 0xF4 /* 't' -> */, +/* pos 037b: 518 */ 0xF9 /* 'y' -> */, +/* pos 037c: 519 */ 0xBA /* ':' -> */, +/* pos 037d: 520 */ 0x00, 0x39 /* - terminal marker 57 - */, +/* pos 037f: 521 */ 0xE5 /* 'e' -> */, +/* pos 0380: 522 */ 0xF2 /* 'r' -> */, +/* pos 0381: 523 */ 0xAD /* '-' -> */, +/* pos 0382: 524 */ 0xE1 /* 'a' -> */, +/* pos 0383: 525 */ 0xE7 /* 'g' -> */, +/* pos 0384: 526 */ 0xE5 /* 'e' -> */, +/* pos 0385: 527 */ 0xEE /* 'n' -> */, +/* pos 0386: 528 */ 0xF4 /* 't' -> */, +/* pos 0387: 529 */ 0xBA /* ':' -> */, +/* pos 0388: 530 */ 0x00, 0x3B /* - terminal marker 59 - */, +/* pos 038a: 531 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0391 state 532) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0396 state 536) */, + 0x08, /* fail */ +/* pos 0391: 532 */ 0xF2 /* 'r' -> */, +/* pos 0392: 533 */ 0xF9 /* 'y' -> */, +/* pos 0393: 534 */ 0xBA /* ':' -> */, +/* pos 0394: 535 */ 0x00, 0x3C /* - terminal marker 60 - */, +/* pos 0396: 536 */ 0xE1 /* 'a' -> */, +/* pos 0397: 537 */ 0xBA /* ':' -> */, +/* pos 0398: 538 */ 0x00, 0x3D /* - terminal marker 61 - */, +/* pos 039a: 539 */ 0xF7 /* 'w' -> */, +/* pos 039b: 540 */ 0xF7 /* 'w' -> */, +/* pos 039c: 541 */ 0xAD /* '-' -> */, +/* pos 039d: 542 */ 0xE1 /* 'a' -> */, +/* pos 039e: 543 */ 0xF5 /* 'u' -> */, +/* pos 039f: 544 */ 0xF4 /* 't' -> */, +/* pos 03a0: 545 */ 0xE8 /* 'h' -> */, +/* pos 03a1: 546 */ 0xE5 /* 'e' -> */, +/* pos 03a2: 547 */ 0xEE /* 'n' -> */, +/* pos 03a3: 548 */ 0xF4 /* 't' -> */, +/* pos 03a4: 549 */ 0xE9 /* 'i' -> */, +/* pos 03a5: 550 */ 0xE3 /* 'c' -> */, +/* pos 03a6: 551 */ 0xE1 /* 'a' -> */, +/* pos 03a7: 552 */ 0xF4 /* 't' -> */, +/* pos 03a8: 553 */ 0xE5 /* 'e' -> */, +/* pos 03a9: 554 */ 0xBA /* ':' -> */, +/* pos 03aa: 555 */ 0x00, 0x3E /* - terminal marker 62 - */, +/* pos 03ac: 556 */ 0xF4 /* 't' -> */, +/* pos 03ad: 557 */ 0xE3 /* 'c' -> */, +/* pos 03ae: 558 */ 0xE8 /* 'h' -> */, +/* pos 03af: 559 */ 0x00, 0x3F /* - terminal marker 63 - */, +/* pos 03b1: 560 */ 0xF4 /* 't' -> */, +/* pos 03b2: 561 */ 0x00, 0x40 /* - terminal marker 64 - */, +/* pos 03b4: 562 */ 0xEC /* 'l' -> */, +/* pos 03b5: 563 */ 0xE5 /* 'e' -> */, +/* pos 03b6: 564 */ 0xF4 /* 't' -> */, +/* pos 03b7: 565 */ 0xE5 /* 'e' -> */, +/* pos 03b8: 566 */ 0x00, 0x41 /* - terminal marker 65 - */, +/* pos 03ba: 567 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 03bc: 568 */ 0xE5 /* 'e' -> */, +/* pos 03bd: 569 */ 0xE1 /* 'a' -> */, +/* pos 03be: 570 */ 0xEC /* 'l' -> */, +/* pos 03bf: 571 */ 0xAD /* '-' -> */, +/* pos 03c0: 572 */ 0xE9 /* 'i' -> */, +/* pos 03c1: 573 */ 0xF0 /* 'p' -> */, +/* pos 03c2: 574 */ 0xBA /* ':' -> */, +/* pos 03c3: 575 */ 0x00, 0x44 /* - terminal marker 68 - */, +/* pos 03c5: 576 */ 0xBA /* ':' -> */, +/* pos 03c6: 577 */ 0x00, 0x49 /* - terminal marker 73 - */, +/* pos 03c8: 578 */ 0xEC /* 'l' -> */, +/* pos 03c9: 579 */ 0xE1 /* 'a' -> */, +/* pos 03ca: 580 */ 0xF9 /* 'y' -> */, +/* pos 03cb: 581 */ 0xAD /* '-' -> */, +/* pos 03cc: 582 */ 0xEE /* 'n' -> */, +/* pos 03cd: 583 */ 0xEF /* 'o' -> */, +/* pos 03ce: 584 */ 0xEE /* 'n' -> */, +/* pos 03cf: 585 */ 0xE3 /* 'c' -> */, +/* pos 03d0: 586 */ 0xE5 /* 'e' -> */, +/* pos 03d1: 587 */ 0xBA /* ':' -> */, +/* pos 03d2: 588 */ 0x00, 0x4A /* - terminal marker 74 - */, +/* pos 03d4: 589 */ 0xAD /* '-' -> */, +/* pos 03d5: 590 */ 0xF7 /* 'w' -> */, +/* pos 03d6: 591 */ 0xE5 /* 'e' -> */, +/* pos 03d7: 592 */ 0xE2 /* 'b' -> */, +/* pos 03d8: 593 */ 0xF3 /* 's' -> */, +/* pos 03d9: 594 */ 0xEF /* 'o' -> */, +/* pos 03da: 595 */ 0xE3 /* 'c' -> */, +/* pos 03db: 596 */ 0xEB /* 'k' -> */, +/* pos 03dc: 597 */ 0xE5 /* 'e' -> */, +/* pos 03dd: 598 */ 0xF4 /* 't' -> */, +/* pos 03de: 599 */ 0xAD /* '-' -> */, +/* pos 03df: 600 */ 0x64 /* 'd' */, 0x19, 0x00 /* (to 0x03F8 state 601) */, + 0x65 /* 'e' */, 0x1D, 0x00 /* (to 0x03FF state 607) */, + 0x6B /* 'k' */, 0x26, 0x00 /* (to 0x040B state 618) */, + 0x70 /* 'p' */, 0x35, 0x00 /* (to 0x041D state 625) */, + 0x61 /* 'a' */, 0x3C, 0x00 /* (to 0x0427 state 634) */, + 0x6E /* 'n' */, 0x41, 0x00 /* (to 0x042F state 641) */, + 0x76 /* 'v' */, 0x47, 0x00 /* (to 0x0438 state 648) */, + 0x6F /* 'o' */, 0x4D, 0x00 /* (to 0x0441 state 656) */, + 0x08, /* fail */ +/* pos 03f8: 601 */ 0xF2 /* 'r' -> */, +/* pos 03f9: 602 */ 0xE1 /* 'a' -> */, +/* pos 03fa: 603 */ 0xE6 /* 'f' -> */, +/* pos 03fb: 604 */ 0xF4 /* 't' -> */, +/* pos 03fc: 605 */ 0xBA /* ':' -> */, +/* pos 03fd: 606 */ 0x00, 0x07 /* - terminal marker 7 - */, +/* pos 03ff: 607 */ 0xF8 /* 'x' -> */, +/* pos 0400: 608 */ 0xF4 /* 't' -> */, +/* pos 0401: 609 */ 0xE5 /* 'e' -> */, +/* pos 0402: 610 */ 0xEE /* 'n' -> */, +/* pos 0403: 611 */ 0xF3 /* 's' -> */, +/* pos 0404: 612 */ 0xE9 /* 'i' -> */, +/* pos 0405: 613 */ 0xEF /* 'o' -> */, +/* pos 0406: 614 */ 0xEE /* 'n' -> */, +/* pos 0407: 615 */ 0xF3 /* 's' -> */, +/* pos 0408: 616 */ 0xBA /* ':' -> */, +/* pos 0409: 617 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 040b: 618 */ 0xE5 /* 'e' -> */, +/* pos 040c: 619 */ 0xF9 /* 'y' -> */, +/* pos 040d: 620 */ 0x31 /* '1' */, 0x0A, 0x00 /* (to 0x0417 state 621) */, + 0x32 /* '2' */, 0x0A, 0x00 /* (to 0x041A state 623) */, + 0x3A /* ':' */, 0x23, 0x00 /* (to 0x0436 state 647) */, + 0x08, /* fail */ +/* pos 0417: 621 */ 0xBA /* ':' -> */, +/* pos 0418: 622 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 041a: 623 */ 0xBA /* ':' -> */, +/* pos 041b: 624 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 041d: 625 */ 0xF2 /* 'r' -> */, +/* pos 041e: 626 */ 0xEF /* 'o' -> */, +/* pos 041f: 627 */ 0xF4 /* 't' -> */, +/* pos 0420: 628 */ 0xEF /* 'o' -> */, +/* pos 0421: 629 */ 0xE3 /* 'c' -> */, +/* pos 0422: 630 */ 0xEF /* 'o' -> */, +/* pos 0423: 631 */ 0xEC /* 'l' -> */, +/* pos 0424: 632 */ 0xBA /* ':' -> */, +/* pos 0425: 633 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 0427: 634 */ 0xE3 /* 'c' -> */, +/* pos 0428: 635 */ 0xE3 /* 'c' -> */, +/* pos 0429: 636 */ 0xE5 /* 'e' -> */, +/* pos 042a: 637 */ 0xF0 /* 'p' -> */, +/* pos 042b: 638 */ 0xF4 /* 't' -> */, +/* pos 042c: 639 */ 0xBA /* ':' -> */, +/* pos 042d: 640 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 042f: 641 */ 0xEF /* 'o' -> */, +/* pos 0430: 642 */ 0xEE /* 'n' -> */, +/* pos 0431: 643 */ 0xE3 /* 'c' -> */, +/* pos 0432: 644 */ 0xE5 /* 'e' -> */, +/* pos 0433: 645 */ 0xBA /* ':' -> */, +/* pos 0434: 646 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 0436: 647 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 0438: 648 */ 0xE5 /* 'e' -> */, +/* pos 0439: 649 */ 0xF2 /* 'r' -> */, +/* pos 043a: 650 */ 0xF3 /* 's' -> */, +/* pos 043b: 651 */ 0xE9 /* 'i' -> */, +/* pos 043c: 652 */ 0xEF /* 'o' -> */, +/* pos 043d: 653 */ 0xEE /* 'n' -> */, +/* pos 043e: 654 */ 0xBA /* ':' -> */, +/* pos 043f: 655 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 0441: 656 */ 0xF2 /* 'r' -> */, +/* pos 0442: 657 */ 0xE9 /* 'i' -> */, +/* pos 0443: 658 */ 0xE7 /* 'g' -> */, +/* pos 0444: 659 */ 0xE9 /* 'i' -> */, +/* pos 0445: 660 */ 0xEE /* 'n' -> */, +/* pos 0446: 661 */ 0xBA /* ':' -> */, +/* pos 0447: 662 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* pos 0449: 663 */ 0xAD /* '-' -> */, +/* pos 044a: 664 */ 0xF3 /* 's' -> */, +/* pos 044b: 665 */ 0xE5 /* 'e' -> */, +/* pos 044c: 666 */ 0xF4 /* 't' -> */, +/* pos 044d: 667 */ 0xF4 /* 't' -> */, +/* pos 044e: 668 */ 0xE9 /* 'i' -> */, +/* pos 044f: 669 */ 0xEE /* 'n' -> */, +/* pos 0450: 670 */ 0xE7 /* 'g' -> */, +/* pos 0451: 671 */ 0xF3 /* 's' -> */, +/* pos 0452: 672 */ 0xBA /* ':' -> */, +/* pos 0453: 673 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 0455: 674 */ 0x61 /* 'a' */, 0x0D, 0x00 /* (to 0x0462 state 675) */, + 0x6D /* 'm' */, 0x14, 0x00 /* (to 0x046C state 684) */, + 0x70 /* 'p' */, 0x18, 0x00 /* (to 0x0473 state 690) */, + 0x73 /* 's' */, 0x20, 0x00 /* (to 0x047E state 694) */, + 0x08, /* fail */ +/* pos 0462: 675 */ 0xF5 /* 'u' -> */, +/* pos 0463: 676 */ 0xF4 /* 't' -> */, +/* pos 0464: 677 */ 0xE8 /* 'h' -> */, +/* pos 0465: 678 */ 0xEF /* 'o' -> */, +/* pos 0466: 679 */ 0xF2 /* 'r' -> */, +/* pos 0467: 680 */ 0xE9 /* 'i' -> */, +/* pos 0468: 681 */ 0xF4 /* 't' -> */, +/* pos 0469: 682 */ 0xF9 /* 'y' -> */, +/* pos 046a: 683 */ 0x00, 0x19 /* - terminal marker 25 - */, +/* pos 046c: 684 */ 0xE5 /* 'e' -> */, +/* pos 046d: 685 */ 0xF4 /* 't' -> */, +/* pos 046e: 686 */ 0xE8 /* 'h' -> */, +/* pos 046f: 687 */ 0xEF /* 'o' -> */, +/* pos 0470: 688 */ 0xE4 /* 'd' -> */, +/* pos 0471: 689 */ 0x00, 0x1A /* - terminal marker 26 - */, +/* pos 0473: 690 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x047A state 691) */, + 0x72 /* 'r' */, 0x1B, 0x00 /* (to 0x0491 state 705) */, + 0x08, /* fail */ +/* pos 047a: 691 */ 0xF4 /* 't' -> */, +/* pos 047b: 692 */ 0xE8 /* 'h' -> */, +/* pos 047c: 693 */ 0x00, 0x1B /* - terminal marker 27 - */, +/* pos 047e: 694 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x0485 state 695) */, + 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x048B state 700) */, + 0x08, /* fail */ +/* pos 0485: 695 */ 0xE8 /* 'h' -> */, +/* pos 0486: 696 */ 0xE5 /* 'e' -> */, +/* pos 0487: 697 */ 0xED /* 'm' -> */, +/* pos 0488: 698 */ 0xE5 /* 'e' -> */, +/* pos 0489: 699 */ 0x00, 0x1C /* - terminal marker 28 - */, +/* pos 048b: 700 */ 0xE1 /* 'a' -> */, +/* pos 048c: 701 */ 0xF4 /* 't' -> */, +/* pos 048d: 702 */ 0xF5 /* 'u' -> */, +/* pos 048e: 703 */ 0xF3 /* 's' -> */, +/* pos 048f: 704 */ 0x00, 0x1D /* - terminal marker 29 - */, +/* pos 0491: 705 */ 0xEF /* 'o' -> */, +/* pos 0492: 706 */ 0xF4 /* 't' -> */, +/* pos 0493: 707 */ 0xEF /* 'o' -> */, +/* pos 0494: 708 */ 0xE3 /* 'c' -> */, +/* pos 0495: 709 */ 0xEF /* 'o' -> */, +/* pos 0496: 710 */ 0xEC /* 'l' -> */, /* pos 0497: 711 */ 0x00, 0x4B /* - terminal marker 75 - */, /* total size 1177 bytes */ #endif @@ -4917,7 +4852,7 @@ /* 14: 15: http/1.1 */ /* 15: 16: http2-settings: */ /* 16: 17: accept: */ - /* 17: 18: access-control-request-headers: */ + /* 17: 19: if-modified-since: */ /* 18: 20: if-none-match: */ /* 19: 21: accept-encoding: */ /* 20: 22: accept-language: */ @@ -4971,8 +4906,8 @@ /* 68: 70: vary: */ /* 69: 71: via: */ /* 70: 72: www-authenticate: */ - /* 71: 73: patch */ - /* 72: 77: proxy */ + /* 71: 76: uri-args */ + /* 72: 79: http/1.0 */ /* 73: 80: x-forwarded-for: */ /* 74: 81: connect */ /* 75: 82: head */ @@ -4988,29 +4923,29 @@ 0x75 /* 'u' */, 0x7E, 0x00 /* (to 0x008A state 26) */, 0x6F /* 'o' */, 0x8D, 0x00 /* (to 0x009C state 34) */, 0x0D /* '.' */, 0x98, 0x00 /* (to 0x00AA state 41) */, - 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 57) */, - 0x69 /* 'i' */, 0xE2, 0x00 /* (to 0x00FA state 88) */, - 0x64 /* 'd' */, 0x7D, 0x01 /* (to 0x0198 state 177) */, - 0x72 /* 'r' */, 0x86, 0x01 /* (to 0x01A4 state 182) */, - 0x65 /* 'e' */, 0xEB, 0x01 /* (to 0x020C state 256) */, - 0x66 /* 'f' */, 0x07, 0x02 /* (to 0x022B state 272) */, - 0x6C /* 'l' */, 0x30, 0x02 /* (to 0x0257 state 306) */, - 0x6D /* 'm' */, 0x53, 0x02 /* (to 0x027D state 332) */, - 0x73 /* 's' */, 0x69, 0x02 /* (to 0x0296 state 355) */, - 0x78 /* 'x' */, 0xB7, 0x02 /* (to 0x02E7 state 410) */, - 0x74 /* 't' */, 0xD5, 0x02 /* (to 0x0308 state 431) */, - 0x76 /* 'v' */, 0x69, 0x03 /* (to 0x039F state 527) */, - 0x77 /* 'w' */, 0x76, 0x03 /* (to 0x03AF state 535) */, - 0x3A /* ':' */, 0xBC, 0x03 /* (to 0x03F8 state 594) */, + 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 51) */, + 0x69 /* 'i' */, 0xCA, 0x00 /* (to 0x00E2 state 58) */, + 0x64 /* 'd' */, 0x73, 0x01 /* (to 0x018E state 160) */, + 0x72 /* 'r' */, 0x7C, 0x01 /* (to 0x019A state 165) */, + 0x65 /* 'e' */, 0xC8, 0x01 /* (to 0x01E9 state 229) */, + 0x66 /* 'f' */, 0xE4, 0x01 /* (to 0x0208 state 245) */, + 0x6C /* 'l' */, 0x06, 0x02 /* (to 0x022D state 278) */, + 0x73 /* 's' */, 0x4B, 0x02 /* (to 0x0275 state 321) */, + 0x74 /* 't' */, 0x69, 0x02 /* (to 0x0296 state 337) */, + 0x78 /* 'x' */, 0x8A, 0x02 /* (to 0x02BA state 364) */, + 0x6D /* 'm' */, 0xFB, 0x02 /* (to 0x032E state 456) */, + 0x76 /* 'v' */, 0x54, 0x03 /* (to 0x038A state 531) */, + 0x77 /* 'w' */, 0x61, 0x03 /* (to 0x039A state 539) */, + 0x3A /* ':' */, 0x19, 0x04 /* (to 0x0455 state 674) */, 0x08, /* fail */ /* pos 0040: 1 */ 0xE5 /* 'e' -> */, /* pos 0041: 2 */ 0xF4 /* 't' -> */, /* pos 0042: 3 */ 0xA0 /* ' ' -> */, /* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, /* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */, - 0x72 /* 'r' */, 0xF6, 0x00 /* (to 0x013E state 123) */, - 0x61 /* 'a' */, 0x76, 0x03 /* (to 0x03C1 state 552) */, - 0x75 /* 'u' */, 0x78, 0x03 /* (to 0x03C6 state 556) */, + 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x0134 state 106) */, + 0x61 /* 'a' */, 0x61, 0x03 /* (to 0x03AC state 556) */, + 0x75 /* 'u' */, 0x63, 0x03 /* (to 0x03B1 state 560) */, 0x08, /* fail */ /* pos 0052: 6 */ 0xF3 /* 's' -> */, /* pos 0053: 7 */ 0xF4 /* 't' -> */, @@ -5018,34 +4953,34 @@ /* pos 0055: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, /* pos 0057: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0061 state 11) */, 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AD state 43) */, - 0x65 /* 'e' */, 0xA6, 0x02 /* (to 0x0303 state 427) */, + 0x65 /* 'e' */, 0x79, 0x02 /* (to 0x02D6 state 381) */, 0x08, /* fail */ /* pos 0061: 11 */ 0xF3 /* 's' -> */, /* pos 0062: 12 */ 0xF4 /* 't' -> */, /* pos 0063: 13 */ 0xBA /* ':' -> */, /* pos 0064: 14 */ 0x00, 0x02 /* - terminal marker 2 - */, /* pos 0066: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006D state 16) */, - 0x61 /* 'a' */, 0xE2, 0x00 /* (to 0x014B state 129) */, + 0x61 /* 'a' */, 0xD8, 0x00 /* (to 0x0141 state 112) */, 0x08, /* fail */ /* pos 006d: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0074 state 17) */, - 0x6F /* 'o' */, 0xF7, 0x00 /* (to 0x0167 state 155) */, + 0x6F /* 'o' */, 0xED, 0x00 /* (to 0x015D state 138) */, 0x08, /* fail */ /* pos 0074: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x007B state 18) */, - 0x74 /* 't' */, 0xF6, 0x00 /* (to 0x016D state 160) */, + 0x74 /* 't' */, 0xEC, 0x00 /* (to 0x0163 state 143) */, 0x08, /* fail */ /* pos 007b: 18 */ 0xE5 /* 'e' -> */, /* pos 007c: 19 */ 0xE3 /* 'c' -> */, /* pos 007d: 20 */ 0xF4 /* 't' -> */, /* pos 007e: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0085 state 22) */, - 0x20 /* ' ' */, 0x80, 0x02 /* (to 0x0301 state 426) */, + 0x20 /* ' ' */, 0x53, 0x02 /* (to 0x02D4 state 380) */, 0x08, /* fail */ /* pos 0085: 22 */ 0xEF /* 'o' -> */, /* pos 0086: 23 */ 0xEE /* 'n' -> */, /* pos 0087: 24 */ 0xBA /* ':' -> */, /* pos 0088: 25 */ 0x00, 0x03 /* - terminal marker 3 - */, /* pos 008a: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0094 state 27) */, - 0x73 /* 's' */, 0x44, 0x02 /* (to 0x02D1 state 396) */, - 0x72 /* 'r' */, 0x3F, 0x03 /* (to 0x03CF state 563) */, + 0x72 /* 'r' */, 0x22, 0x02 /* (to 0x02AF state 355) */, + 0x73 /* 's' */, 0xEF, 0x02 /* (to 0x037F state 521) */, 0x08, /* fail */ /* pos 0094: 27 */ 0xE7 /* 'g' -> */, /* pos 0095: 28 */ 0xF2 /* 'r' -> */, @@ -5055,7 +4990,7 @@ /* pos 0099: 32 */ 0xBA /* ':' -> */, /* pos 009a: 33 */ 0x00, 0x04 /* - terminal marker 4 - */, /* pos 009c: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A3 state 35) */, - 0x70 /* 'p' */, 0x73, 0x02 /* (to 0x0312 state 434) */, + 0x70 /* 'p' */, 0x48, 0x02 /* (to 0x02E7 state 396) */, 0x08, /* fail */ /* pos 00a3: 35 */ 0xE9 /* 'i' -> */, /* pos 00a4: 36 */ 0xE7 /* 'g' -> */, @@ -5067,758 +5002,758 @@ /* pos 00ab: 42 */ 0x00, 0x07 /* - terminal marker 7 - */, /* pos 00ad: 43 */ 0xF4 /* 't' -> */, /* pos 00ae: 44 */ 0xF0 /* 'p' -> */, -/* pos 00af: 45 */ 0x32 /* '2' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, - 0x2F /* '/' */, 0x2E, 0x03 /* (to 0x03E0 state 578) */, - 0x08, /* fail */ -/* pos 00b6: 46 */ 0xAD /* '-' -> */, -/* pos 00b7: 47 */ 0xF3 /* 's' -> */, -/* pos 00b8: 48 */ 0xE5 /* 'e' -> */, -/* pos 00b9: 49 */ 0xF4 /* 't' -> */, -/* pos 00ba: 50 */ 0xF4 /* 't' -> */, -/* pos 00bb: 51 */ 0xE9 /* 'i' -> */, -/* pos 00bc: 52 */ 0xEE /* 'n' -> */, -/* pos 00bd: 53 */ 0xE7 /* 'g' -> */, -/* pos 00be: 54 */ 0xF3 /* 's' -> */, -/* pos 00bf: 55 */ 0xBA /* ':' -> */, -/* pos 00c0: 56 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 00c2: 57 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 58) */, - 0x75 /* 'u' */, 0x94, 0x00 /* (to 0x0159 state 142) */, - 0x6C /* 'l' */, 0x0E, 0x01 /* (to 0x01D6 state 208) */, - 0x67 /* 'g' */, 0x98, 0x02 /* (to 0x0363 state 478) */, - 0x08, /* fail */ -/* pos 00cf: 58 */ 0xE3 /* 'c' -> */, -/* pos 00d0: 59 */ 0xE5 /* 'e' -> */, -/* pos 00d1: 60 */ 0x73 /* 's' */, 0x07, 0x00 /* (to 0x00D8 state 61) */, - 0x70 /* 'p' */, 0x41, 0x00 /* (to 0x0115 state 102) */, - 0x08, /* fail */ -/* pos 00d8: 61 */ 0xF3 /* 's' -> */, -/* pos 00d9: 62 */ 0xAD /* '-' -> */, -/* pos 00da: 63 */ 0xE3 /* 'c' -> */, -/* pos 00db: 64 */ 0xEF /* 'o' -> */, -/* pos 00dc: 65 */ 0xEE /* 'n' -> */, -/* pos 00dd: 66 */ 0xF4 /* 't' -> */, -/* pos 00de: 67 */ 0xF2 /* 'r' -> */, -/* pos 00df: 68 */ 0xEF /* 'o' -> */, -/* pos 00e0: 69 */ 0xEC /* 'l' -> */, -/* pos 00e1: 70 */ 0xAD /* '-' -> */, -/* pos 00e2: 71 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00E9 state 72) */, - 0x61 /* 'a' */, 0xE3, 0x00 /* (to 0x01C8 state 195) */, - 0x08, /* fail */ -/* pos 00e9: 72 */ 0xE5 /* 'e' -> */, -/* pos 00ea: 73 */ 0xF1 /* 'q' -> */, -/* pos 00eb: 74 */ 0xF5 /* 'u' -> */, -/* pos 00ec: 75 */ 0xE5 /* 'e' -> */, -/* pos 00ed: 76 */ 0xF3 /* 's' -> */, -/* pos 00ee: 77 */ 0xF4 /* 't' -> */, -/* pos 00ef: 78 */ 0xAD /* '-' -> */, -/* pos 00f0: 79 */ 0xE8 /* 'h' -> */, -/* pos 00f1: 80 */ 0xE5 /* 'e' -> */, -/* pos 00f2: 81 */ 0xE1 /* 'a' -> */, -/* pos 00f3: 82 */ 0xE4 /* 'd' -> */, -/* pos 00f4: 83 */ 0xE5 /* 'e' -> */, -/* pos 00f5: 84 */ 0xF2 /* 'r' -> */, -/* pos 00f6: 85 */ 0xF3 /* 's' -> */, -/* pos 00f7: 86 */ 0xBA /* ':' -> */, -/* pos 00f8: 87 */ 0x00, 0x11 /* - terminal marker 17 - */, -/* pos 00fa: 88 */ 0xE6 /* 'f' -> */, -/* pos 00fb: 89 */ 0xAD /* '-' -> */, -/* pos 00fc: 90 */ 0x6E /* 'n' */, 0x0D, 0x00 /* (to 0x0109 state 91) */, - 0x6D /* 'm' */, 0x32, 0x01 /* (to 0x0231 state 277) */, - 0x72 /* 'r' */, 0x3C, 0x01 /* (to 0x023E state 283) */, - 0x75 /* 'u' */, 0x40, 0x01 /* (to 0x0245 state 289) */, - 0x08, /* fail */ -/* pos 0109: 91 */ 0xEF /* 'o' -> */, -/* pos 010a: 92 */ 0xEE /* 'n' -> */, -/* pos 010b: 93 */ 0xE5 /* 'e' -> */, -/* pos 010c: 94 */ 0xAD /* '-' -> */, -/* pos 010d: 95 */ 0xED /* 'm' -> */, -/* pos 010e: 96 */ 0xE1 /* 'a' -> */, -/* pos 010f: 97 */ 0xF4 /* 't' -> */, -/* pos 0110: 98 */ 0xE3 /* 'c' -> */, -/* pos 0111: 99 */ 0xE8 /* 'h' -> */, -/* pos 0112: 100 */ 0xBA /* ':' -> */, -/* pos 0113: 101 */ 0x00, 0x12 /* - terminal marker 18 - */, -/* pos 0115: 102 */ 0xF4 /* 't' -> */, -/* pos 0116: 103 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x011D state 104) */, - 0x3A /* ':' */, 0x4B, 0x03 /* (to 0x0464 state 672) */, - 0x08, /* fail */ -/* pos 011d: 104 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x012A state 105) */, - 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x0134 state 114) */, - 0x72 /* 'r' */, 0x38, 0x02 /* (to 0x035B state 471) */, - 0x63 /* 'c' */, 0x5E, 0x03 /* (to 0x0484 state 693) */, - 0x08, /* fail */ -/* pos 012a: 105 */ 0xEE /* 'n' -> */, -/* pos 012b: 106 */ 0xE3 /* 'c' -> */, -/* pos 012c: 107 */ 0xEF /* 'o' -> */, -/* pos 012d: 108 */ 0xE4 /* 'd' -> */, -/* pos 012e: 109 */ 0xE9 /* 'i' -> */, -/* pos 012f: 110 */ 0xEE /* 'n' -> */, -/* pos 0130: 111 */ 0xE7 /* 'g' -> */, -/* pos 0131: 112 */ 0xBA /* ':' -> */, -/* pos 0132: 113 */ 0x00, 0x13 /* - terminal marker 19 - */, -/* pos 0134: 114 */ 0xE1 /* 'a' -> */, -/* pos 0135: 115 */ 0xEE /* 'n' -> */, -/* pos 0136: 116 */ 0xE7 /* 'g' -> */, -/* pos 0137: 117 */ 0xF5 /* 'u' -> */, -/* pos 0138: 118 */ 0xE1 /* 'a' -> */, -/* pos 0139: 119 */ 0xE7 /* 'g' -> */, -/* pos 013a: 120 */ 0xE5 /* 'e' -> */, -/* pos 013b: 121 */ 0xBA /* ':' -> */, -/* pos 013c: 122 */ 0x00, 0x14 /* - terminal marker 20 - */, -/* pos 013e: 123 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0145 state 124) */, - 0x6F /* 'o' */, 0x9B, 0x01 /* (to 0x02DC state 406) */, - 0x08, /* fail */ -/* pos 0145: 124 */ 0xE7 /* 'g' -> */, -/* pos 0146: 125 */ 0xED /* 'm' -> */, -/* pos 0147: 126 */ 0xE1 /* 'a' -> */, -/* pos 0148: 127 */ 0xBA /* ':' -> */, -/* pos 0149: 128 */ 0x00, 0x15 /* - terminal marker 21 - */, -/* pos 014b: 129 */ 0xE3 /* 'c' -> */, -/* pos 014c: 130 */ 0xE8 /* 'h' -> */, -/* pos 014d: 131 */ 0xE5 /* 'e' -> */, -/* pos 014e: 132 */ 0xAD /* '-' -> */, -/* pos 014f: 133 */ 0xE3 /* 'c' -> */, -/* pos 0150: 134 */ 0xEF /* 'o' -> */, -/* pos 0151: 135 */ 0xEE /* 'n' -> */, -/* pos 0152: 136 */ 0xF4 /* 't' -> */, -/* pos 0153: 137 */ 0xF2 /* 'r' -> */, -/* pos 0154: 138 */ 0xEF /* 'o' -> */, -/* pos 0155: 139 */ 0xEC /* 'l' -> */, -/* pos 0156: 140 */ 0xBA /* ':' -> */, -/* pos 0157: 141 */ 0x00, 0x16 /* - terminal marker 22 - */, -/* pos 0159: 142 */ 0xF4 /* 't' -> */, -/* pos 015a: 143 */ 0xE8 /* 'h' -> */, -/* pos 015b: 144 */ 0xEF /* 'o' -> */, -/* pos 015c: 145 */ 0xF2 /* 'r' -> */, -/* pos 015d: 146 */ 0xE9 /* 'i' -> */, -/* pos 015e: 147 */ 0xFA /* 'z' -> */, -/* pos 015f: 148 */ 0xE1 /* 'a' -> */, -/* pos 0160: 149 */ 0xF4 /* 't' -> */, -/* pos 0161: 150 */ 0xE9 /* 'i' -> */, -/* pos 0162: 151 */ 0xEF /* 'o' -> */, -/* pos 0163: 152 */ 0xEE /* 'n' -> */, -/* pos 0164: 153 */ 0xBA /* ':' -> */, -/* pos 0165: 154 */ 0x00, 0x17 /* - terminal marker 23 - */, -/* pos 0167: 155 */ 0xEB /* 'k' -> */, -/* pos 0168: 156 */ 0xE9 /* 'i' -> */, -/* pos 0169: 157 */ 0xE5 /* 'e' -> */, -/* pos 016a: 158 */ 0xBA /* ':' -> */, -/* pos 016b: 159 */ 0x00, 0x18 /* - terminal marker 24 - */, -/* pos 016d: 160 */ 0xE5 /* 'e' -> */, -/* pos 016e: 161 */ 0xEE /* 'n' -> */, -/* pos 016f: 162 */ 0xF4 /* 't' -> */, -/* pos 0170: 163 */ 0xAD /* '-' -> */, -/* pos 0171: 164 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0181 state 165) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0192 state 172) */, - 0x64 /* 'd' */, 0x65, 0x00 /* (to 0x01DC state 213) */, - 0x65 /* 'e' */, 0x6F, 0x00 /* (to 0x01E9 state 225) */, - 0x72 /* 'r' */, 0x88, 0x00 /* (to 0x0205 state 250) */, - 0x08, /* fail */ -/* pos 0181: 165 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x018B state 166) */, - 0x61 /* 'a' */, 0x6F, 0x00 /* (to 0x01F3 state 234) */, - 0x6F /* 'o' */, 0x75, 0x00 /* (to 0x01FC state 242) */, - 0x08, /* fail */ -/* pos 018b: 166 */ 0xEE /* 'n' -> */, -/* pos 018c: 167 */ 0xE7 /* 'g' -> */, -/* pos 018d: 168 */ 0xF4 /* 't' -> */, -/* pos 018e: 169 */ 0xE8 /* 'h' -> */, -/* pos 018f: 170 */ 0xBA /* ':' -> */, -/* pos 0190: 171 */ 0x00, 0x19 /* - terminal marker 25 - */, -/* pos 0192: 172 */ 0xF9 /* 'y' -> */, -/* pos 0193: 173 */ 0xF0 /* 'p' -> */, -/* pos 0194: 174 */ 0xE5 /* 'e' -> */, -/* pos 0195: 175 */ 0xBA /* ':' -> */, -/* pos 0196: 176 */ 0x00, 0x1A /* - terminal marker 26 - */, -/* pos 0198: 177 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x019F state 178) */, - 0x65 /* 'e' */, 0x2E, 0x02 /* (to 0x03C9 state 558) */, - 0x08, /* fail */ -/* pos 019f: 178 */ 0xF4 /* 't' -> */, -/* pos 01a0: 179 */ 0xE5 /* 'e' -> */, -/* pos 01a1: 180 */ 0xBA /* ':' -> */, -/* pos 01a2: 181 */ 0x00, 0x1B /* - terminal marker 27 - */, -/* pos 01a4: 182 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01AB state 183) */, - 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x01B1 state 188) */, - 0x08, /* fail */ -/* pos 01ab: 183 */ 0xEE /* 'n' -> */, -/* pos 01ac: 184 */ 0xE7 /* 'g' -> */, -/* pos 01ad: 185 */ 0xE5 /* 'e' -> */, -/* pos 01ae: 186 */ 0xBA /* ':' -> */, -/* pos 01af: 187 */ 0x00, 0x1C /* - terminal marker 28 - */, -/* pos 01b1: 188 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x01BB state 189) */, - 0x74 /* 't' */, 0xD7, 0x00 /* (to 0x028B state 345) */, - 0x70 /* 'p' */, 0x35, 0x02 /* (to 0x03EC state 583) */, - 0x08, /* fail */ -/* pos 01bb: 189 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01C2 state 190) */, - 0x72 /* 'r' */, 0xC9, 0x01 /* (to 0x0387 state 505) */, - 0x08, /* fail */ -/* pos 01c2: 190 */ 0xF2 /* 'r' -> */, -/* pos 01c3: 191 */ 0xE5 /* 'e' -> */, -/* pos 01c4: 192 */ 0xF2 /* 'r' -> */, -/* pos 01c5: 193 */ 0xBA /* ':' -> */, -/* pos 01c6: 194 */ 0x00, 0x1D /* - terminal marker 29 - */, -/* pos 01c8: 195 */ 0xEC /* 'l' -> */, -/* pos 01c9: 196 */ 0xEC /* 'l' -> */, -/* pos 01ca: 197 */ 0xEF /* 'o' -> */, -/* pos 01cb: 198 */ 0xF7 /* 'w' -> */, -/* pos 01cc: 199 */ 0xAD /* '-' -> */, -/* pos 01cd: 200 */ 0xEF /* 'o' -> */, -/* pos 01ce: 201 */ 0xF2 /* 'r' -> */, -/* pos 01cf: 202 */ 0xE9 /* 'i' -> */, -/* pos 01d0: 203 */ 0xE7 /* 'g' -> */, -/* pos 01d1: 204 */ 0xE9 /* 'i' -> */, -/* pos 01d2: 205 */ 0xEE /* 'n' -> */, -/* pos 01d3: 206 */ 0xBA /* ':' -> */, -/* pos 01d4: 207 */ 0x00, 0x28 /* - terminal marker 40 - */, -/* pos 01d6: 208 */ 0xEC /* 'l' -> */, -/* pos 01d7: 209 */ 0xEF /* 'o' -> */, -/* pos 01d8: 210 */ 0xF7 /* 'w' -> */, -/* pos 01d9: 211 */ 0xBA /* ':' -> */, -/* pos 01da: 212 */ 0x00, 0x2A /* - terminal marker 42 - */, -/* pos 01dc: 213 */ 0xE9 /* 'i' -> */, -/* pos 01dd: 214 */ 0xF3 /* 's' -> */, -/* pos 01de: 215 */ 0xF0 /* 'p' -> */, -/* pos 01df: 216 */ 0xEF /* 'o' -> */, -/* pos 01e0: 217 */ 0xF3 /* 's' -> */, -/* pos 01e1: 218 */ 0xE9 /* 'i' -> */, -/* pos 01e2: 219 */ 0xF4 /* 't' -> */, -/* pos 01e3: 220 */ 0xE9 /* 'i' -> */, -/* pos 01e4: 221 */ 0xEF /* 'o' -> */, -/* pos 01e5: 222 */ 0xEE /* 'n' -> */, -/* pos 01e6: 223 */ 0xBA /* ':' -> */, -/* pos 01e7: 224 */ 0x00, 0x2B /* - terminal marker 43 - */, -/* pos 01e9: 225 */ 0xEE /* 'n' -> */, -/* pos 01ea: 226 */ 0xE3 /* 'c' -> */, -/* pos 01eb: 227 */ 0xEF /* 'o' -> */, -/* pos 01ec: 228 */ 0xE4 /* 'd' -> */, -/* pos 01ed: 229 */ 0xE9 /* 'i' -> */, -/* pos 01ee: 230 */ 0xEE /* 'n' -> */, -/* pos 01ef: 231 */ 0xE7 /* 'g' -> */, -/* pos 01f0: 232 */ 0xBA /* ':' -> */, -/* pos 01f1: 233 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 01f3: 234 */ 0xEE /* 'n' -> */, -/* pos 01f4: 235 */ 0xE7 /* 'g' -> */, -/* pos 01f5: 236 */ 0xF5 /* 'u' -> */, -/* pos 01f6: 237 */ 0xE1 /* 'a' -> */, -/* pos 01f7: 238 */ 0xE7 /* 'g' -> */, -/* pos 01f8: 239 */ 0xE5 /* 'e' -> */, -/* pos 01f9: 240 */ 0xBA /* ':' -> */, -/* pos 01fa: 241 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 01fc: 242 */ 0xE3 /* 'c' -> */, -/* pos 01fd: 243 */ 0xE1 /* 'a' -> */, -/* pos 01fe: 244 */ 0xF4 /* 't' -> */, -/* pos 01ff: 245 */ 0xE9 /* 'i' -> */, -/* pos 0200: 246 */ 0xEF /* 'o' -> */, -/* pos 0201: 247 */ 0xEE /* 'n' -> */, -/* pos 0202: 248 */ 0xBA /* ':' -> */, -/* pos 0203: 249 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 0205: 250 */ 0xE1 /* 'a' -> */, -/* pos 0206: 251 */ 0xEE /* 'n' -> */, -/* pos 0207: 252 */ 0xE7 /* 'g' -> */, -/* pos 0208: 253 */ 0xE5 /* 'e' -> */, -/* pos 0209: 254 */ 0xBA /* ':' -> */, -/* pos 020a: 255 */ 0x00, 0x2F /* - terminal marker 47 - */, -/* pos 020c: 256 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x0213 state 257) */, - 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x0218 state 261) */, - 0x08, /* fail */ -/* pos 0213: 257 */ 0xE1 /* 'a' -> */, -/* pos 0214: 258 */ 0xE7 /* 'g' -> */, -/* pos 0215: 259 */ 0xBA /* ':' -> */, -/* pos 0216: 260 */ 0x00, 0x30 /* - terminal marker 48 - */, -/* pos 0218: 261 */ 0xF0 /* 'p' -> */, -/* pos 0219: 262 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0220 state 263) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0225 state 267) */, - 0x08, /* fail */ -/* pos 0220: 263 */ 0xE3 /* 'c' -> */, -/* pos 0221: 264 */ 0xF4 /* 't' -> */, -/* pos 0222: 265 */ 0xBA /* ':' -> */, -/* pos 0223: 266 */ 0x00, 0x31 /* - terminal marker 49 - */, -/* pos 0225: 267 */ 0xF2 /* 'r' -> */, -/* pos 0226: 268 */ 0xE5 /* 'e' -> */, -/* pos 0227: 269 */ 0xF3 /* 's' -> */, -/* pos 0228: 270 */ 0xBA /* ':' -> */, -/* pos 0229: 271 */ 0x00, 0x32 /* - terminal marker 50 - */, -/* pos 022b: 272 */ 0xF2 /* 'r' -> */, -/* pos 022c: 273 */ 0xEF /* 'o' -> */, -/* pos 022d: 274 */ 0xED /* 'm' -> */, -/* pos 022e: 275 */ 0xBA /* ':' -> */, -/* pos 022f: 276 */ 0x00, 0x33 /* - terminal marker 51 - */, -/* pos 0231: 277 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0238 state 278) */, - 0x6F /* 'o' */, 0xE6, 0x00 /* (to 0x031A state 441) */, - 0x08, /* fail */ -/* pos 0238: 278 */ 0xF4 /* 't' -> */, -/* pos 0239: 279 */ 0xE3 /* 'c' -> */, -/* pos 023a: 280 */ 0xE8 /* 'h' -> */, -/* pos 023b: 281 */ 0xBA /* ':' -> */, -/* pos 023c: 282 */ 0x00, 0x34 /* - terminal marker 52 - */, -/* pos 023e: 283 */ 0xE1 /* 'a' -> */, -/* pos 023f: 284 */ 0xEE /* 'n' -> */, -/* pos 0240: 285 */ 0xE7 /* 'g' -> */, -/* pos 0241: 286 */ 0xE5 /* 'e' -> */, -/* pos 0242: 287 */ 0xBA /* ':' -> */, -/* pos 0243: 288 */ 0x00, 0x35 /* - terminal marker 53 - */, -/* pos 0245: 289 */ 0xEE /* 'n' -> */, -/* pos 0246: 290 */ 0xED /* 'm' -> */, -/* pos 0247: 291 */ 0xEF /* 'o' -> */, -/* pos 0248: 292 */ 0xE4 /* 'd' -> */, -/* pos 0249: 293 */ 0xE9 /* 'i' -> */, -/* pos 024a: 294 */ 0xE6 /* 'f' -> */, -/* pos 024b: 295 */ 0xE9 /* 'i' -> */, -/* pos 024c: 296 */ 0xE5 /* 'e' -> */, -/* pos 024d: 297 */ 0xE4 /* 'd' -> */, -/* pos 024e: 298 */ 0xAD /* '-' -> */, -/* pos 024f: 299 */ 0xF3 /* 's' -> */, -/* pos 0250: 300 */ 0xE9 /* 'i' -> */, -/* pos 0251: 301 */ 0xEE /* 'n' -> */, -/* pos 0252: 302 */ 0xE3 /* 'c' -> */, -/* pos 0253: 303 */ 0xE5 /* 'e' -> */, -/* pos 0254: 304 */ 0xBA /* ':' -> */, -/* pos 0255: 305 */ 0x00, 0x36 /* - terminal marker 54 - */, -/* pos 0257: 306 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0261 state 307) */, - 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x026F state 320) */, - 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0274 state 324) */, - 0x08, /* fail */ -/* pos 0261: 307 */ 0xF3 /* 's' -> */, -/* pos 0262: 308 */ 0xF4 /* 't' -> */, -/* pos 0263: 309 */ 0xAD /* '-' -> */, -/* pos 0264: 310 */ 0xED /* 'm' -> */, -/* pos 0265: 311 */ 0xEF /* 'o' -> */, -/* pos 0266: 312 */ 0xE4 /* 'd' -> */, -/* pos 0267: 313 */ 0xE9 /* 'i' -> */, -/* pos 0268: 314 */ 0xE6 /* 'f' -> */, -/* pos 0269: 315 */ 0xE9 /* 'i' -> */, -/* pos 026a: 316 */ 0xE5 /* 'e' -> */, -/* pos 026b: 317 */ 0xE4 /* 'd' -> */, -/* pos 026c: 318 */ 0xBA /* ':' -> */, -/* pos 026d: 319 */ 0x00, 0x37 /* - terminal marker 55 - */, -/* pos 026f: 320 */ 0xEE /* 'n' -> */, -/* pos 0270: 321 */ 0xEB /* 'k' -> */, -/* pos 0271: 322 */ 0xBA /* ':' -> */, -/* pos 0272: 323 */ 0x00, 0x38 /* - terminal marker 56 - */, -/* pos 0274: 324 */ 0xE3 /* 'c' -> */, -/* pos 0275: 325 */ 0xE1 /* 'a' -> */, -/* pos 0276: 326 */ 0xF4 /* 't' -> */, -/* pos 0277: 327 */ 0xE9 /* 'i' -> */, -/* pos 0278: 328 */ 0xEF /* 'o' -> */, -/* pos 0279: 329 */ 0xEE /* 'n' -> */, -/* pos 027a: 330 */ 0xBA /* ':' -> */, -/* pos 027b: 331 */ 0x00, 0x39 /* - terminal marker 57 - */, -/* pos 027d: 332 */ 0xE1 /* 'a' -> */, -/* pos 027e: 333 */ 0xF8 /* 'x' -> */, -/* pos 027f: 334 */ 0xAD /* '-' -> */, -/* pos 0280: 335 */ 0xE6 /* 'f' -> */, -/* pos 0281: 336 */ 0xEF /* 'o' -> */, -/* pos 0282: 337 */ 0xF2 /* 'r' -> */, -/* pos 0283: 338 */ 0xF7 /* 'w' -> */, -/* pos 0284: 339 */ 0xE1 /* 'a' -> */, -/* pos 0285: 340 */ 0xF2 /* 'r' -> */, -/* pos 0286: 341 */ 0xE4 /* 'd' -> */, -/* pos 0287: 342 */ 0xF3 /* 's' -> */, -/* pos 0288: 343 */ 0xBA /* ':' -> */, -/* pos 0289: 344 */ 0x00, 0x3A /* - terminal marker 58 - */, -/* pos 028b: 345 */ 0xF2 /* 'r' -> */, -/* pos 028c: 346 */ 0xF9 /* 'y' -> */, -/* pos 028d: 347 */ 0xAD /* '-' -> */, -/* pos 028e: 348 */ 0xE1 /* 'a' -> */, -/* pos 028f: 349 */ 0xE6 /* 'f' -> */, -/* pos 0290: 350 */ 0xF4 /* 't' -> */, -/* pos 0291: 351 */ 0xE5 /* 'e' -> */, -/* pos 0292: 352 */ 0xF2 /* 'r' -> */, -/* pos 0293: 353 */ 0xBA /* ':' -> */, -/* pos 0294: 354 */ 0x00, 0x3E /* - terminal marker 62 - */, -/* pos 0296: 355 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x029D state 356) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x02B7 state 371) */, - 0x08, /* fail */ -/* pos 029d: 356 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x02A7 state 357) */, - 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x02AD state 362) */, - 0x63 /* 'c' */, 0x86, 0x00 /* (to 0x0329 state 455) */, - 0x08, /* fail */ -/* pos 02a7: 357 */ 0xF6 /* 'v' -> */, -/* pos 02a8: 358 */ 0xE5 /* 'e' -> */, -/* pos 02a9: 359 */ 0xF2 /* 'r' -> */, -/* pos 02aa: 360 */ 0xBA /* ':' -> */, -/* pos 02ab: 361 */ 0x00, 0x3F /* - terminal marker 63 - */, -/* pos 02ad: 362 */ 0xAD /* '-' -> */, -/* pos 02ae: 363 */ 0xE3 /* 'c' -> */, -/* pos 02af: 364 */ 0xEF /* 'o' -> */, -/* pos 02b0: 365 */ 0xEF /* 'o' -> */, -/* pos 02b1: 366 */ 0xEB /* 'k' -> */, -/* pos 02b2: 367 */ 0xE9 /* 'i' -> */, -/* pos 02b3: 368 */ 0xE5 /* 'e' -> */, -/* pos 02b4: 369 */ 0xBA /* ':' -> */, -/* pos 02b5: 370 */ 0x00, 0x40 /* - terminal marker 64 - */, -/* pos 02b7: 371 */ 0xF2 /* 'r' -> */, -/* pos 02b8: 372 */ 0xE9 /* 'i' -> */, -/* pos 02b9: 373 */ 0xE3 /* 'c' -> */, -/* pos 02ba: 374 */ 0xF4 /* 't' -> */, -/* pos 02bb: 375 */ 0xAD /* '-' -> */, -/* pos 02bc: 376 */ 0xF4 /* 't' -> */, -/* pos 02bd: 377 */ 0xF2 /* 'r' -> */, -/* pos 02be: 378 */ 0xE1 /* 'a' -> */, -/* pos 02bf: 379 */ 0xEE /* 'n' -> */, -/* pos 02c0: 380 */ 0xF3 /* 's' -> */, -/* pos 02c1: 381 */ 0xF0 /* 'p' -> */, -/* pos 02c2: 382 */ 0xEF /* 'o' -> */, -/* pos 02c3: 383 */ 0xF2 /* 'r' -> */, -/* pos 02c4: 384 */ 0xF4 /* 't' -> */, -/* pos 02c5: 385 */ 0xAD /* '-' -> */, -/* pos 02c6: 386 */ 0xF3 /* 's' -> */, -/* pos 02c7: 387 */ 0xE5 /* 'e' -> */, -/* pos 02c8: 388 */ 0xE3 /* 'c' -> */, -/* pos 02c9: 389 */ 0xF5 /* 'u' -> */, -/* pos 02ca: 390 */ 0xF2 /* 'r' -> */, -/* pos 02cb: 391 */ 0xE9 /* 'i' -> */, -/* pos 02cc: 392 */ 0xF4 /* 't' -> */, -/* pos 02cd: 393 */ 0xF9 /* 'y' -> */, -/* pos 02ce: 394 */ 0xBA /* ':' -> */, -/* pos 02cf: 395 */ 0x00, 0x41 /* - terminal marker 65 - */, -/* pos 02d1: 396 */ 0xE5 /* 'e' -> */, -/* pos 02d2: 397 */ 0xF2 /* 'r' -> */, -/* pos 02d3: 398 */ 0xAD /* '-' -> */, -/* pos 02d4: 399 */ 0xE1 /* 'a' -> */, -/* pos 02d5: 400 */ 0xE7 /* 'g' -> */, -/* pos 02d6: 401 */ 0xE5 /* 'e' -> */, -/* pos 02d7: 402 */ 0xEE /* 'n' -> */, -/* pos 02d8: 403 */ 0xF4 /* 't' -> */, -/* pos 02d9: 404 */ 0xBA /* ':' -> */, -/* pos 02da: 405 */ 0x00, 0x43 /* - terminal marker 67 - */, -/* pos 02dc: 406 */ 0xF8 /* 'x' -> */, -/* pos 02dd: 407 */ 0xF9 /* 'y' -> */, -/* pos 02de: 408 */ 0x20 /* ' ' */, 0x07, 0x00 /* (to 0x02E5 state 409) */, - 0x2D /* '-' */, 0x86, 0x00 /* (to 0x0367 state 481) */, - 0x08, /* fail */ -/* pos 02e5: 409 */ 0x00, 0x48 /* - terminal marker 72 - */, -/* pos 02e7: 410 */ 0xAD /* '-' -> */, -/* pos 02e8: 411 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02F2 state 412) */, - 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x03D7 state 570) */, - 0x61 /* 'a' */, 0x9F, 0x01 /* (to 0x048D state 701) */, - 0x08, /* fail */ -/* pos 02f2: 412 */ 0xEF /* 'o' -> */, -/* pos 02f3: 413 */ 0xF2 /* 'r' -> */, -/* pos 02f4: 414 */ 0xF7 /* 'w' -> */, -/* pos 02f5: 415 */ 0xE1 /* 'a' -> */, -/* pos 02f6: 416 */ 0xF2 /* 'r' -> */, -/* pos 02f7: 417 */ 0xE4 /* 'd' -> */, -/* pos 02f8: 418 */ 0xE5 /* 'e' -> */, -/* pos 02f9: 419 */ 0xE4 /* 'd' -> */, -/* pos 02fa: 420 */ 0xAD /* '-' -> */, -/* pos 02fb: 421 */ 0xE6 /* 'f' -> */, -/* pos 02fc: 422 */ 0xEF /* 'o' -> */, -/* pos 02fd: 423 */ 0xF2 /* 'r' -> */, -/* pos 02fe: 424 */ 0xBA /* ':' -> */, -/* pos 02ff: 425 */ 0x00, 0x49 /* - terminal marker 73 - */, -/* pos 0301: 426 */ 0x00, 0x4A /* - terminal marker 74 - */, -/* pos 0303: 427 */ 0xE1 /* 'a' -> */, -/* pos 0304: 428 */ 0xE4 /* 'd' -> */, -/* pos 0305: 429 */ 0xA0 /* ' ' -> */, -/* pos 0306: 430 */ 0x00, 0x4B /* - terminal marker 75 - */, -/* pos 0308: 431 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x030F state 432) */, - 0x72 /* 'r' */, 0x82, 0x00 /* (to 0x038D state 510) */, - 0x08, /* fail */ -/* pos 030f: 432 */ 0xBA /* ':' -> */, -/* pos 0310: 433 */ 0x00, 0x4C /* - terminal marker 76 - */, -/* pos 0312: 434 */ 0xF4 /* 't' -> */, -/* pos 0313: 435 */ 0xE9 /* 'i' -> */, -/* pos 0314: 436 */ 0xEF /* 'o' -> */, -/* pos 0315: 437 */ 0xEE /* 'n' -> */, -/* pos 0316: 438 */ 0xF3 /* 's' -> */, -/* pos 0317: 439 */ 0xA0 /* ' ' -> */, -/* pos 0318: 440 */ 0x00, 0x02 /* - terminal marker 2 - */, -/* pos 031a: 441 */ 0xE4 /* 'd' -> */, -/* pos 031b: 442 */ 0xE9 /* 'i' -> */, -/* pos 031c: 443 */ 0xE6 /* 'f' -> */, -/* pos 031d: 444 */ 0xE9 /* 'i' -> */, -/* pos 031e: 445 */ 0xE5 /* 'e' -> */, -/* pos 031f: 446 */ 0xE4 /* 'd' -> */, -/* pos 0320: 447 */ 0xAD /* '-' -> */, -/* pos 0321: 448 */ 0xF3 /* 's' -> */, -/* pos 0322: 449 */ 0xE9 /* 'i' -> */, -/* pos 0323: 450 */ 0xEE /* 'n' -> */, -/* pos 0324: 451 */ 0xE3 /* 'c' -> */, -/* pos 0325: 452 */ 0xE5 /* 'e' -> */, -/* pos 0326: 453 */ 0xBA /* ':' -> */, -/* pos 0327: 454 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 0329: 455 */ 0xAD /* '-' -> */, -/* pos 032a: 456 */ 0xF7 /* 'w' -> */, -/* pos 032b: 457 */ 0xE5 /* 'e' -> */, -/* pos 032c: 458 */ 0xE2 /* 'b' -> */, -/* pos 032d: 459 */ 0xF3 /* 's' -> */, -/* pos 032e: 460 */ 0xEF /* 'o' -> */, -/* pos 032f: 461 */ 0xE3 /* 'c' -> */, -/* pos 0330: 462 */ 0xEB /* 'k' -> */, -/* pos 0331: 463 */ 0xE5 /* 'e' -> */, -/* pos 0332: 464 */ 0xF4 /* 't' -> */, -/* pos 0333: 465 */ 0xAD /* '-' -> */, -/* pos 0334: 466 */ 0x6B /* 'k' */, 0x19, 0x00 /* (to 0x034D state 467) */, - 0x64 /* 'd' */, 0xDD, 0x00 /* (to 0x0414 state 603) */, - 0x65 /* 'e' */, 0xE1, 0x00 /* (to 0x041B state 609) */, - 0x70 /* 'p' */, 0xF0, 0x00 /* (to 0x042D state 624) */, - 0x61 /* 'a' */, 0xF7, 0x00 /* (to 0x0437 state 633) */, - 0x6E /* 'n' */, 0xFC, 0x00 /* (to 0x043F state 640) */, - 0x76 /* 'v' */, 0x03, 0x01 /* (to 0x0449 state 648) */, - 0x6F /* 'o' */, 0x09, 0x01 /* (to 0x0452 state 656) */, - 0x08, /* fail */ -/* pos 034d: 467 */ 0xE5 /* 'e' -> */, -/* pos 034e: 468 */ 0xF9 /* 'y' -> */, -/* pos 034f: 469 */ 0x3A /* ':' */, 0x0A, 0x00 /* (to 0x0359 state 470) */, - 0x31 /* '1' */, 0xD5, 0x00 /* (to 0x0427 state 620) */, - 0x32 /* '2' */, 0xD5, 0x00 /* (to 0x042A state 622) */, - 0x08, /* fail */ -/* pos 0359: 470 */ 0x00, 0x1E /* - terminal marker 30 - */, -/* pos 035b: 471 */ 0xE1 /* 'a' -> */, -/* pos 035c: 472 */ 0xEE /* 'n' -> */, -/* pos 035d: 473 */ 0xE7 /* 'g' -> */, -/* pos 035e: 474 */ 0xE5 /* 'e' -> */, -/* pos 035f: 475 */ 0xF3 /* 's' -> */, -/* pos 0360: 476 */ 0xBA /* ':' -> */, -/* pos 0361: 477 */ 0x00, 0x27 /* - terminal marker 39 - */, -/* pos 0363: 478 */ 0xE5 /* 'e' -> */, -/* pos 0364: 479 */ 0xBA /* ':' -> */, -/* pos 0365: 480 */ 0x00, 0x29 /* - terminal marker 41 - */, -/* pos 0367: 481 */ 0xE1 /* 'a' -> */, -/* pos 0368: 482 */ 0xF5 /* 'u' -> */, -/* pos 0369: 483 */ 0xF4 /* 't' -> */, -/* pos 036a: 484 */ 0xE8 /* 'h' -> */, -/* pos 036b: 485 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0372 state 486) */, - 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x037C state 495) */, - 0x08, /* fail */ -/* pos 0372: 486 */ 0xEE /* 'n' -> */, -/* pos 0373: 487 */ 0xF4 /* 't' -> */, -/* pos 0374: 488 */ 0xE9 /* 'i' -> */, -/* pos 0375: 489 */ 0xE3 /* 'c' -> */, -/* pos 0376: 490 */ 0xE1 /* 'a' -> */, -/* pos 0377: 491 */ 0xF4 /* 't' -> */, -/* pos 0378: 492 */ 0xE5 /* 'e' -> */, -/* pos 0379: 493 */ 0xBA /* ':' -> */, -/* pos 037a: 494 */ 0x00, 0x3B /* - terminal marker 59 - */, -/* pos 037c: 495 */ 0xF2 /* 'r' -> */, -/* pos 037d: 496 */ 0xE9 /* 'i' -> */, -/* pos 037e: 497 */ 0xFA /* 'z' -> */, -/* pos 037f: 498 */ 0xE1 /* 'a' -> */, -/* pos 0380: 499 */ 0xF4 /* 't' -> */, -/* pos 0381: 500 */ 0xE9 /* 'i' -> */, -/* pos 0382: 501 */ 0xEF /* 'o' -> */, -/* pos 0383: 502 */ 0xEE /* 'n' -> */, -/* pos 0384: 503 */ 0xBA /* ':' -> */, -/* pos 0385: 504 */ 0x00, 0x3C /* - terminal marker 60 - */, -/* pos 0387: 505 */ 0xE5 /* 'e' -> */, -/* pos 0388: 506 */ 0xF3 /* 's' -> */, -/* pos 0389: 507 */ 0xE8 /* 'h' -> */, -/* pos 038a: 508 */ 0xBA /* ':' -> */, -/* pos 038b: 509 */ 0x00, 0x3D /* - terminal marker 61 - */, -/* pos 038d: 510 */ 0xE1 /* 'a' -> */, -/* pos 038e: 511 */ 0xEE /* 'n' -> */, -/* pos 038f: 512 */ 0xF3 /* 's' -> */, -/* pos 0390: 513 */ 0xE6 /* 'f' -> */, -/* pos 0391: 514 */ 0xE5 /* 'e' -> */, -/* pos 0392: 515 */ 0xF2 /* 'r' -> */, -/* pos 0393: 516 */ 0xAD /* '-' -> */, -/* pos 0394: 517 */ 0xE5 /* 'e' -> */, -/* pos 0395: 518 */ 0xEE /* 'n' -> */, -/* pos 0396: 519 */ 0xE3 /* 'c' -> */, -/* pos 0397: 520 */ 0xEF /* 'o' -> */, -/* pos 0398: 521 */ 0xE4 /* 'd' -> */, -/* pos 0399: 522 */ 0xE9 /* 'i' -> */, -/* pos 039a: 523 */ 0xEE /* 'n' -> */, -/* pos 039b: 524 */ 0xE7 /* 'g' -> */, -/* pos 039c: 525 */ 0xBA /* ':' -> */, -/* pos 039d: 526 */ 0x00, 0x42 /* - terminal marker 66 - */, -/* pos 039f: 527 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x03A6 state 528) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x03AB state 532) */, - 0x08, /* fail */ -/* pos 03a6: 528 */ 0xF2 /* 'r' -> */, -/* pos 03a7: 529 */ 0xF9 /* 'y' -> */, -/* pos 03a8: 530 */ 0xBA /* ':' -> */, -/* pos 03a9: 531 */ 0x00, 0x44 /* - terminal marker 68 - */, -/* pos 03ab: 532 */ 0xE1 /* 'a' -> */, -/* pos 03ac: 533 */ 0xBA /* ':' -> */, -/* pos 03ad: 534 */ 0x00, 0x45 /* - terminal marker 69 - */, -/* pos 03af: 535 */ 0xF7 /* 'w' -> */, -/* pos 03b0: 536 */ 0xF7 /* 'w' -> */, -/* pos 03b1: 537 */ 0xAD /* '-' -> */, -/* pos 03b2: 538 */ 0xE1 /* 'a' -> */, -/* pos 03b3: 539 */ 0xF5 /* 'u' -> */, -/* pos 03b4: 540 */ 0xF4 /* 't' -> */, -/* pos 03b5: 541 */ 0xE8 /* 'h' -> */, -/* pos 03b6: 542 */ 0xE5 /* 'e' -> */, -/* pos 03b7: 543 */ 0xEE /* 'n' -> */, -/* pos 03b8: 544 */ 0xF4 /* 't' -> */, -/* pos 03b9: 545 */ 0xE9 /* 'i' -> */, -/* pos 03ba: 546 */ 0xE3 /* 'c' -> */, -/* pos 03bb: 547 */ 0xE1 /* 'a' -> */, -/* pos 03bc: 548 */ 0xF4 /* 't' -> */, -/* pos 03bd: 549 */ 0xE5 /* 'e' -> */, -/* pos 03be: 550 */ 0xBA /* ':' -> */, -/* pos 03bf: 551 */ 0x00, 0x46 /* - terminal marker 70 - */, -/* pos 03c1: 552 */ 0xF4 /* 't' -> */, -/* pos 03c2: 553 */ 0xE3 /* 'c' -> */, -/* pos 03c3: 554 */ 0xE8 /* 'h' -> */, -/* pos 03c4: 555 */ 0x00, 0x47 /* - terminal marker 71 - */, -/* pos 03c6: 556 */ 0xF4 /* 't' -> */, -/* pos 03c7: 557 */ 0x00, 0x3F /* - terminal marker 63 - */, -/* pos 03c9: 558 */ 0xEC /* 'l' -> */, -/* pos 03ca: 559 */ 0xE5 /* 'e' -> */, -/* pos 03cb: 560 */ 0xF4 /* 't' -> */, -/* pos 03cc: 561 */ 0xE5 /* 'e' -> */, -/* pos 03cd: 562 */ 0x00, 0x40 /* - terminal marker 64 - */, -/* pos 03cf: 563 */ 0xE9 /* 'i' -> */, -/* pos 03d0: 564 */ 0xAD /* '-' -> */, -/* pos 03d1: 565 */ 0xE1 /* 'a' -> */, -/* pos 03d2: 566 */ 0xF2 /* 'r' -> */, -/* pos 03d3: 567 */ 0xE7 /* 'g' -> */, -/* pos 03d4: 568 */ 0xF3 /* 's' -> */, -/* pos 03d5: 569 */ 0x00, 0x41 /* - terminal marker 65 - */, -/* pos 03d7: 570 */ 0xE5 /* 'e' -> */, -/* pos 03d8: 571 */ 0xE1 /* 'a' -> */, -/* pos 03d9: 572 */ 0xEC /* 'l' -> */, -/* pos 03da: 573 */ 0xAD /* '-' -> */, -/* pos 03db: 574 */ 0xE9 /* 'i' -> */, -/* pos 03dc: 575 */ 0xF0 /* 'p' -> */, -/* pos 03dd: 576 */ 0xBA /* ':' -> */, -/* pos 03de: 577 */ 0x00, 0x43 /* - terminal marker 67 - */, -/* pos 03e0: 578 */ 0xB1 /* '1' -> */, -/* pos 03e1: 579 */ 0xAE /* '.' -> */, -/* pos 03e2: 580 */ 0x30 /* '0' */, 0x07, 0x00 /* (to 0x03E9 state 581) */, - 0x31 /* '1' */, 0x61, 0x00 /* (to 0x0446 state 646) */, - 0x08, /* fail */ -/* pos 03e9: 581 */ 0xA0 /* ' ' -> */, -/* pos 03ea: 582 */ 0x00, 0x44 /* - terminal marker 68 - */, -/* pos 03ec: 583 */ 0xEC /* 'l' -> */, -/* pos 03ed: 584 */ 0xE1 /* 'a' -> */, -/* pos 03ee: 585 */ 0xF9 /* 'y' -> */, -/* pos 03ef: 586 */ 0xAD /* '-' -> */, -/* pos 03f0: 587 */ 0xEE /* 'n' -> */, -/* pos 03f1: 588 */ 0xEF /* 'o' -> */, -/* pos 03f2: 589 */ 0xEE /* 'n' -> */, -/* pos 03f3: 590 */ 0xE3 /* 'c' -> */, -/* pos 03f4: 591 */ 0xE5 /* 'e' -> */, -/* pos 03f5: 592 */ 0xBA /* ':' -> */, -/* pos 03f6: 593 */ 0x00, 0x4D /* - terminal marker 77 - */, -/* pos 03f8: 594 */ 0x70 /* 'p' */, 0x0D, 0x00 /* (to 0x0405 state 595) */, - 0x61 /* 'a' */, 0x5F, 0x00 /* (to 0x045A state 663) */, - 0x6D /* 'm' */, 0x68, 0x00 /* (to 0x0466 state 673) */, - 0x73 /* 's' */, 0x70, 0x00 /* (to 0x0471 state 682) */, - 0x08, /* fail */ -/* pos 0405: 595 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x040C state 596) */, - 0x61 /* 'a' */, 0x65, 0x00 /* (to 0x046D state 679) */, - 0x08, /* fail */ -/* pos 040c: 596 */ 0xEF /* 'o' -> */, -/* pos 040d: 597 */ 0xF4 /* 't' -> */, -/* pos 040e: 598 */ 0xEF /* 'o' -> */, -/* pos 040f: 599 */ 0xE3 /* 'c' -> */, -/* pos 0410: 600 */ 0xEF /* 'o' -> */, -/* pos 0411: 601 */ 0xEC /* 'l' -> */, -/* pos 0412: 602 */ 0x00, 0x4E /* - terminal marker 78 - */, -/* pos 0414: 603 */ 0xF2 /* 'r' -> */, -/* pos 0415: 604 */ 0xE1 /* 'a' -> */, -/* pos 0416: 605 */ 0xE6 /* 'f' -> */, -/* pos 0417: 606 */ 0xF4 /* 't' -> */, -/* pos 0418: 607 */ 0xBA /* ':' -> */, -/* pos 0419: 608 */ 0x00, 0x06 /* - terminal marker 6 - */, -/* pos 041b: 609 */ 0xF8 /* 'x' -> */, -/* pos 041c: 610 */ 0xF4 /* 't' -> */, -/* pos 041d: 611 */ 0xE5 /* 'e' -> */, -/* pos 041e: 612 */ 0xEE /* 'n' -> */, -/* pos 041f: 613 */ 0xF3 /* 's' -> */, -/* pos 0420: 614 */ 0xE9 /* 'i' -> */, -/* pos 0421: 615 */ 0xEF /* 'o' -> */, -/* pos 0422: 616 */ 0xEE /* 'n' -> */, -/* pos 0423: 617 */ 0xF3 /* 's' -> */, -/* pos 0424: 618 */ 0xBA /* ':' -> */, -/* pos 0425: 619 */ 0x00, 0x08 /* - terminal marker 8 - */, -/* pos 0427: 620 */ 0xBA /* ':' -> */, -/* pos 0428: 621 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 042a: 622 */ 0xBA /* ':' -> */, -/* pos 042b: 623 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 042d: 624 */ 0xF2 /* 'r' -> */, -/* pos 042e: 625 */ 0xEF /* 'o' -> */, -/* pos 042f: 626 */ 0xF4 /* 't' -> */, -/* pos 0430: 627 */ 0xEF /* 'o' -> */, -/* pos 0431: 628 */ 0xE3 /* 'c' -> */, -/* pos 0432: 629 */ 0xEF /* 'o' -> */, -/* pos 0433: 630 */ 0xEC /* 'l' -> */, -/* pos 0434: 631 */ 0xBA /* ':' -> */, -/* pos 0435: 632 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 0437: 633 */ 0xE3 /* 'c' -> */, -/* pos 0438: 634 */ 0xE3 /* 'c' -> */, -/* pos 0439: 635 */ 0xE5 /* 'e' -> */, -/* pos 043a: 636 */ 0xF0 /* 'p' -> */, -/* pos 043b: 637 */ 0xF4 /* 't' -> */, -/* pos 043c: 638 */ 0xBA /* ':' -> */, -/* pos 043d: 639 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 043f: 640 */ 0xEF /* 'o' -> */, -/* pos 0440: 641 */ 0xEE /* 'n' -> */, -/* pos 0441: 642 */ 0xE3 /* 'c' -> */, -/* pos 0442: 643 */ 0xE5 /* 'e' -> */, -/* pos 0443: 644 */ 0xBA /* ':' -> */, -/* pos 0444: 645 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 0446: 646 */ 0xA0 /* ' ' -> */, -/* pos 0447: 647 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 0449: 648 */ 0xE5 /* 'e' -> */, -/* pos 044a: 649 */ 0xF2 /* 'r' -> */, -/* pos 044b: 650 */ 0xF3 /* 's' -> */, -/* pos 044c: 651 */ 0xE9 /* 'i' -> */, -/* pos 044d: 652 */ 0xEF /* 'o' -> */, -/* pos 044e: 653 */ 0xEE /* 'n' -> */, -/* pos 044f: 654 */ 0xBA /* ':' -> */, -/* pos 0450: 655 */ 0x00, 0x1F /* - terminal marker 31 - */, -/* pos 0452: 656 */ 0xF2 /* 'r' -> */, -/* pos 0453: 657 */ 0xE9 /* 'i' -> */, -/* pos 0454: 658 */ 0xE7 /* 'g' -> */, -/* pos 0455: 659 */ 0xE9 /* 'i' -> */, -/* pos 0456: 660 */ 0xEE /* 'n' -> */, -/* pos 0457: 661 */ 0xBA /* ':' -> */, -/* pos 0458: 662 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 045a: 663 */ 0xF5 /* 'u' -> */, -/* pos 045b: 664 */ 0xF4 /* 't' -> */, -/* pos 045c: 665 */ 0xE8 /* 'h' -> */, -/* pos 045d: 666 */ 0xEF /* 'o' -> */, -/* pos 045e: 667 */ 0xF2 /* 'r' -> */, -/* pos 045f: 668 */ 0xE9 /* 'i' -> */, -/* pos 0460: 669 */ 0xF4 /* 't' -> */, -/* pos 0461: 670 */ 0xF9 /* 'y' -> */, -/* pos 0462: 671 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 0464: 672 */ 0x00, 0x10 /* - terminal marker 16 - */, -/* pos 0466: 673 */ 0xE5 /* 'e' -> */, -/* pos 0467: 674 */ 0xF4 /* 't' -> */, -/* pos 0468: 675 */ 0xE8 /* 'h' -> */, -/* pos 0469: 676 */ 0xEF /* 'o' -> */, -/* pos 046a: 677 */ 0xE4 /* 'd' -> */, -/* pos 046b: 678 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* pos 046d: 679 */ 0xF4 /* 't' -> */, -/* pos 046e: 680 */ 0xE8 /* 'h' -> */, -/* pos 046f: 681 */ 0x00, 0x23 /* - terminal marker 35 - */, -/* pos 0471: 682 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x0478 state 683) */, - 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x047E state 688) */, - 0x08, /* fail */ -/* pos 0478: 683 */ 0xE8 /* 'h' -> */, -/* pos 0479: 684 */ 0xE5 /* 'e' -> */, -/* pos 047a: 685 */ 0xED /* 'm' -> */, -/* pos 047b: 686 */ 0xE5 /* 'e' -> */, -/* pos 047c: 687 */ 0x00, 0x24 /* - terminal marker 36 - */, -/* pos 047e: 688 */ 0xE1 /* 'a' -> */, -/* pos 047f: 689 */ 0xF4 /* 't' -> */, -/* pos 0480: 690 */ 0xF5 /* 'u' -> */, -/* pos 0481: 691 */ 0xF3 /* 's' -> */, -/* pos 0482: 692 */ 0x00, 0x25 /* - terminal marker 37 - */, -/* pos 0484: 693 */ 0xE8 /* 'h' -> */, -/* pos 0485: 694 */ 0xE1 /* 'a' -> */, -/* pos 0486: 695 */ 0xF2 /* 'r' -> */, -/* pos 0487: 696 */ 0xF3 /* 's' -> */, -/* pos 0488: 697 */ 0xE5 /* 'e' -> */, -/* pos 0489: 698 */ 0xF4 /* 't' -> */, -/* pos 048a: 699 */ 0xBA /* ':' -> */, -/* pos 048b: 700 */ 0x00, 0x26 /* - terminal marker 38 - */, -/* pos 048d: 701 */ 0xF5 /* 'u' -> */, -/* pos 048e: 702 */ 0xF4 /* 't' -> */, -/* pos 048f: 703 */ 0xE8 /* 'h' -> */, -/* pos 0490: 704 */ 0xAD /* '-' -> */, -/* pos 0491: 705 */ 0xF4 /* 't' -> */, -/* pos 0492: 706 */ 0xEF /* 'o' -> */, -/* pos 0493: 707 */ 0xEB /* 'k' -> */, -/* pos 0494: 708 */ 0xE5 /* 'e' -> */, -/* pos 0495: 709 */ 0xEE /* 'n' -> */, -/* pos 0496: 710 */ 0xBA /* ':' -> */, -/* pos 0497: 711 */ 0x00, 0x4F /* - terminal marker 79 - */, +/* pos 00af: 45 */ 0x2F /* '/' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, + 0x32 /* '2' */, 0x97, 0x03 /* (to 0x0449 state 663) */, + 0x08, /* fail */ +/* pos 00b6: 46 */ 0xB1 /* '1' -> */, +/* pos 00b7: 47 */ 0xAE /* '.' -> */, +/* pos 00b8: 48 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x00BF state 49) */, + 0x30 /* '0' */, 0xFC, 0x01 /* (to 0x02B7 state 362) */, + 0x08, /* fail */ +/* pos 00bf: 49 */ 0xA0 /* ' ' -> */, +/* pos 00c0: 50 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 00c2: 51 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 52) */, + 0x75 /* 'u' */, 0x8A, 0x00 /* (to 0x014F state 125) */, + 0x67 /* 'g' */, 0xE7, 0x00 /* (to 0x01AF state 178) */, + 0x6C /* 'l' */, 0xE8, 0x00 /* (to 0x01B3 state 181) */, + 0x08, /* fail */ +/* pos 00cf: 52 */ 0xE3 /* 'c' -> */, +/* pos 00d0: 53 */ 0xE5 /* 'e' -> */, +/* pos 00d1: 54 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x00D8 state 55) */, + 0x73 /* 's' */, 0x1B, 0x02 /* (to 0x02EF state 403) */, + 0x08, /* fail */ +/* pos 00d8: 55 */ 0xF4 /* 't' -> */, +/* pos 00d9: 56 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x00E0 state 57) */, + 0x2D /* '-' */, 0x37, 0x00 /* (to 0x0113 state 87) */, + 0x08, /* fail */ +/* pos 00e0: 57 */ 0x00, 0x10 /* - terminal marker 16 - */, +/* pos 00e2: 58 */ 0xE6 /* 'f' -> */, +/* pos 00e3: 59 */ 0xAD /* '-' -> */, +/* pos 00e4: 60 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x00F1 state 61) */, + 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x0107 state 76) */, + 0x72 /* 'r' */, 0x2A, 0x01 /* (to 0x0214 state 255) */, + 0x75 /* 'u' */, 0x2E, 0x01 /* (to 0x021B state 261) */, + 0x08, /* fail */ +/* pos 00f1: 61 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x00F8 state 62) */, + 0x61 /* 'a' */, 0x1A, 0x01 /* (to 0x020E state 250) */, + 0x08, /* fail */ +/* pos 00f8: 62 */ 0xE4 /* 'd' -> */, +/* pos 00f9: 63 */ 0xE9 /* 'i' -> */, +/* pos 00fa: 64 */ 0xE6 /* 'f' -> */, +/* pos 00fb: 65 */ 0xE9 /* 'i' -> */, +/* pos 00fc: 66 */ 0xE5 /* 'e' -> */, +/* pos 00fd: 67 */ 0xE4 /* 'd' -> */, +/* pos 00fe: 68 */ 0xAD /* '-' -> */, +/* pos 00ff: 69 */ 0xF3 /* 's' -> */, +/* pos 0100: 70 */ 0xE9 /* 'i' -> */, +/* pos 0101: 71 */ 0xEE /* 'n' -> */, +/* pos 0102: 72 */ 0xE3 /* 'c' -> */, +/* pos 0103: 73 */ 0xE5 /* 'e' -> */, +/* pos 0104: 74 */ 0xBA /* ':' -> */, +/* pos 0105: 75 */ 0x00, 0x11 /* - terminal marker 17 - */, +/* pos 0107: 76 */ 0xEF /* 'o' -> */, +/* pos 0108: 77 */ 0xEE /* 'n' -> */, +/* pos 0109: 78 */ 0xE5 /* 'e' -> */, +/* pos 010a: 79 */ 0xAD /* '-' -> */, +/* pos 010b: 80 */ 0xED /* 'm' -> */, +/* pos 010c: 81 */ 0xE1 /* 'a' -> */, +/* pos 010d: 82 */ 0xF4 /* 't' -> */, +/* pos 010e: 83 */ 0xE3 /* 'c' -> */, +/* pos 010f: 84 */ 0xE8 /* 'h' -> */, +/* pos 0110: 85 */ 0xBA /* ':' -> */, +/* pos 0111: 86 */ 0x00, 0x12 /* - terminal marker 18 - */, +/* pos 0113: 87 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x0120 state 88) */, + 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x012A state 97) */, + 0x72 /* 'r' */, 0x8E, 0x00 /* (to 0x01A7 state 171) */, + 0x63 /* 'c' */, 0xFB, 0x01 /* (to 0x0317 state 435) */, + 0x08, /* fail */ +/* pos 0120: 88 */ 0xEE /* 'n' -> */, +/* pos 0121: 89 */ 0xE3 /* 'c' -> */, +/* pos 0122: 90 */ 0xEF /* 'o' -> */, +/* pos 0123: 91 */ 0xE4 /* 'd' -> */, +/* pos 0124: 92 */ 0xE9 /* 'i' -> */, +/* pos 0125: 93 */ 0xEE /* 'n' -> */, +/* pos 0126: 94 */ 0xE7 /* 'g' -> */, +/* pos 0127: 95 */ 0xBA /* ':' -> */, +/* pos 0128: 96 */ 0x00, 0x13 /* - terminal marker 19 - */, +/* pos 012a: 97 */ 0xE1 /* 'a' -> */, +/* pos 012b: 98 */ 0xEE /* 'n' -> */, +/* pos 012c: 99 */ 0xE7 /* 'g' -> */, +/* pos 012d: 100 */ 0xF5 /* 'u' -> */, +/* pos 012e: 101 */ 0xE1 /* 'a' -> */, +/* pos 012f: 102 */ 0xE7 /* 'g' -> */, +/* pos 0130: 103 */ 0xE5 /* 'e' -> */, +/* pos 0131: 104 */ 0xBA /* ':' -> */, +/* pos 0132: 105 */ 0x00, 0x14 /* - terminal marker 20 - */, +/* pos 0134: 106 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x013B state 107) */, + 0x6F /* 'o' */, 0x05, 0x02 /* (to 0x033C state 469) */, + 0x08, /* fail */ +/* pos 013b: 107 */ 0xE7 /* 'g' -> */, +/* pos 013c: 108 */ 0xED /* 'm' -> */, +/* pos 013d: 109 */ 0xE1 /* 'a' -> */, +/* pos 013e: 110 */ 0xBA /* ':' -> */, +/* pos 013f: 111 */ 0x00, 0x15 /* - terminal marker 21 - */, +/* pos 0141: 112 */ 0xE3 /* 'c' -> */, +/* pos 0142: 113 */ 0xE8 /* 'h' -> */, +/* pos 0143: 114 */ 0xE5 /* 'e' -> */, +/* pos 0144: 115 */ 0xAD /* '-' -> */, +/* pos 0145: 116 */ 0xE3 /* 'c' -> */, +/* pos 0146: 117 */ 0xEF /* 'o' -> */, +/* pos 0147: 118 */ 0xEE /* 'n' -> */, +/* pos 0148: 119 */ 0xF4 /* 't' -> */, +/* pos 0149: 120 */ 0xF2 /* 'r' -> */, +/* pos 014a: 121 */ 0xEF /* 'o' -> */, +/* pos 014b: 122 */ 0xEC /* 'l' -> */, +/* pos 014c: 123 */ 0xBA /* ':' -> */, +/* pos 014d: 124 */ 0x00, 0x16 /* - terminal marker 22 - */, +/* pos 014f: 125 */ 0xF4 /* 't' -> */, +/* pos 0150: 126 */ 0xE8 /* 'h' -> */, +/* pos 0151: 127 */ 0xEF /* 'o' -> */, +/* pos 0152: 128 */ 0xF2 /* 'r' -> */, +/* pos 0153: 129 */ 0xE9 /* 'i' -> */, +/* pos 0154: 130 */ 0xFA /* 'z' -> */, +/* pos 0155: 131 */ 0xE1 /* 'a' -> */, +/* pos 0156: 132 */ 0xF4 /* 't' -> */, +/* pos 0157: 133 */ 0xE9 /* 'i' -> */, +/* pos 0158: 134 */ 0xEF /* 'o' -> */, +/* pos 0159: 135 */ 0xEE /* 'n' -> */, +/* pos 015a: 136 */ 0xBA /* ':' -> */, +/* pos 015b: 137 */ 0x00, 0x17 /* - terminal marker 23 - */, +/* pos 015d: 138 */ 0xEB /* 'k' -> */, +/* pos 015e: 139 */ 0xE9 /* 'i' -> */, +/* pos 015f: 140 */ 0xE5 /* 'e' -> */, +/* pos 0160: 141 */ 0xBA /* ':' -> */, +/* pos 0161: 142 */ 0x00, 0x18 /* - terminal marker 24 - */, +/* pos 0163: 143 */ 0xE5 /* 'e' -> */, +/* pos 0164: 144 */ 0xEE /* 'n' -> */, +/* pos 0165: 145 */ 0xF4 /* 't' -> */, +/* pos 0166: 146 */ 0xAD /* '-' -> */, +/* pos 0167: 147 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0177 state 148) */, + 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0188 state 155) */, + 0x64 /* 'd' */, 0x4C, 0x00 /* (to 0x01B9 state 186) */, + 0x65 /* 'e' */, 0x56, 0x00 /* (to 0x01C6 state 198) */, + 0x72 /* 'r' */, 0x6F, 0x00 /* (to 0x01E2 state 223) */, + 0x08, /* fail */ +/* pos 0177: 148 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0181 state 149) */, + 0x61 /* 'a' */, 0x56, 0x00 /* (to 0x01D0 state 207) */, + 0x6F /* 'o' */, 0x5C, 0x00 /* (to 0x01D9 state 215) */, + 0x08, /* fail */ +/* pos 0181: 149 */ 0xEE /* 'n' -> */, +/* pos 0182: 150 */ 0xE7 /* 'g' -> */, +/* pos 0183: 151 */ 0xF4 /* 't' -> */, +/* pos 0184: 152 */ 0xE8 /* 'h' -> */, +/* pos 0185: 153 */ 0xBA /* ':' -> */, +/* pos 0186: 154 */ 0x00, 0x19 /* - terminal marker 25 - */, +/* pos 0188: 155 */ 0xF9 /* 'y' -> */, +/* pos 0189: 156 */ 0xF0 /* 'p' -> */, +/* pos 018a: 157 */ 0xE5 /* 'e' -> */, +/* pos 018b: 158 */ 0xBA /* ':' -> */, +/* pos 018c: 159 */ 0x00, 0x1A /* - terminal marker 26 - */, +/* pos 018e: 160 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0195 state 161) */, + 0x65 /* 'e' */, 0x23, 0x02 /* (to 0x03B4 state 562) */, + 0x08, /* fail */ +/* pos 0195: 161 */ 0xF4 /* 't' -> */, +/* pos 0196: 162 */ 0xE5 /* 'e' -> */, +/* pos 0197: 163 */ 0xBA /* ':' -> */, +/* pos 0198: 164 */ 0x00, 0x1B /* - terminal marker 27 - */, +/* pos 019a: 165 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01A1 state 166) */, + 0x65 /* 'e' */, 0xB6, 0x00 /* (to 0x0253 state 304) */, + 0x08, /* fail */ +/* pos 01a1: 166 */ 0xEE /* 'n' -> */, +/* pos 01a2: 167 */ 0xE7 /* 'g' -> */, +/* pos 01a3: 168 */ 0xE5 /* 'e' -> */, +/* pos 01a4: 169 */ 0xBA /* ':' -> */, +/* pos 01a5: 170 */ 0x00, 0x1C /* - terminal marker 28 - */, +/* pos 01a7: 171 */ 0xE1 /* 'a' -> */, +/* pos 01a8: 172 */ 0xEE /* 'n' -> */, +/* pos 01a9: 173 */ 0xE7 /* 'g' -> */, +/* pos 01aa: 174 */ 0xE5 /* 'e' -> */, +/* pos 01ab: 175 */ 0xF3 /* 's' -> */, +/* pos 01ac: 176 */ 0xBA /* ':' -> */, +/* pos 01ad: 177 */ 0x00, 0x27 /* - terminal marker 39 - */, +/* pos 01af: 178 */ 0xE5 /* 'e' -> */, +/* pos 01b0: 179 */ 0xBA /* ':' -> */, +/* pos 01b1: 180 */ 0x00, 0x29 /* - terminal marker 41 - */, +/* pos 01b3: 181 */ 0xEC /* 'l' -> */, +/* pos 01b4: 182 */ 0xEF /* 'o' -> */, +/* pos 01b5: 183 */ 0xF7 /* 'w' -> */, +/* pos 01b6: 184 */ 0xBA /* ':' -> */, +/* pos 01b7: 185 */ 0x00, 0x2A /* - terminal marker 42 - */, +/* pos 01b9: 186 */ 0xE9 /* 'i' -> */, +/* pos 01ba: 187 */ 0xF3 /* 's' -> */, +/* pos 01bb: 188 */ 0xF0 /* 'p' -> */, +/* pos 01bc: 189 */ 0xEF /* 'o' -> */, +/* pos 01bd: 190 */ 0xF3 /* 's' -> */, +/* pos 01be: 191 */ 0xE9 /* 'i' -> */, +/* pos 01bf: 192 */ 0xF4 /* 't' -> */, +/* pos 01c0: 193 */ 0xE9 /* 'i' -> */, +/* pos 01c1: 194 */ 0xEF /* 'o' -> */, +/* pos 01c2: 195 */ 0xEE /* 'n' -> */, +/* pos 01c3: 196 */ 0xBA /* ':' -> */, +/* pos 01c4: 197 */ 0x00, 0x2B /* - terminal marker 43 - */, +/* pos 01c6: 198 */ 0xEE /* 'n' -> */, +/* pos 01c7: 199 */ 0xE3 /* 'c' -> */, +/* pos 01c8: 200 */ 0xEF /* 'o' -> */, +/* pos 01c9: 201 */ 0xE4 /* 'd' -> */, +/* pos 01ca: 202 */ 0xE9 /* 'i' -> */, +/* pos 01cb: 203 */ 0xEE /* 'n' -> */, +/* pos 01cc: 204 */ 0xE7 /* 'g' -> */, +/* pos 01cd: 205 */ 0xBA /* ':' -> */, +/* pos 01ce: 206 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 01d0: 207 */ 0xEE /* 'n' -> */, +/* pos 01d1: 208 */ 0xE7 /* 'g' -> */, +/* pos 01d2: 209 */ 0xF5 /* 'u' -> */, +/* pos 01d3: 210 */ 0xE1 /* 'a' -> */, +/* pos 01d4: 211 */ 0xE7 /* 'g' -> */, +/* pos 01d5: 212 */ 0xE5 /* 'e' -> */, +/* pos 01d6: 213 */ 0xBA /* ':' -> */, +/* pos 01d7: 214 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 01d9: 215 */ 0xE3 /* 'c' -> */, +/* pos 01da: 216 */ 0xE1 /* 'a' -> */, +/* pos 01db: 217 */ 0xF4 /* 't' -> */, +/* pos 01dc: 218 */ 0xE9 /* 'i' -> */, +/* pos 01dd: 219 */ 0xEF /* 'o' -> */, +/* pos 01de: 220 */ 0xEE /* 'n' -> */, +/* pos 01df: 221 */ 0xBA /* ':' -> */, +/* pos 01e0: 222 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 01e2: 223 */ 0xE1 /* 'a' -> */, +/* pos 01e3: 224 */ 0xEE /* 'n' -> */, +/* pos 01e4: 225 */ 0xE7 /* 'g' -> */, +/* pos 01e5: 226 */ 0xE5 /* 'e' -> */, +/* pos 01e6: 227 */ 0xBA /* ':' -> */, +/* pos 01e7: 228 */ 0x00, 0x2F /* - terminal marker 47 - */, +/* pos 01e9: 229 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x01F0 state 230) */, + 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x01F5 state 234) */, + 0x08, /* fail */ +/* pos 01f0: 230 */ 0xE1 /* 'a' -> */, +/* pos 01f1: 231 */ 0xE7 /* 'g' -> */, +/* pos 01f2: 232 */ 0xBA /* ':' -> */, +/* pos 01f3: 233 */ 0x00, 0x30 /* - terminal marker 48 - */, +/* pos 01f5: 234 */ 0xF0 /* 'p' -> */, +/* pos 01f6: 235 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01FD state 236) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0202 state 240) */, + 0x08, /* fail */ +/* pos 01fd: 236 */ 0xE3 /* 'c' -> */, +/* pos 01fe: 237 */ 0xF4 /* 't' -> */, +/* pos 01ff: 238 */ 0xBA /* ':' -> */, +/* pos 0200: 239 */ 0x00, 0x31 /* - terminal marker 49 - */, +/* pos 0202: 240 */ 0xF2 /* 'r' -> */, +/* pos 0203: 241 */ 0xE5 /* 'e' -> */, +/* pos 0204: 242 */ 0xF3 /* 's' -> */, +/* pos 0205: 243 */ 0xBA /* ':' -> */, +/* pos 0206: 244 */ 0x00, 0x32 /* - terminal marker 50 - */, +/* pos 0208: 245 */ 0xF2 /* 'r' -> */, +/* pos 0209: 246 */ 0xEF /* 'o' -> */, +/* pos 020a: 247 */ 0xED /* 'm' -> */, +/* pos 020b: 248 */ 0xBA /* ':' -> */, +/* pos 020c: 249 */ 0x00, 0x33 /* - terminal marker 51 - */, +/* pos 020e: 250 */ 0xF4 /* 't' -> */, +/* pos 020f: 251 */ 0xE3 /* 'c' -> */, +/* pos 0210: 252 */ 0xE8 /* 'h' -> */, +/* pos 0211: 253 */ 0xBA /* ':' -> */, +/* pos 0212: 254 */ 0x00, 0x34 /* - terminal marker 52 - */, +/* pos 0214: 255 */ 0xE1 /* 'a' -> */, +/* pos 0215: 256 */ 0xEE /* 'n' -> */, +/* pos 0216: 257 */ 0xE7 /* 'g' -> */, +/* pos 0217: 258 */ 0xE5 /* 'e' -> */, +/* pos 0218: 259 */ 0xBA /* ':' -> */, +/* pos 0219: 260 */ 0x00, 0x35 /* - terminal marker 53 - */, +/* pos 021b: 261 */ 0xEE /* 'n' -> */, +/* pos 021c: 262 */ 0xED /* 'm' -> */, +/* pos 021d: 263 */ 0xEF /* 'o' -> */, +/* pos 021e: 264 */ 0xE4 /* 'd' -> */, +/* pos 021f: 265 */ 0xE9 /* 'i' -> */, +/* pos 0220: 266 */ 0xE6 /* 'f' -> */, +/* pos 0221: 267 */ 0xE9 /* 'i' -> */, +/* pos 0222: 268 */ 0xE5 /* 'e' -> */, +/* pos 0223: 269 */ 0xE4 /* 'd' -> */, +/* pos 0224: 270 */ 0xAD /* '-' -> */, +/* pos 0225: 271 */ 0xF3 /* 's' -> */, +/* pos 0226: 272 */ 0xE9 /* 'i' -> */, +/* pos 0227: 273 */ 0xEE /* 'n' -> */, +/* pos 0228: 274 */ 0xE3 /* 'c' -> */, +/* pos 0229: 275 */ 0xE5 /* 'e' -> */, +/* pos 022a: 276 */ 0xBA /* ':' -> */, +/* pos 022b: 277 */ 0x00, 0x36 /* - terminal marker 54 - */, +/* pos 022d: 278 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0237 state 279) */, + 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x0245 state 292) */, + 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x024A state 296) */, + 0x08, /* fail */ +/* pos 0237: 279 */ 0xF3 /* 's' -> */, +/* pos 0238: 280 */ 0xF4 /* 't' -> */, +/* pos 0239: 281 */ 0xAD /* '-' -> */, +/* pos 023a: 282 */ 0xED /* 'm' -> */, +/* pos 023b: 283 */ 0xEF /* 'o' -> */, +/* pos 023c: 284 */ 0xE4 /* 'd' -> */, +/* pos 023d: 285 */ 0xE9 /* 'i' -> */, +/* pos 023e: 286 */ 0xE6 /* 'f' -> */, +/* pos 023f: 287 */ 0xE9 /* 'i' -> */, +/* pos 0240: 288 */ 0xE5 /* 'e' -> */, +/* pos 0241: 289 */ 0xE4 /* 'd' -> */, +/* pos 0242: 290 */ 0xBA /* ':' -> */, +/* pos 0243: 291 */ 0x00, 0x37 /* - terminal marker 55 - */, +/* pos 0245: 292 */ 0xEE /* 'n' -> */, +/* pos 0246: 293 */ 0xEB /* 'k' -> */, +/* pos 0247: 294 */ 0xBA /* ':' -> */, +/* pos 0248: 295 */ 0x00, 0x38 /* - terminal marker 56 - */, +/* pos 024a: 296 */ 0xE3 /* 'c' -> */, +/* pos 024b: 297 */ 0xE1 /* 'a' -> */, +/* pos 024c: 298 */ 0xF4 /* 't' -> */, +/* pos 024d: 299 */ 0xE9 /* 'i' -> */, +/* pos 024e: 300 */ 0xEF /* 'o' -> */, +/* pos 024f: 301 */ 0xEE /* 'n' -> */, +/* pos 0250: 302 */ 0xBA /* ':' -> */, +/* pos 0251: 303 */ 0x00, 0x39 /* - terminal marker 57 - */, +/* pos 0253: 304 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x025D state 305) */, + 0x74 /* 't' */, 0x14, 0x00 /* (to 0x026A state 311) */, + 0x70 /* 'p' */, 0x6F, 0x01 /* (to 0x03C8 state 578) */, + 0x08, /* fail */ +/* pos 025d: 305 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0264 state 306) */, + 0x65 /* 'e' */, 0xB1, 0x00 /* (to 0x0311 state 430) */, + 0x08, /* fail */ +/* pos 0264: 306 */ 0xE5 /* 'e' -> */, +/* pos 0265: 307 */ 0xF3 /* 's' -> */, +/* pos 0266: 308 */ 0xE8 /* 'h' -> */, +/* pos 0267: 309 */ 0xBA /* ':' -> */, +/* pos 0268: 310 */ 0x00, 0x3D /* - terminal marker 61 - */, +/* pos 026a: 311 */ 0xF2 /* 'r' -> */, +/* pos 026b: 312 */ 0xF9 /* 'y' -> */, +/* pos 026c: 313 */ 0xAD /* '-' -> */, +/* pos 026d: 314 */ 0xE1 /* 'a' -> */, +/* pos 026e: 315 */ 0xE6 /* 'f' -> */, +/* pos 026f: 316 */ 0xF4 /* 't' -> */, +/* pos 0270: 317 */ 0xE5 /* 'e' -> */, +/* pos 0271: 318 */ 0xF2 /* 'r' -> */, +/* pos 0272: 319 */ 0xBA /* ':' -> */, +/* pos 0273: 320 */ 0x00, 0x3E /* - terminal marker 62 - */, +/* pos 0275: 321 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x027C state 322) */, + 0x74 /* 't' */, 0xED, 0x00 /* (to 0x0365 state 496) */, + 0x08, /* fail */ +/* pos 027c: 322 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x0286 state 323) */, + 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x028C state 328) */, + 0x63 /* 'c' */, 0x52, 0x01 /* (to 0x03D4 state 589) */, + 0x08, /* fail */ +/* pos 0286: 323 */ 0xF6 /* 'v' -> */, +/* pos 0287: 324 */ 0xE5 /* 'e' -> */, +/* pos 0288: 325 */ 0xF2 /* 'r' -> */, +/* pos 0289: 326 */ 0xBA /* ':' -> */, +/* pos 028a: 327 */ 0x00, 0x3F /* - terminal marker 63 - */, +/* pos 028c: 328 */ 0xAD /* '-' -> */, +/* pos 028d: 329 */ 0xE3 /* 'c' -> */, +/* pos 028e: 330 */ 0xEF /* 'o' -> */, +/* pos 028f: 331 */ 0xEF /* 'o' -> */, +/* pos 0290: 332 */ 0xEB /* 'k' -> */, +/* pos 0291: 333 */ 0xE9 /* 'i' -> */, +/* pos 0292: 334 */ 0xE5 /* 'e' -> */, +/* pos 0293: 335 */ 0xBA /* ':' -> */, +/* pos 0294: 336 */ 0x00, 0x40 /* - terminal marker 64 - */, +/* pos 0296: 337 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x029D state 338) */, + 0x65 /* 'e' */, 0x2C, 0x01 /* (to 0x03C5 state 576) */, + 0x08, /* fail */ +/* pos 029d: 338 */ 0xE1 /* 'a' -> */, +/* pos 029e: 339 */ 0xEE /* 'n' -> */, +/* pos 029f: 340 */ 0xF3 /* 's' -> */, +/* pos 02a0: 341 */ 0xE6 /* 'f' -> */, +/* pos 02a1: 342 */ 0xE5 /* 'e' -> */, +/* pos 02a2: 343 */ 0xF2 /* 'r' -> */, +/* pos 02a3: 344 */ 0xAD /* '-' -> */, +/* pos 02a4: 345 */ 0xE5 /* 'e' -> */, +/* pos 02a5: 346 */ 0xEE /* 'n' -> */, +/* pos 02a6: 347 */ 0xE3 /* 'c' -> */, +/* pos 02a7: 348 */ 0xEF /* 'o' -> */, +/* pos 02a8: 349 */ 0xE4 /* 'd' -> */, +/* pos 02a9: 350 */ 0xE9 /* 'i' -> */, +/* pos 02aa: 351 */ 0xEE /* 'n' -> */, +/* pos 02ab: 352 */ 0xE7 /* 'g' -> */, +/* pos 02ac: 353 */ 0xBA /* ':' -> */, +/* pos 02ad: 354 */ 0x00, 0x42 /* - terminal marker 66 - */, +/* pos 02af: 355 */ 0xE9 /* 'i' -> */, +/* pos 02b0: 356 */ 0xAD /* '-' -> */, +/* pos 02b1: 357 */ 0xE1 /* 'a' -> */, +/* pos 02b2: 358 */ 0xF2 /* 'r' -> */, +/* pos 02b3: 359 */ 0xE7 /* 'g' -> */, +/* pos 02b4: 360 */ 0xF3 /* 's' -> */, +/* pos 02b5: 361 */ 0x00, 0x47 /* - terminal marker 71 - */, +/* pos 02b7: 362 */ 0xA0 /* ' ' -> */, +/* pos 02b8: 363 */ 0x00, 0x48 /* - terminal marker 72 - */, +/* pos 02ba: 364 */ 0xAD /* '-' -> */, +/* pos 02bb: 365 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02C5 state 366) */, + 0x61 /* 'a' */, 0x1D, 0x00 /* (to 0x02DB state 385) */, + 0x72 /* 'r' */, 0xFB, 0x00 /* (to 0x03BC state 568) */, + 0x08, /* fail */ +/* pos 02c5: 366 */ 0xEF /* 'o' -> */, +/* pos 02c6: 367 */ 0xF2 /* 'r' -> */, +/* pos 02c7: 368 */ 0xF7 /* 'w' -> */, +/* pos 02c8: 369 */ 0xE1 /* 'a' -> */, +/* pos 02c9: 370 */ 0xF2 /* 'r' -> */, +/* pos 02ca: 371 */ 0xE4 /* 'd' -> */, +/* pos 02cb: 372 */ 0xE5 /* 'e' -> */, +/* pos 02cc: 373 */ 0xE4 /* 'd' -> */, +/* pos 02cd: 374 */ 0xAD /* '-' -> */, +/* pos 02ce: 375 */ 0xE6 /* 'f' -> */, +/* pos 02cf: 376 */ 0xEF /* 'o' -> */, +/* pos 02d0: 377 */ 0xF2 /* 'r' -> */, +/* pos 02d1: 378 */ 0xBA /* ':' -> */, +/* pos 02d2: 379 */ 0x00, 0x49 /* - terminal marker 73 - */, +/* pos 02d4: 380 */ 0x00, 0x4A /* - terminal marker 74 - */, +/* pos 02d6: 381 */ 0xE1 /* 'a' -> */, +/* pos 02d7: 382 */ 0xE4 /* 'd' -> */, +/* pos 02d8: 383 */ 0xA0 /* ' ' -> */, +/* pos 02d9: 384 */ 0x00, 0x4B /* - terminal marker 75 - */, +/* pos 02db: 385 */ 0xF5 /* 'u' -> */, +/* pos 02dc: 386 */ 0xF4 /* 't' -> */, +/* pos 02dd: 387 */ 0xE8 /* 'h' -> */, +/* pos 02de: 388 */ 0xAD /* '-' -> */, +/* pos 02df: 389 */ 0xF4 /* 't' -> */, +/* pos 02e0: 390 */ 0xEF /* 'o' -> */, +/* pos 02e1: 391 */ 0xEB /* 'k' -> */, +/* pos 02e2: 392 */ 0xE5 /* 'e' -> */, +/* pos 02e3: 393 */ 0xEE /* 'n' -> */, +/* pos 02e4: 394 */ 0xBA /* ':' -> */, +/* pos 02e5: 395 */ 0x00, 0x4F /* - terminal marker 79 - */, +/* pos 02e7: 396 */ 0xF4 /* 't' -> */, +/* pos 02e8: 397 */ 0xE9 /* 'i' -> */, +/* pos 02e9: 398 */ 0xEF /* 'o' -> */, +/* pos 02ea: 399 */ 0xEE /* 'n' -> */, +/* pos 02eb: 400 */ 0xF3 /* 's' -> */, +/* pos 02ec: 401 */ 0xA0 /* ' ' -> */, +/* pos 02ed: 402 */ 0x00, 0x02 /* - terminal marker 2 - */, +/* pos 02ef: 403 */ 0xF3 /* 's' -> */, +/* pos 02f0: 404 */ 0xAD /* '-' -> */, +/* pos 02f1: 405 */ 0xE3 /* 'c' -> */, +/* pos 02f2: 406 */ 0xEF /* 'o' -> */, +/* pos 02f3: 407 */ 0xEE /* 'n' -> */, +/* pos 02f4: 408 */ 0xF4 /* 't' -> */, +/* pos 02f5: 409 */ 0xF2 /* 'r' -> */, +/* pos 02f6: 410 */ 0xEF /* 'o' -> */, +/* pos 02f7: 411 */ 0xEC /* 'l' -> */, +/* pos 02f8: 412 */ 0xAD /* '-' -> */, +/* pos 02f9: 413 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0300 state 414) */, + 0x61 /* 'a' */, 0x24, 0x00 /* (to 0x0320 state 443) */, + 0x08, /* fail */ +/* pos 0300: 414 */ 0xE5 /* 'e' -> */, +/* pos 0301: 415 */ 0xF1 /* 'q' -> */, +/* pos 0302: 416 */ 0xF5 /* 'u' -> */, +/* pos 0303: 417 */ 0xE5 /* 'e' -> */, +/* pos 0304: 418 */ 0xF3 /* 's' -> */, +/* pos 0305: 419 */ 0xF4 /* 't' -> */, +/* pos 0306: 420 */ 0xAD /* '-' -> */, +/* pos 0307: 421 */ 0xE8 /* 'h' -> */, +/* pos 0308: 422 */ 0xE5 /* 'e' -> */, +/* pos 0309: 423 */ 0xE1 /* 'a' -> */, +/* pos 030a: 424 */ 0xE4 /* 'd' -> */, +/* pos 030b: 425 */ 0xE5 /* 'e' -> */, +/* pos 030c: 426 */ 0xF2 /* 'r' -> */, +/* pos 030d: 427 */ 0xF3 /* 's' -> */, +/* pos 030e: 428 */ 0xBA /* ':' -> */, +/* pos 030f: 429 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 0311: 430 */ 0xF2 /* 'r' -> */, +/* pos 0312: 431 */ 0xE5 /* 'e' -> */, +/* pos 0313: 432 */ 0xF2 /* 'r' -> */, +/* pos 0314: 433 */ 0xBA /* ':' -> */, +/* pos 0315: 434 */ 0x00, 0x1D /* - terminal marker 29 - */, +/* pos 0317: 435 */ 0xE8 /* 'h' -> */, +/* pos 0318: 436 */ 0xE1 /* 'a' -> */, +/* pos 0319: 437 */ 0xF2 /* 'r' -> */, +/* pos 031a: 438 */ 0xF3 /* 's' -> */, +/* pos 031b: 439 */ 0xE5 /* 'e' -> */, +/* pos 031c: 440 */ 0xF4 /* 't' -> */, +/* pos 031d: 441 */ 0xBA /* ':' -> */, +/* pos 031e: 442 */ 0x00, 0x26 /* - terminal marker 38 - */, +/* pos 0320: 443 */ 0xEC /* 'l' -> */, +/* pos 0321: 444 */ 0xEC /* 'l' -> */, +/* pos 0322: 445 */ 0xEF /* 'o' -> */, +/* pos 0323: 446 */ 0xF7 /* 'w' -> */, +/* pos 0324: 447 */ 0xAD /* '-' -> */, +/* pos 0325: 448 */ 0xEF /* 'o' -> */, +/* pos 0326: 449 */ 0xF2 /* 'r' -> */, +/* pos 0327: 450 */ 0xE9 /* 'i' -> */, +/* pos 0328: 451 */ 0xE7 /* 'g' -> */, +/* pos 0329: 452 */ 0xE9 /* 'i' -> */, +/* pos 032a: 453 */ 0xEE /* 'n' -> */, +/* pos 032b: 454 */ 0xBA /* ':' -> */, +/* pos 032c: 455 */ 0x00, 0x28 /* - terminal marker 40 - */, +/* pos 032e: 456 */ 0xE1 /* 'a' -> */, +/* pos 032f: 457 */ 0xF8 /* 'x' -> */, +/* pos 0330: 458 */ 0xAD /* '-' -> */, +/* pos 0331: 459 */ 0xE6 /* 'f' -> */, +/* pos 0332: 460 */ 0xEF /* 'o' -> */, +/* pos 0333: 461 */ 0xF2 /* 'r' -> */, +/* pos 0334: 462 */ 0xF7 /* 'w' -> */, +/* pos 0335: 463 */ 0xE1 /* 'a' -> */, +/* pos 0336: 464 */ 0xF2 /* 'r' -> */, +/* pos 0337: 465 */ 0xE4 /* 'd' -> */, +/* pos 0338: 466 */ 0xF3 /* 's' -> */, +/* pos 0339: 467 */ 0xBA /* ':' -> */, +/* pos 033a: 468 */ 0x00, 0x3A /* - terminal marker 58 - */, +/* pos 033c: 469 */ 0xF8 /* 'x' -> */, +/* pos 033d: 470 */ 0xF9 /* 'y' -> */, +/* pos 033e: 471 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x0345 state 472) */, + 0x20 /* ' ' */, 0x79, 0x00 /* (to 0x03BA state 567) */, + 0x08, /* fail */ +/* pos 0345: 472 */ 0xE1 /* 'a' -> */, +/* pos 0346: 473 */ 0xF5 /* 'u' -> */, +/* pos 0347: 474 */ 0xF4 /* 't' -> */, +/* pos 0348: 475 */ 0xE8 /* 'h' -> */, +/* pos 0349: 476 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0350 state 477) */, + 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x035A state 486) */, + 0x08, /* fail */ +/* pos 0350: 477 */ 0xEE /* 'n' -> */, +/* pos 0351: 478 */ 0xF4 /* 't' -> */, +/* pos 0352: 479 */ 0xE9 /* 'i' -> */, +/* pos 0353: 480 */ 0xE3 /* 'c' -> */, +/* pos 0354: 481 */ 0xE1 /* 'a' -> */, +/* pos 0355: 482 */ 0xF4 /* 't' -> */, +/* pos 0356: 483 */ 0xE5 /* 'e' -> */, +/* pos 0357: 484 */ 0xBA /* ':' -> */, +/* pos 0358: 485 */ 0x00, 0x3B /* - terminal marker 59 - */, +/* pos 035a: 486 */ 0xF2 /* 'r' -> */, +/* pos 035b: 487 */ 0xE9 /* 'i' -> */, +/* pos 035c: 488 */ 0xFA /* 'z' -> */, +/* pos 035d: 489 */ 0xE1 /* 'a' -> */, +/* pos 035e: 490 */ 0xF4 /* 't' -> */, +/* pos 035f: 491 */ 0xE9 /* 'i' -> */, +/* pos 0360: 492 */ 0xEF /* 'o' -> */, +/* pos 0361: 493 */ 0xEE /* 'n' -> */, +/* pos 0362: 494 */ 0xBA /* ':' -> */, +/* pos 0363: 495 */ 0x00, 0x3C /* - terminal marker 60 - */, +/* pos 0365: 496 */ 0xF2 /* 'r' -> */, +/* pos 0366: 497 */ 0xE9 /* 'i' -> */, +/* pos 0367: 498 */ 0xE3 /* 'c' -> */, +/* pos 0368: 499 */ 0xF4 /* 't' -> */, +/* pos 0369: 500 */ 0xAD /* '-' -> */, +/* pos 036a: 501 */ 0xF4 /* 't' -> */, +/* pos 036b: 502 */ 0xF2 /* 'r' -> */, +/* pos 036c: 503 */ 0xE1 /* 'a' -> */, +/* pos 036d: 504 */ 0xEE /* 'n' -> */, +/* pos 036e: 505 */ 0xF3 /* 's' -> */, +/* pos 036f: 506 */ 0xF0 /* 'p' -> */, +/* pos 0370: 507 */ 0xEF /* 'o' -> */, +/* pos 0371: 508 */ 0xF2 /* 'r' -> */, +/* pos 0372: 509 */ 0xF4 /* 't' -> */, +/* pos 0373: 510 */ 0xAD /* '-' -> */, +/* pos 0374: 511 */ 0xF3 /* 's' -> */, +/* pos 0375: 512 */ 0xE5 /* 'e' -> */, +/* pos 0376: 513 */ 0xE3 /* 'c' -> */, +/* pos 0377: 514 */ 0xF5 /* 'u' -> */, +/* pos 0378: 515 */ 0xF2 /* 'r' -> */, +/* pos 0379: 516 */ 0xE9 /* 'i' -> */, +/* pos 037a: 517 */ 0xF4 /* 't' -> */, +/* pos 037b: 518 */ 0xF9 /* 'y' -> */, +/* pos 037c: 519 */ 0xBA /* ':' -> */, +/* pos 037d: 520 */ 0x00, 0x41 /* - terminal marker 65 - */, +/* pos 037f: 521 */ 0xE5 /* 'e' -> */, +/* pos 0380: 522 */ 0xF2 /* 'r' -> */, +/* pos 0381: 523 */ 0xAD /* '-' -> */, +/* pos 0382: 524 */ 0xE1 /* 'a' -> */, +/* pos 0383: 525 */ 0xE7 /* 'g' -> */, +/* pos 0384: 526 */ 0xE5 /* 'e' -> */, +/* pos 0385: 527 */ 0xEE /* 'n' -> */, +/* pos 0386: 528 */ 0xF4 /* 't' -> */, +/* pos 0387: 529 */ 0xBA /* ':' -> */, +/* pos 0388: 530 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 038a: 531 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0391 state 532) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0396 state 536) */, + 0x08, /* fail */ +/* pos 0391: 532 */ 0xF2 /* 'r' -> */, +/* pos 0392: 533 */ 0xF9 /* 'y' -> */, +/* pos 0393: 534 */ 0xBA /* ':' -> */, +/* pos 0394: 535 */ 0x00, 0x44 /* - terminal marker 68 - */, +/* pos 0396: 536 */ 0xE1 /* 'a' -> */, +/* pos 0397: 537 */ 0xBA /* ':' -> */, +/* pos 0398: 538 */ 0x00, 0x45 /* - terminal marker 69 - */, +/* pos 039a: 539 */ 0xF7 /* 'w' -> */, +/* pos 039b: 540 */ 0xF7 /* 'w' -> */, +/* pos 039c: 541 */ 0xAD /* '-' -> */, +/* pos 039d: 542 */ 0xE1 /* 'a' -> */, +/* pos 039e: 543 */ 0xF5 /* 'u' -> */, +/* pos 039f: 544 */ 0xF4 /* 't' -> */, +/* pos 03a0: 545 */ 0xE8 /* 'h' -> */, +/* pos 03a1: 546 */ 0xE5 /* 'e' -> */, +/* pos 03a2: 547 */ 0xEE /* 'n' -> */, +/* pos 03a3: 548 */ 0xF4 /* 't' -> */, +/* pos 03a4: 549 */ 0xE9 /* 'i' -> */, +/* pos 03a5: 550 */ 0xE3 /* 'c' -> */, +/* pos 03a6: 551 */ 0xE1 /* 'a' -> */, +/* pos 03a7: 552 */ 0xF4 /* 't' -> */, +/* pos 03a8: 553 */ 0xE5 /* 'e' -> */, +/* pos 03a9: 554 */ 0xBA /* ':' -> */, +/* pos 03aa: 555 */ 0x00, 0x46 /* - terminal marker 70 - */, +/* pos 03ac: 556 */ 0xF4 /* 't' -> */, +/* pos 03ad: 557 */ 0xE3 /* 'c' -> */, +/* pos 03ae: 558 */ 0xE8 /* 'h' -> */, +/* pos 03af: 559 */ 0x00, 0x3F /* - terminal marker 63 - */, +/* pos 03b1: 560 */ 0xF4 /* 't' -> */, +/* pos 03b2: 561 */ 0x00, 0x40 /* - terminal marker 64 - */, +/* pos 03b4: 562 */ 0xEC /* 'l' -> */, +/* pos 03b5: 563 */ 0xE5 /* 'e' -> */, +/* pos 03b6: 564 */ 0xF4 /* 't' -> */, +/* pos 03b7: 565 */ 0xE5 /* 'e' -> */, +/* pos 03b8: 566 */ 0x00, 0x41 /* - terminal marker 65 - */, +/* pos 03ba: 567 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 03bc: 568 */ 0xE5 /* 'e' -> */, +/* pos 03bd: 569 */ 0xE1 /* 'a' -> */, +/* pos 03be: 570 */ 0xEC /* 'l' -> */, +/* pos 03bf: 571 */ 0xAD /* '-' -> */, +/* pos 03c0: 572 */ 0xE9 /* 'i' -> */, +/* pos 03c1: 573 */ 0xF0 /* 'p' -> */, +/* pos 03c2: 574 */ 0xBA /* ':' -> */, +/* pos 03c3: 575 */ 0x00, 0x44 /* - terminal marker 68 - */, +/* pos 03c5: 576 */ 0xBA /* ':' -> */, +/* pos 03c6: 577 */ 0x00, 0x4C /* - terminal marker 76 - */, +/* pos 03c8: 578 */ 0xEC /* 'l' -> */, +/* pos 03c9: 579 */ 0xE1 /* 'a' -> */, +/* pos 03ca: 580 */ 0xF9 /* 'y' -> */, +/* pos 03cb: 581 */ 0xAD /* '-' -> */, +/* pos 03cc: 582 */ 0xEE /* 'n' -> */, +/* pos 03cd: 583 */ 0xEF /* 'o' -> */, +/* pos 03ce: 584 */ 0xEE /* 'n' -> */, +/* pos 03cf: 585 */ 0xE3 /* 'c' -> */, +/* pos 03d0: 586 */ 0xE5 /* 'e' -> */, +/* pos 03d1: 587 */ 0xBA /* ':' -> */, +/* pos 03d2: 588 */ 0x00, 0x4D /* - terminal marker 77 - */, +/* pos 03d4: 589 */ 0xAD /* '-' -> */, +/* pos 03d5: 590 */ 0xF7 /* 'w' -> */, +/* pos 03d6: 591 */ 0xE5 /* 'e' -> */, +/* pos 03d7: 592 */ 0xE2 /* 'b' -> */, +/* pos 03d8: 593 */ 0xF3 /* 's' -> */, +/* pos 03d9: 594 */ 0xEF /* 'o' -> */, +/* pos 03da: 595 */ 0xE3 /* 'c' -> */, +/* pos 03db: 596 */ 0xEB /* 'k' -> */, +/* pos 03dc: 597 */ 0xE5 /* 'e' -> */, +/* pos 03dd: 598 */ 0xF4 /* 't' -> */, +/* pos 03de: 599 */ 0xAD /* '-' -> */, +/* pos 03df: 600 */ 0x64 /* 'd' */, 0x19, 0x00 /* (to 0x03F8 state 601) */, + 0x65 /* 'e' */, 0x1D, 0x00 /* (to 0x03FF state 607) */, + 0x6B /* 'k' */, 0x26, 0x00 /* (to 0x040B state 618) */, + 0x70 /* 'p' */, 0x35, 0x00 /* (to 0x041D state 625) */, + 0x61 /* 'a' */, 0x3C, 0x00 /* (to 0x0427 state 634) */, + 0x6E /* 'n' */, 0x41, 0x00 /* (to 0x042F state 641) */, + 0x76 /* 'v' */, 0x47, 0x00 /* (to 0x0438 state 648) */, + 0x6F /* 'o' */, 0x4D, 0x00 /* (to 0x0441 state 656) */, + 0x08, /* fail */ +/* pos 03f8: 601 */ 0xF2 /* 'r' -> */, +/* pos 03f9: 602 */ 0xE1 /* 'a' -> */, +/* pos 03fa: 603 */ 0xE6 /* 'f' -> */, +/* pos 03fb: 604 */ 0xF4 /* 't' -> */, +/* pos 03fc: 605 */ 0xBA /* ':' -> */, +/* pos 03fd: 606 */ 0x00, 0x06 /* - terminal marker 6 - */, +/* pos 03ff: 607 */ 0xF8 /* 'x' -> */, +/* pos 0400: 608 */ 0xF4 /* 't' -> */, +/* pos 0401: 609 */ 0xE5 /* 'e' -> */, +/* pos 0402: 610 */ 0xEE /* 'n' -> */, +/* pos 0403: 611 */ 0xF3 /* 's' -> */, +/* pos 0404: 612 */ 0xE9 /* 'i' -> */, +/* pos 0405: 613 */ 0xEF /* 'o' -> */, +/* pos 0406: 614 */ 0xEE /* 'n' -> */, +/* pos 0407: 615 */ 0xF3 /* 's' -> */, +/* pos 0408: 616 */ 0xBA /* ':' -> */, +/* pos 0409: 617 */ 0x00, 0x08 /* - terminal marker 8 - */, +/* pos 040b: 618 */ 0xE5 /* 'e' -> */, +/* pos 040c: 619 */ 0xF9 /* 'y' -> */, +/* pos 040d: 620 */ 0x31 /* '1' */, 0x0A, 0x00 /* (to 0x0417 state 621) */, + 0x32 /* '2' */, 0x0A, 0x00 /* (to 0x041A state 623) */, + 0x3A /* ':' */, 0x23, 0x00 /* (to 0x0436 state 647) */, + 0x08, /* fail */ +/* pos 0417: 621 */ 0xBA /* ':' -> */, +/* pos 0418: 622 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 041a: 623 */ 0xBA /* ':' -> */, +/* pos 041b: 624 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 041d: 625 */ 0xF2 /* 'r' -> */, +/* pos 041e: 626 */ 0xEF /* 'o' -> */, +/* pos 041f: 627 */ 0xF4 /* 't' -> */, +/* pos 0420: 628 */ 0xEF /* 'o' -> */, +/* pos 0421: 629 */ 0xE3 /* 'c' -> */, +/* pos 0422: 630 */ 0xEF /* 'o' -> */, +/* pos 0423: 631 */ 0xEC /* 'l' -> */, +/* pos 0424: 632 */ 0xBA /* ':' -> */, +/* pos 0425: 633 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 0427: 634 */ 0xE3 /* 'c' -> */, +/* pos 0428: 635 */ 0xE3 /* 'c' -> */, +/* pos 0429: 636 */ 0xE5 /* 'e' -> */, +/* pos 042a: 637 */ 0xF0 /* 'p' -> */, +/* pos 042b: 638 */ 0xF4 /* 't' -> */, +/* pos 042c: 639 */ 0xBA /* ':' -> */, +/* pos 042d: 640 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 042f: 641 */ 0xEF /* 'o' -> */, +/* pos 0430: 642 */ 0xEE /* 'n' -> */, +/* pos 0431: 643 */ 0xE3 /* 'c' -> */, +/* pos 0432: 644 */ 0xE5 /* 'e' -> */, +/* pos 0433: 645 */ 0xBA /* ':' -> */, +/* pos 0434: 646 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 0436: 647 */ 0x00, 0x1E /* - terminal marker 30 - */, +/* pos 0438: 648 */ 0xE5 /* 'e' -> */, +/* pos 0439: 649 */ 0xF2 /* 'r' -> */, +/* pos 043a: 650 */ 0xF3 /* 's' -> */, +/* pos 043b: 651 */ 0xE9 /* 'i' -> */, +/* pos 043c: 652 */ 0xEF /* 'o' -> */, +/* pos 043d: 653 */ 0xEE /* 'n' -> */, +/* pos 043e: 654 */ 0xBA /* ':' -> */, +/* pos 043f: 655 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 0441: 656 */ 0xF2 /* 'r' -> */, +/* pos 0442: 657 */ 0xE9 /* 'i' -> */, +/* pos 0443: 658 */ 0xE7 /* 'g' -> */, +/* pos 0444: 659 */ 0xE9 /* 'i' -> */, +/* pos 0445: 660 */ 0xEE /* 'n' -> */, +/* pos 0446: 661 */ 0xBA /* ':' -> */, +/* pos 0447: 662 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 0449: 663 */ 0xAD /* '-' -> */, +/* pos 044a: 664 */ 0xF3 /* 's' -> */, +/* pos 044b: 665 */ 0xE5 /* 'e' -> */, +/* pos 044c: 666 */ 0xF4 /* 't' -> */, +/* pos 044d: 667 */ 0xF4 /* 't' -> */, +/* pos 044e: 668 */ 0xE9 /* 'i' -> */, +/* pos 044f: 669 */ 0xEE /* 'n' -> */, +/* pos 0450: 670 */ 0xE7 /* 'g' -> */, +/* pos 0451: 671 */ 0xF3 /* 's' -> */, +/* pos 0452: 672 */ 0xBA /* ':' -> */, +/* pos 0453: 673 */ 0x00, 0x0F /* - terminal marker 15 - */, +/* pos 0455: 674 */ 0x61 /* 'a' */, 0x0D, 0x00 /* (to 0x0462 state 675) */, + 0x6D /* 'm' */, 0x14, 0x00 /* (to 0x046C state 684) */, + 0x70 /* 'p' */, 0x18, 0x00 /* (to 0x0473 state 690) */, + 0x73 /* 's' */, 0x20, 0x00 /* (to 0x047E state 694) */, + 0x08, /* fail */ +/* pos 0462: 675 */ 0xF5 /* 'u' -> */, +/* pos 0463: 676 */ 0xF4 /* 't' -> */, +/* pos 0464: 677 */ 0xE8 /* 'h' -> */, +/* pos 0465: 678 */ 0xEF /* 'o' -> */, +/* pos 0466: 679 */ 0xF2 /* 'r' -> */, +/* pos 0467: 680 */ 0xE9 /* 'i' -> */, +/* pos 0468: 681 */ 0xF4 /* 't' -> */, +/* pos 0469: 682 */ 0xF9 /* 'y' -> */, +/* pos 046a: 683 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* pos 046c: 684 */ 0xE5 /* 'e' -> */, +/* pos 046d: 685 */ 0xF4 /* 't' -> */, +/* pos 046e: 686 */ 0xE8 /* 'h' -> */, +/* pos 046f: 687 */ 0xEF /* 'o' -> */, +/* pos 0470: 688 */ 0xE4 /* 'd' -> */, +/* pos 0471: 689 */ 0x00, 0x22 /* - terminal marker 34 - */, +/* pos 0473: 690 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x047A state 691) */, + 0x72 /* 'r' */, 0x1B, 0x00 /* (to 0x0491 state 705) */, + 0x08, /* fail */ +/* pos 047a: 691 */ 0xF4 /* 't' -> */, +/* pos 047b: 692 */ 0xE8 /* 'h' -> */, +/* pos 047c: 693 */ 0x00, 0x23 /* - terminal marker 35 - */, +/* pos 047e: 694 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x0485 state 695) */, + 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x048B state 700) */, + 0x08, /* fail */ +/* pos 0485: 695 */ 0xE8 /* 'h' -> */, +/* pos 0486: 696 */ 0xE5 /* 'e' -> */, +/* pos 0487: 697 */ 0xED /* 'm' -> */, +/* pos 0488: 698 */ 0xE5 /* 'e' -> */, +/* pos 0489: 699 */ 0x00, 0x24 /* - terminal marker 36 - */, +/* pos 048b: 700 */ 0xE1 /* 'a' -> */, +/* pos 048c: 701 */ 0xF4 /* 't' -> */, +/* pos 048d: 702 */ 0xF5 /* 'u' -> */, +/* pos 048e: 703 */ 0xF3 /* 's' -> */, +/* pos 048f: 704 */ 0x00, 0x25 /* - terminal marker 37 - */, +/* pos 0491: 705 */ 0xEF /* 'o' -> */, +/* pos 0492: 706 */ 0xF4 /* 't' -> */, +/* pos 0493: 707 */ 0xEF /* 'o' -> */, +/* pos 0494: 708 */ 0xE3 /* 'c' -> */, +/* pos 0495: 709 */ 0xEF /* 'o' -> */, +/* pos 0496: 710 */ 0xEC /* 'l' -> */, +/* pos 0497: 711 */ 0x00, 0x4E /* - terminal marker 78 - */, /* total size 1177 bytes */ #endif @@ -5919,29 +5854,29 @@ 0x75 /* 'u' */, 0x7E, 0x00 /* (to 0x008A state 26) */, 0x6F /* 'o' */, 0x8D, 0x00 /* (to 0x009C state 34) */, 0x0D /* '.' */, 0x98, 0x00 /* (to 0x00AA state 41) */, - 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 57) */, - 0x69 /* 'i' */, 0xE2, 0x00 /* (to 0x00FA state 88) */, - 0x64 /* 'd' */, 0x7D, 0x01 /* (to 0x0198 state 177) */, - 0x72 /* 'r' */, 0x86, 0x01 /* (to 0x01A4 state 182) */, - 0x65 /* 'e' */, 0xEB, 0x01 /* (to 0x020C state 256) */, - 0x66 /* 'f' */, 0x07, 0x02 /* (to 0x022B state 272) */, - 0x6C /* 'l' */, 0x30, 0x02 /* (to 0x0257 state 306) */, - 0x6D /* 'm' */, 0x53, 0x02 /* (to 0x027D state 332) */, - 0x73 /* 's' */, 0x69, 0x02 /* (to 0x0296 state 355) */, - 0x78 /* 'x' */, 0xB7, 0x02 /* (to 0x02E7 state 410) */, - 0x74 /* 't' */, 0xD5, 0x02 /* (to 0x0308 state 431) */, - 0x76 /* 'v' */, 0x69, 0x03 /* (to 0x039F state 527) */, - 0x77 /* 'w' */, 0x76, 0x03 /* (to 0x03AF state 535) */, - 0x3A /* ':' */, 0xBC, 0x03 /* (to 0x03F8 state 594) */, + 0x61 /* 'a' */, 0xAD, 0x00 /* (to 0x00C2 state 51) */, + 0x69 /* 'i' */, 0xCA, 0x00 /* (to 0x00E2 state 58) */, + 0x64 /* 'd' */, 0x73, 0x01 /* (to 0x018E state 160) */, + 0x72 /* 'r' */, 0x7C, 0x01 /* (to 0x019A state 165) */, + 0x65 /* 'e' */, 0xC8, 0x01 /* (to 0x01E9 state 229) */, + 0x66 /* 'f' */, 0xE4, 0x01 /* (to 0x0208 state 245) */, + 0x6C /* 'l' */, 0x06, 0x02 /* (to 0x022D state 278) */, + 0x73 /* 's' */, 0x4B, 0x02 /* (to 0x0275 state 321) */, + 0x74 /* 't' */, 0x69, 0x02 /* (to 0x0296 state 337) */, + 0x78 /* 'x' */, 0x8A, 0x02 /* (to 0x02BA state 364) */, + 0x6D /* 'm' */, 0xFB, 0x02 /* (to 0x032E state 456) */, + 0x76 /* 'v' */, 0x54, 0x03 /* (to 0x038A state 531) */, + 0x77 /* 'w' */, 0x61, 0x03 /* (to 0x039A state 539) */, + 0x3A /* ':' */, 0x19, 0x04 /* (to 0x0455 state 674) */, 0x08, /* fail */ /* pos 0040: 1 */ 0xE5 /* 'e' -> */, /* pos 0041: 2 */ 0xF4 /* 't' -> */, /* pos 0042: 3 */ 0xA0 /* ' ' -> */, /* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */, /* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */, - 0x72 /* 'r' */, 0xF6, 0x00 /* (to 0x013E state 123) */, - 0x61 /* 'a' */, 0x76, 0x03 /* (to 0x03C1 state 552) */, - 0x75 /* 'u' */, 0x78, 0x03 /* (to 0x03C6 state 556) */, + 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x0134 state 106) */, + 0x61 /* 'a' */, 0x61, 0x03 /* (to 0x03AC state 556) */, + 0x75 /* 'u' */, 0x63, 0x03 /* (to 0x03B1 state 560) */, 0x08, /* fail */ /* pos 0052: 6 */ 0xF3 /* 's' -> */, /* pos 0053: 7 */ 0xF4 /* 't' -> */, @@ -5949,34 +5884,34 @@ /* pos 0055: 9 */ 0x00, 0x01 /* - terminal marker 1 - */, /* pos 0057: 10 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0061 state 11) */, 0x74 /* 't' */, 0x53, 0x00 /* (to 0x00AD state 43) */, - 0x65 /* 'e' */, 0xA6, 0x02 /* (to 0x0303 state 427) */, + 0x65 /* 'e' */, 0x79, 0x02 /* (to 0x02D6 state 381) */, 0x08, /* fail */ /* pos 0061: 11 */ 0xF3 /* 's' -> */, /* pos 0062: 12 */ 0xF4 /* 't' -> */, /* pos 0063: 13 */ 0xBA /* ':' -> */, /* pos 0064: 14 */ 0x00, 0x03 /* - terminal marker 3 - */, /* pos 0066: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x006D state 16) */, - 0x61 /* 'a' */, 0xE2, 0x00 /* (to 0x014B state 129) */, + 0x61 /* 'a' */, 0xD8, 0x00 /* (to 0x0141 state 112) */, 0x08, /* fail */ /* pos 006d: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0074 state 17) */, - 0x6F /* 'o' */, 0xF7, 0x00 /* (to 0x0167 state 155) */, + 0x6F /* 'o' */, 0xED, 0x00 /* (to 0x015D state 138) */, 0x08, /* fail */ /* pos 0074: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x007B state 18) */, - 0x74 /* 't' */, 0xF6, 0x00 /* (to 0x016D state 160) */, + 0x74 /* 't' */, 0xEC, 0x00 /* (to 0x0163 state 143) */, 0x08, /* fail */ /* pos 007b: 18 */ 0xE5 /* 'e' -> */, /* pos 007c: 19 */ 0xE3 /* 'c' -> */, /* pos 007d: 20 */ 0xF4 /* 't' -> */, /* pos 007e: 21 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0085 state 22) */, - 0x20 /* ' ' */, 0x80, 0x02 /* (to 0x0301 state 426) */, + 0x20 /* ' ' */, 0x53, 0x02 /* (to 0x02D4 state 380) */, 0x08, /* fail */ /* pos 0085: 22 */ 0xEF /* 'o' -> */, /* pos 0086: 23 */ 0xEE /* 'n' -> */, /* pos 0087: 24 */ 0xBA /* ':' -> */, /* pos 0088: 25 */ 0x00, 0x04 /* - terminal marker 4 - */, /* pos 008a: 26 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x0094 state 27) */, - 0x73 /* 's' */, 0x44, 0x02 /* (to 0x02D1 state 396) */, - 0x72 /* 'r' */, 0x3F, 0x03 /* (to 0x03CF state 563) */, + 0x72 /* 'r' */, 0x22, 0x02 /* (to 0x02AF state 355) */, + 0x73 /* 's' */, 0xEF, 0x02 /* (to 0x037F state 521) */, 0x08, /* fail */ /* pos 0094: 27 */ 0xE7 /* 'g' -> */, /* pos 0095: 28 */ 0xF2 /* 'r' -> */, @@ -5986,7 +5921,7 @@ /* pos 0099: 32 */ 0xBA /* ':' -> */, /* pos 009a: 33 */ 0x00, 0x05 /* - terminal marker 5 - */, /* pos 009c: 34 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00A3 state 35) */, - 0x70 /* 'p' */, 0x73, 0x02 /* (to 0x0312 state 434) */, + 0x70 /* 'p' */, 0x48, 0x02 /* (to 0x02E7 state 396) */, 0x08, /* fail */ /* pos 00a3: 35 */ 0xE9 /* 'i' -> */, /* pos 00a4: 36 */ 0xE7 /* 'g' -> */, @@ -5998,758 +5933,758 @@ /* pos 00ab: 42 */ 0x00, 0x08 /* - terminal marker 8 - */, /* pos 00ad: 43 */ 0xF4 /* 't' -> */, /* pos 00ae: 44 */ 0xF0 /* 'p' -> */, -/* pos 00af: 45 */ 0x32 /* '2' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, - 0x2F /* '/' */, 0x2E, 0x03 /* (to 0x03E0 state 578) */, - 0x08, /* fail */ -/* pos 00b6: 46 */ 0xAD /* '-' -> */, -/* pos 00b7: 47 */ 0xF3 /* 's' -> */, -/* pos 00b8: 48 */ 0xE5 /* 'e' -> */, -/* pos 00b9: 49 */ 0xF4 /* 't' -> */, -/* pos 00ba: 50 */ 0xF4 /* 't' -> */, -/* pos 00bb: 51 */ 0xE9 /* 'i' -> */, -/* pos 00bc: 52 */ 0xEE /* 'n' -> */, -/* pos 00bd: 53 */ 0xE7 /* 'g' -> */, -/* pos 00be: 54 */ 0xF3 /* 's' -> */, -/* pos 00bf: 55 */ 0xBA /* ':' -> */, -/* pos 00c0: 56 */ 0x00, 0x10 /* - terminal marker 16 - */, -/* pos 00c2: 57 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 58) */, - 0x75 /* 'u' */, 0x94, 0x00 /* (to 0x0159 state 142) */, - 0x6C /* 'l' */, 0x0E, 0x01 /* (to 0x01D6 state 208) */, - 0x67 /* 'g' */, 0x98, 0x02 /* (to 0x0363 state 478) */, - 0x08, /* fail */ -/* pos 00cf: 58 */ 0xE3 /* 'c' -> */, -/* pos 00d0: 59 */ 0xE5 /* 'e' -> */, -/* pos 00d1: 60 */ 0x73 /* 's' */, 0x07, 0x00 /* (to 0x00D8 state 61) */, - 0x70 /* 'p' */, 0x41, 0x00 /* (to 0x0115 state 102) */, - 0x08, /* fail */ -/* pos 00d8: 61 */ 0xF3 /* 's' -> */, -/* pos 00d9: 62 */ 0xAD /* '-' -> */, -/* pos 00da: 63 */ 0xE3 /* 'c' -> */, -/* pos 00db: 64 */ 0xEF /* 'o' -> */, -/* pos 00dc: 65 */ 0xEE /* 'n' -> */, -/* pos 00dd: 66 */ 0xF4 /* 't' -> */, -/* pos 00de: 67 */ 0xF2 /* 'r' -> */, -/* pos 00df: 68 */ 0xEF /* 'o' -> */, -/* pos 00e0: 69 */ 0xEC /* 'l' -> */, -/* pos 00e1: 70 */ 0xAD /* '-' -> */, -/* pos 00e2: 71 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x00E9 state 72) */, - 0x61 /* 'a' */, 0xE3, 0x00 /* (to 0x01C8 state 195) */, - 0x08, /* fail */ -/* pos 00e9: 72 */ 0xE5 /* 'e' -> */, -/* pos 00ea: 73 */ 0xF1 /* 'q' -> */, -/* pos 00eb: 74 */ 0xF5 /* 'u' -> */, -/* pos 00ec: 75 */ 0xE5 /* 'e' -> */, -/* pos 00ed: 76 */ 0xF3 /* 's' -> */, -/* pos 00ee: 77 */ 0xF4 /* 't' -> */, -/* pos 00ef: 78 */ 0xAD /* '-' -> */, -/* pos 00f0: 79 */ 0xE8 /* 'h' -> */, -/* pos 00f1: 80 */ 0xE5 /* 'e' -> */, -/* pos 00f2: 81 */ 0xE1 /* 'a' -> */, -/* pos 00f3: 82 */ 0xE4 /* 'd' -> */, -/* pos 00f4: 83 */ 0xE5 /* 'e' -> */, -/* pos 00f5: 84 */ 0xF2 /* 'r' -> */, -/* pos 00f6: 85 */ 0xF3 /* 's' -> */, -/* pos 00f7: 86 */ 0xBA /* ':' -> */, -/* pos 00f8: 87 */ 0x00, 0x12 /* - terminal marker 18 - */, -/* pos 00fa: 88 */ 0xE6 /* 'f' -> */, -/* pos 00fb: 89 */ 0xAD /* '-' -> */, -/* pos 00fc: 90 */ 0x6E /* 'n' */, 0x0D, 0x00 /* (to 0x0109 state 91) */, - 0x6D /* 'm' */, 0x32, 0x01 /* (to 0x0231 state 277) */, - 0x72 /* 'r' */, 0x3C, 0x01 /* (to 0x023E state 283) */, - 0x75 /* 'u' */, 0x40, 0x01 /* (to 0x0245 state 289) */, - 0x08, /* fail */ -/* pos 0109: 91 */ 0xEF /* 'o' -> */, -/* pos 010a: 92 */ 0xEE /* 'n' -> */, -/* pos 010b: 93 */ 0xE5 /* 'e' -> */, -/* pos 010c: 94 */ 0xAD /* '-' -> */, -/* pos 010d: 95 */ 0xED /* 'm' -> */, -/* pos 010e: 96 */ 0xE1 /* 'a' -> */, -/* pos 010f: 97 */ 0xF4 /* 't' -> */, -/* pos 0110: 98 */ 0xE3 /* 'c' -> */, -/* pos 0111: 99 */ 0xE8 /* 'h' -> */, -/* pos 0112: 100 */ 0xBA /* ':' -> */, -/* pos 0113: 101 */ 0x00, 0x14 /* - terminal marker 20 - */, -/* pos 0115: 102 */ 0xF4 /* 't' -> */, -/* pos 0116: 103 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x011D state 104) */, - 0x3A /* ':' */, 0x4B, 0x03 /* (to 0x0464 state 672) */, - 0x08, /* fail */ -/* pos 011d: 104 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x012A state 105) */, - 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x0134 state 114) */, - 0x72 /* 'r' */, 0x38, 0x02 /* (to 0x035B state 471) */, - 0x63 /* 'c' */, 0x5E, 0x03 /* (to 0x0484 state 693) */, - 0x08, /* fail */ -/* pos 012a: 105 */ 0xEE /* 'n' -> */, -/* pos 012b: 106 */ 0xE3 /* 'c' -> */, -/* pos 012c: 107 */ 0xEF /* 'o' -> */, -/* pos 012d: 108 */ 0xE4 /* 'd' -> */, -/* pos 012e: 109 */ 0xE9 /* 'i' -> */, -/* pos 012f: 110 */ 0xEE /* 'n' -> */, -/* pos 0130: 111 */ 0xE7 /* 'g' -> */, -/* pos 0131: 112 */ 0xBA /* ':' -> */, -/* pos 0132: 113 */ 0x00, 0x15 /* - terminal marker 21 - */, -/* pos 0134: 114 */ 0xE1 /* 'a' -> */, -/* pos 0135: 115 */ 0xEE /* 'n' -> */, -/* pos 0136: 116 */ 0xE7 /* 'g' -> */, -/* pos 0137: 117 */ 0xF5 /* 'u' -> */, -/* pos 0138: 118 */ 0xE1 /* 'a' -> */, -/* pos 0139: 119 */ 0xE7 /* 'g' -> */, -/* pos 013a: 120 */ 0xE5 /* 'e' -> */, -/* pos 013b: 121 */ 0xBA /* ':' -> */, -/* pos 013c: 122 */ 0x00, 0x16 /* - terminal marker 22 - */, -/* pos 013e: 123 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0145 state 124) */, - 0x6F /* 'o' */, 0x9B, 0x01 /* (to 0x02DC state 406) */, - 0x08, /* fail */ -/* pos 0145: 124 */ 0xE7 /* 'g' -> */, -/* pos 0146: 125 */ 0xED /* 'm' -> */, -/* pos 0147: 126 */ 0xE1 /* 'a' -> */, -/* pos 0148: 127 */ 0xBA /* ':' -> */, -/* pos 0149: 128 */ 0x00, 0x17 /* - terminal marker 23 - */, -/* pos 014b: 129 */ 0xE3 /* 'c' -> */, -/* pos 014c: 130 */ 0xE8 /* 'h' -> */, -/* pos 014d: 131 */ 0xE5 /* 'e' -> */, -/* pos 014e: 132 */ 0xAD /* '-' -> */, -/* pos 014f: 133 */ 0xE3 /* 'c' -> */, -/* pos 0150: 134 */ 0xEF /* 'o' -> */, -/* pos 0151: 135 */ 0xEE /* 'n' -> */, -/* pos 0152: 136 */ 0xF4 /* 't' -> */, -/* pos 0153: 137 */ 0xF2 /* 'r' -> */, -/* pos 0154: 138 */ 0xEF /* 'o' -> */, -/* pos 0155: 139 */ 0xEC /* 'l' -> */, -/* pos 0156: 140 */ 0xBA /* ':' -> */, -/* pos 0157: 141 */ 0x00, 0x18 /* - terminal marker 24 - */, -/* pos 0159: 142 */ 0xF4 /* 't' -> */, -/* pos 015a: 143 */ 0xE8 /* 'h' -> */, -/* pos 015b: 144 */ 0xEF /* 'o' -> */, -/* pos 015c: 145 */ 0xF2 /* 'r' -> */, -/* pos 015d: 146 */ 0xE9 /* 'i' -> */, -/* pos 015e: 147 */ 0xFA /* 'z' -> */, -/* pos 015f: 148 */ 0xE1 /* 'a' -> */, -/* pos 0160: 149 */ 0xF4 /* 't' -> */, -/* pos 0161: 150 */ 0xE9 /* 'i' -> */, -/* pos 0162: 151 */ 0xEF /* 'o' -> */, -/* pos 0163: 152 */ 0xEE /* 'n' -> */, -/* pos 0164: 153 */ 0xBA /* ':' -> */, -/* pos 0165: 154 */ 0x00, 0x19 /* - terminal marker 25 - */, -/* pos 0167: 155 */ 0xEB /* 'k' -> */, -/* pos 0168: 156 */ 0xE9 /* 'i' -> */, -/* pos 0169: 157 */ 0xE5 /* 'e' -> */, -/* pos 016a: 158 */ 0xBA /* ':' -> */, -/* pos 016b: 159 */ 0x00, 0x1A /* - terminal marker 26 - */, -/* pos 016d: 160 */ 0xE5 /* 'e' -> */, -/* pos 016e: 161 */ 0xEE /* 'n' -> */, -/* pos 016f: 162 */ 0xF4 /* 't' -> */, -/* pos 0170: 163 */ 0xAD /* '-' -> */, -/* pos 0171: 164 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0181 state 165) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0192 state 172) */, - 0x64 /* 'd' */, 0x65, 0x00 /* (to 0x01DC state 213) */, - 0x65 /* 'e' */, 0x6F, 0x00 /* (to 0x01E9 state 225) */, - 0x72 /* 'r' */, 0x88, 0x00 /* (to 0x0205 state 250) */, - 0x08, /* fail */ -/* pos 0181: 165 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x018B state 166) */, - 0x61 /* 'a' */, 0x6F, 0x00 /* (to 0x01F3 state 234) */, - 0x6F /* 'o' */, 0x75, 0x00 /* (to 0x01FC state 242) */, - 0x08, /* fail */ -/* pos 018b: 166 */ 0xEE /* 'n' -> */, -/* pos 018c: 167 */ 0xE7 /* 'g' -> */, -/* pos 018d: 168 */ 0xF4 /* 't' -> */, -/* pos 018e: 169 */ 0xE8 /* 'h' -> */, -/* pos 018f: 170 */ 0xBA /* ':' -> */, -/* pos 0190: 171 */ 0x00, 0x1B /* - terminal marker 27 - */, -/* pos 0192: 172 */ 0xF9 /* 'y' -> */, -/* pos 0193: 173 */ 0xF0 /* 'p' -> */, -/* pos 0194: 174 */ 0xE5 /* 'e' -> */, -/* pos 0195: 175 */ 0xBA /* ':' -> */, -/* pos 0196: 176 */ 0x00, 0x1C /* - terminal marker 28 - */, -/* pos 0198: 177 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x019F state 178) */, - 0x65 /* 'e' */, 0x2E, 0x02 /* (to 0x03C9 state 558) */, - 0x08, /* fail */ -/* pos 019f: 178 */ 0xF4 /* 't' -> */, -/* pos 01a0: 179 */ 0xE5 /* 'e' -> */, -/* pos 01a1: 180 */ 0xBA /* ':' -> */, -/* pos 01a2: 181 */ 0x00, 0x1D /* - terminal marker 29 - */, -/* pos 01a4: 182 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01AB state 183) */, - 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x01B1 state 188) */, - 0x08, /* fail */ -/* pos 01ab: 183 */ 0xEE /* 'n' -> */, -/* pos 01ac: 184 */ 0xE7 /* 'g' -> */, -/* pos 01ad: 185 */ 0xE5 /* 'e' -> */, -/* pos 01ae: 186 */ 0xBA /* ':' -> */, -/* pos 01af: 187 */ 0x00, 0x1E /* - terminal marker 30 - */, -/* pos 01b1: 188 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x01BB state 189) */, - 0x74 /* 't' */, 0xD7, 0x00 /* (to 0x028B state 345) */, - 0x70 /* 'p' */, 0x35, 0x02 /* (to 0x03EC state 583) */, - 0x08, /* fail */ -/* pos 01bb: 189 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01C2 state 190) */, - 0x72 /* 'r' */, 0xC9, 0x01 /* (to 0x0387 state 505) */, - 0x08, /* fail */ -/* pos 01c2: 190 */ 0xF2 /* 'r' -> */, -/* pos 01c3: 191 */ 0xE5 /* 'e' -> */, -/* pos 01c4: 192 */ 0xF2 /* 'r' -> */, -/* pos 01c5: 193 */ 0xBA /* ':' -> */, -/* pos 01c6: 194 */ 0x00, 0x1F /* - terminal marker 31 - */, -/* pos 01c8: 195 */ 0xEC /* 'l' -> */, -/* pos 01c9: 196 */ 0xEC /* 'l' -> */, -/* pos 01ca: 197 */ 0xEF /* 'o' -> */, -/* pos 01cb: 198 */ 0xF7 /* 'w' -> */, -/* pos 01cc: 199 */ 0xAD /* '-' -> */, -/* pos 01cd: 200 */ 0xEF /* 'o' -> */, -/* pos 01ce: 201 */ 0xF2 /* 'r' -> */, -/* pos 01cf: 202 */ 0xE9 /* 'i' -> */, -/* pos 01d0: 203 */ 0xE7 /* 'g' -> */, -/* pos 01d1: 204 */ 0xE9 /* 'i' -> */, -/* pos 01d2: 205 */ 0xEE /* 'n' -> */, -/* pos 01d3: 206 */ 0xBA /* ':' -> */, -/* pos 01d4: 207 */ 0x00, 0x2A /* - terminal marker 42 - */, -/* pos 01d6: 208 */ 0xEC /* 'l' -> */, -/* pos 01d7: 209 */ 0xEF /* 'o' -> */, -/* pos 01d8: 210 */ 0xF7 /* 'w' -> */, -/* pos 01d9: 211 */ 0xBA /* ':' -> */, -/* pos 01da: 212 */ 0x00, 0x2C /* - terminal marker 44 - */, -/* pos 01dc: 213 */ 0xE9 /* 'i' -> */, -/* pos 01dd: 214 */ 0xF3 /* 's' -> */, -/* pos 01de: 215 */ 0xF0 /* 'p' -> */, -/* pos 01df: 216 */ 0xEF /* 'o' -> */, -/* pos 01e0: 217 */ 0xF3 /* 's' -> */, -/* pos 01e1: 218 */ 0xE9 /* 'i' -> */, -/* pos 01e2: 219 */ 0xF4 /* 't' -> */, -/* pos 01e3: 220 */ 0xE9 /* 'i' -> */, -/* pos 01e4: 221 */ 0xEF /* 'o' -> */, -/* pos 01e5: 222 */ 0xEE /* 'n' -> */, -/* pos 01e6: 223 */ 0xBA /* ':' -> */, -/* pos 01e7: 224 */ 0x00, 0x2D /* - terminal marker 45 - */, -/* pos 01e9: 225 */ 0xEE /* 'n' -> */, -/* pos 01ea: 226 */ 0xE3 /* 'c' -> */, -/* pos 01eb: 227 */ 0xEF /* 'o' -> */, -/* pos 01ec: 228 */ 0xE4 /* 'd' -> */, -/* pos 01ed: 229 */ 0xE9 /* 'i' -> */, -/* pos 01ee: 230 */ 0xEE /* 'n' -> */, -/* pos 01ef: 231 */ 0xE7 /* 'g' -> */, -/* pos 01f0: 232 */ 0xBA /* ':' -> */, -/* pos 01f1: 233 */ 0x00, 0x2E /* - terminal marker 46 - */, -/* pos 01f3: 234 */ 0xEE /* 'n' -> */, -/* pos 01f4: 235 */ 0xE7 /* 'g' -> */, -/* pos 01f5: 236 */ 0xF5 /* 'u' -> */, -/* pos 01f6: 237 */ 0xE1 /* 'a' -> */, -/* pos 01f7: 238 */ 0xE7 /* 'g' -> */, -/* pos 01f8: 239 */ 0xE5 /* 'e' -> */, -/* pos 01f9: 240 */ 0xBA /* ':' -> */, -/* pos 01fa: 241 */ 0x00, 0x2F /* - terminal marker 47 - */, -/* pos 01fc: 242 */ 0xE3 /* 'c' -> */, -/* pos 01fd: 243 */ 0xE1 /* 'a' -> */, -/* pos 01fe: 244 */ 0xF4 /* 't' -> */, -/* pos 01ff: 245 */ 0xE9 /* 'i' -> */, -/* pos 0200: 246 */ 0xEF /* 'o' -> */, -/* pos 0201: 247 */ 0xEE /* 'n' -> */, -/* pos 0202: 248 */ 0xBA /* ':' -> */, -/* pos 0203: 249 */ 0x00, 0x30 /* - terminal marker 48 - */, -/* pos 0205: 250 */ 0xE1 /* 'a' -> */, -/* pos 0206: 251 */ 0xEE /* 'n' -> */, -/* pos 0207: 252 */ 0xE7 /* 'g' -> */, -/* pos 0208: 253 */ 0xE5 /* 'e' -> */, -/* pos 0209: 254 */ 0xBA /* ':' -> */, -/* pos 020a: 255 */ 0x00, 0x31 /* - terminal marker 49 - */, -/* pos 020c: 256 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x0213 state 257) */, - 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x0218 state 261) */, - 0x08, /* fail */ -/* pos 0213: 257 */ 0xE1 /* 'a' -> */, -/* pos 0214: 258 */ 0xE7 /* 'g' -> */, -/* pos 0215: 259 */ 0xBA /* ':' -> */, -/* pos 0216: 260 */ 0x00, 0x32 /* - terminal marker 50 - */, -/* pos 0218: 261 */ 0xF0 /* 'p' -> */, -/* pos 0219: 262 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0220 state 263) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0225 state 267) */, - 0x08, /* fail */ -/* pos 0220: 263 */ 0xE3 /* 'c' -> */, -/* pos 0221: 264 */ 0xF4 /* 't' -> */, -/* pos 0222: 265 */ 0xBA /* ':' -> */, -/* pos 0223: 266 */ 0x00, 0x33 /* - terminal marker 51 - */, -/* pos 0225: 267 */ 0xF2 /* 'r' -> */, -/* pos 0226: 268 */ 0xE5 /* 'e' -> */, -/* pos 0227: 269 */ 0xF3 /* 's' -> */, -/* pos 0228: 270 */ 0xBA /* ':' -> */, -/* pos 0229: 271 */ 0x00, 0x34 /* - terminal marker 52 - */, -/* pos 022b: 272 */ 0xF2 /* 'r' -> */, -/* pos 022c: 273 */ 0xEF /* 'o' -> */, -/* pos 022d: 274 */ 0xED /* 'm' -> */, -/* pos 022e: 275 */ 0xBA /* ':' -> */, -/* pos 022f: 276 */ 0x00, 0x35 /* - terminal marker 53 - */, -/* pos 0231: 277 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0238 state 278) */, - 0x6F /* 'o' */, 0xE6, 0x00 /* (to 0x031A state 441) */, - 0x08, /* fail */ -/* pos 0238: 278 */ 0xF4 /* 't' -> */, -/* pos 0239: 279 */ 0xE3 /* 'c' -> */, -/* pos 023a: 280 */ 0xE8 /* 'h' -> */, -/* pos 023b: 281 */ 0xBA /* ':' -> */, -/* pos 023c: 282 */ 0x00, 0x36 /* - terminal marker 54 - */, -/* pos 023e: 283 */ 0xE1 /* 'a' -> */, -/* pos 023f: 284 */ 0xEE /* 'n' -> */, -/* pos 0240: 285 */ 0xE7 /* 'g' -> */, -/* pos 0241: 286 */ 0xE5 /* 'e' -> */, -/* pos 0242: 287 */ 0xBA /* ':' -> */, -/* pos 0243: 288 */ 0x00, 0x37 /* - terminal marker 55 - */, -/* pos 0245: 289 */ 0xEE /* 'n' -> */, -/* pos 0246: 290 */ 0xED /* 'm' -> */, -/* pos 0247: 291 */ 0xEF /* 'o' -> */, -/* pos 0248: 292 */ 0xE4 /* 'd' -> */, -/* pos 0249: 293 */ 0xE9 /* 'i' -> */, -/* pos 024a: 294 */ 0xE6 /* 'f' -> */, -/* pos 024b: 295 */ 0xE9 /* 'i' -> */, -/* pos 024c: 296 */ 0xE5 /* 'e' -> */, -/* pos 024d: 297 */ 0xE4 /* 'd' -> */, -/* pos 024e: 298 */ 0xAD /* '-' -> */, -/* pos 024f: 299 */ 0xF3 /* 's' -> */, -/* pos 0250: 300 */ 0xE9 /* 'i' -> */, -/* pos 0251: 301 */ 0xEE /* 'n' -> */, -/* pos 0252: 302 */ 0xE3 /* 'c' -> */, -/* pos 0253: 303 */ 0xE5 /* 'e' -> */, -/* pos 0254: 304 */ 0xBA /* ':' -> */, -/* pos 0255: 305 */ 0x00, 0x38 /* - terminal marker 56 - */, -/* pos 0257: 306 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0261 state 307) */, - 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x026F state 320) */, - 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0274 state 324) */, - 0x08, /* fail */ -/* pos 0261: 307 */ 0xF3 /* 's' -> */, -/* pos 0262: 308 */ 0xF4 /* 't' -> */, -/* pos 0263: 309 */ 0xAD /* '-' -> */, -/* pos 0264: 310 */ 0xED /* 'm' -> */, -/* pos 0265: 311 */ 0xEF /* 'o' -> */, -/* pos 0266: 312 */ 0xE4 /* 'd' -> */, -/* pos 0267: 313 */ 0xE9 /* 'i' -> */, -/* pos 0268: 314 */ 0xE6 /* 'f' -> */, -/* pos 0269: 315 */ 0xE9 /* 'i' -> */, -/* pos 026a: 316 */ 0xE5 /* 'e' -> */, -/* pos 026b: 317 */ 0xE4 /* 'd' -> */, -/* pos 026c: 318 */ 0xBA /* ':' -> */, -/* pos 026d: 319 */ 0x00, 0x39 /* - terminal marker 57 - */, -/* pos 026f: 320 */ 0xEE /* 'n' -> */, -/* pos 0270: 321 */ 0xEB /* 'k' -> */, -/* pos 0271: 322 */ 0xBA /* ':' -> */, -/* pos 0272: 323 */ 0x00, 0x3A /* - terminal marker 58 - */, -/* pos 0274: 324 */ 0xE3 /* 'c' -> */, -/* pos 0275: 325 */ 0xE1 /* 'a' -> */, -/* pos 0276: 326 */ 0xF4 /* 't' -> */, -/* pos 0277: 327 */ 0xE9 /* 'i' -> */, -/* pos 0278: 328 */ 0xEF /* 'o' -> */, -/* pos 0279: 329 */ 0xEE /* 'n' -> */, -/* pos 027a: 330 */ 0xBA /* ':' -> */, -/* pos 027b: 331 */ 0x00, 0x3B /* - terminal marker 59 - */, -/* pos 027d: 332 */ 0xE1 /* 'a' -> */, -/* pos 027e: 333 */ 0xF8 /* 'x' -> */, -/* pos 027f: 334 */ 0xAD /* '-' -> */, -/* pos 0280: 335 */ 0xE6 /* 'f' -> */, -/* pos 0281: 336 */ 0xEF /* 'o' -> */, -/* pos 0282: 337 */ 0xF2 /* 'r' -> */, -/* pos 0283: 338 */ 0xF7 /* 'w' -> */, -/* pos 0284: 339 */ 0xE1 /* 'a' -> */, -/* pos 0285: 340 */ 0xF2 /* 'r' -> */, -/* pos 0286: 341 */ 0xE4 /* 'd' -> */, -/* pos 0287: 342 */ 0xF3 /* 's' -> */, -/* pos 0288: 343 */ 0xBA /* ':' -> */, -/* pos 0289: 344 */ 0x00, 0x3C /* - terminal marker 60 - */, -/* pos 028b: 345 */ 0xF2 /* 'r' -> */, -/* pos 028c: 346 */ 0xF9 /* 'y' -> */, -/* pos 028d: 347 */ 0xAD /* '-' -> */, -/* pos 028e: 348 */ 0xE1 /* 'a' -> */, -/* pos 028f: 349 */ 0xE6 /* 'f' -> */, -/* pos 0290: 350 */ 0xF4 /* 't' -> */, -/* pos 0291: 351 */ 0xE5 /* 'e' -> */, -/* pos 0292: 352 */ 0xF2 /* 'r' -> */, -/* pos 0293: 353 */ 0xBA /* ':' -> */, -/* pos 0294: 354 */ 0x00, 0x40 /* - terminal marker 64 - */, -/* pos 0296: 355 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x029D state 356) */, - 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x02B7 state 371) */, - 0x08, /* fail */ -/* pos 029d: 356 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x02A7 state 357) */, - 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x02AD state 362) */, - 0x63 /* 'c' */, 0x86, 0x00 /* (to 0x0329 state 455) */, - 0x08, /* fail */ -/* pos 02a7: 357 */ 0xF6 /* 'v' -> */, -/* pos 02a8: 358 */ 0xE5 /* 'e' -> */, -/* pos 02a9: 359 */ 0xF2 /* 'r' -> */, -/* pos 02aa: 360 */ 0xBA /* ':' -> */, -/* pos 02ab: 361 */ 0x00, 0x41 /* - terminal marker 65 - */, -/* pos 02ad: 362 */ 0xAD /* '-' -> */, -/* pos 02ae: 363 */ 0xE3 /* 'c' -> */, -/* pos 02af: 364 */ 0xEF /* 'o' -> */, -/* pos 02b0: 365 */ 0xEF /* 'o' -> */, -/* pos 02b1: 366 */ 0xEB /* 'k' -> */, -/* pos 02b2: 367 */ 0xE9 /* 'i' -> */, -/* pos 02b3: 368 */ 0xE5 /* 'e' -> */, -/* pos 02b4: 369 */ 0xBA /* ':' -> */, -/* pos 02b5: 370 */ 0x00, 0x42 /* - terminal marker 66 - */, -/* pos 02b7: 371 */ 0xF2 /* 'r' -> */, -/* pos 02b8: 372 */ 0xE9 /* 'i' -> */, -/* pos 02b9: 373 */ 0xE3 /* 'c' -> */, -/* pos 02ba: 374 */ 0xF4 /* 't' -> */, -/* pos 02bb: 375 */ 0xAD /* '-' -> */, -/* pos 02bc: 376 */ 0xF4 /* 't' -> */, -/* pos 02bd: 377 */ 0xF2 /* 'r' -> */, -/* pos 02be: 378 */ 0xE1 /* 'a' -> */, -/* pos 02bf: 379 */ 0xEE /* 'n' -> */, -/* pos 02c0: 380 */ 0xF3 /* 's' -> */, -/* pos 02c1: 381 */ 0xF0 /* 'p' -> */, -/* pos 02c2: 382 */ 0xEF /* 'o' -> */, -/* pos 02c3: 383 */ 0xF2 /* 'r' -> */, -/* pos 02c4: 384 */ 0xF4 /* 't' -> */, -/* pos 02c5: 385 */ 0xAD /* '-' -> */, -/* pos 02c6: 386 */ 0xF3 /* 's' -> */, -/* pos 02c7: 387 */ 0xE5 /* 'e' -> */, -/* pos 02c8: 388 */ 0xE3 /* 'c' -> */, -/* pos 02c9: 389 */ 0xF5 /* 'u' -> */, -/* pos 02ca: 390 */ 0xF2 /* 'r' -> */, -/* pos 02cb: 391 */ 0xE9 /* 'i' -> */, -/* pos 02cc: 392 */ 0xF4 /* 't' -> */, -/* pos 02cd: 393 */ 0xF9 /* 'y' -> */, -/* pos 02ce: 394 */ 0xBA /* ':' -> */, -/* pos 02cf: 395 */ 0x00, 0x43 /* - terminal marker 67 - */, -/* pos 02d1: 396 */ 0xE5 /* 'e' -> */, -/* pos 02d2: 397 */ 0xF2 /* 'r' -> */, -/* pos 02d3: 398 */ 0xAD /* '-' -> */, -/* pos 02d4: 399 */ 0xE1 /* 'a' -> */, -/* pos 02d5: 400 */ 0xE7 /* 'g' -> */, -/* pos 02d6: 401 */ 0xE5 /* 'e' -> */, -/* pos 02d7: 402 */ 0xEE /* 'n' -> */, -/* pos 02d8: 403 */ 0xF4 /* 't' -> */, -/* pos 02d9: 404 */ 0xBA /* ':' -> */, -/* pos 02da: 405 */ 0x00, 0x45 /* - terminal marker 69 - */, -/* pos 02dc: 406 */ 0xF8 /* 'x' -> */, -/* pos 02dd: 407 */ 0xF9 /* 'y' -> */, -/* pos 02de: 408 */ 0x20 /* ' ' */, 0x07, 0x00 /* (to 0x02E5 state 409) */, - 0x2D /* '-' */, 0x86, 0x00 /* (to 0x0367 state 481) */, - 0x08, /* fail */ -/* pos 02e5: 409 */ 0x00, 0x4D /* - terminal marker 77 - */, -/* pos 02e7: 410 */ 0xAD /* '-' -> */, -/* pos 02e8: 411 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02F2 state 412) */, - 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x03D7 state 570) */, - 0x61 /* 'a' */, 0x9F, 0x01 /* (to 0x048D state 701) */, - 0x08, /* fail */ -/* pos 02f2: 412 */ 0xEF /* 'o' -> */, -/* pos 02f3: 413 */ 0xF2 /* 'r' -> */, -/* pos 02f4: 414 */ 0xF7 /* 'w' -> */, -/* pos 02f5: 415 */ 0xE1 /* 'a' -> */, -/* pos 02f6: 416 */ 0xF2 /* 'r' -> */, -/* pos 02f7: 417 */ 0xE4 /* 'd' -> */, -/* pos 02f8: 418 */ 0xE5 /* 'e' -> */, -/* pos 02f9: 419 */ 0xE4 /* 'd' -> */, -/* pos 02fa: 420 */ 0xAD /* '-' -> */, -/* pos 02fb: 421 */ 0xE6 /* 'f' -> */, -/* pos 02fc: 422 */ 0xEF /* 'o' -> */, -/* pos 02fd: 423 */ 0xF2 /* 'r' -> */, -/* pos 02fe: 424 */ 0xBA /* ':' -> */, -/* pos 02ff: 425 */ 0x00, 0x50 /* - terminal marker 80 - */, -/* pos 0301: 426 */ 0x00, 0x51 /* - terminal marker 81 - */, -/* pos 0303: 427 */ 0xE1 /* 'a' -> */, -/* pos 0304: 428 */ 0xE4 /* 'd' -> */, -/* pos 0305: 429 */ 0xA0 /* ' ' -> */, -/* pos 0306: 430 */ 0x00, 0x52 /* - terminal marker 82 - */, -/* pos 0308: 431 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x030F state 432) */, - 0x72 /* 'r' */, 0x82, 0x00 /* (to 0x038D state 510) */, - 0x08, /* fail */ -/* pos 030f: 432 */ 0xBA /* ':' -> */, -/* pos 0310: 433 */ 0x00, 0x53 /* - terminal marker 83 - */, -/* pos 0312: 434 */ 0xF4 /* 't' -> */, -/* pos 0313: 435 */ 0xE9 /* 'i' -> */, -/* pos 0314: 436 */ 0xEF /* 'o' -> */, -/* pos 0315: 437 */ 0xEE /* 'n' -> */, -/* pos 0316: 438 */ 0xF3 /* 's' -> */, -/* pos 0317: 439 */ 0xA0 /* ' ' -> */, -/* pos 0318: 440 */ 0x00, 0x02 /* - terminal marker 2 - */, -/* pos 031a: 441 */ 0xE4 /* 'd' -> */, -/* pos 031b: 442 */ 0xE9 /* 'i' -> */, -/* pos 031c: 443 */ 0xE6 /* 'f' -> */, -/* pos 031d: 444 */ 0xE9 /* 'i' -> */, -/* pos 031e: 445 */ 0xE5 /* 'e' -> */, -/* pos 031f: 446 */ 0xE4 /* 'd' -> */, -/* pos 0320: 447 */ 0xAD /* '-' -> */, -/* pos 0321: 448 */ 0xF3 /* 's' -> */, -/* pos 0322: 449 */ 0xE9 /* 'i' -> */, -/* pos 0323: 450 */ 0xEE /* 'n' -> */, -/* pos 0324: 451 */ 0xE3 /* 'c' -> */, -/* pos 0325: 452 */ 0xE5 /* 'e' -> */, -/* pos 0326: 453 */ 0xBA /* ':' -> */, -/* pos 0327: 454 */ 0x00, 0x13 /* - terminal marker 19 - */, -/* pos 0329: 455 */ 0xAD /* '-' -> */, -/* pos 032a: 456 */ 0xF7 /* 'w' -> */, -/* pos 032b: 457 */ 0xE5 /* 'e' -> */, -/* pos 032c: 458 */ 0xE2 /* 'b' -> */, -/* pos 032d: 459 */ 0xF3 /* 's' -> */, -/* pos 032e: 460 */ 0xEF /* 'o' -> */, -/* pos 032f: 461 */ 0xE3 /* 'c' -> */, -/* pos 0330: 462 */ 0xEB /* 'k' -> */, -/* pos 0331: 463 */ 0xE5 /* 'e' -> */, -/* pos 0332: 464 */ 0xF4 /* 't' -> */, -/* pos 0333: 465 */ 0xAD /* '-' -> */, -/* pos 0334: 466 */ 0x6B /* 'k' */, 0x19, 0x00 /* (to 0x034D state 467) */, - 0x64 /* 'd' */, 0xDD, 0x00 /* (to 0x0414 state 603) */, - 0x65 /* 'e' */, 0xE1, 0x00 /* (to 0x041B state 609) */, - 0x70 /* 'p' */, 0xF0, 0x00 /* (to 0x042D state 624) */, - 0x61 /* 'a' */, 0xF7, 0x00 /* (to 0x0437 state 633) */, - 0x6E /* 'n' */, 0xFC, 0x00 /* (to 0x043F state 640) */, - 0x76 /* 'v' */, 0x03, 0x01 /* (to 0x0449 state 648) */, - 0x6F /* 'o' */, 0x09, 0x01 /* (to 0x0452 state 656) */, - 0x08, /* fail */ -/* pos 034d: 467 */ 0xE5 /* 'e' -> */, -/* pos 034e: 468 */ 0xF9 /* 'y' -> */, -/* pos 034f: 469 */ 0x3A /* ':' */, 0x0A, 0x00 /* (to 0x0359 state 470) */, - 0x31 /* '1' */, 0xD5, 0x00 /* (to 0x0427 state 620) */, - 0x32 /* '2' */, 0xD5, 0x00 /* (to 0x042A state 622) */, - 0x08, /* fail */ -/* pos 0359: 470 */ 0x00, 0x20 /* - terminal marker 32 - */, -/* pos 035b: 471 */ 0xE1 /* 'a' -> */, -/* pos 035c: 472 */ 0xEE /* 'n' -> */, -/* pos 035d: 473 */ 0xE7 /* 'g' -> */, -/* pos 035e: 474 */ 0xE5 /* 'e' -> */, -/* pos 035f: 475 */ 0xF3 /* 's' -> */, -/* pos 0360: 476 */ 0xBA /* ':' -> */, -/* pos 0361: 477 */ 0x00, 0x29 /* - terminal marker 41 - */, -/* pos 0363: 478 */ 0xE5 /* 'e' -> */, -/* pos 0364: 479 */ 0xBA /* ':' -> */, -/* pos 0365: 480 */ 0x00, 0x2B /* - terminal marker 43 - */, -/* pos 0367: 481 */ 0xE1 /* 'a' -> */, -/* pos 0368: 482 */ 0xF5 /* 'u' -> */, -/* pos 0369: 483 */ 0xF4 /* 't' -> */, -/* pos 036a: 484 */ 0xE8 /* 'h' -> */, -/* pos 036b: 485 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0372 state 486) */, - 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x037C state 495) */, - 0x08, /* fail */ -/* pos 0372: 486 */ 0xEE /* 'n' -> */, -/* pos 0373: 487 */ 0xF4 /* 't' -> */, -/* pos 0374: 488 */ 0xE9 /* 'i' -> */, -/* pos 0375: 489 */ 0xE3 /* 'c' -> */, -/* pos 0376: 490 */ 0xE1 /* 'a' -> */, -/* pos 0377: 491 */ 0xF4 /* 't' -> */, -/* pos 0378: 492 */ 0xE5 /* 'e' -> */, -/* pos 0379: 493 */ 0xBA /* ':' -> */, -/* pos 037a: 494 */ 0x00, 0x3D /* - terminal marker 61 - */, -/* pos 037c: 495 */ 0xF2 /* 'r' -> */, -/* pos 037d: 496 */ 0xE9 /* 'i' -> */, -/* pos 037e: 497 */ 0xFA /* 'z' -> */, -/* pos 037f: 498 */ 0xE1 /* 'a' -> */, -/* pos 0380: 499 */ 0xF4 /* 't' -> */, -/* pos 0381: 500 */ 0xE9 /* 'i' -> */, -/* pos 0382: 501 */ 0xEF /* 'o' -> */, -/* pos 0383: 502 */ 0xEE /* 'n' -> */, -/* pos 0384: 503 */ 0xBA /* ':' -> */, -/* pos 0385: 504 */ 0x00, 0x3E /* - terminal marker 62 - */, -/* pos 0387: 505 */ 0xE5 /* 'e' -> */, -/* pos 0388: 506 */ 0xF3 /* 's' -> */, -/* pos 0389: 507 */ 0xE8 /* 'h' -> */, -/* pos 038a: 508 */ 0xBA /* ':' -> */, -/* pos 038b: 509 */ 0x00, 0x3F /* - terminal marker 63 - */, -/* pos 038d: 510 */ 0xE1 /* 'a' -> */, -/* pos 038e: 511 */ 0xEE /* 'n' -> */, -/* pos 038f: 512 */ 0xF3 /* 's' -> */, -/* pos 0390: 513 */ 0xE6 /* 'f' -> */, -/* pos 0391: 514 */ 0xE5 /* 'e' -> */, -/* pos 0392: 515 */ 0xF2 /* 'r' -> */, -/* pos 0393: 516 */ 0xAD /* '-' -> */, -/* pos 0394: 517 */ 0xE5 /* 'e' -> */, -/* pos 0395: 518 */ 0xEE /* 'n' -> */, -/* pos 0396: 519 */ 0xE3 /* 'c' -> */, -/* pos 0397: 520 */ 0xEF /* 'o' -> */, -/* pos 0398: 521 */ 0xE4 /* 'd' -> */, -/* pos 0399: 522 */ 0xE9 /* 'i' -> */, -/* pos 039a: 523 */ 0xEE /* 'n' -> */, -/* pos 039b: 524 */ 0xE7 /* 'g' -> */, -/* pos 039c: 525 */ 0xBA /* ':' -> */, -/* pos 039d: 526 */ 0x00, 0x44 /* - terminal marker 68 - */, -/* pos 039f: 527 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x03A6 state 528) */, - 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x03AB state 532) */, - 0x08, /* fail */ -/* pos 03a6: 528 */ 0xF2 /* 'r' -> */, -/* pos 03a7: 529 */ 0xF9 /* 'y' -> */, -/* pos 03a8: 530 */ 0xBA /* ':' -> */, -/* pos 03a9: 531 */ 0x00, 0x46 /* - terminal marker 70 - */, -/* pos 03ab: 532 */ 0xE1 /* 'a' -> */, -/* pos 03ac: 533 */ 0xBA /* ':' -> */, -/* pos 03ad: 534 */ 0x00, 0x47 /* - terminal marker 71 - */, -/* pos 03af: 535 */ 0xF7 /* 'w' -> */, -/* pos 03b0: 536 */ 0xF7 /* 'w' -> */, -/* pos 03b1: 537 */ 0xAD /* '-' -> */, -/* pos 03b2: 538 */ 0xE1 /* 'a' -> */, -/* pos 03b3: 539 */ 0xF5 /* 'u' -> */, -/* pos 03b4: 540 */ 0xF4 /* 't' -> */, -/* pos 03b5: 541 */ 0xE8 /* 'h' -> */, -/* pos 03b6: 542 */ 0xE5 /* 'e' -> */, -/* pos 03b7: 543 */ 0xEE /* 'n' -> */, -/* pos 03b8: 544 */ 0xF4 /* 't' -> */, -/* pos 03b9: 545 */ 0xE9 /* 'i' -> */, -/* pos 03ba: 546 */ 0xE3 /* 'c' -> */, -/* pos 03bb: 547 */ 0xE1 /* 'a' -> */, -/* pos 03bc: 548 */ 0xF4 /* 't' -> */, -/* pos 03bd: 549 */ 0xE5 /* 'e' -> */, -/* pos 03be: 550 */ 0xBA /* ':' -> */, -/* pos 03bf: 551 */ 0x00, 0x48 /* - terminal marker 72 - */, -/* pos 03c1: 552 */ 0xF4 /* 't' -> */, -/* pos 03c2: 553 */ 0xE3 /* 'c' -> */, -/* pos 03c3: 554 */ 0xE8 /* 'h' -> */, -/* pos 03c4: 555 */ 0x00, 0x49 /* - terminal marker 73 - */, -/* pos 03c6: 556 */ 0xF4 /* 't' -> */, -/* pos 03c7: 557 */ 0x00, 0x4A /* - terminal marker 74 - */, -/* pos 03c9: 558 */ 0xEC /* 'l' -> */, -/* pos 03ca: 559 */ 0xE5 /* 'e' -> */, -/* pos 03cb: 560 */ 0xF4 /* 't' -> */, -/* pos 03cc: 561 */ 0xE5 /* 'e' -> */, -/* pos 03cd: 562 */ 0x00, 0x4B /* - terminal marker 75 - */, -/* pos 03cf: 563 */ 0xE9 /* 'i' -> */, -/* pos 03d0: 564 */ 0xAD /* '-' -> */, -/* pos 03d1: 565 */ 0xE1 /* 'a' -> */, -/* pos 03d2: 566 */ 0xF2 /* 'r' -> */, -/* pos 03d3: 567 */ 0xE7 /* 'g' -> */, -/* pos 03d4: 568 */ 0xF3 /* 's' -> */, -/* pos 03d5: 569 */ 0x00, 0x4C /* - terminal marker 76 - */, -/* pos 03d7: 570 */ 0xE5 /* 'e' -> */, -/* pos 03d8: 571 */ 0xE1 /* 'a' -> */, -/* pos 03d9: 572 */ 0xEC /* 'l' -> */, -/* pos 03da: 573 */ 0xAD /* '-' -> */, -/* pos 03db: 574 */ 0xE9 /* 'i' -> */, -/* pos 03dc: 575 */ 0xF0 /* 'p' -> */, -/* pos 03dd: 576 */ 0xBA /* ':' -> */, -/* pos 03de: 577 */ 0x00, 0x4E /* - terminal marker 78 - */, -/* pos 03e0: 578 */ 0xB1 /* '1' -> */, -/* pos 03e1: 579 */ 0xAE /* '.' -> */, -/* pos 03e2: 580 */ 0x30 /* '0' */, 0x07, 0x00 /* (to 0x03E9 state 581) */, - 0x31 /* '1' */, 0x61, 0x00 /* (to 0x0446 state 646) */, - 0x08, /* fail */ -/* pos 03e9: 581 */ 0xA0 /* ' ' -> */, -/* pos 03ea: 582 */ 0x00, 0x4F /* - terminal marker 79 - */, -/* pos 03ec: 583 */ 0xEC /* 'l' -> */, -/* pos 03ed: 584 */ 0xE1 /* 'a' -> */, -/* pos 03ee: 585 */ 0xF9 /* 'y' -> */, -/* pos 03ef: 586 */ 0xAD /* '-' -> */, -/* pos 03f0: 587 */ 0xEE /* 'n' -> */, -/* pos 03f1: 588 */ 0xEF /* 'o' -> */, -/* pos 03f2: 589 */ 0xEE /* 'n' -> */, -/* pos 03f3: 590 */ 0xE3 /* 'c' -> */, -/* pos 03f4: 591 */ 0xE5 /* 'e' -> */, -/* pos 03f5: 592 */ 0xBA /* ':' -> */, -/* pos 03f6: 593 */ 0x00, 0x54 /* - terminal marker 84 - */, -/* pos 03f8: 594 */ 0x70 /* 'p' */, 0x0D, 0x00 /* (to 0x0405 state 595) */, - 0x61 /* 'a' */, 0x5F, 0x00 /* (to 0x045A state 663) */, - 0x6D /* 'm' */, 0x68, 0x00 /* (to 0x0466 state 673) */, - 0x73 /* 's' */, 0x70, 0x00 /* (to 0x0471 state 682) */, - 0x08, /* fail */ -/* pos 0405: 595 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x040C state 596) */, - 0x61 /* 'a' */, 0x65, 0x00 /* (to 0x046D state 679) */, - 0x08, /* fail */ -/* pos 040c: 596 */ 0xEF /* 'o' -> */, -/* pos 040d: 597 */ 0xF4 /* 't' -> */, -/* pos 040e: 598 */ 0xEF /* 'o' -> */, -/* pos 040f: 599 */ 0xE3 /* 'c' -> */, -/* pos 0410: 600 */ 0xEF /* 'o' -> */, -/* pos 0411: 601 */ 0xEC /* 'l' -> */, -/* pos 0412: 602 */ 0x00, 0x55 /* - terminal marker 85 - */, -/* pos 0414: 603 */ 0xF2 /* 'r' -> */, -/* pos 0415: 604 */ 0xE1 /* 'a' -> */, -/* pos 0416: 605 */ 0xE6 /* 'f' -> */, -/* pos 0417: 606 */ 0xF4 /* 't' -> */, -/* pos 0418: 607 */ 0xBA /* ':' -> */, -/* pos 0419: 608 */ 0x00, 0x07 /* - terminal marker 7 - */, -/* pos 041b: 609 */ 0xF8 /* 'x' -> */, -/* pos 041c: 610 */ 0xF4 /* 't' -> */, -/* pos 041d: 611 */ 0xE5 /* 'e' -> */, -/* pos 041e: 612 */ 0xEE /* 'n' -> */, -/* pos 041f: 613 */ 0xF3 /* 's' -> */, -/* pos 0420: 614 */ 0xE9 /* 'i' -> */, -/* pos 0421: 615 */ 0xEF /* 'o' -> */, -/* pos 0422: 616 */ 0xEE /* 'n' -> */, -/* pos 0423: 617 */ 0xF3 /* 's' -> */, -/* pos 0424: 618 */ 0xBA /* ':' -> */, -/* pos 0425: 619 */ 0x00, 0x09 /* - terminal marker 9 - */, -/* pos 0427: 620 */ 0xBA /* ':' -> */, -/* pos 0428: 621 */ 0x00, 0x0A /* - terminal marker 10 - */, -/* pos 042a: 622 */ 0xBA /* ':' -> */, -/* pos 042b: 623 */ 0x00, 0x0B /* - terminal marker 11 - */, -/* pos 042d: 624 */ 0xF2 /* 'r' -> */, -/* pos 042e: 625 */ 0xEF /* 'o' -> */, -/* pos 042f: 626 */ 0xF4 /* 't' -> */, -/* pos 0430: 627 */ 0xEF /* 'o' -> */, -/* pos 0431: 628 */ 0xE3 /* 'c' -> */, -/* pos 0432: 629 */ 0xEF /* 'o' -> */, -/* pos 0433: 630 */ 0xEC /* 'l' -> */, -/* pos 0434: 631 */ 0xBA /* ':' -> */, -/* pos 0435: 632 */ 0x00, 0x0C /* - terminal marker 12 - */, -/* pos 0437: 633 */ 0xE3 /* 'c' -> */, -/* pos 0438: 634 */ 0xE3 /* 'c' -> */, -/* pos 0439: 635 */ 0xE5 /* 'e' -> */, -/* pos 043a: 636 */ 0xF0 /* 'p' -> */, -/* pos 043b: 637 */ 0xF4 /* 't' -> */, -/* pos 043c: 638 */ 0xBA /* ':' -> */, -/* pos 043d: 639 */ 0x00, 0x0D /* - terminal marker 13 - */, -/* pos 043f: 640 */ 0xEF /* 'o' -> */, -/* pos 0440: 641 */ 0xEE /* 'n' -> */, -/* pos 0441: 642 */ 0xE3 /* 'c' -> */, -/* pos 0442: 643 */ 0xE5 /* 'e' -> */, -/* pos 0443: 644 */ 0xBA /* ':' -> */, -/* pos 0444: 645 */ 0x00, 0x0E /* - terminal marker 14 - */, -/* pos 0446: 646 */ 0xA0 /* ' ' -> */, -/* pos 0447: 647 */ 0x00, 0x0F /* - terminal marker 15 - */, -/* pos 0449: 648 */ 0xE5 /* 'e' -> */, -/* pos 044a: 649 */ 0xF2 /* 'r' -> */, -/* pos 044b: 650 */ 0xF3 /* 's' -> */, -/* pos 044c: 651 */ 0xE9 /* 'i' -> */, -/* pos 044d: 652 */ 0xEF /* 'o' -> */, -/* pos 044e: 653 */ 0xEE /* 'n' -> */, -/* pos 044f: 654 */ 0xBA /* ':' -> */, -/* pos 0450: 655 */ 0x00, 0x21 /* - terminal marker 33 - */, -/* pos 0452: 656 */ 0xF2 /* 'r' -> */, -/* pos 0453: 657 */ 0xE9 /* 'i' -> */, -/* pos 0454: 658 */ 0xE7 /* 'g' -> */, -/* pos 0455: 659 */ 0xE9 /* 'i' -> */, -/* pos 0456: 660 */ 0xEE /* 'n' -> */, -/* pos 0457: 661 */ 0xBA /* ':' -> */, -/* pos 0458: 662 */ 0x00, 0x22 /* - terminal marker 34 - */, -/* pos 045a: 663 */ 0xF5 /* 'u' -> */, -/* pos 045b: 664 */ 0xF4 /* 't' -> */, -/* pos 045c: 665 */ 0xE8 /* 'h' -> */, -/* pos 045d: 666 */ 0xEF /* 'o' -> */, -/* pos 045e: 667 */ 0xF2 /* 'r' -> */, -/* pos 045f: 668 */ 0xE9 /* 'i' -> */, -/* pos 0460: 669 */ 0xF4 /* 't' -> */, -/* pos 0461: 670 */ 0xF9 /* 'y' -> */, -/* pos 0462: 671 */ 0x00, 0x23 /* - terminal marker 35 - */, -/* pos 0464: 672 */ 0x00, 0x11 /* - terminal marker 17 - */, -/* pos 0466: 673 */ 0xE5 /* 'e' -> */, -/* pos 0467: 674 */ 0xF4 /* 't' -> */, -/* pos 0468: 675 */ 0xE8 /* 'h' -> */, -/* pos 0469: 676 */ 0xEF /* 'o' -> */, -/* pos 046a: 677 */ 0xE4 /* 'd' -> */, -/* pos 046b: 678 */ 0x00, 0x24 /* - terminal marker 36 - */, -/* pos 046d: 679 */ 0xF4 /* 't' -> */, -/* pos 046e: 680 */ 0xE8 /* 'h' -> */, -/* pos 046f: 681 */ 0x00, 0x25 /* - terminal marker 37 - */, -/* pos 0471: 682 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x0478 state 683) */, - 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x047E state 688) */, - 0x08, /* fail */ -/* pos 0478: 683 */ 0xE8 /* 'h' -> */, -/* pos 0479: 684 */ 0xE5 /* 'e' -> */, -/* pos 047a: 685 */ 0xED /* 'm' -> */, -/* pos 047b: 686 */ 0xE5 /* 'e' -> */, -/* pos 047c: 687 */ 0x00, 0x26 /* - terminal marker 38 - */, -/* pos 047e: 688 */ 0xE1 /* 'a' -> */, -/* pos 047f: 689 */ 0xF4 /* 't' -> */, -/* pos 0480: 690 */ 0xF5 /* 'u' -> */, -/* pos 0481: 691 */ 0xF3 /* 's' -> */, -/* pos 0482: 692 */ 0x00, 0x27 /* - terminal marker 39 - */, -/* pos 0484: 693 */ 0xE8 /* 'h' -> */, -/* pos 0485: 694 */ 0xE1 /* 'a' -> */, -/* pos 0486: 695 */ 0xF2 /* 'r' -> */, -/* pos 0487: 696 */ 0xF3 /* 's' -> */, -/* pos 0488: 697 */ 0xE5 /* 'e' -> */, -/* pos 0489: 698 */ 0xF4 /* 't' -> */, -/* pos 048a: 699 */ 0xBA /* ':' -> */, -/* pos 048b: 700 */ 0x00, 0x28 /* - terminal marker 40 - */, -/* pos 048d: 701 */ 0xF5 /* 'u' -> */, -/* pos 048e: 702 */ 0xF4 /* 't' -> */, -/* pos 048f: 703 */ 0xE8 /* 'h' -> */, -/* pos 0490: 704 */ 0xAD /* '-' -> */, -/* pos 0491: 705 */ 0xF4 /* 't' -> */, -/* pos 0492: 706 */ 0xEF /* 'o' -> */, -/* pos 0493: 707 */ 0xEB /* 'k' -> */, -/* pos 0494: 708 */ 0xE5 /* 'e' -> */, -/* pos 0495: 709 */ 0xEE /* 'n' -> */, -/* pos 0496: 710 */ 0xBA /* ':' -> */, -/* pos 0497: 711 */ 0x00, 0x56 /* - terminal marker 86 - */, +/* pos 00af: 45 */ 0x2F /* '/' */, 0x07, 0x00 /* (to 0x00B6 state 46) */, + 0x32 /* '2' */, 0x97, 0x03 /* (to 0x0449 state 663) */, + 0x08, /* fail */ +/* pos 00b6: 46 */ 0xB1 /* '1' -> */, +/* pos 00b7: 47 */ 0xAE /* '.' -> */, +/* pos 00b8: 48 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x00BF state 49) */, + 0x30 /* '0' */, 0xFC, 0x01 /* (to 0x02B7 state 362) */, + 0x08, /* fail */ +/* pos 00bf: 49 */ 0xA0 /* ' ' -> */, +/* pos 00c0: 50 */ 0x00, 0x0F /* - terminal marker 15 - */, +/* pos 00c2: 51 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x00CF state 52) */, + 0x75 /* 'u' */, 0x8A, 0x00 /* (to 0x014F state 125) */, + 0x67 /* 'g' */, 0xE7, 0x00 /* (to 0x01AF state 178) */, + 0x6C /* 'l' */, 0xE8, 0x00 /* (to 0x01B3 state 181) */, + 0x08, /* fail */ +/* pos 00cf: 52 */ 0xE3 /* 'c' -> */, +/* pos 00d0: 53 */ 0xE5 /* 'e' -> */, +/* pos 00d1: 54 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x00D8 state 55) */, + 0x73 /* 's' */, 0x1B, 0x02 /* (to 0x02EF state 403) */, + 0x08, /* fail */ +/* pos 00d8: 55 */ 0xF4 /* 't' -> */, +/* pos 00d9: 56 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x00E0 state 57) */, + 0x2D /* '-' */, 0x37, 0x00 /* (to 0x0113 state 87) */, + 0x08, /* fail */ +/* pos 00e0: 57 */ 0x00, 0x11 /* - terminal marker 17 - */, +/* pos 00e2: 58 */ 0xE6 /* 'f' -> */, +/* pos 00e3: 59 */ 0xAD /* '-' -> */, +/* pos 00e4: 60 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x00F1 state 61) */, + 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x0107 state 76) */, + 0x72 /* 'r' */, 0x2A, 0x01 /* (to 0x0214 state 255) */, + 0x75 /* 'u' */, 0x2E, 0x01 /* (to 0x021B state 261) */, + 0x08, /* fail */ +/* pos 00f1: 61 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x00F8 state 62) */, + 0x61 /* 'a' */, 0x1A, 0x01 /* (to 0x020E state 250) */, + 0x08, /* fail */ +/* pos 00f8: 62 */ 0xE4 /* 'd' -> */, +/* pos 00f9: 63 */ 0xE9 /* 'i' -> */, +/* pos 00fa: 64 */ 0xE6 /* 'f' -> */, +/* pos 00fb: 65 */ 0xE9 /* 'i' -> */, +/* pos 00fc: 66 */ 0xE5 /* 'e' -> */, +/* pos 00fd: 67 */ 0xE4 /* 'd' -> */, +/* pos 00fe: 68 */ 0xAD /* '-' -> */, +/* pos 00ff: 69 */ 0xF3 /* 's' -> */, +/* pos 0100: 70 */ 0xE9 /* 'i' -> */, +/* pos 0101: 71 */ 0xEE /* 'n' -> */, +/* pos 0102: 72 */ 0xE3 /* 'c' -> */, +/* pos 0103: 73 */ 0xE5 /* 'e' -> */, +/* pos 0104: 74 */ 0xBA /* ':' -> */, +/* pos 0105: 75 */ 0x00, 0x13 /* - terminal marker 19 - */, +/* pos 0107: 76 */ 0xEF /* 'o' -> */, +/* pos 0108: 77 */ 0xEE /* 'n' -> */, +/* pos 0109: 78 */ 0xE5 /* 'e' -> */, +/* pos 010a: 79 */ 0xAD /* '-' -> */, +/* pos 010b: 80 */ 0xED /* 'm' -> */, +/* pos 010c: 81 */ 0xE1 /* 'a' -> */, +/* pos 010d: 82 */ 0xF4 /* 't' -> */, +/* pos 010e: 83 */ 0xE3 /* 'c' -> */, +/* pos 010f: 84 */ 0xE8 /* 'h' -> */, +/* pos 0110: 85 */ 0xBA /* ':' -> */, +/* pos 0111: 86 */ 0x00, 0x14 /* - terminal marker 20 - */, +/* pos 0113: 87 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x0120 state 88) */, + 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x012A state 97) */, + 0x72 /* 'r' */, 0x8E, 0x00 /* (to 0x01A7 state 171) */, + 0x63 /* 'c' */, 0xFB, 0x01 /* (to 0x0317 state 435) */, + 0x08, /* fail */ +/* pos 0120: 88 */ 0xEE /* 'n' -> */, +/* pos 0121: 89 */ 0xE3 /* 'c' -> */, +/* pos 0122: 90 */ 0xEF /* 'o' -> */, +/* pos 0123: 91 */ 0xE4 /* 'd' -> */, +/* pos 0124: 92 */ 0xE9 /* 'i' -> */, +/* pos 0125: 93 */ 0xEE /* 'n' -> */, +/* pos 0126: 94 */ 0xE7 /* 'g' -> */, +/* pos 0127: 95 */ 0xBA /* ':' -> */, +/* pos 0128: 96 */ 0x00, 0x15 /* - terminal marker 21 - */, +/* pos 012a: 97 */ 0xE1 /* 'a' -> */, +/* pos 012b: 98 */ 0xEE /* 'n' -> */, +/* pos 012c: 99 */ 0xE7 /* 'g' -> */, +/* pos 012d: 100 */ 0xF5 /* 'u' -> */, +/* pos 012e: 101 */ 0xE1 /* 'a' -> */, +/* pos 012f: 102 */ 0xE7 /* 'g' -> */, +/* pos 0130: 103 */ 0xE5 /* 'e' -> */, +/* pos 0131: 104 */ 0xBA /* ':' -> */, +/* pos 0132: 105 */ 0x00, 0x16 /* - terminal marker 22 - */, +/* pos 0134: 106 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x013B state 107) */, + 0x6F /* 'o' */, 0x05, 0x02 /* (to 0x033C state 469) */, + 0x08, /* fail */ +/* pos 013b: 107 */ 0xE7 /* 'g' -> */, +/* pos 013c: 108 */ 0xED /* 'm' -> */, +/* pos 013d: 109 */ 0xE1 /* 'a' -> */, +/* pos 013e: 110 */ 0xBA /* ':' -> */, +/* pos 013f: 111 */ 0x00, 0x17 /* - terminal marker 23 - */, +/* pos 0141: 112 */ 0xE3 /* 'c' -> */, +/* pos 0142: 113 */ 0xE8 /* 'h' -> */, +/* pos 0143: 114 */ 0xE5 /* 'e' -> */, +/* pos 0144: 115 */ 0xAD /* '-' -> */, +/* pos 0145: 116 */ 0xE3 /* 'c' -> */, +/* pos 0146: 117 */ 0xEF /* 'o' -> */, +/* pos 0147: 118 */ 0xEE /* 'n' -> */, +/* pos 0148: 119 */ 0xF4 /* 't' -> */, +/* pos 0149: 120 */ 0xF2 /* 'r' -> */, +/* pos 014a: 121 */ 0xEF /* 'o' -> */, +/* pos 014b: 122 */ 0xEC /* 'l' -> */, +/* pos 014c: 123 */ 0xBA /* ':' -> */, +/* pos 014d: 124 */ 0x00, 0x18 /* - terminal marker 24 - */, +/* pos 014f: 125 */ 0xF4 /* 't' -> */, +/* pos 0150: 126 */ 0xE8 /* 'h' -> */, +/* pos 0151: 127 */ 0xEF /* 'o' -> */, +/* pos 0152: 128 */ 0xF2 /* 'r' -> */, +/* pos 0153: 129 */ 0xE9 /* 'i' -> */, +/* pos 0154: 130 */ 0xFA /* 'z' -> */, +/* pos 0155: 131 */ 0xE1 /* 'a' -> */, +/* pos 0156: 132 */ 0xF4 /* 't' -> */, +/* pos 0157: 133 */ 0xE9 /* 'i' -> */, +/* pos 0158: 134 */ 0xEF /* 'o' -> */, +/* pos 0159: 135 */ 0xEE /* 'n' -> */, +/* pos 015a: 136 */ 0xBA /* ':' -> */, +/* pos 015b: 137 */ 0x00, 0x19 /* - terminal marker 25 - */, +/* pos 015d: 138 */ 0xEB /* 'k' -> */, +/* pos 015e: 139 */ 0xE9 /* 'i' -> */, +/* pos 015f: 140 */ 0xE5 /* 'e' -> */, +/* pos 0160: 141 */ 0xBA /* ':' -> */, +/* pos 0161: 142 */ 0x00, 0x1A /* - terminal marker 26 - */, +/* pos 0163: 143 */ 0xE5 /* 'e' -> */, +/* pos 0164: 144 */ 0xEE /* 'n' -> */, +/* pos 0165: 145 */ 0xF4 /* 't' -> */, +/* pos 0166: 146 */ 0xAD /* '-' -> */, +/* pos 0167: 147 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0177 state 148) */, + 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0188 state 155) */, + 0x64 /* 'd' */, 0x4C, 0x00 /* (to 0x01B9 state 186) */, + 0x65 /* 'e' */, 0x56, 0x00 /* (to 0x01C6 state 198) */, + 0x72 /* 'r' */, 0x6F, 0x00 /* (to 0x01E2 state 223) */, + 0x08, /* fail */ +/* pos 0177: 148 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0181 state 149) */, + 0x61 /* 'a' */, 0x56, 0x00 /* (to 0x01D0 state 207) */, + 0x6F /* 'o' */, 0x5C, 0x00 /* (to 0x01D9 state 215) */, + 0x08, /* fail */ +/* pos 0181: 149 */ 0xEE /* 'n' -> */, +/* pos 0182: 150 */ 0xE7 /* 'g' -> */, +/* pos 0183: 151 */ 0xF4 /* 't' -> */, +/* pos 0184: 152 */ 0xE8 /* 'h' -> */, +/* pos 0185: 153 */ 0xBA /* ':' -> */, +/* pos 0186: 154 */ 0x00, 0x1B /* - terminal marker 27 - */, +/* pos 0188: 155 */ 0xF9 /* 'y' -> */, +/* pos 0189: 156 */ 0xF0 /* 'p' -> */, +/* pos 018a: 157 */ 0xE5 /* 'e' -> */, +/* pos 018b: 158 */ 0xBA /* ':' -> */, +/* pos 018c: 159 */ 0x00, 0x1C /* - terminal marker 28 - */, +/* pos 018e: 160 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0195 state 161) */, + 0x65 /* 'e' */, 0x23, 0x02 /* (to 0x03B4 state 562) */, + 0x08, /* fail */ +/* pos 0195: 161 */ 0xF4 /* 't' -> */, +/* pos 0196: 162 */ 0xE5 /* 'e' -> */, +/* pos 0197: 163 */ 0xBA /* ':' -> */, +/* pos 0198: 164 */ 0x00, 0x1D /* - terminal marker 29 - */, +/* pos 019a: 165 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01A1 state 166) */, + 0x65 /* 'e' */, 0xB6, 0x00 /* (to 0x0253 state 304) */, + 0x08, /* fail */ +/* pos 01a1: 166 */ 0xEE /* 'n' -> */, +/* pos 01a2: 167 */ 0xE7 /* 'g' -> */, +/* pos 01a3: 168 */ 0xE5 /* 'e' -> */, +/* pos 01a4: 169 */ 0xBA /* ':' -> */, +/* pos 01a5: 170 */ 0x00, 0x1E /* - terminal marker 30 - */, +/* pos 01a7: 171 */ 0xE1 /* 'a' -> */, +/* pos 01a8: 172 */ 0xEE /* 'n' -> */, +/* pos 01a9: 173 */ 0xE7 /* 'g' -> */, +/* pos 01aa: 174 */ 0xE5 /* 'e' -> */, +/* pos 01ab: 175 */ 0xF3 /* 's' -> */, +/* pos 01ac: 176 */ 0xBA /* ':' -> */, +/* pos 01ad: 177 */ 0x00, 0x29 /* - terminal marker 41 - */, +/* pos 01af: 178 */ 0xE5 /* 'e' -> */, +/* pos 01b0: 179 */ 0xBA /* ':' -> */, +/* pos 01b1: 180 */ 0x00, 0x2B /* - terminal marker 43 - */, +/* pos 01b3: 181 */ 0xEC /* 'l' -> */, +/* pos 01b4: 182 */ 0xEF /* 'o' -> */, +/* pos 01b5: 183 */ 0xF7 /* 'w' -> */, +/* pos 01b6: 184 */ 0xBA /* ':' -> */, +/* pos 01b7: 185 */ 0x00, 0x2C /* - terminal marker 44 - */, +/* pos 01b9: 186 */ 0xE9 /* 'i' -> */, +/* pos 01ba: 187 */ 0xF3 /* 's' -> */, +/* pos 01bb: 188 */ 0xF0 /* 'p' -> */, +/* pos 01bc: 189 */ 0xEF /* 'o' -> */, +/* pos 01bd: 190 */ 0xF3 /* 's' -> */, +/* pos 01be: 191 */ 0xE9 /* 'i' -> */, +/* pos 01bf: 192 */ 0xF4 /* 't' -> */, +/* pos 01c0: 193 */ 0xE9 /* 'i' -> */, +/* pos 01c1: 194 */ 0xEF /* 'o' -> */, +/* pos 01c2: 195 */ 0xEE /* 'n' -> */, +/* pos 01c3: 196 */ 0xBA /* ':' -> */, +/* pos 01c4: 197 */ 0x00, 0x2D /* - terminal marker 45 - */, +/* pos 01c6: 198 */ 0xEE /* 'n' -> */, +/* pos 01c7: 199 */ 0xE3 /* 'c' -> */, +/* pos 01c8: 200 */ 0xEF /* 'o' -> */, +/* pos 01c9: 201 */ 0xE4 /* 'd' -> */, +/* pos 01ca: 202 */ 0xE9 /* 'i' -> */, +/* pos 01cb: 203 */ 0xEE /* 'n' -> */, +/* pos 01cc: 204 */ 0xE7 /* 'g' -> */, +/* pos 01cd: 205 */ 0xBA /* ':' -> */, +/* pos 01ce: 206 */ 0x00, 0x2E /* - terminal marker 46 - */, +/* pos 01d0: 207 */ 0xEE /* 'n' -> */, +/* pos 01d1: 208 */ 0xE7 /* 'g' -> */, +/* pos 01d2: 209 */ 0xF5 /* 'u' -> */, +/* pos 01d3: 210 */ 0xE1 /* 'a' -> */, +/* pos 01d4: 211 */ 0xE7 /* 'g' -> */, +/* pos 01d5: 212 */ 0xE5 /* 'e' -> */, +/* pos 01d6: 213 */ 0xBA /* ':' -> */, +/* pos 01d7: 214 */ 0x00, 0x2F /* - terminal marker 47 - */, +/* pos 01d9: 215 */ 0xE3 /* 'c' -> */, +/* pos 01da: 216 */ 0xE1 /* 'a' -> */, +/* pos 01db: 217 */ 0xF4 /* 't' -> */, +/* pos 01dc: 218 */ 0xE9 /* 'i' -> */, +/* pos 01dd: 219 */ 0xEF /* 'o' -> */, +/* pos 01de: 220 */ 0xEE /* 'n' -> */, +/* pos 01df: 221 */ 0xBA /* ':' -> */, +/* pos 01e0: 222 */ 0x00, 0x30 /* - terminal marker 48 - */, +/* pos 01e2: 223 */ 0xE1 /* 'a' -> */, +/* pos 01e3: 224 */ 0xEE /* 'n' -> */, +/* pos 01e4: 225 */ 0xE7 /* 'g' -> */, +/* pos 01e5: 226 */ 0xE5 /* 'e' -> */, +/* pos 01e6: 227 */ 0xBA /* ':' -> */, +/* pos 01e7: 228 */ 0x00, 0x31 /* - terminal marker 49 - */, +/* pos 01e9: 229 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x01F0 state 230) */, + 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x01F5 state 234) */, + 0x08, /* fail */ +/* pos 01f0: 230 */ 0xE1 /* 'a' -> */, +/* pos 01f1: 231 */ 0xE7 /* 'g' -> */, +/* pos 01f2: 232 */ 0xBA /* ':' -> */, +/* pos 01f3: 233 */ 0x00, 0x32 /* - terminal marker 50 - */, +/* pos 01f5: 234 */ 0xF0 /* 'p' -> */, +/* pos 01f6: 235 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x01FD state 236) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0202 state 240) */, + 0x08, /* fail */ +/* pos 01fd: 236 */ 0xE3 /* 'c' -> */, +/* pos 01fe: 237 */ 0xF4 /* 't' -> */, +/* pos 01ff: 238 */ 0xBA /* ':' -> */, +/* pos 0200: 239 */ 0x00, 0x33 /* - terminal marker 51 - */, +/* pos 0202: 240 */ 0xF2 /* 'r' -> */, +/* pos 0203: 241 */ 0xE5 /* 'e' -> */, +/* pos 0204: 242 */ 0xF3 /* 's' -> */, +/* pos 0205: 243 */ 0xBA /* ':' -> */, +/* pos 0206: 244 */ 0x00, 0x34 /* - terminal marker 52 - */, +/* pos 0208: 245 */ 0xF2 /* 'r' -> */, +/* pos 0209: 246 */ 0xEF /* 'o' -> */, +/* pos 020a: 247 */ 0xED /* 'm' -> */, +/* pos 020b: 248 */ 0xBA /* ':' -> */, +/* pos 020c: 249 */ 0x00, 0x35 /* - terminal marker 53 - */, +/* pos 020e: 250 */ 0xF4 /* 't' -> */, +/* pos 020f: 251 */ 0xE3 /* 'c' -> */, +/* pos 0210: 252 */ 0xE8 /* 'h' -> */, +/* pos 0211: 253 */ 0xBA /* ':' -> */, +/* pos 0212: 254 */ 0x00, 0x36 /* - terminal marker 54 - */, +/* pos 0214: 255 */ 0xE1 /* 'a' -> */, +/* pos 0215: 256 */ 0xEE /* 'n' -> */, +/* pos 0216: 257 */ 0xE7 /* 'g' -> */, +/* pos 0217: 258 */ 0xE5 /* 'e' -> */, +/* pos 0218: 259 */ 0xBA /* ':' -> */, +/* pos 0219: 260 */ 0x00, 0x37 /* - terminal marker 55 - */, +/* pos 021b: 261 */ 0xEE /* 'n' -> */, +/* pos 021c: 262 */ 0xED /* 'm' -> */, +/* pos 021d: 263 */ 0xEF /* 'o' -> */, +/* pos 021e: 264 */ 0xE4 /* 'd' -> */, +/* pos 021f: 265 */ 0xE9 /* 'i' -> */, +/* pos 0220: 266 */ 0xE6 /* 'f' -> */, +/* pos 0221: 267 */ 0xE9 /* 'i' -> */, +/* pos 0222: 268 */ 0xE5 /* 'e' -> */, +/* pos 0223: 269 */ 0xE4 /* 'd' -> */, +/* pos 0224: 270 */ 0xAD /* '-' -> */, +/* pos 0225: 271 */ 0xF3 /* 's' -> */, +/* pos 0226: 272 */ 0xE9 /* 'i' -> */, +/* pos 0227: 273 */ 0xEE /* 'n' -> */, +/* pos 0228: 274 */ 0xE3 /* 'c' -> */, +/* pos 0229: 275 */ 0xE5 /* 'e' -> */, +/* pos 022a: 276 */ 0xBA /* ':' -> */, +/* pos 022b: 277 */ 0x00, 0x38 /* - terminal marker 56 - */, +/* pos 022d: 278 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x0237 state 279) */, + 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x0245 state 292) */, + 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x024A state 296) */, + 0x08, /* fail */ +/* pos 0237: 279 */ 0xF3 /* 's' -> */, +/* pos 0238: 280 */ 0xF4 /* 't' -> */, +/* pos 0239: 281 */ 0xAD /* '-' -> */, +/* pos 023a: 282 */ 0xED /* 'm' -> */, +/* pos 023b: 283 */ 0xEF /* 'o' -> */, +/* pos 023c: 284 */ 0xE4 /* 'd' -> */, +/* pos 023d: 285 */ 0xE9 /* 'i' -> */, +/* pos 023e: 286 */ 0xE6 /* 'f' -> */, +/* pos 023f: 287 */ 0xE9 /* 'i' -> */, +/* pos 0240: 288 */ 0xE5 /* 'e' -> */, +/* pos 0241: 289 */ 0xE4 /* 'd' -> */, +/* pos 0242: 290 */ 0xBA /* ':' -> */, +/* pos 0243: 291 */ 0x00, 0x39 /* - terminal marker 57 - */, +/* pos 0245: 292 */ 0xEE /* 'n' -> */, +/* pos 0246: 293 */ 0xEB /* 'k' -> */, +/* pos 0247: 294 */ 0xBA /* ':' -> */, +/* pos 0248: 295 */ 0x00, 0x3A /* - terminal marker 58 - */, +/* pos 024a: 296 */ 0xE3 /* 'c' -> */, +/* pos 024b: 297 */ 0xE1 /* 'a' -> */, +/* pos 024c: 298 */ 0xF4 /* 't' -> */, +/* pos 024d: 299 */ 0xE9 /* 'i' -> */, +/* pos 024e: 300 */ 0xEF /* 'o' -> */, +/* pos 024f: 301 */ 0xEE /* 'n' -> */, +/* pos 0250: 302 */ 0xBA /* ':' -> */, +/* pos 0251: 303 */ 0x00, 0x3B /* - terminal marker 59 - */, +/* pos 0253: 304 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x025D state 305) */, + 0x74 /* 't' */, 0x14, 0x00 /* (to 0x026A state 311) */, + 0x70 /* 'p' */, 0x6F, 0x01 /* (to 0x03C8 state 578) */, + 0x08, /* fail */ +/* pos 025d: 305 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0264 state 306) */, + 0x65 /* 'e' */, 0xB1, 0x00 /* (to 0x0311 state 430) */, + 0x08, /* fail */ +/* pos 0264: 306 */ 0xE5 /* 'e' -> */, +/* pos 0265: 307 */ 0xF3 /* 's' -> */, +/* pos 0266: 308 */ 0xE8 /* 'h' -> */, +/* pos 0267: 309 */ 0xBA /* ':' -> */, +/* pos 0268: 310 */ 0x00, 0x3F /* - terminal marker 63 - */, +/* pos 026a: 311 */ 0xF2 /* 'r' -> */, +/* pos 026b: 312 */ 0xF9 /* 'y' -> */, +/* pos 026c: 313 */ 0xAD /* '-' -> */, +/* pos 026d: 314 */ 0xE1 /* 'a' -> */, +/* pos 026e: 315 */ 0xE6 /* 'f' -> */, +/* pos 026f: 316 */ 0xF4 /* 't' -> */, +/* pos 0270: 317 */ 0xE5 /* 'e' -> */, +/* pos 0271: 318 */ 0xF2 /* 'r' -> */, +/* pos 0272: 319 */ 0xBA /* ':' -> */, +/* pos 0273: 320 */ 0x00, 0x40 /* - terminal marker 64 - */, +/* pos 0275: 321 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x027C state 322) */, + 0x74 /* 't' */, 0xED, 0x00 /* (to 0x0365 state 496) */, + 0x08, /* fail */ +/* pos 027c: 322 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x0286 state 323) */, + 0x74 /* 't' */, 0x0D, 0x00 /* (to 0x028C state 328) */, + 0x63 /* 'c' */, 0x52, 0x01 /* (to 0x03D4 state 589) */, + 0x08, /* fail */ +/* pos 0286: 323 */ 0xF6 /* 'v' -> */, +/* pos 0287: 324 */ 0xE5 /* 'e' -> */, +/* pos 0288: 325 */ 0xF2 /* 'r' -> */, +/* pos 0289: 326 */ 0xBA /* ':' -> */, +/* pos 028a: 327 */ 0x00, 0x41 /* - terminal marker 65 - */, +/* pos 028c: 328 */ 0xAD /* '-' -> */, +/* pos 028d: 329 */ 0xE3 /* 'c' -> */, +/* pos 028e: 330 */ 0xEF /* 'o' -> */, +/* pos 028f: 331 */ 0xEF /* 'o' -> */, +/* pos 0290: 332 */ 0xEB /* 'k' -> */, +/* pos 0291: 333 */ 0xE9 /* 'i' -> */, +/* pos 0292: 334 */ 0xE5 /* 'e' -> */, +/* pos 0293: 335 */ 0xBA /* ':' -> */, +/* pos 0294: 336 */ 0x00, 0x42 /* - terminal marker 66 - */, +/* pos 0296: 337 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x029D state 338) */, + 0x65 /* 'e' */, 0x2C, 0x01 /* (to 0x03C5 state 576) */, + 0x08, /* fail */ +/* pos 029d: 338 */ 0xE1 /* 'a' -> */, +/* pos 029e: 339 */ 0xEE /* 'n' -> */, +/* pos 029f: 340 */ 0xF3 /* 's' -> */, +/* pos 02a0: 341 */ 0xE6 /* 'f' -> */, +/* pos 02a1: 342 */ 0xE5 /* 'e' -> */, +/* pos 02a2: 343 */ 0xF2 /* 'r' -> */, +/* pos 02a3: 344 */ 0xAD /* '-' -> */, +/* pos 02a4: 345 */ 0xE5 /* 'e' -> */, +/* pos 02a5: 346 */ 0xEE /* 'n' -> */, +/* pos 02a6: 347 */ 0xE3 /* 'c' -> */, +/* pos 02a7: 348 */ 0xEF /* 'o' -> */, +/* pos 02a8: 349 */ 0xE4 /* 'd' -> */, +/* pos 02a9: 350 */ 0xE9 /* 'i' -> */, +/* pos 02aa: 351 */ 0xEE /* 'n' -> */, +/* pos 02ab: 352 */ 0xE7 /* 'g' -> */, +/* pos 02ac: 353 */ 0xBA /* ':' -> */, +/* pos 02ad: 354 */ 0x00, 0x44 /* - terminal marker 68 - */, +/* pos 02af: 355 */ 0xE9 /* 'i' -> */, +/* pos 02b0: 356 */ 0xAD /* '-' -> */, +/* pos 02b1: 357 */ 0xE1 /* 'a' -> */, +/* pos 02b2: 358 */ 0xF2 /* 'r' -> */, +/* pos 02b3: 359 */ 0xE7 /* 'g' -> */, +/* pos 02b4: 360 */ 0xF3 /* 's' -> */, +/* pos 02b5: 361 */ 0x00, 0x4C /* - terminal marker 76 - */, +/* pos 02b7: 362 */ 0xA0 /* ' ' -> */, +/* pos 02b8: 363 */ 0x00, 0x4F /* - terminal marker 79 - */, +/* pos 02ba: 364 */ 0xAD /* '-' -> */, +/* pos 02bb: 365 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x02C5 state 366) */, + 0x61 /* 'a' */, 0x1D, 0x00 /* (to 0x02DB state 385) */, + 0x72 /* 'r' */, 0xFB, 0x00 /* (to 0x03BC state 568) */, + 0x08, /* fail */ +/* pos 02c5: 366 */ 0xEF /* 'o' -> */, +/* pos 02c6: 367 */ 0xF2 /* 'r' -> */, +/* pos 02c7: 368 */ 0xF7 /* 'w' -> */, +/* pos 02c8: 369 */ 0xE1 /* 'a' -> */, +/* pos 02c9: 370 */ 0xF2 /* 'r' -> */, +/* pos 02ca: 371 */ 0xE4 /* 'd' -> */, +/* pos 02cb: 372 */ 0xE5 /* 'e' -> */, +/* pos 02cc: 373 */ 0xE4 /* 'd' -> */, +/* pos 02cd: 374 */ 0xAD /* '-' -> */, +/* pos 02ce: 375 */ 0xE6 /* 'f' -> */, +/* pos 02cf: 376 */ 0xEF /* 'o' -> */, +/* pos 02d0: 377 */ 0xF2 /* 'r' -> */, +/* pos 02d1: 378 */ 0xBA /* ':' -> */, +/* pos 02d2: 379 */ 0x00, 0x50 /* - terminal marker 80 - */, +/* pos 02d4: 380 */ 0x00, 0x51 /* - terminal marker 81 - */, +/* pos 02d6: 381 */ 0xE1 /* 'a' -> */, +/* pos 02d7: 382 */ 0xE4 /* 'd' -> */, +/* pos 02d8: 383 */ 0xA0 /* ' ' -> */, +/* pos 02d9: 384 */ 0x00, 0x52 /* - terminal marker 82 - */, +/* pos 02db: 385 */ 0xF5 /* 'u' -> */, +/* pos 02dc: 386 */ 0xF4 /* 't' -> */, +/* pos 02dd: 387 */ 0xE8 /* 'h' -> */, +/* pos 02de: 388 */ 0xAD /* '-' -> */, +/* pos 02df: 389 */ 0xF4 /* 't' -> */, +/* pos 02e0: 390 */ 0xEF /* 'o' -> */, +/* pos 02e1: 391 */ 0xEB /* 'k' -> */, +/* pos 02e2: 392 */ 0xE5 /* 'e' -> */, +/* pos 02e3: 393 */ 0xEE /* 'n' -> */, +/* pos 02e4: 394 */ 0xBA /* ':' -> */, +/* pos 02e5: 395 */ 0x00, 0x56 /* - terminal marker 86 - */, +/* pos 02e7: 396 */ 0xF4 /* 't' -> */, +/* pos 02e8: 397 */ 0xE9 /* 'i' -> */, +/* pos 02e9: 398 */ 0xEF /* 'o' -> */, +/* pos 02ea: 399 */ 0xEE /* 'n' -> */, +/* pos 02eb: 400 */ 0xF3 /* 's' -> */, +/* pos 02ec: 401 */ 0xA0 /* ' ' -> */, +/* pos 02ed: 402 */ 0x00, 0x02 /* - terminal marker 2 - */, +/* pos 02ef: 403 */ 0xF3 /* 's' -> */, +/* pos 02f0: 404 */ 0xAD /* '-' -> */, +/* pos 02f1: 405 */ 0xE3 /* 'c' -> */, +/* pos 02f2: 406 */ 0xEF /* 'o' -> */, +/* pos 02f3: 407 */ 0xEE /* 'n' -> */, +/* pos 02f4: 408 */ 0xF4 /* 't' -> */, +/* pos 02f5: 409 */ 0xF2 /* 'r' -> */, +/* pos 02f6: 410 */ 0xEF /* 'o' -> */, +/* pos 02f7: 411 */ 0xEC /* 'l' -> */, +/* pos 02f8: 412 */ 0xAD /* '-' -> */, +/* pos 02f9: 413 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x0300 state 414) */, + 0x61 /* 'a' */, 0x24, 0x00 /* (to 0x0320 state 443) */, + 0x08, /* fail */ +/* pos 0300: 414 */ 0xE5 /* 'e' -> */, +/* pos 0301: 415 */ 0xF1 /* 'q' -> */, +/* pos 0302: 416 */ 0xF5 /* 'u' -> */, +/* pos 0303: 417 */ 0xE5 /* 'e' -> */, +/* pos 0304: 418 */ 0xF3 /* 's' -> */, +/* pos 0305: 419 */ 0xF4 /* 't' -> */, +/* pos 0306: 420 */ 0xAD /* '-' -> */, +/* pos 0307: 421 */ 0xE8 /* 'h' -> */, +/* pos 0308: 422 */ 0xE5 /* 'e' -> */, +/* pos 0309: 423 */ 0xE1 /* 'a' -> */, +/* pos 030a: 424 */ 0xE4 /* 'd' -> */, +/* pos 030b: 425 */ 0xE5 /* 'e' -> */, +/* pos 030c: 426 */ 0xF2 /* 'r' -> */, +/* pos 030d: 427 */ 0xF3 /* 's' -> */, +/* pos 030e: 428 */ 0xBA /* ':' -> */, +/* pos 030f: 429 */ 0x00, 0x12 /* - terminal marker 18 - */, +/* pos 0311: 430 */ 0xF2 /* 'r' -> */, +/* pos 0312: 431 */ 0xE5 /* 'e' -> */, +/* pos 0313: 432 */ 0xF2 /* 'r' -> */, +/* pos 0314: 433 */ 0xBA /* ':' -> */, +/* pos 0315: 434 */ 0x00, 0x1F /* - terminal marker 31 - */, +/* pos 0317: 435 */ 0xE8 /* 'h' -> */, +/* pos 0318: 436 */ 0xE1 /* 'a' -> */, +/* pos 0319: 437 */ 0xF2 /* 'r' -> */, +/* pos 031a: 438 */ 0xF3 /* 's' -> */, +/* pos 031b: 439 */ 0xE5 /* 'e' -> */, +/* pos 031c: 440 */ 0xF4 /* 't' -> */, +/* pos 031d: 441 */ 0xBA /* ':' -> */, +/* pos 031e: 442 */ 0x00, 0x28 /* - terminal marker 40 - */, +/* pos 0320: 443 */ 0xEC /* 'l' -> */, +/* pos 0321: 444 */ 0xEC /* 'l' -> */, +/* pos 0322: 445 */ 0xEF /* 'o' -> */, +/* pos 0323: 446 */ 0xF7 /* 'w' -> */, +/* pos 0324: 447 */ 0xAD /* '-' -> */, +/* pos 0325: 448 */ 0xEF /* 'o' -> */, +/* pos 0326: 449 */ 0xF2 /* 'r' -> */, +/* pos 0327: 450 */ 0xE9 /* 'i' -> */, +/* pos 0328: 451 */ 0xE7 /* 'g' -> */, +/* pos 0329: 452 */ 0xE9 /* 'i' -> */, +/* pos 032a: 453 */ 0xEE /* 'n' -> */, +/* pos 032b: 454 */ 0xBA /* ':' -> */, +/* pos 032c: 455 */ 0x00, 0x2A /* - terminal marker 42 - */, +/* pos 032e: 456 */ 0xE1 /* 'a' -> */, +/* pos 032f: 457 */ 0xF8 /* 'x' -> */, +/* pos 0330: 458 */ 0xAD /* '-' -> */, +/* pos 0331: 459 */ 0xE6 /* 'f' -> */, +/* pos 0332: 460 */ 0xEF /* 'o' -> */, +/* pos 0333: 461 */ 0xF2 /* 'r' -> */, +/* pos 0334: 462 */ 0xF7 /* 'w' -> */, +/* pos 0335: 463 */ 0xE1 /* 'a' -> */, +/* pos 0336: 464 */ 0xF2 /* 'r' -> */, +/* pos 0337: 465 */ 0xE4 /* 'd' -> */, +/* pos 0338: 466 */ 0xF3 /* 's' -> */, +/* pos 0339: 467 */ 0xBA /* ':' -> */, +/* pos 033a: 468 */ 0x00, 0x3C /* - terminal marker 60 - */, +/* pos 033c: 469 */ 0xF8 /* 'x' -> */, +/* pos 033d: 470 */ 0xF9 /* 'y' -> */, +/* pos 033e: 471 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x0345 state 472) */, + 0x20 /* ' ' */, 0x79, 0x00 /* (to 0x03BA state 567) */, + 0x08, /* fail */ +/* pos 0345: 472 */ 0xE1 /* 'a' -> */, +/* pos 0346: 473 */ 0xF5 /* 'u' -> */, +/* pos 0347: 474 */ 0xF4 /* 't' -> */, +/* pos 0348: 475 */ 0xE8 /* 'h' -> */, +/* pos 0349: 476 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0350 state 477) */, + 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x035A state 486) */, + 0x08, /* fail */ +/* pos 0350: 477 */ 0xEE /* 'n' -> */, +/* pos 0351: 478 */ 0xF4 /* 't' -> */, +/* pos 0352: 479 */ 0xE9 /* 'i' -> */, +/* pos 0353: 480 */ 0xE3 /* 'c' -> */, +/* pos 0354: 481 */ 0xE1 /* 'a' -> */, +/* pos 0355: 482 */ 0xF4 /* 't' -> */, +/* pos 0356: 483 */ 0xE5 /* 'e' -> */, +/* pos 0357: 484 */ 0xBA /* ':' -> */, +/* pos 0358: 485 */ 0x00, 0x3D /* - terminal marker 61 - */, +/* pos 035a: 486 */ 0xF2 /* 'r' -> */, +/* pos 035b: 487 */ 0xE9 /* 'i' -> */, +/* pos 035c: 488 */ 0xFA /* 'z' -> */, +/* pos 035d: 489 */ 0xE1 /* 'a' -> */, +/* pos 035e: 490 */ 0xF4 /* 't' -> */, +/* pos 035f: 491 */ 0xE9 /* 'i' -> */, +/* pos 0360: 492 */ 0xEF /* 'o' -> */, +/* pos 0361: 493 */ 0xEE /* 'n' -> */, +/* pos 0362: 494 */ 0xBA /* ':' -> */, +/* pos 0363: 495 */ 0x00, 0x3E /* - terminal marker 62 - */, +/* pos 0365: 496 */ 0xF2 /* 'r' -> */, +/* pos 0366: 497 */ 0xE9 /* 'i' -> */, +/* pos 0367: 498 */ 0xE3 /* 'c' -> */, +/* pos 0368: 499 */ 0xF4 /* 't' -> */, +/* pos 0369: 500 */ 0xAD /* '-' -> */, +/* pos 036a: 501 */ 0xF4 /* 't' -> */, +/* pos 036b: 502 */ 0xF2 /* 'r' -> */, +/* pos 036c: 503 */ 0xE1 /* 'a' -> */, +/* pos 036d: 504 */ 0xEE /* 'n' -> */, +/* pos 036e: 505 */ 0xF3 /* 's' -> */, +/* pos 036f: 506 */ 0xF0 /* 'p' -> */, +/* pos 0370: 507 */ 0xEF /* 'o' -> */, +/* pos 0371: 508 */ 0xF2 /* 'r' -> */, +/* pos 0372: 509 */ 0xF4 /* 't' -> */, +/* pos 0373: 510 */ 0xAD /* '-' -> */, +/* pos 0374: 511 */ 0xF3 /* 's' -> */, +/* pos 0375: 512 */ 0xE5 /* 'e' -> */, +/* pos 0376: 513 */ 0xE3 /* 'c' -> */, +/* pos 0377: 514 */ 0xF5 /* 'u' -> */, +/* pos 0378: 515 */ 0xF2 /* 'r' -> */, +/* pos 0379: 516 */ 0xE9 /* 'i' -> */, +/* pos 037a: 517 */ 0xF4 /* 't' -> */, +/* pos 037b: 518 */ 0xF9 /* 'y' -> */, +/* pos 037c: 519 */ 0xBA /* ':' -> */, +/* pos 037d: 520 */ 0x00, 0x43 /* - terminal marker 67 - */, +/* pos 037f: 521 */ 0xE5 /* 'e' -> */, +/* pos 0380: 522 */ 0xF2 /* 'r' -> */, +/* pos 0381: 523 */ 0xAD /* '-' -> */, +/* pos 0382: 524 */ 0xE1 /* 'a' -> */, +/* pos 0383: 525 */ 0xE7 /* 'g' -> */, +/* pos 0384: 526 */ 0xE5 /* 'e' -> */, +/* pos 0385: 527 */ 0xEE /* 'n' -> */, +/* pos 0386: 528 */ 0xF4 /* 't' -> */, +/* pos 0387: 529 */ 0xBA /* ':' -> */, +/* pos 0388: 530 */ 0x00, 0x45 /* - terminal marker 69 - */, +/* pos 038a: 531 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0391 state 532) */, + 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0396 state 536) */, + 0x08, /* fail */ +/* pos 0391: 532 */ 0xF2 /* 'r' -> */, +/* pos 0392: 533 */ 0xF9 /* 'y' -> */, +/* pos 0393: 534 */ 0xBA /* ':' -> */, +/* pos 0394: 535 */ 0x00, 0x46 /* - terminal marker 70 - */, +/* pos 0396: 536 */ 0xE1 /* 'a' -> */, +/* pos 0397: 537 */ 0xBA /* ':' -> */, +/* pos 0398: 538 */ 0x00, 0x47 /* - terminal marker 71 - */, +/* pos 039a: 539 */ 0xF7 /* 'w' -> */, +/* pos 039b: 540 */ 0xF7 /* 'w' -> */, +/* pos 039c: 541 */ 0xAD /* '-' -> */, +/* pos 039d: 542 */ 0xE1 /* 'a' -> */, +/* pos 039e: 543 */ 0xF5 /* 'u' -> */, +/* pos 039f: 544 */ 0xF4 /* 't' -> */, +/* pos 03a0: 545 */ 0xE8 /* 'h' -> */, +/* pos 03a1: 546 */ 0xE5 /* 'e' -> */, +/* pos 03a2: 547 */ 0xEE /* 'n' -> */, +/* pos 03a3: 548 */ 0xF4 /* 't' -> */, +/* pos 03a4: 549 */ 0xE9 /* 'i' -> */, +/* pos 03a5: 550 */ 0xE3 /* 'c' -> */, +/* pos 03a6: 551 */ 0xE1 /* 'a' -> */, +/* pos 03a7: 552 */ 0xF4 /* 't' -> */, +/* pos 03a8: 553 */ 0xE5 /* 'e' -> */, +/* pos 03a9: 554 */ 0xBA /* ':' -> */, +/* pos 03aa: 555 */ 0x00, 0x48 /* - terminal marker 72 - */, +/* pos 03ac: 556 */ 0xF4 /* 't' -> */, +/* pos 03ad: 557 */ 0xE3 /* 'c' -> */, +/* pos 03ae: 558 */ 0xE8 /* 'h' -> */, +/* pos 03af: 559 */ 0x00, 0x49 /* - terminal marker 73 - */, +/* pos 03b1: 560 */ 0xF4 /* 't' -> */, +/* pos 03b2: 561 */ 0x00, 0x4A /* - terminal marker 74 - */, +/* pos 03b4: 562 */ 0xEC /* 'l' -> */, +/* pos 03b5: 563 */ 0xE5 /* 'e' -> */, +/* pos 03b6: 564 */ 0xF4 /* 't' -> */, +/* pos 03b7: 565 */ 0xE5 /* 'e' -> */, +/* pos 03b8: 566 */ 0x00, 0x4B /* - terminal marker 75 - */, +/* pos 03ba: 567 */ 0x00, 0x4D /* - terminal marker 77 - */, +/* pos 03bc: 568 */ 0xE5 /* 'e' -> */, +/* pos 03bd: 569 */ 0xE1 /* 'a' -> */, +/* pos 03be: 570 */ 0xEC /* 'l' -> */, +/* pos 03bf: 571 */ 0xAD /* '-' -> */, +/* pos 03c0: 572 */ 0xE9 /* 'i' -> */, +/* pos 03c1: 573 */ 0xF0 /* 'p' -> */, +/* pos 03c2: 574 */ 0xBA /* ':' -> */, +/* pos 03c3: 575 */ 0x00, 0x4E /* - terminal marker 78 - */, +/* pos 03c5: 576 */ 0xBA /* ':' -> */, +/* pos 03c6: 577 */ 0x00, 0x53 /* - terminal marker 83 - */, +/* pos 03c8: 578 */ 0xEC /* 'l' -> */, +/* pos 03c9: 579 */ 0xE1 /* 'a' -> */, +/* pos 03ca: 580 */ 0xF9 /* 'y' -> */, +/* pos 03cb: 581 */ 0xAD /* '-' -> */, +/* pos 03cc: 582 */ 0xEE /* 'n' -> */, +/* pos 03cd: 583 */ 0xEF /* 'o' -> */, +/* pos 03ce: 584 */ 0xEE /* 'n' -> */, +/* pos 03cf: 585 */ 0xE3 /* 'c' -> */, +/* pos 03d0: 586 */ 0xE5 /* 'e' -> */, +/* pos 03d1: 587 */ 0xBA /* ':' -> */, +/* pos 03d2: 588 */ 0x00, 0x54 /* - terminal marker 84 - */, +/* pos 03d4: 589 */ 0xAD /* '-' -> */, +/* pos 03d5: 590 */ 0xF7 /* 'w' -> */, +/* pos 03d6: 591 */ 0xE5 /* 'e' -> */, +/* pos 03d7: 592 */ 0xE2 /* 'b' -> */, +/* pos 03d8: 593 */ 0xF3 /* 's' -> */, +/* pos 03d9: 594 */ 0xEF /* 'o' -> */, +/* pos 03da: 595 */ 0xE3 /* 'c' -> */, +/* pos 03db: 596 */ 0xEB /* 'k' -> */, +/* pos 03dc: 597 */ 0xE5 /* 'e' -> */, +/* pos 03dd: 598 */ 0xF4 /* 't' -> */, +/* pos 03de: 599 */ 0xAD /* '-' -> */, +/* pos 03df: 600 */ 0x64 /* 'd' */, 0x19, 0x00 /* (to 0x03F8 state 601) */, + 0x65 /* 'e' */, 0x1D, 0x00 /* (to 0x03FF state 607) */, + 0x6B /* 'k' */, 0x26, 0x00 /* (to 0x040B state 618) */, + 0x70 /* 'p' */, 0x35, 0x00 /* (to 0x041D state 625) */, + 0x61 /* 'a' */, 0x3C, 0x00 /* (to 0x0427 state 634) */, + 0x6E /* 'n' */, 0x41, 0x00 /* (to 0x042F state 641) */, + 0x76 /* 'v' */, 0x47, 0x00 /* (to 0x0438 state 648) */, + 0x6F /* 'o' */, 0x4D, 0x00 /* (to 0x0441 state 656) */, + 0x08, /* fail */ +/* pos 03f8: 601 */ 0xF2 /* 'r' -> */, +/* pos 03f9: 602 */ 0xE1 /* 'a' -> */, +/* pos 03fa: 603 */ 0xE6 /* 'f' -> */, +/* pos 03fb: 604 */ 0xF4 /* 't' -> */, +/* pos 03fc: 605 */ 0xBA /* ':' -> */, +/* pos 03fd: 606 */ 0x00, 0x07 /* - terminal marker 7 - */, +/* pos 03ff: 607 */ 0xF8 /* 'x' -> */, +/* pos 0400: 608 */ 0xF4 /* 't' -> */, +/* pos 0401: 609 */ 0xE5 /* 'e' -> */, +/* pos 0402: 610 */ 0xEE /* 'n' -> */, +/* pos 0403: 611 */ 0xF3 /* 's' -> */, +/* pos 0404: 612 */ 0xE9 /* 'i' -> */, +/* pos 0405: 613 */ 0xEF /* 'o' -> */, +/* pos 0406: 614 */ 0xEE /* 'n' -> */, +/* pos 0407: 615 */ 0xF3 /* 's' -> */, +/* pos 0408: 616 */ 0xBA /* ':' -> */, +/* pos 0409: 617 */ 0x00, 0x09 /* - terminal marker 9 - */, +/* pos 040b: 618 */ 0xE5 /* 'e' -> */, +/* pos 040c: 619 */ 0xF9 /* 'y' -> */, +/* pos 040d: 620 */ 0x31 /* '1' */, 0x0A, 0x00 /* (to 0x0417 state 621) */, + 0x32 /* '2' */, 0x0A, 0x00 /* (to 0x041A state 623) */, + 0x3A /* ':' */, 0x23, 0x00 /* (to 0x0436 state 647) */, + 0x08, /* fail */ +/* pos 0417: 621 */ 0xBA /* ':' -> */, +/* pos 0418: 622 */ 0x00, 0x0A /* - terminal marker 10 - */, +/* pos 041a: 623 */ 0xBA /* ':' -> */, +/* pos 041b: 624 */ 0x00, 0x0B /* - terminal marker 11 - */, +/* pos 041d: 625 */ 0xF2 /* 'r' -> */, +/* pos 041e: 626 */ 0xEF /* 'o' -> */, +/* pos 041f: 627 */ 0xF4 /* 't' -> */, +/* pos 0420: 628 */ 0xEF /* 'o' -> */, +/* pos 0421: 629 */ 0xE3 /* 'c' -> */, +/* pos 0422: 630 */ 0xEF /* 'o' -> */, +/* pos 0423: 631 */ 0xEC /* 'l' -> */, +/* pos 0424: 632 */ 0xBA /* ':' -> */, +/* pos 0425: 633 */ 0x00, 0x0C /* - terminal marker 12 - */, +/* pos 0427: 634 */ 0xE3 /* 'c' -> */, +/* pos 0428: 635 */ 0xE3 /* 'c' -> */, +/* pos 0429: 636 */ 0xE5 /* 'e' -> */, +/* pos 042a: 637 */ 0xF0 /* 'p' -> */, +/* pos 042b: 638 */ 0xF4 /* 't' -> */, +/* pos 042c: 639 */ 0xBA /* ':' -> */, +/* pos 042d: 640 */ 0x00, 0x0D /* - terminal marker 13 - */, +/* pos 042f: 641 */ 0xEF /* 'o' -> */, +/* pos 0430: 642 */ 0xEE /* 'n' -> */, +/* pos 0431: 643 */ 0xE3 /* 'c' -> */, +/* pos 0432: 644 */ 0xE5 /* 'e' -> */, +/* pos 0433: 645 */ 0xBA /* ':' -> */, +/* pos 0434: 646 */ 0x00, 0x0E /* - terminal marker 14 - */, +/* pos 0436: 647 */ 0x00, 0x20 /* - terminal marker 32 - */, +/* pos 0438: 648 */ 0xE5 /* 'e' -> */, +/* pos 0439: 649 */ 0xF2 /* 'r' -> */, +/* pos 043a: 650 */ 0xF3 /* 's' -> */, +/* pos 043b: 651 */ 0xE9 /* 'i' -> */, +/* pos 043c: 652 */ 0xEF /* 'o' -> */, +/* pos 043d: 653 */ 0xEE /* 'n' -> */, +/* pos 043e: 654 */ 0xBA /* ':' -> */, +/* pos 043f: 655 */ 0x00, 0x21 /* - terminal marker 33 - */, +/* pos 0441: 656 */ 0xF2 /* 'r' -> */, +/* pos 0442: 657 */ 0xE9 /* 'i' -> */, +/* pos 0443: 658 */ 0xE7 /* 'g' -> */, +/* pos 0444: 659 */ 0xE9 /* 'i' -> */, +/* pos 0445: 660 */ 0xEE /* 'n' -> */, +/* pos 0446: 661 */ 0xBA /* ':' -> */, +/* pos 0447: 662 */ 0x00, 0x22 /* - terminal marker 34 - */, +/* pos 0449: 663 */ 0xAD /* '-' -> */, +/* pos 044a: 664 */ 0xF3 /* 's' -> */, +/* pos 044b: 665 */ 0xE5 /* 'e' -> */, +/* pos 044c: 666 */ 0xF4 /* 't' -> */, +/* pos 044d: 667 */ 0xF4 /* 't' -> */, +/* pos 044e: 668 */ 0xE9 /* 'i' -> */, +/* pos 044f: 669 */ 0xEE /* 'n' -> */, +/* pos 0450: 670 */ 0xE7 /* 'g' -> */, +/* pos 0451: 671 */ 0xF3 /* 's' -> */, +/* pos 0452: 672 */ 0xBA /* ':' -> */, +/* pos 0453: 673 */ 0x00, 0x10 /* - terminal marker 16 - */, +/* pos 0455: 674 */ 0x61 /* 'a' */, 0x0D, 0x00 /* (to 0x0462 state 675) */, + 0x6D /* 'm' */, 0x14, 0x00 /* (to 0x046C state 684) */, + 0x70 /* 'p' */, 0x18, 0x00 /* (to 0x0473 state 690) */, + 0x73 /* 's' */, 0x20, 0x00 /* (to 0x047E state 694) */, + 0x08, /* fail */ +/* pos 0462: 675 */ 0xF5 /* 'u' -> */, +/* pos 0463: 676 */ 0xF4 /* 't' -> */, +/* pos 0464: 677 */ 0xE8 /* 'h' -> */, +/* pos 0465: 678 */ 0xEF /* 'o' -> */, +/* pos 0466: 679 */ 0xF2 /* 'r' -> */, +/* pos 0467: 680 */ 0xE9 /* 'i' -> */, +/* pos 0468: 681 */ 0xF4 /* 't' -> */, +/* pos 0469: 682 */ 0xF9 /* 'y' -> */, +/* pos 046a: 683 */ 0x00, 0x23 /* - terminal marker 35 - */, +/* pos 046c: 684 */ 0xE5 /* 'e' -> */, +/* pos 046d: 685 */ 0xF4 /* 't' -> */, +/* pos 046e: 686 */ 0xE8 /* 'h' -> */, +/* pos 046f: 687 */ 0xEF /* 'o' -> */, +/* pos 0470: 688 */ 0xE4 /* 'd' -> */, +/* pos 0471: 689 */ 0x00, 0x24 /* - terminal marker 36 - */, +/* pos 0473: 690 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x047A state 691) */, + 0x72 /* 'r' */, 0x1B, 0x00 /* (to 0x0491 state 705) */, + 0x08, /* fail */ +/* pos 047a: 691 */ 0xF4 /* 't' -> */, +/* pos 047b: 692 */ 0xE8 /* 'h' -> */, +/* pos 047c: 693 */ 0x00, 0x25 /* - terminal marker 37 - */, +/* pos 047e: 694 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x0485 state 695) */, + 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x048B state 700) */, + 0x08, /* fail */ +/* pos 0485: 695 */ 0xE8 /* 'h' -> */, +/* pos 0486: 696 */ 0xE5 /* 'e' -> */, +/* pos 0487: 697 */ 0xED /* 'm' -> */, +/* pos 0488: 698 */ 0xE5 /* 'e' -> */, +/* pos 0489: 699 */ 0x00, 0x26 /* - terminal marker 38 - */, +/* pos 048b: 700 */ 0xE1 /* 'a' -> */, +/* pos 048c: 701 */ 0xF4 /* 't' -> */, +/* pos 048d: 702 */ 0xF5 /* 'u' -> */, +/* pos 048e: 703 */ 0xF3 /* 's' -> */, +/* pos 048f: 704 */ 0x00, 0x27 /* - terminal marker 39 - */, +/* pos 0491: 705 */ 0xEF /* 'o' -> */, +/* pos 0492: 706 */ 0xF4 /* 't' -> */, +/* pos 0493: 707 */ 0xEF /* 'o' -> */, +/* pos 0494: 708 */ 0xE3 /* 'c' -> */, +/* pos 0495: 709 */ 0xEF /* 'o' -> */, +/* pos 0496: 710 */ 0xEC /* 'l' -> */, +/* pos 0497: 711 */ 0x00, 0x55 /* - terminal marker 85 - */, /* total size 1177 bytes */ #endif @@ -6757,42 +6692,42 @@ /* #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { -0x03,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { -0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { -0x03,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { -0x07,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { -0x03,0x00,0x80,0x07,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { -0x07,0x00,0x00,0x1e,0x00,0x00,0x00,0xc0,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { -0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { -0x07,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00, }; #endif */ diff --git a/lib/roles/http/minilex.c b/lib/roles/http/minilex.c index bf844c98..2f9d6a8d 100644 --- a/lib/roles/http/minilex.c +++ b/lib/roles/http/minilex.c @@ -46,15 +46,94 @@ */ unsigned char filter_array[] = { - 0xff, 0xff, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xff, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xff, 0xf0, 0xff, 0xaa, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfa, 0xcc, 0xcc, 0xcc, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xfa, 0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xff, - 0xfa, 0xfa, 0xfa, 0xfa, 0xaa, 0xaa, 0xaa, 0xff, 0xaa, 0xaa, - 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xf0, 0xff, 0xff + 0xff, /* get */ + 0xff, /* post */ + 0xaa, /* options */ + 0xff, /* host */ + 0xff, /* connection */ + 0xff, /* upgrade */ + 0xff, /* origin */ + 0xcc, /* sec-ws-draft */ + 0xff, /* crlf */ + 0xcc, /* sec-ws-ext */ + 0xcc, /* sec-ws-key1 */ + 0xcc, /* sec-ws-key2 */ + 0xcc, /* sec-ws-protocol */ + 0xcc, /* sec-ws-accept */ + 0xcc, /* sec-ws-nonce */ + 0xff, /* http/1.1 */ + 0xf0, /* http2-settings */ + 0xff, /* accept */ + 0xaa, /* access-control-req-hdrs */ + 0xff, /* if-modified-since */ + 0xff, /* if-none-match */ + 0xff, /* accept-encoding */ + 0xff, /* accept-language */ + 0xff, /* pragma */ + 0xff, /* cache-control */ + 0xff, /* authorization */ + 0xff, /* cookie */ + 0xff, /* content-length */ + 0xff, /* content-type */ + 0xff, /* date */ + 0xff, /* range */ + 0xfa, /* referer */ + 0xcc, /* sec-ws-key */ + 0xcc, /* sec-ws-version */ + 0xcc, /* sec-sc-origin */ + 0xf0, /* authority */ + 0xf0, /* method */ + 0xf0, /* path */ + 0xf0, /* scheme */ + 0xf0, /* status */ + 0xfa, /* accept-charset */ + 0xff, /* accept-ranges */ + 0xfa, /* access-control-allow-origin */ + 0xff, /* age */ + 0xff, /* allow */ + 0xff, /* content-disposition */ + 0xff, /* content-encoding */ + 0xff, /* content-language */ + 0xff, /* content-location */ + 0xff, /* content-range */ + 0xff, /* etag */ + 0xff, /* expect */ + 0xff, /* expires */ + 0xff, /* from */ + 0xff, /* if-match */ + 0xff, /* if-range */ + 0xff, /* if-unmodified-since */ + 0xff, /* last-modified */ + 0xff, /* link */ + 0xff, /* location */ + 0xfa, /* max-forwards */ + 0xfa, /* proxy-authenticate */ + 0xfa, /* proxy-authorization */ + 0xff, /* refresh */ + 0xff, /* retry-after */ + 0xff, /* server */ + 0xff, /* set-cookie */ + 0xfa, /* strict-transport-security */ + 0xff, /* transfer-encoding */ + 0xfa, /* user-agent */ + 0xfa, /* vary */ + 0xfa, /* via */ + 0xfa, /* www-authenticate */ + 0xaa, /* patch */ + 0xaa, /* put */ + 0xaa, /* delete */ + 0xff, /* uri-args */ + 0xaa, /* proxy */ + 0xaa, /* x-real-ip */ + 0xff, /* http/1.0 */ + 0xff, /* x-forwarded-for */ + 0xff, /* connect */ + 0xff, /* head */ + 0xfa, /* te */ + 0xfa, /* replay-nonce */ + 0xf0, /* protocol */ + 0xff, /* x-auth-token */ + 0xff /* not matchable */ }; static unsigned char lws_header_implies_psuedoheader_map[] = { diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index 5c503649..e6205c9c 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -1078,6 +1078,7 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, struct lws *cwsi; int n, na; +#if defined(LWS_ROLE_WS) if (ws) /* * Neither our inbound ws upgrade request side, nor our onward @@ -1094,7 +1095,7 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, * the .local_protocol_name. */ lws_bind_protocol(wsi, &lws_ws_proxy, __func__); - +#endif memset(&i, 0, sizeof(i)); i.context = lws_get_context(wsi); @@ -1228,9 +1229,11 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, i.alpn = "http/1.1"; i.parent_wsi = wsi; i.pwsi = &cwsi; +#if defined(LWS_ROLE_WS) i.protocol = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL); if (ws) i.local_protocol_name = "lws-ws-proxy"; +#endif // i.uri_replace_from = hit->origin; // i.uri_replace_to = hit->mountpoint; diff --git a/test-apps/test-server.c b/test-apps/test-server.c index a2f6eeb3..0da86b0d 100644 --- a/test-apps/test-server.c +++ b/test-apps/test-server.c @@ -82,8 +82,8 @@ char crl_path[1024] = ""; #include "../plugins/protocol_lws_mirror.c" #include "../plugins/protocol_lws_status.c" #include "../plugins/protocol_dumb_increment.c" -#include "../plugins/protocol_post_demo.c" #endif +#include "../plugins/protocol_post_demo.c" static int lws_callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, @@ -155,8 +155,8 @@ static struct lws_protocols protocols[] = { LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT, LWS_PLUGIN_PROTOCOL_MIRROR, LWS_PLUGIN_PROTOCOL_LWS_STATUS, - LWS_PLUGIN_PROTOCOL_POST_DEMO, #endif + LWS_PLUGIN_PROTOCOL_POST_DEMO, { NULL, NULL, 0, 0 } /* terminator */ }; -- Gitee From f6215f64704de89255e1fcdecce514ebf8fea374 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 7 Mar 2020 06:26:40 +0000 Subject: [PATCH 0002/1062] README: update changlog link and include content --- README.md | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ff2a0696..ce2e1398 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,99 @@ News Users wanting a stable branch should follow v4.0-stable to get the most stable version at any given time. -See the [changelog](https://libwebsockets.org/git/libwebsockets/tree/lib/changelog) for +See the [changelog](https://libwebsockets.org/git/libwebsockets/tree/changelog) for information on the huge amount of new features in this release, and additional information below. +``` + - NEW: Lws is now under the MIT license, see ./LICENSE for details + + - NEW: GLIB native event loop support, lws + gtk example + + - NEW: native lws MQTT client... supports client stream binding like h2 when + multiple logical connections are going to the same endpoint over MQTT, they + transparently and independently share the one connection + tls tunnel + + - NEW: "Secure Streams"... if you are making a device with client connections + to the internet or cloud, this allows separation of the communications + policy (endpoints, tls cert validation, protocols, etc) from the code, with + the goal you can combine streams, change protocols and cloud provision, and + reflect that in the device's JSON policy document without having to change + any code. + + - NEW: lws_system: New lightweight and efficient Asynchronous DNS resolver + implementation for both A and AAAA records, supports recursive (without + recursion in code) lookups, caching, and getaddrinfo() compatible results + scheme (from cache directly without per-consumer allocation). Able to + perform DNS lookups without introducing latency in the event loop. + + - NEW: lws_system: ntpclient implementation with interface for setting system + time via lws_system ops + + - NEW: lws_system: dhcpclient implementation + + - NEW: Connection validity tracking, autoproduce PING/PONG for protocols that + support it if not informed that the connection has passed data in both + directions recently enough + + - NEW: lws_retry: standardized exponential backoff and retry timing based + around backoff table and lws_sul + + - NEW: there are official public helpers for unaligned de/serialization of all + common types, see eh, lws_ser_wu16be() in include/libwebsockets/lws-misc.h + + - NEW: lws_tls_client_vhost_extra_cert_mem() api allows attaching extra certs + to a client vhost from DER in memory + + - NEW: lws_system: generic blobs support passing auth tokens, per-connection + client certs etc from platform into lws + + - NEW: public helpers to consume and produce ipv4/6 addresses in a clean way, + along with lws_sockaddr46 type now public. See eg, lws_sockaddr46-based + lws_sa46_parse_numeric_address(), lws_write_numeric_address() + in include/libwebsockets/lws-network-helper.h + + - Improved client redirect handling, h2 compatibility + + - NEW: lwsac: additional features for constant folding support (strings that + already are in the lwsac can be pointed to without copying again), backfill + (look for gaps in previous chunks that could take a new use size), and + lwsac_extend() so last use() can attempt to use more unallocated chunk space + + - NEW: lws_humanize: apis for reporting scalar quanties like 1234 as "1.234KB" + with the scaled symbol strings passed in by caller + + - NEW: freertos: support lws_cancel_service() by using UDP pair bound to lo, + since it doesn't have logical pipes + + - NEW: "esp32" plat, which implemented freertos plat compatibility on esp32, is + renamed to "freertos" plat, targeting esp32 and other freertos platforms + + - NEW: base64 has an additional api supporting stateful decode, where the input + is not all in the same place at the same time and can be processed + incrementally + + - NEW: lws ws proxy: support RFC8441 + + - NEW: lws_spawn_piped apis: generic support for vforking a process with child + wsis attached to its stdin, stdout and stderr via pipes. When processes are + reaped, a specified callback is triggered. Currently Linux + OSX. + + - NEW: lws_fsmount apis: Linux-only overlayfs mount and unmount management for + aggregating read-only layers with disposable, changeable upper layer fs + + - Improvements for RTOS / small build case bring the footprint of lws v4 below + that of v3.1 on ARM + + - lws_tokenize: flag specifying # should mark rest of line as comment + + - NEW: minimal example for integrating libasound / alsa via raw file + + - lws_struct: sqlite and json / lejp translation now usable + + +``` + ## Introducing Secure Streams client support Secure Streams is an optional layer above lws (`-DLWS_WITH_SECURE_STREAMS=1`) that -- Gitee From 7044434d1f06995097b50d9a5f790767853dfb96 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 7 Mar 2020 06:28:15 +0000 Subject: [PATCH 0003/1062] version: bump master to 4.0.99 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c6cfb94..2cab9b3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -317,7 +317,7 @@ set(PACKAGE "libwebsockets") set(CPACK_PACKAGE_NAME "${PACKAGE}") set(CPACK_PACKAGE_VERSION_MAJOR "4") set(CPACK_PACKAGE_VERSION_MINOR "0") -set(CPACK_PACKAGE_VERSION_PATCH "0") +set(CPACK_PACKAGE_VERSION_PATCH "99") set(CPACK_PACKAGE_RELEASE 1) set(CPACK_GENERATOR "RPM") set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") -- Gitee From eaab6e28b09b8bedeaef163e9f49621b41289807 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 7 Mar 2020 20:03:58 +0000 Subject: [PATCH 0004/1062] client: unify post tls accept handling --- lib/core-net/connect.c | 31 +++--- lib/roles/http/client/client-handshake.c | 51 ++++------ lib/roles/http/client/client-http.c | 98 ++++++++++++++----- lib/roles/http/private-lib-roles-http.h | 3 + lib/roles/mqtt/client/client-mqtt.c | 24 ++--- lib/roles/raw-skt/ops-raw-skt.c | 26 +---- lib/secure-streams/README.md | 2 +- .../minimal-http-client-post/selftest.sh | 2 +- 8 files changed, 119 insertions(+), 118 deletions(-) diff --git a/lib/core-net/connect.c b/lib/core-net/connect.c index 384e90ca..a63bab30 100644 --- a/lib/core-net/connect.c +++ b/lib/core-net/connect.c @@ -328,30 +328,27 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) wsi->tls.ssl = NULL; if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { + const char *cce = NULL; - /* we can retry this... just cook the SSL BIO the first time */ - - if (lws_ssl_client_bio_create(wsi) < 0) { - lwsl_err("%s: bio_create failed\n", __func__); - goto bail3; - } - + switch ( #if !defined(LWS_WITH_SYS_ASYNC_DNS) - if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { - n = lws_ssl_client_connect1(wsi); - if (!n) - return wsi; - if (n < 0) { - lwsl_err("%s: lws_ssl_client_connect1 failed\n", __func__); - goto bail3; - } - } + lws_client_create_tls(wsi, &cce, 1) +#else + lws_client_create_tls(wsi, &cce, 0) #endif + ) { + case 1: + return wsi; + case 0: + break; + default: + goto bail3; + } } +#endif /* fallthru */ -#endif lws_http_client_connect_via_info2(wsi); } diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 7cefff28..780c97bc 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -190,9 +190,9 @@ send_hs: lwsl_info("%s: wsi %p: waiting to send hdrs (par state 0x%x)\n", __func__, wsi, lwsi_state(wsi_piggyback)); } else { - lwsl_info("%s: wsi %p: %s %s client created own conn (raw %d) vh %s\n", + lwsl_info("%s: wsi %p: %s %s client created own conn (raw %d) vh %sm st 0x%x\n", __func__, wsi, wsi->role_ops->name, - wsi->protocol->name, rawish, wsi->vhost->name); + wsi->protocol->name, rawish, wsi->vhost->name, lwsi_state(wsi)); /* we are making our own connection */ @@ -203,32 +203,30 @@ send_hs: if (lwsi_state(wsi) == LRS_WAITING_CONNECT && (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { - if (!wsi->transaction_from_pipeline_queue && - lws_tls_restrict_borrow(wsi->context)) { - cce = "tls restriction limit"; - goto failed; - } + /* we can retry this... just cook the SSL BIO the first time */ - if (lws_ssl_client_bio_create(wsi) < 0) { - lwsl_err("%s: bio_create failed\n", __func__); + switch (lws_client_create_tls(wsi, &cce, 1)) { + case 0: + break; + case 1: + return wsi; + default: goto failed; } -//#if !defined(LWS_WITH_SYS_ASYNC_DNS) - if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { - n = lws_ssl_client_connect1(wsi); - if (!n) - return wsi; - if (n < 0) { - lwsl_err("%s: lws_ssl_client_connect1 failed\n", __func__); - goto failed; - } - } -//#endif - lwsi_set_state(wsi, LRS_WAITING_SSL); + + lwsl_notice("%s: wsi %p: st 0x%x\n", + __func__, wsi, lwsi_state(wsi)); + + if (lwsi_state(wsi) == LRS_WAITING_CONNECT) + lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); + lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, + wsi->context->timeout_secs); + + //if () return wsi; } #endif @@ -239,17 +237,6 @@ send_hs: /* for a method = "RAW" connection, this makes us * established */ -#if 0 -#if defined(LWS_WITH_SYS_ASYNC_DNS) - if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { - n = lws_ssl_client_connect1(wsi); - if (n < 0) { - lwsl_err("%s: lws_ssl_client_connect1 failed\n", __func__); - goto failed; - } - } -#endif -#endif /* clear his established timeout */ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index cba95eee..b5c9d935 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -24,6 +24,68 @@ #include "private-lib-core.h" +#if defined(LWS_WITH_TLS) +int +lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) +{ + int n; + + /* we can retry this... just cook the SSL BIO the first time */ + + if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { + + if (!wsi->tls.ssl) { + if (lws_ssl_client_bio_create(wsi) < 0) { + *pcce = "bio_create failed"; + return -1; + } + + if (!wsi->transaction_from_pipeline_queue && + lws_tls_restrict_borrow(wsi->context)) { + *pcce = "tls restriction limit"; + return -1; + } + } + + if (!do_c1) + return 0; + + n = lws_ssl_client_connect1(wsi); + if (!n) + return 1; /* caller should return 0 */ + if (n < 0) { + *pcce = "lws_ssl_client_connect1 failed"; + return -1; + } + } else + wsi->tls.ssl = NULL; + +#if defined (LWS_WITH_HTTP2) + if (wsi->client_h2_alpn) { + /* + * We connected to the server and set up tls, and + * negotiated "h2". + * + * So this is it, we are an h2 master client connection + * now, not an h1 client connection. + */ +#if defined(LWS_WITH_TLS) + lws_tls_server_conn_alpn(wsi); +#endif + + /* send the H2 preface to legitimize the connection */ + if (lws_h2_issue_preface(wsi)) { + *pcce = "error sending h2 preface"; + return -1; + } + } +#endif + + return 0; /* OK */ +} + +#endif + void lws_client_http_body_pending(struct lws *wsi, int something_left_to_send) { @@ -151,30 +213,11 @@ start_ws_handshake: return -1; #if defined(LWS_WITH_TLS) - /* we can retry this... just cook the SSL BIO the first time */ - - if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { - - if (!wsi->transaction_from_pipeline_queue && - lws_tls_restrict_borrow(wsi->context)) { - cce = "tls restriction limit"; - goto bail3; - } - - if (!wsi->tls.ssl && lws_ssl_client_bio_create(wsi) < 0) { - cce = "bio_create failed"; - goto bail3; - } - - n = lws_ssl_client_connect1(wsi); - if (!n) - return 0; - if (n < 0) { - cce = "lws_ssl_client_connect1 failed"; - goto bail3; - } - } else - wsi->tls.ssl = NULL; + n = lws_client_create_tls(wsi, &cce, 1); + if (n < 0) + goto bail3; + if (n == 1) + return 0; /* fallthru */ @@ -220,12 +263,13 @@ start_ws_handshake: goto bail3; } + // lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); + lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, + context->timeout_secs); + break; } #endif - lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); - lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, - context->timeout_secs); /* fallthru */ diff --git a/lib/roles/http/private-lib-roles-http.h b/lib/roles/http/private-lib-roles-http.h index 1284020a..2bf43fe0 100644 --- a/lib/roles/http/private-lib-roles-http.h +++ b/lib/roles/http/private-lib-roles-http.h @@ -326,3 +326,6 @@ lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul); uint8_t * lws_http_multipart_headers(struct lws *wsi, uint8_t *p); + +int +lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1); diff --git a/lib/roles/mqtt/client/client-mqtt.c b/lib/roles/mqtt/client/client-mqtt.c index 19130123..3f6fcecd 100644 --- a/lib/roles/mqtt/client/client-mqtt.c +++ b/lib/roles/mqtt/client/client-mqtt.c @@ -204,23 +204,17 @@ lws_mqtt_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd, if (!(wsi->tls.use_ssl & LCCSCF_USE_SSL)) goto start_ws_handshake; - /* we can retry this... just cook the SSL BIO the first time */ - - if (lws_ssl_client_bio_create(wsi) < 0) { - lwsl_err("%s: bio_create failed\n", __func__); + switch (lws_client_create_tls(wsi, &cce, 0)) { + case 0: + break; + case 1: + return 0; + default: goto bail3; } - if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { - n = lws_ssl_client_connect1(wsi); - if (!n) - return 0; - if (n < 0) { - lwsl_err("%s: lws_ssl_client_connect1 failed\n", - __func__); - goto bail3; - } - } + break; + default: break; } @@ -349,7 +343,7 @@ start_ws_handshake: goto fail; case LWS_SSL_CAPABLE_MORE_SERVICE: lwsl_info("SSL Capable more service\n"); - goto fail; + return 0; case LWS_SSL_CAPABLE_ERROR: lwsl_info("%s: LWS_SSL_CAPABLE_ERROR\n", __func__); diff --git a/lib/roles/raw-skt/ops-raw-skt.c b/lib/roles/raw-skt/ops-raw-skt.c index 30041026..75d1776f 100644 --- a/lib/roles/raw-skt/ops-raw-skt.c +++ b/lib/roles/raw-skt/ops-raw-skt.c @@ -105,32 +105,8 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, * go down the tls path on it now if that's what * we want */ + goto post_rx; -// if (!(wsi->tls.use_ssl & LCCSCF_USE_SSL)) { -// lwsi_set_state(wsi, LRS_ESTABLISHED); - goto post_rx; -// } -#if 0 - /* we can retry this... just cook the SSL BIO - * the first time */ - - if (lws_ssl_client_bio_create(wsi) < 0) { - lwsl_err("%s: bio_create failed\n", - __func__); - goto fail; - } - - if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { - n = lws_ssl_client_connect1(wsi); - if (!n) - return 0; - if (n < 0) { - lwsl_err("%s: connect1 failed\n", - __func__); - goto fail; - } - } -#endif default: break; } diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index b970d3aa..8f815e05 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -393,7 +393,7 @@ directly parses the policy and makes the outgoing connections itself. However when configured at cmake with ``` --DLWS_WITH_SOCKS=1 -DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 +-DLWS_WITH_SOCKS5=1 -DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 ``` and define `LWS_SS_USE_SSPC` when building the application, applications forward diff --git a/minimal-examples/http-client/minimal-http-client-post/selftest.sh b/minimal-examples/http-client/minimal-http-client-post/selftest.sh index 2f887f2a..8d3476f4 100755 --- a/minimal-examples/http-client/minimal-http-client-post/selftest.sh +++ b/minimal-examples/http-client/minimal-http-client-post/selftest.sh @@ -26,7 +26,7 @@ dotest $1 $2 warmcat-m -m dotest $1 $2 warmcat-m-h1 -m --h1 spawn "" $5 $1/libwebsockets-test-server -s -dotest $1 $2 localhost -l +dotest $1 $2 localhost -l -d1151 spawn $SPID $5 $1/libwebsockets-test-server -s dotest $1 $2 localhost-h1 -l --h1 spawn $SPID $5 $1/libwebsockets-test-server -s -- Gitee From b6824c88fdb6f54de9e3c452fa3de09aa4a50e6a Mon Sep 17 00:00:00 2001 From: Olivier Langlois Date: Sun, 1 Mar 2020 12:24:29 -0500 Subject: [PATCH 0005/1062] http: allow receiving body in case ws upgrade failed Process HTTP headers related to content length for ws connections and make 1 callback before continuing to the ws upgrade code. This gives one last opportunity to ws protocols to inspect server reply before the ws upgrade code discard it. ie: download reply body in case of any other response code than 101. --- include/libwebsockets/lws-http.h | 12 +- lib/roles/http/client/client-http.c | 175 +++++++++++++++------------- 2 files changed, 105 insertions(+), 82 deletions(-) diff --git a/include/libwebsockets/lws-http.h b/include/libwebsockets/lws-http.h index 5c3b69ce..d0daeda9 100644 --- a/include/libwebsockets/lws-http.h +++ b/include/libwebsockets/lws-http.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -850,6 +850,16 @@ lws_http_compression_apply(struct lws *wsi, const char *name, LWS_VISIBLE LWS_EXTERN int lws_http_is_redirected_to_get(struct lws *wsi); +/** + * lws_http_client_http_error() - determine if the response code indicates an error + * + * \param code: the response code to test + * + * Returns nonzero if the code indicates an error, else zero if reflects a + * non-error condition + */ +#define lws_http_client_http_resp_is_error(code) (!(code < 400)) + /** * lws_h2_update_peer_txcredit() - manually update stream peer tx credit * diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index b5c9d935..76b788fb 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -779,72 +779,113 @@ lws_client_interpret_server_handshake(struct lws *wsi) return 0; } - if (!wsi->do_ws) { + /* if h1 KA is allowed, enable the queued pipeline guys */ - /* if h1 KA is allowed, enable the queued pipeline guys */ + if (!wsi->client_h2_alpn && !wsi->client_mux_substream) { + /* ie, coming to this for the first time */ + if (wsi->http.conn_type == HTTP_CONNECTION_KEEP_ALIVE) + wsi->keepalive_active = 1; + else { + /* + * Ugh... now the main http connection has seen + * both sides, we learn the server doesn't + * support keepalive. + * + * That means any guys queued on us are going + * to have to be restarted from connect2 with + * their own connections. + */ - if (!wsi->client_h2_alpn && !wsi->client_mux_substream) { - /* ie, coming to this for the first time */ - if (wsi->http.conn_type == HTTP_CONNECTION_KEEP_ALIVE) - wsi->keepalive_active = 1; - else { - /* - * Ugh... now the main http connection has seen - * both sides, we learn the server doesn't - * support keepalive. - * - * That means any guys queued on us are going - * to have to be restarted from connect2 with - * their own connections. - */ - - /* - * stick around telling any new guys they can't - * pipeline to this server - */ - wsi->keepalive_rejected = 1; - - lws_vhost_lock(wsi->vhost); - lws_start_foreach_dll_safe(struct lws_dll2 *, - d, d1, - wsi->dll2_cli_txn_queue_owner.head) { - struct lws *ww = lws_container_of(d, - struct lws, - dll2_cli_txn_queue); - - /* remove him from our queue */ - lws_dll2_remove(&ww->dll2_cli_txn_queue); - /* give up on pipelining */ - ww->client_pipeline = 0; - - /* go back to "trying to connect" state */ - lws_role_transition(ww, LWSIFR_CLIENT, - LRS_UNCONNECTED, + /* + * stick around telling any new guys they can't + * pipeline to this server + */ + wsi->keepalive_rejected = 1; + + lws_vhost_lock(wsi->vhost); + lws_start_foreach_dll_safe(struct lws_dll2 *, + d, d1, + wsi->dll2_cli_txn_queue_owner.head) { + struct lws *ww = lws_container_of(d, + struct lws, + dll2_cli_txn_queue); + + /* remove him from our queue */ + lws_dll2_remove(&ww->dll2_cli_txn_queue); + /* give up on pipelining */ + ww->client_pipeline = 0; + + /* go back to "trying to connect" state */ + lws_role_transition(ww, LWSIFR_CLIENT, + LRS_UNCONNECTED, #if defined(LWS_ROLE_H1) - &role_ops_h1); + &role_ops_h1); #else #if defined (LWS_ROLE_H2) - &role_ops_h2); + &role_ops_h2); #else - &role_ops_raw); + &role_ops_raw); #endif #endif - ww->user_space = NULL; - } lws_end_foreach_dll_safe(d, d1); - lws_vhost_unlock(wsi->vhost); - } + ww->user_space = NULL; + } lws_end_foreach_dll_safe(d, d1); + lws_vhost_unlock(wsi->vhost); } + } #ifdef LWS_WITH_HTTP_PROXY - wsi->http.perform_rewrite = 0; - if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) { - if (!strncmp(lws_hdr_simple_ptr(wsi, - WSI_TOKEN_HTTP_CONTENT_TYPE), - "text/html", 9)) - wsi->http.perform_rewrite = 0; - } + wsi->http.perform_rewrite = 0; + if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) { + if (!strncmp(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_CONTENT_TYPE), + "text/html", 9)) + wsi->http.perform_rewrite = 0; + } #endif + /* he may choose to send us stuff in chunked transfer-coding */ + wsi->chunked = 0; + wsi->chunk_remaining = 0; /* ie, next thing is chunk size */ + if (lws_hdr_total_length(wsi, + WSI_TOKEN_HTTP_TRANSFER_ENCODING)) { + wsi->chunked = !strcmp(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_TRANSFER_ENCODING), + "chunked"); + /* first thing is hex, after payload there is crlf */ + wsi->chunk_parser = ELCP_HEX; + } + + wsi->http.content_length_given = 0; + if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) { + wsi->http.rx_content_length = + atoll(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_CONTENT_LENGTH)); + lwsl_info("%s: incoming content length %llu\n", + __func__, (unsigned long long) + wsi->http.rx_content_length); + wsi->http.rx_content_remain = + wsi->http.rx_content_length; + wsi->http.content_length_given = 1; + } else { /* can't do 1.1 without a content length or chunked */ + if (!wsi->chunked) + wsi->http.conn_type = HTTP_CONNECTION_CLOSE; + lwsl_debug("%s: no content length\n", __func__); + } + + if (wsi->do_ws) { + /* + * Give one last opportunity to ws protocols to inspect server reply + * before the ws upgrade code discard it. ie: download reply body in case + * of any other response code than 101. + */ + if (wsi->protocol->callback(wsi, + LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP, + wsi->user_space, NULL, 0)) { + + cce = "HS: disallowed by client filter"; + goto bail2; + } + } else { /* allocate the per-connection user memory (if any) */ if (lws_ensure_user_space(wsi)) { lwsl_err("Problem allocating wsi user mem\n"); @@ -852,34 +893,6 @@ lws_client_interpret_server_handshake(struct lws *wsi) goto bail2; } - /* he may choose to send us stuff in chunked transfer-coding */ - wsi->chunked = 0; - wsi->chunk_remaining = 0; /* ie, next thing is chunk size */ - if (lws_hdr_total_length(wsi, - WSI_TOKEN_HTTP_TRANSFER_ENCODING)) { - wsi->chunked = !strcmp(lws_hdr_simple_ptr(wsi, - WSI_TOKEN_HTTP_TRANSFER_ENCODING), - "chunked"); - /* first thing is hex, after payload there is crlf */ - wsi->chunk_parser = ELCP_HEX; - } - - wsi->http.content_length_given = 0; - if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) { - wsi->http.rx_content_length = - atoll(lws_hdr_simple_ptr(wsi, - WSI_TOKEN_HTTP_CONTENT_LENGTH)); - lwsl_info("%s: incoming content length %llu\n", - __func__, (unsigned long long) - wsi->http.rx_content_length); - wsi->http.rx_content_remain = - wsi->http.rx_content_length; - wsi->http.content_length_given = 1; - } else { /* can't do 1.1 without a content length or chunked */ - if (!wsi->chunked) - wsi->http.conn_type = HTTP_CONNECTION_CLOSE; - lwsl_debug("%s: no content length\n", __func__); - } /* * we seem to be good to go, give client last chance to check -- Gitee From 5b9fe01863d023c0c30e4693b161ec8c0448e5bb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 10 Mar 2020 06:45:24 +0000 Subject: [PATCH 0006/1062] build: release mode compile fixes --- lib/roles/cgi/cgi-server.c | 2 +- lib/roles/mqtt/mqtt.c | 17 ++++++++++++++--- lib/roles/raw-skt/ops-raw-skt.c | 2 +- lib/tls/openssl/openssl-client.c | 10 ++++++++-- .../minimal-secure-streams-avs/avs.c | 6 +++++- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/roles/cgi/cgi-server.c b/lib/roles/cgi/cgi-server.c index c0941622..f9f95471 100644 --- a/lib/roles/cgi/cgi-server.c +++ b/lib/roles/cgi/cgi-server.c @@ -167,7 +167,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, if (m >= 0) { env_array[n++] = p; - if (m < 8) { + if (m < (int)LWS_ARRAY_SIZE(meths) - 1) { p += lws_snprintf(p, end - p, "REQUEST_METHOD=%s", meth_names[m]); diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index bb07feb5..8e2079de 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -1760,7 +1760,10 @@ lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub) lws_mqtt_str_t mqtt_vh_payload; uint8_t exists[8], extant; lws_mqtt_subs_t *mysub; - uint32_t rem_len, tops; + uint32_t rem_len; +#if defined(_DEBUG) + uint32_t tops; +#endif uint32_t n; assert(sub->num_topics); @@ -1826,6 +1829,7 @@ lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub) return 0; } +#if defined(_DEBUG) /* * zero or more of the topics already existed, but not all, * so we must go to the server with a filtered list of the @@ -1833,6 +1837,7 @@ lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub) */ tops = sub->num_topics - extant; +#endif /* * Pid + (Topic len field + Topic len + Req. QoS) x Num of Topics @@ -1844,8 +1849,10 @@ lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub) wsi->mqtt->sub_size = rem_len; +#if defined(_DEBUG) lwsl_debug("%s: Number of topics = %d, Remaining len = %d\n", __func__, (int)tops, (int)rem_len); +#endif p += lws_mqtt_vbi_encode(rem_len, p); @@ -1933,8 +1940,11 @@ lws_mqtt_client_send_unsubcribe(struct lws *wsi, struct lws *nwsi = lws_get_network_wsi(wsi); lws_mqtt_str_t mqtt_vh_payload; uint8_t send_unsub[8], orphaned; - uint32_t rem_len, n, tops; + uint32_t rem_len, n; lws_mqtt_subs_t *mysub; +#if defined(_DEBUG) + uint32_t tops; +#endif lwsl_info("%s: Enter\n", __func__); @@ -1978,7 +1988,7 @@ lws_mqtt_client_send_unsubcribe(struct lws *wsi, return 0; } - +#if defined(_DEBUG) /* * one or more of the topics needs to be unsubscribed * from, so we must go to the server with a filtered @@ -1986,6 +1996,7 @@ lws_mqtt_client_send_unsubcribe(struct lws *wsi, */ tops = orphaned; +#endif if (lws_mqtt_fill_fixed_header(p++, LMQCP_CTOS_UNSUBSCRIBE, 0, 0, 0)) { diff --git a/lib/roles/raw-skt/ops-raw-skt.c b/lib/roles/raw-skt/ops-raw-skt.c index 75d1776f..9cdfe2f9 100644 --- a/lib/roles/raw-skt/ops-raw-skt.c +++ b/lib/roles/raw-skt/ops-raw-skt.c @@ -32,7 +32,7 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, const char *cce = NULL; #endif struct lws_tokens ebuf; - int n, buffered; + int n = 0, buffered = 0; /* pending truncated sends have uber priority */ diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index cbf95f50..7d435806 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -369,13 +369,17 @@ lws_tls_client_connect(struct lws *wsi) char a[32]; unsigned int len; #endif - int m, n, en; + int m, n; +#if defined(WIN32) || defined(_DEBUG) + int en; +#endif errno = 0; ERR_clear_error(); n = SSL_connect(wsi->tls.ssl); +#if defined(WIN32) || defined(_DEBUG) en = errno; - +#endif m = lws_ssl_get_error(wsi, n); if (m == SSL_ERROR_SYSCALL @@ -383,7 +387,9 @@ lws_tls_client_connect(struct lws *wsi) && en #endif ) { +#if defined(WIN32) || defined(_DEBUG) lwsl_info("%s: n %d, m %d, errno %d\n", __func__, n, m, en); +#endif return LWS_SSL_CAPABLE_ERROR; } diff --git a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c index 722b4a01..fe8dd2ee 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c @@ -124,7 +124,11 @@ ss_avs_metadata_rx(void *userobj, const uint8_t *buf, size_t len, int flags) lwsl_info("%s: len %d, buf h %d, t %d, space %d\n", __func__, (int)len, (int)m->head, (int)m->tail, (int)n); lws_ss_get_est_peer_tx_credit(m->ss); - assert (len <= n); + if (len > n) { + assert(0); + lwsl_err("%s: bad len\n", __func__); + return 1; + } if (m->head < m->tail) /* |****h-------t**| */ memcpy(&m->buf[m->head], buf, len); -- Gitee From 84b9b2c69ce959c64908c8e84a85337eefbc09c9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 10 Mar 2020 12:34:34 +0000 Subject: [PATCH 0007/1062] glib: accidentally fixed unsupported signal watcher for glib We worked fine while an earlier typo meant this was never getting past the preprocessor... when it did, it exposes that the signal handler type was never implemented. Just remove for glib. --- lib/core/private-lib-core.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index f1343836..c508e91f 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -228,9 +228,6 @@ struct lws_signal_watcher { #endif #ifdef LWS_WITH_LIBEVENT struct lws_signal_watcher_libevent event; -#endif -#ifdef LWS_WITH_GLIB - struct lws_signal_watcher_glib glib; #endif struct lws_context *context; }; -- Gitee From 0648a83ca2dce384c05b7839569d3479cc3c4c6a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 10 Mar 2020 19:11:15 +0000 Subject: [PATCH 0008/1062] event libs: h1 pipelining needs to manage event lib additional data during handover too --- lib/core-net/wsi.c | 17 +++++++++++++++++ lib/event-libs/glib/glib.c | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index 78e086e5..21305253 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -822,6 +822,8 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi) assert(lws_socket_is_valid(wsi->desc.sockfd)); + __lws_change_pollfd(wsi, LWS_POLLOUT | LWS_POLLIN, 0); + /* copy the fd */ wnew->desc = wsi->desc; @@ -833,6 +835,21 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi) return -1; wsi->desc.sockfd = LWS_SOCK_INVALID; + /* + * ... we're doing some magic here in terms of handing off the socket + * that has been active to a wsi that has not yet itself been active... + * depending on the event lib we may need to give a magic spark to the + * new guy and snuff out the old guy's magic spark at that level as well + */ + +#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \ + defined(LWS_WITH_LIBEVENT) || defined(LWS_WITH_GLIB) + if (wsi->context->event_loop_ops->destroy_wsi) + wsi->context->event_loop_ops->destroy_wsi(wsi); + if (wsi->context->event_loop_ops->sock_accept) + wsi->context->event_loop_ops->sock_accept(wnew); +#endif + /* point the fd table entry to new guy */ assert(lws_socket_is_valid(wnew->desc.sockfd)); diff --git a/lib/event-libs/glib/glib.c b/lib/event-libs/glib/glib.c index 92292968..af42dc86 100644 --- a/lib/event-libs/glib/glib.c +++ b/lib/event-libs/glib/glib.c @@ -352,6 +352,11 @@ elops_io_glib(struct lws *wsi, int flags) lwsl_debug("%s: wsi %p, fd %d, 0x%x/0x%x\n", __func__, wsi, wsi->desc.sockfd, flags, (int)cond); + if (!wsi_to_subclass(wsi)) { + lwsl_err("%s: glib wsi source pointer is NULL\n", __func__); + return; + } + g_source_modify_unix_fd(wsi_to_gsource(wsi), wsi_to_subclass(wsi)->tag, cond); } -- Gitee From fdb9b7fdd329da3e7eff90c6972f7318f2c55530 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 10 Mar 2020 19:13:43 +0000 Subject: [PATCH 0009/1062] event libs: context_destroy sequencing --- lib/core/context.c | 9 +++++++-- lib/event-libs/glib/glib.c | 5 +++++ lib/event-libs/libevent/libevent.c | 9 +++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index 8b075945..66eb625c 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -937,7 +937,11 @@ lws_context_destroy3(struct lws_context *context) #if defined(LWS_WITH_NETWORK) - lwsl_debug("%s\n", __func__); + lwsl_err("%s\n", __func__); + + context->finalize_destroy_after_internal_loops_stopped = 1; + if (context->event_loop_ops->destroy_context2) + context->event_loop_ops->destroy_context2(context); for (n = 0; n < context->count_threads; n++) { struct lws_context_per_thread *pt = &context->pt[n]; @@ -953,9 +957,10 @@ lws_context_destroy3(struct lws_context *context) #if defined(LWS_WITH_CGI) role_ops_cgi.pt_init_destroy(context, NULL, pt, 1); #endif - +#if 0 if (context->event_loop_ops->destroy_pt) context->event_loop_ops->destroy_pt(context, n); +#endif #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) while (pt->http.ah_list) diff --git a/lib/event-libs/glib/glib.c b/lib/event-libs/glib/glib.c index af42dc86..4adea145 100644 --- a/lib/event-libs/glib/glib.c +++ b/lib/event-libs/glib/glib.c @@ -357,6 +357,11 @@ elops_io_glib(struct lws *wsi, int flags) return; } + if (!wsi_to_subclass(wsi)) { + lwsl_err("%s: glib wsi source pointer is NULL\n", __func__); + return; + } + g_source_modify_unix_fd(wsi_to_gsource(wsi), wsi_to_subclass(wsi)->tag, cond); } diff --git a/lib/event-libs/libevent/libevent.c b/lib/event-libs/libevent/libevent.c index f64a0f9d..786c4f88 100644 --- a/lib/event-libs/libevent/libevent.c +++ b/lib/event-libs/libevent/libevent.c @@ -134,6 +134,7 @@ lws_event_cb(evutil_socket_t sock_fd, short revents, void *ctx) lws_service_fd_tsi(context, &eventfd, wsi->tsi); if (pt->destroy_self) { + lwsl_notice("%s: pt destroy self coming true\n", __func__); lws_context_destroy(pt->context); return; } @@ -326,8 +327,10 @@ elops_destroy_pt_event(struct lws_context *context, int tsi) if (!pt->event_loop_foreign) { event_del(pt->w_sigint.event.watcher); event_free(pt->w_sigint.event.watcher); - - event_base_free(pt->event.io_loop); + event_base_loopexit(pt->event.io_loop, NULL); + // event_base_free(pt->event.io_loop); + // pt->event.io_loop = NULL; + lwsl_notice("%s: set to exit loop\n", __func__); } } @@ -428,7 +431,9 @@ elops_destroy_context2_event(struct lws_context *context) } else lwsl_debug("%s: %d: everything closed OK\n", __func__, n); #endif + lwsl_err("%s: event_base_free\n", __func__); event_base_free(pt->event.io_loop); + pt->event.io_loop = NULL; } -- Gitee From a60cb84c9ea1c7013c151e3b8cdadbe0e5bd884b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 11 Mar 2020 12:44:01 +0000 Subject: [PATCH 0010/1062] captive portal Implement Captive Portal detection support in lws, with the actual detection happening in platform code hooked up by lws_system_ops_t. Add an implementation using Secure Streams as well, if the policy defines captive_portal_detect streamtype, a SS using that streamtype is used to probe if it's behind a captive portal. --- CMakeLists.txt | 2 + READMEs/README.captive-portal-detection.md | 88 +++++ include/libwebsockets/lws-callbacks.h | 3 + .../libwebsockets/lws-secure-streams-policy.h | 3 + include/libwebsockets/lws-system.h | 74 +++- lib/core-net/state.c | 3 + lib/core/context.c | 66 +++- lib/core/private-lib-core.h | 2 + lib/roles/http/client/client-http.c | 9 + lib/secure-streams/README.md | 37 ++ lib/secure-streams/policy.c | 14 + .../private-lib-secure-streams.h | 3 + lib/secure-streams/protocols/ss-h1.c | 15 +- lib/secure-streams/secure-streams.c | 4 +- .../captive-portal-detect.c | 111 ++++++ .../CMakeLists.txt | 82 +++++ .../README.md | 45 +++ .../minimal-http-client-captive-portal.c | 321 ++++++++++++++++++ .../minimal-secure-streams.c | 43 ++- 19 files changed, 914 insertions(+), 11 deletions(-) create mode 100644 READMEs/README.captive-portal-detection.md create mode 100644 lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c create mode 100644 minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt create mode 100644 minimal-examples/http-client/minimal-http-client-captive-portal/README.md create mode 100644 minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cab9b3e..1dd4cbcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1178,6 +1178,7 @@ if (LWS_WITH_NETWORK) lib/secure-streams/secure-streams.c lib/secure-streams/policy.c lib/secure-streams/system/fetch-policy/fetch-policy.c + lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c ) if (LWS_ROLE_H1) list(APPEND SOURCES @@ -1218,6 +1219,7 @@ if (LWS_WITH_NETWORK) lib/secure-streams/system/auth-api.amazon.com/auth.c ) endif() + endif() if (LWS_WITH_STATS) diff --git a/READMEs/README.captive-portal-detection.md b/READMEs/README.captive-portal-detection.md new file mode 100644 index 00000000..ceab7b42 --- /dev/null +++ b/READMEs/README.captive-portal-detection.md @@ -0,0 +1,88 @@ +# Captive Portal Detection + +## Background + +Wifi devices may face some interception of their connection to the +internet, it's very common for, eg, coffee shop wifi to present some +kind of login or other clickthrough before access to the Internet is +granted. Devices may need to understand that they are in this +situation, and there are several different techniques for trying to +gague it. + +Sequence-wise the device has been granted a DHCP lease and has been +configured with DNS, but the DNS may be wrongly resolving everything +to an address on the LAN or a portal on the net. + +Whether there is a captive portal active should be a sticky state for a given +connection if there is not going to be any attempt to login or pass the landing +page, it only needs checking for after DHCP acquisition then. If there will be +an attempt to satisfy the landing page, the test should be repeated after the +attempt. + +## Detection schemes + +The most popular detection scheme by numbers is Android's method, +which is to make an HTTP client GET to `http://connectivitycheck.android.com/generate_204` +and see if a 204 is coming back... if intercepted, typically there'll be a +3xx redirect to the portal, perhaps on https. Or, it may reply on http with +a 200 and show the portal directly... either way it won't deliver a 204 +like the real remote server does. + +Variations include expecting a 200 but with specific http body content, and +doing a DNS lookup for a static IP that the device knows; if it's resolved to +something else, it knows there's monkey business implying a captive portal. + +Other schemes involve https connections going out and detecting that the cert +of the server it's actually talking to doesn't check out, although this is +potentially ambiguous. + +Yet more methods are possible outside of tcp or http. + +## lws captive portal detect support + +lws provides a generic api to start captive portal detection... + +``` +LWS_EXTERN LWS_VISIBLE int +lws_system_cpd_start(struct lws_context *context); +``` + +and two states in `lws_system` states to trigger it from, either +`LWS_SYSTATE_CPD_PRE_TIME` which happens after DHCP acquisition but before +ntpclient and is suitable for non https-based scheme where the time doesn't +need to be known, or the alternative `LWS_SYSTATE_CPD_POST_TIME` state which +happens after ntpclient has completed and we know the time. + +The actual platform implementation is set using `lws_system_ops_t` function +pointer `captive_portal_detect_request`, ie + +``` + int (*captive_portal_detect_request)(struct lws_context *context); + /**< Check if we can go out on the internet cleanly, or if we are being + * redirected or intercepted by a captive portal. + * Start the check that proceeds asynchronously, and report the results + * by calling lws_captive_portal_detect_result() api + */ +``` + +User platform code can provide this to implement whatever scheme they want, when +it has arrived at a result, it can call the lws api `lws_system_cpd_result()` to +inform lws. If there isn't any captive portal, this will also try to advance the +system state towards OPERATIONAL. + +``` +/** + * lws_system_cpd_result() - report the result of the captive portal detection + * + * \param context: the lws_context + * \param result: one of the LWS_CPD_ constants representing captive portal state + * \param redirect_url: NULL, or the url we were redirected to if result is + * LWS_CPD_HTTP_REDIRECT + * + * Sets the context's captive portal detection state to result. User captive + * portal detection code would call this once it had a result from its test. + */ +LWS_EXTERN LWS_VISIBLE int +lws_system_cpd_result(struct lws_context *context, int result, const char *redirect_url); +``` + diff --git a/include/libwebsockets/lws-callbacks.h b/include/libwebsockets/lws-callbacks.h index 727fdca8..50cb7385 100644 --- a/include/libwebsockets/lws-callbacks.h +++ b/include/libwebsockets/lws-callbacks.h @@ -390,6 +390,9 @@ enum lws_callback_reasons { * lws know by calling lws_client_http_body_pending(wsi, 0) */ + LWS_CALLBACK_CLIENT_HTTP_REDIRECT = 104, + /**< we're handling a 3xx redirect... return nonzero to hang up */ + LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL = 85, LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL = 76, diff --git a/include/libwebsockets/lws-secure-streams-policy.h b/include/libwebsockets/lws-secure-streams-policy.h index 7cf3dce4..f64fd80d 100644 --- a/include/libwebsockets/lws-secure-streams-policy.h +++ b/include/libwebsockets/lws-secure-streams-policy.h @@ -206,6 +206,9 @@ typedef struct lws_ss_policy { /* false = TEXT, true = BINARY */ } ws; } u; + + uint16_t resp_expect; + uint8_t fail_redirect:1; } http; struct { diff --git a/include/libwebsockets/lws-system.h b/include/libwebsockets/lws-system.h index 61ddf3bd..1f437068 100644 --- a/include/libwebsockets/lws-system.h +++ b/include/libwebsockets/lws-system.h @@ -98,9 +98,24 @@ typedef enum { /* keep system_state_names[] in sync in context.c */ * can operate normally */ LWS_SYSTATE_IFACE_COLDPLUG, /* existing net ifaces iterated */ LWS_SYSTATE_DHCP, /* at least one net iface configured */ + LWS_SYSTATE_CPD_PRE_TIME, /* Captive portal detect without valid + * time, good for non-https tests... if + * you care about it, implement and + * call lws_system_ops_t + * .captive_portal_detect_request() + * and move the state forward according + * to the result. */ LWS_SYSTATE_TIME_VALID, /* ntpclient ran, or hw time valid... * tls cannot work until we reach here */ + LWS_SYSTATE_CPD_POST_TIME, /* Captive portal detect after time was + * time, good for https tests... if + * you care about it, implement and + * call lws_system_ops_t + * .captive_portal_detect_request() + * and move the state forward according + * to the result. */ + LWS_SYSTATE_POLICY_VALID, /* user code knows how to operate... */ LWS_SYSTATE_REGISTERED, /* device has an identity... */ LWS_SYSTATE_AUTH1, /* identity used for main auth token */ @@ -114,6 +129,16 @@ typedef enum { /* keep system_state_names[] in sync in context.c */ * LWS_SYSTATE_POLICY_VALID */ } lws_system_states_t; +/* Captive Portal Detect -related */ + +typedef enum { + LWS_CPD_UNKNOWN = 0, /* test didn't happen ince last DHCP acq yet */ + LWS_CPD_INTERNET_OK, /* no captive portal: our CPD test passed OK, + * we can go out on the internet */ + LWS_CPD_CAPTIVE_PORTAL, /* we inferred we're behind a captive portal */ + LWS_CPD_NO_INTERNET, /* we couldn't touch anything */ +} lws_cpd_result_t; + typedef void (*lws_attach_cb_t)(struct lws_context *context, int tsi, void *opaque); struct lws_attach_item; @@ -138,6 +163,12 @@ typedef struct lws_system_ops { * __lws_system_attach() is provided to do the actual work inside the * system-specific locking. */ + int (*captive_portal_detect_request)(struct lws_context *context); + /**< Check if we can go out on the internet cleanly, or if we are being + * redirected or intercepted by a captive portal. + * Start the check that proceeds asynchronously, and report the results + * by calling lws_captive_portal_detect_result() api + */ } lws_system_ops_t; /** @@ -231,7 +262,7 @@ typedef int (*dhcpc_cb_t)(void *opaque, int af, uint8_t *ip, int ip_len); * Register a network interface as being managed by DHCP. lws will proceed to * try to acquire an IP. Requires LWS_WITH_SYS_DHCP_CLIENT at cmake. */ -int +LWS_EXTERN LWS_VISIBLE int lws_dhcpc_request(struct lws_context *c, const char *i, int af, dhcpc_cb_t cb, void *opaque); @@ -243,7 +274,7 @@ lws_dhcpc_request(struct lws_context *c, const char *i, int af, dhcpc_cb_t cb, * * Remove handling of the network interface from dhcp. */ -int +LWS_EXTERN LWS_VISIBLE int lws_dhcpc_remove(struct lws_context *context, const char *iface); /** @@ -255,5 +286,42 @@ lws_dhcpc_remove(struct lws_context *context, const char *iface); * Returns 1 if any network interface managed by dhcpc has reached the BOUND * state (has acquired an IP, gateway and DNS server), otherwise 0. */ -int +LWS_EXTERN LWS_VISIBLE int lws_dhcpc_status(struct lws_context *context, lws_sockaddr46 *sa46); + +/** + * lws_system_cpd_start() - helper to initiate captive portal detection + * + * \param context: the lws_context + * + * Resets the context's captive portal state to LWS_CPD_UNKNOWN and calls the + * lws_system_ops_t captive_portal_detect_request() implementation to begin + * testing the captive portal state. + */ +LWS_EXTERN LWS_VISIBLE int +lws_system_cpd_start(struct lws_context *context); + + +/** + * lws_system_cpd_set() - report the result of the captive portal detection + * + * \param context: the lws_context + * \param result: one of the LWS_CPD_ constants representing captive portal state + * + * Sets the context's captive portal detection state to result. User captive + * portal detection code would call this once it had a result from its test. + */ +LWS_EXTERN LWS_VISIBLE void +lws_system_cpd_set(struct lws_context *context, lws_cpd_result_t result); + + +/** + * lws_system_cpd_state_get() - returns the last tested captive portal state + * + * \param context: the lws_context + * + * Returns one of the LWS_CPD_ constants indicating the system's understanding + * of the current captive portal situation. + */ +LWS_EXTERN LWS_VISIBLE lws_cpd_result_t +lws_system_cpd_state_get(struct lws_context *context); diff --git a/lib/core-net/state.c b/lib/core-net/state.c index fd924292..56424647 100644 --- a/lib/core-net/state.c +++ b/lib/core-net/state.c @@ -119,6 +119,9 @@ lws_state_transition_steps(lws_state_manager_t *mgr, int target) char temp8[8]; #endif + if (mgr->state > target) + return 0; + while (!n && mgr->state != target) n = _lws_state_transition(mgr, mgr->state + 1); diff --git a/lib/core/context.c b/lib/core/context.c index 66eb625c..ced00eb3 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -82,7 +82,9 @@ static const char * system_state_names[] = { "INITIALIZED", "IFACE_COLDPLUG", "DHCP", + "CPD_PRE_TIME", "TIME_VALID", + "CPD_POST_TIME", "POLICY_VALID", "REGISTERED", "AUTH1", @@ -145,6 +147,20 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, #endif #if defined(LWS_WITH_SECURE_STREAMS) + /* + * See if we should do the SS Captive Portal Detection + */ + if (target == LWS_SYSTATE_CPD_PRE_TIME) { + if (lws_system_cpd_state_get(context)) + return 0; /* allow it */ + + lwsl_info("%s: LWS_SYSTATE_CPD_PRE_TIME\n", __func__); + if (!lws_system_cpd_start(context)) + return 1; + + /* it failed, eg, no streamtype for it in the policy */ + } + /* * Skip this if we are running something without the policy for it */ @@ -896,10 +912,56 @@ fail_event_libs: return NULL; } +#if defined(LWS_WITH_NETWORK) +int +lws_system_cpd_start(struct lws_context *cx) +{ + cx->captive_portal_detect = LWS_CPD_UNKNOWN; + + /* if there's a platform implementation, use it */ + + if (lws_system_get_ops(cx) && + lws_system_get_ops(cx)->captive_portal_detect_request) + return lws_system_get_ops(cx)->captive_portal_detect_request(cx); + +#if defined(LWS_WITH_SECURE_STREAMS) + /* + * Otherwise try to use SS "captive_portal_detect" if that's enabled + */ + return lws_ss_sys_cpd(cx); +#else + return 0; +#endif +} + +static const char *cname[] = { "?", "OK", "Captive", "No internet" }; + +void +lws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result) +{ + if (cx->captive_portal_detect != LWS_CPD_UNKNOWN) + return; + + lwsl_notice("%s: setting CPD result %s\n", __func__, cname[result]); + + cx->captive_portal_detect = (uint8_t)result; + + /* if nothing is there to intercept anything, go all the way */ + lws_state_transition_steps(&cx->mgr_system, LWS_SYSTATE_OPERATIONAL); +} + +lws_cpd_result_t +lws_system_cpd_state_get(struct lws_context *cx) +{ + return (lws_cpd_result_t)cx->captive_portal_detect; +} + +#endif + int -lws_context_is_deprecated(struct lws_context *context) +lws_context_is_deprecated(struct lws_context *cx) { - return context->deprecated; + return cx->deprecated; } /* diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index c508e91f..77380456 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -523,6 +523,8 @@ struct lws_context { uint8_t max_fi; uint8_t udp_loss_sim_tx_pc; uint8_t udp_loss_sim_rx_pc; + uint8_t captive_portal_detect; + uint8_t captive_portal_detect_type; #if defined(LWS_WITH_STATS) uint8_t updated; diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 76b788fb..009a918a 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -678,6 +678,15 @@ lws_client_interpret_server_handshake(struct lws *wsi) goto bail3; } + /* let's let the user code know, if he cares */ + + if (wsi->protocol->callback(wsi, + LWS_CALLBACK_CLIENT_HTTP_REDIRECT, + wsi->user_space, p, n)) { + cce = "HS: user code rejected redirect"; + goto bail3; + } + /* * Some redirect codes imply we have to change the method * used for the subsequent transaction, commonly POST -> diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index 8f815e05..59ccf319 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -177,6 +177,23 @@ to validate the remote server cert. HTTP method to use with http-related protocols, like GET or POST. Not required for ws. +### `http_expect` + +Optionally indicates that success for HTTP transactions using this +streamtype is different than the default 200 - 299. + +Eg, you may choose to set this to 204 for Captive Portal Detect usage +if that's what you expect the server to reply with to indicate +success. In that case, anything other than 204 will be treated as a +connection failure. + +### `http_fail_redirect` + +Set to `true` if you want to fail the connection on meeting an +http redirect. This is needed to, eg, detect Captive Portals +correctly. Normally, if on https, you would want the default behaviour +of following the redirect. + ### `http_url` Url path to use with http-related protocols @@ -352,6 +369,26 @@ The secure-streams-proxy minimal example shows how this is done and fetches its real policy from warmcat.com at startup using the built-in one. +## Captive Portal Detection + +If the policy contains a streamtype `captive_portal_detect` then the +type of transaction described there is automatically performed after +acquiring a DHCP address to try to determine the captive portal +situation. + +``` + "captive_portal_detect": { + "endpoint": "connectivitycheck.android.com", + "port": 80, + "protocol": "h1", + "http_method": "GET", + "http_url": "generate_204", + "opportunistic": true, + "http_expect": 204, + "http_fail_redirect": true + } +``` + ## Stream serialization and proxying By default Secure Streams expects to make the outgoing connection described in diff --git a/lib/secure-streams/policy.c b/lib/secure-streams/policy.c index ec59e7fc..d35c003c 100644 --- a/lib/secure-streams/policy.c +++ b/lib/secure-streams/policy.c @@ -79,6 +79,8 @@ static const char * const lejp_tokens_policy[] = { "s[].*.http_multipart_filename", "s[].*.http_mime_content_type", "s[].*.http_www_form_urlencoded", + "s[].*.http_expect", + "s[].*.http_fail_redirect", "s[].*.ws_subprotocol", "s[].*.ws_binary", "s[].*.local_sink", @@ -142,6 +144,8 @@ typedef enum { LSSPPT_HTTP_MULTIPART_FILENAME, LSSPPT_HTTP_MULTIPART_CONTENT_TYPE, LSSPPT_HTTP_WWW_FORM_URLENCODED, + LSSPPT_HTTP_EXPECT, + LSSPPT_HTTP_FAIL_REDIRECT, LSSPPT_WS_SUBPROTOCOL, LSSPPT_WS_BINARY, LSSPPT_LOCAL_SINK, @@ -524,6 +528,10 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->client_cert = atoi(ctx->buf) + 1; break; + case LSSPPT_HTTP_EXPECT: + a->curr[LTY_POLICY].p->u.http.resp_expect = atoi(ctx->buf); + break; + case LSSPPT_OPPORTUNISTIC: if (reason == LEJPCB_VAL_TRUE) a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_OPPORTUNISTIC; @@ -644,6 +652,12 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_MULTIPART; pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_content_type; goto string2; + + case LSSPPT_HTTP_FAIL_REDIRECT: + a->curr[LTY_POLICY].p->u.http.fail_redirect = + reason == LEJPCB_VAL_TRUE; + break; + case LSSPPT_WS_SUBPROTOCOL: pp = (char **)&a->curr[LTY_POLICY].p->u.http.u.ws.subprotocol; goto string2; diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index b22211a3..fc8b88e8 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -318,6 +318,9 @@ int lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, size_t olen, size_t *exp_ofs); +int +lws_ss_sys_cpd(struct lws_context *cx); + typedef int (* const secstream_protocol_connect_munge_t)(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct); diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index c9c6185c..1de0868f 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -167,7 +167,6 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, switch (reason) { - /* because we are protocols[0] ... */ case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: assert(h); assert(h->policy); @@ -178,6 +177,13 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_ss_backoff(h); break; + case LWS_CALLBACK_CLIENT_HTTP_REDIRECT: + if (h->policy->u.http.fail_redirect) + lws_system_cpd_set(lws_get_context(wsi), + LWS_CPD_CAPTIVE_PORTAL); + /* don't follow it */ + return 1; + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: if (!h) break; @@ -201,7 +207,12 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, // if (!status) /* it's just telling use we connected / joined the nwsi */ // break; - h->u.http.good_respcode = (status >= 200 && status < 300); + + if (h->policy->u.http.resp_expect) + h->u.http.good_respcode = + status == h->policy->u.http.resp_expect; + else + h->u.http.good_respcode = (status >= 200 && status < 300); // lwsl_err("%s: good resp %d %d\n", __func__, status, h->u.http.good_respcode); if (h->u.http.good_respcode) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 652f6c9a..b5eb4033 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -302,8 +302,8 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, pol = lws_ss_policy_lookup(context, ssi->streamtype); if (!pol) { - lwsl_err("%s: unknown stream type %s\n", __func__, - ssi->streamtype); + lwsl_notice("%s: unknown stream type %s\n", __func__, + ssi->streamtype); return 1; } diff --git a/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c b/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c new file mode 100644 index 00000000..82b74949 --- /dev/null +++ b/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c @@ -0,0 +1,111 @@ +/* + * Captive portal detect for Secure Streams + * + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +typedef struct ss_cpd { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + + lws_sorted_usec_list_t sul; + + uint8_t partway; +} ss_cpd_t; + +/* secure streams payload interface */ + +static int +ss_cpd_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ + return 0; +} + +static int +ss_cpd_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, + size_t *len, int *flags) +{ + return 1; +} + +static int +ss_cpd_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + ss_cpd_t *m = (ss_cpd_t *)userobj; + struct lws_context *cx = (struct lws_context *)m->opaque_data; + + lwsl_info("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_request_tx(m->ss); + break; + case LWSSSCS_QOS_ACK_REMOTE: + lws_system_cpd_set(cx, LWS_CPD_INTERNET_OK); + break; + + case LWSSSCS_ALL_RETRIES_FAILED: + case LWSSSCS_DISCONNECTED: + /* + * First result reported sticks... if nothing else, this will + * cover the situation we didn't connect to anything + */ + lws_system_cpd_set(cx, LWS_CPD_NO_INTERNET); + break; + + default: + break; + } + + return 0; +} + +int +lws_ss_sys_cpd(struct lws_context *cx) +{ + lws_ss_info_t ssi; + + /* We're making an outgoing secure stream ourselves */ + + memset(&ssi, 0, sizeof(ssi)); + ssi.handle_offset = offsetof(ss_cpd_t, ss); + ssi.opaque_user_data_offset = offsetof(ss_cpd_t, opaque_data); + ssi.rx = ss_cpd_rx; + ssi.tx = ss_cpd_tx; + ssi.state = ss_cpd_state; + ssi.user_alloc = sizeof(ss_cpd_t); + ssi.streamtype = "captive_portal_detect"; + + if (lws_ss_create(cx, 0, &ssi, cx, NULL, NULL, NULL)) { + lwsl_info("%s: Create stream failed (policy?)\n", __func__); + + return 1; + } + + return 0; +} diff --git a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt new file mode 100644 index 00000000..b9d34fdc --- /dev/null +++ b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt @@ -0,0 +1,82 @@ +project(lws-minimal-http-client-captive-portal) +cmake_minimum_required(VERSION 2.8) +include(CheckIncludeFile) +include(CheckCSourceCompiles) + +set(SAMP lws-minimal-http-client-captive-portal) +set(SRCS minimal-http-client-captive-portal.c) + +# If we are being built as part of lws, confirm current build config supports +# reqconfig, else skip building ourselves. +# +# If we are being built externally, confirm installed lws was configured to +# support reqconfig, else error out with a helpful message about the problem. +# +MACRO(require_lws_config reqconfig _val result) + + if (DEFINED ${reqconfig}) + if (${reqconfig}) + set (rq 1) + else() + set (rq 0) + endif() + else() + set(rq 0) + endif() + + if (${_val} EQUAL ${rq}) + set(SAME 1) + else() + set(SAME 0) + endif() + + if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) + if (${_val}) + message("${SAMP}: skipping as lws being built without ${reqconfig}") + else() + message("${SAMP}: skipping as lws built with ${reqconfig}") + endif() + set(${result} 0) + else() + if (LWS_WITH_MINIMAL_EXAMPLES) + set(MET ${SAME}) + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) + if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) + set(HAS_${reqconfig} 0) + else() + set(HAS_${reqconfig} 1) + endif() + if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) + set(MET 1) + else() + set(MET 0) + endif() + endif() + if (NOT MET) + if (${_val}) + message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") + else() + message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") + endif() + endif() + endif() +ENDMACRO() + +set(requirements 1) +if (WIN32) + set(requirements 0) +endif() +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITH_CLIENT 1 requirements) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared pthread) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets pthread) + endif() +endif() diff --git a/minimal-examples/http-client/minimal-http-client-captive-portal/README.md b/minimal-examples/http-client/minimal-http-client-captive-portal/README.md new file mode 100644 index 00000000..8db20026 --- /dev/null +++ b/minimal-examples/http-client/minimal-http-client-captive-portal/README.md @@ -0,0 +1,45 @@ +# lws minimal http client captive portal detect + +This demonstrates how to perform captive portal detection integrated +with `lws_system` states. + +After reaching the `lws_system` DHCP state, the application tries to +connect through to `http://connectivitycheck.android.com/generate_204` +over http... if it succeeds, it will get a 204 response and set the +captive portal detection state to `LWS_CPD_INTERNET_OK` and perform +a GET from warmcat.com. + +If there is a problem detected, the captive portal detection state is +set accordingly and the app will respond by exiting without trying the +read from warmcat.com. + +The captive portal detection scheme is implemented in the user code +and can be modified according to the strategy that's desired for +captive portal detection. + +## build + +``` + $ cmake . && make +``` + +## usage + +``` +$ ./bin/lws-minimal-http-client-captive-portal +[2020/03/11 13:07:07:4519] U: LWS minimal http client captive portal detect +[2020/03/11 13:07:07:4519] N: lws_create_context: using ss proxy bind '(null)', port 0, ads '(null)' +[2020/03/11 13:07:07:5022] U: callback_cpd_http: established with resp 204 +[2020/03/11 13:07:07:5023] U: app_system_state_nf: OPERATIONAL, cpd 1 +[2020/03/11 13:07:07:5896] U: Connected to 46.105.127.147, http response: 200 +[2020/03/11 13:07:07:5931] U: RECEIVE_CLIENT_HTTP_READ: read 4087 +[2020/03/11 13:07:07:5931] U: RECEIVE_CLIENT_HTTP_READ: read 4096 +[2020/03/11 13:07:07:6092] U: RECEIVE_CLIENT_HTTP_READ: read 4087 +[2020/03/11 13:07:07:6092] U: RECEIVE_CLIENT_HTTP_READ: read 4096 +[2020/03/11 13:07:07:6112] U: RECEIVE_CLIENT_HTTP_READ: read 4087 +[2020/03/11 13:07:07:6113] U: RECEIVE_CLIENT_HTTP_READ: read 4096 +[2020/03/11 13:07:07:6113] U: RECEIVE_CLIENT_HTTP_READ: read 2657 +[2020/03/11 13:07:07:6113] U: LWS_CALLBACK_COMPLETED_CLIENT_HTTP +[2020/03/11 13:07:07:6119] U: main: finished OK +``` + diff --git a/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c b/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c new file mode 100644 index 00000000..38d1a766 --- /dev/null +++ b/minimal-examples/http-client/minimal-http-client-captive-portal/minimal-http-client-captive-portal.c @@ -0,0 +1,321 @@ +/* + * lws-minimal-http-client-captive-portal + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates how to use the lws_system captive portal detect integration + * + * We check for a captive portal by doing a GET from + * http://connectivitycheck.android.com/generate_204, if we really are going + * out on the Internet he'll return with a 204 response code and we will + * understand there's no captive portal. If we get something else, we take it + * there is a captive portal. + */ + +#include +#include +#include + +static struct lws_context *context; +static int interrupted, bad = 1, status; +static lws_state_notify_link_t nl; + +/* + * this is the user code http handler + */ + +static int +callback_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + switch (reason) { + + /* because we are protocols[0] ... */ + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", + in ? (char *)in : "(null)"); + interrupted = 1; + break; + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + { + char buf[128]; + + lws_get_peer_simple(wsi, buf, sizeof(buf)); + status = lws_http_client_http_response(wsi); + + lwsl_user("Connected to %s, http response: %d\n", + buf, status); + } + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: + lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len); + +#if 0 /* enable to dump the html */ + { + const char *p = in; + + while (len--) + if (*p < 0x7f) + putchar(*p++); + else + putchar('.'); + } +#endif + return 0; /* don't passthru */ + + /* uninterpreted http content */ + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + } + return 0; /* don't passthru */ + + case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: + lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n"); + interrupted = 1; + bad = status != 200; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + interrupted = 1; + bad = status != 200; + lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +/* + * This is the platform's custom captive portal detection handler + */ + +static int +callback_cpd_http(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + int resp; + + switch (reason) { + + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: + resp = lws_http_client_http_response(wsi); + if (!resp) + break; + lwsl_user("%s: established with resp %d\n", __func__, resp); + switch (resp) { + + case HTTP_STATUS_NO_CONTENT: + /* + * We got the 204 which is used to distinguish the real + * endpoint + */ + lws_system_cpd_set(lws_get_context(wsi), + LWS_CPD_INTERNET_OK); + return 0; + + /* also case HTTP_STATUS_OK: ... */ + default: + break; + } + + /* fallthru */ + + case LWS_CALLBACK_CLIENT_HTTP_REDIRECT: + lws_system_cpd_set(lws_get_context(wsi), LWS_CPD_CAPTIVE_PORTAL); + /* don't follow it, just report it */ + return 1; + + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + case LWS_CALLBACK_CLOSED_CLIENT_HTTP: + /* only the first result counts */ + lws_system_cpd_set(lws_get_context(wsi), LWS_CPD_NO_INTERNET); + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static const struct lws_protocols protocols[] = { + { + "http", + callback_http, + 0, + 0, + }, { + "lws-cpd-http", + callback_cpd_http + }, + { NULL, NULL, 0, 0 } +}; + +void sigint_handler(int sig) +{ + interrupted = 1; +} + +/* + * This triggers our platform implementation of captive portal detection, the + * actual test can be whatever you need. + * + * In this example, we detect it using Android's + * + * http://connectivitycheck.android.com/generate_204 + * + * and seeing if we get an http 204 back. + */ + +static int +captive_portal_detect_request(struct lws_context *context) +{ + struct lws_client_connect_info i; + + memset(&i, 0, sizeof i); + i.context = context; + i.port = 80; + i.address = "connectivitycheck.android.com"; + i.path = "/generate_204"; + i.host = i.address; + i.origin = i.address; + i.method = "GET"; + + i.protocol = "lws-cpd-http"; + + return !lws_client_connect_via_info(&i); +} + + +lws_system_ops_t ops = { + .captive_portal_detect_request = captive_portal_detect_request +}; + + +static int +app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + struct lws_context *cx = lws_system_context_from_system_mgr(mgr); + + switch (target) { + case LWS_SYSTATE_CPD_PRE_TIME: + if (lws_system_cpd_state_get(cx)) + return 0; /* allow it */ + + lwsl_info("%s: LWS_SYSTATE_CPD_PRE_TIME\n", __func__); + lws_system_cpd_start(cx); + /* we'll move the state on when we get a result */ + return 1; + + case LWS_SYSTATE_OPERATIONAL: + if (current == LWS_SYSTATE_OPERATIONAL) { + struct lws_client_connect_info i; + + lwsl_user("%s: OPERATIONAL, cpd %d\n", __func__, + lws_system_cpd_state_get(cx)); + + /* + * When we reach the OPERATIONAL lws_system state, we + * can do our main job knowing we have DHCP, ntpclient, + * captive portal testing done. + */ + + if (lws_system_cpd_state_get(cx) != LWS_CPD_INTERNET_OK) { + lwsl_warn("%s: There's no internet...\n", __func__); + interrupted = 1; + break; + } + + memset(&i, 0, sizeof i); + i.context = context; + i.ssl_connection = LCCSCF_USE_SSL; + i.ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR | + LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; + i.port = 443; + i.address = "warmcat.com"; + i.path = "/"; + i.host = i.address; + i.origin = i.address; + i.method = "GET"; + + i.protocol = protocols[0].name; + + lws_client_connect_via_info(&i); + break; + } + default: + break; + } + + return 0; +} + +static lws_state_notify_link_t * const app_notifier_list[] = { + &nl, NULL +}; + +/* + * We made this into a different thread to model it being run from completely + * different codebase that's all linked together + */ + + +int main(int argc, const char **argv) +{ + int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + struct lws_context_creation_info info; + const char *p; + + signal(SIGINT, sigint_handler); + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS minimal http client captive portal detect\n"); + + memset(&info, 0, sizeof info); + info.port = CONTEXT_PORT_NO_LISTEN; + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.system_ops = &ops; + info.protocols = protocols; + + /* integrate us with lws system state management when context created */ + + nl.name = "app"; + nl.notify_cb = app_system_state_nf; + info.register_notifier_list = app_notifier_list; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + while (!interrupted) + if (lws_service(context, 0)) + interrupted = 1; + + lws_context_destroy(context); + + lwsl_user("%s: finished %s\n", __func__, bad ? "FAIL": "OK"); + + return bad; +} diff --git a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c index fe44a437..2c5a2786 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c @@ -154,6 +154,11 @@ static const char * const default_ss_policy = "}" "]," "\"s\": [" + /* + * "fetch_policy" decides from where the real policy + * will be fetched, if present. Otherwise the initial + * policy is treated as the whole, hardcoded, policy. + */ "{\"fetch_policy\": {" "\"endpoint\":" "\"warmcat.com\"," "\"port\":" "443," @@ -168,8 +173,42 @@ static const char * const default_ss_policy = "\"opportunistic\":" "true," "\"retry\":" "\"default\"," "\"tls_trust_store\":" "\"le_via_isrg\"" - "}}" - "}" + "}},{" + /* + * "captive_portal_detect" describes + * what to do in order to check if the path to + * the Internet is being interrupted by a + * captive portal. If there's a larger policy + * fetched from elsewhere, it should also include + * this since it needs to be done at least after + * every DHCP acquisition + */ + "\"captive_portal_detect\": {" +#if 1 + /* this does the actual test */ + "\"endpoint\": \"connectivitycheck.android.com\"," + "\"http_url\": \"generate_204\"," + "\"port\": 80," +#endif +#if 0 + /* this looks like a captive portal due to redirect */ + "\"endpoint\": \"google.com\"," + "\"http_url\": \"/\"," + "\"port\": 80," +#endif +#if 0 + /* this looks like no internet */ + "\"endpoint\": \"warmcat.com\"," + "\"http_url\": \"/\"," + "\"port\": 999," +#endif + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"opportunistic\": true," + "\"http_expect\": 204," + "\"http_fail_redirect\": true" + "}}" + "]}" ; #endif -- Gitee From 704eaa5e632f9ab29cef75253774f9e0284fca34 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 12 Mar 2020 14:43:32 +0000 Subject: [PATCH 0011/1062] ss: allow streamtype policy overlays Make the policy load apis public with an extra argument that says if you want the JSON to overlay on an existing policy rather than replace it. Teach the stream type parser stuff to realize it already has an entry for the stream type and to modify that rather than create a second one, allowing overlays to modify stream types. Add --force-portal and --force-no-internet flags to minimal-secure-streams and use the new policy overlay stuff to force the policy for captive portal detection to feel that there is one or that there's no internet. --- .../libwebsockets/lws-secure-streams-policy.h | 12 ++++ lib/core/context.c | 2 +- lib/secure-streams/README.md | 39 ++++++++++++ lib/secure-streams/policy.c | 63 ++++++++++++++++--- .../private-lib-secure-streams.h | 10 --- .../system/fetch-policy/fetch-policy.c | 2 +- .../minimal-secure-streams/README.md | 2 + .../minimal-secure-streams.c | 58 ++++++++++++----- 8 files changed, 152 insertions(+), 36 deletions(-) diff --git a/include/libwebsockets/lws-secure-streams-policy.h b/include/libwebsockets/lws-secure-streams-policy.h index f64fd80d..02122fff 100644 --- a/include/libwebsockets/lws-secure-streams-policy.h +++ b/include/libwebsockets/lws-secure-streams-policy.h @@ -247,3 +247,15 @@ typedef struct lws_ss_policy { uint8_t client_cert; /**< which client cert to apply 0 = none, 1+ = cc 0+ */ } lws_ss_policy_t; + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_parse_begin(struct lws_context *context, int overlay); + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_parse_abandon(struct lws_context *context); + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len); + +LWS_VISIBLE LWS_EXTERN int +lws_ss_policy_overlay(struct lws_context *context, const char *overlay); diff --git a/lib/core/context.c b/lib/core/context.c index ced00eb3..be5e70d8 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -828,7 +828,7 @@ lws_create_context(const struct lws_context_creation_info *info) assert(lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)); - if (lws_ss_policy_parse_begin(context)) + if (lws_ss_policy_parse_begin(context, 0)) goto bail; n = lws_ss_policy_parse(context, diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index 59ccf319..cde5aa67 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -369,6 +369,45 @@ The secure-streams-proxy minimal example shows how this is done and fetches its real policy from warmcat.com at startup using the built-in one. +## Applying streamtype policy overlays + +This is intended for modifying policies at runtime for testing, eg, to +force error paths to be taken. After the main policy is processed, you +may parse additional, usually smaller policy fragments on top of it. + +Where streamtype names in the new fragment already exist in the current +parsed policy, the settings in the fragment are applied over the parsed +policy, overriding settings. There's a simple api to enable this by +giving it the override JSON in one string + +``` +int +lws_ss_policy_overlay(struct lws_context *context, const char *overlay); +``` + +but there are also other apis available that can statefully process +larger overlay fragments if needed. + +An example overlay fragment looks like this + +``` + { "s": [{ "captive_portal_detect": { + "endpoint": "google.com", + "http_url": "/", + "port": 80 + }}]} +``` + +ie the overlay fragment completely follows the structure of the main policy, +just misses out anything it doesn't override. + +Currently ONLY streamtypes may be overridden. + +You can see an example of this in use in `minimal-secure-streams` example +where `--force-portal` and `--force-no-internet` options cause the captive +portal detect streamtype to be overridden to force the requested kind of +outcome. + ## Captive Portal Detection If the policy contains a streamtype `captive_portal_detect` then the diff --git a/lib/secure-streams/policy.c b/lib/secure-streams/policy.c index d35c003c..d12f6f80 100644 --- a/lib/secure-streams/policy.c +++ b/lib/secure-streams/policy.c @@ -277,6 +277,7 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) char **pp, dotstar[32], *q; lws_ss_trust_store_t *ts; lws_ss_metadata_t *pmd; + lws_ss_policy_t *p2; lws_retry_bo_t *b; size_t inl, outl; lws_ss_x509_t *x; @@ -336,11 +337,39 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) } if (reason == LEJPCB_PAIR_NAME && n != -1 && n != LTY_TRUSTSTORE) { + + p2 = NULL; + if (n == LTY_POLICY) { + /* + * We want to allow for the possibility of overlays... + * eg, we come later with a JSON snippet that overrides + * select streamtype members of a streamtype that was + * already defined + */ + p2 = (lws_ss_policy_t *)a->context->pss_policies; + + while (p2) { + if (!strncmp(p2->streamtype, + ctx->path + ctx->st[ctx->sp].p, + ctx->path_match_len - + ctx->st[ctx->sp].p)) { + lwsl_info("%s: overriding s[] %s\n", + __func__, p2->streamtype); + break; + } + + p2 = p2->next; + } + } + /* - * We do the pointers always as .b, all of the participating - * structs begin with .next and .name + * We do the pointers always as .b union member, all of the + * participating structs begin with .next and .name the same */ - a->curr[n].b = lwsac_use_zero(&a->ac, sizes[n], POL_AC_GRAIN); + if (p2) /* we may be overriding existing streamtype... */ + a->curr[n].b = (backoff_t *)p2; + else + a->curr[n].b = lwsac_use_zero(&a->ac, sizes[n], POL_AC_GRAIN); if (!a->curr[n].b) goto oom; @@ -352,11 +381,15 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) } a->count = 0; - a->curr[n].b->next = a->heads[n].b; - a->heads[n].b = a->curr[n].b; - pp = (char **)&a->curr[n].b->name; + if (!p2) { + a->curr[n].b->next = a->heads[n].b; + a->heads[n].b = a->curr[n].b; + pp = (char **)&a->curr[n].b->name; - goto string1; + goto string1; + } + + return 0; /* overriding */ } if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match) @@ -762,7 +795,7 @@ oom: } int -lws_ss_policy_parse_begin(struct lws_context *context) +lws_ss_policy_parse_begin(struct lws_context *context, int overlay) { struct policy_cb_args *args; char *p; @@ -773,6 +806,12 @@ lws_ss_policy_parse_begin(struct lws_context *context) return 1; } + if (overlay) + /* continue to use the existing lwsac */ + args->ac = context->ac_policy; + else + /* we don't want to see any old policy */ + context->pss_policies = NULL; context->pol_args = args; args->context = context; @@ -818,6 +857,14 @@ lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len) return m; } +int +lws_ss_policy_overlay(struct lws_context *context, const char *overlay) +{ + lws_ss_policy_parse_begin(context, 1); + return lws_ss_policy_parse(context, (const uint8_t *)overlay, + strlen(overlay)); +} + int lws_ss_policy_set(struct lws_context *context, const char *name) { diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index fc8b88e8..90dd4458 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -272,19 +272,9 @@ lws_ss_destroy_dll(struct lws_dll2 *d, void *user); int lws_sspc_destroy_dll(struct lws_dll2 *d, void *user); - -int -lws_ss_policy_parse_begin(struct lws_context *context); - -int -lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len); - int lws_ss_policy_set(struct lws_context *context, const char *name); -int -lws_ss_policy_parse_abandon(struct lws_context *context); - int lws_ss_sys_fetch_policy(struct lws_context *context); diff --git a/lib/secure-streams/system/fetch-policy/fetch-policy.c b/lib/secure-streams/system/fetch-policy/fetch-policy.c index bd0a3e44..ace853b3 100644 --- a/lib/secure-streams/system/fetch-policy/fetch-policy.c +++ b/lib/secure-streams/system/fetch-policy/fetch-policy.c @@ -45,7 +45,7 @@ ss_fetch_policy_rx(void *userobj, const uint8_t *buf, size_t len, int flags) struct lws_context *context = (struct lws_context *)m->opaque_data; if (flags & LWSSS_FLAG_SOM) { - if (lws_ss_policy_parse_begin(context)) + if (lws_ss_policy_parse_begin(context, 0)) return 1; m->partway = 1; } diff --git a/minimal-examples/secure-streams/minimal-secure-streams/README.md b/minimal-examples/secure-streams/minimal-secure-streams/README.md index 80a1c692..cb9b3b36 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/README.md +++ b/minimal-examples/secure-streams/minimal-secure-streams/README.md @@ -23,6 +23,8 @@ Commandline option|Meaning -d |Debug verbosity in decimal, eg, -d15 -f| Force connecting to the wrong endpoint to check backoff retry flow -p| Run as proxy server for clients to connect to over unix domain socket +--force-portal|Force the SS Captive Portal Detection to feel it's behind a portal +--force-no-internet|Force the SS Captive Portal Detection to feel it can't reach the internet ``` [2019/08/12 07:16:11:0045] USR: LWS minimal secure streams [-d] [-f] diff --git a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c index 2c5a2786..bdd42974 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c @@ -37,7 +37,8 @@ */ // #define VIA_LOCALHOST_SOCKS -static int interrupted, bad = 1; +static int interrupted, bad = 1, force_cpd_fail_portal, + force_cpd_fail_no_internet; static lws_state_notify_link_t nl; /* @@ -184,24 +185,9 @@ static const char * const default_ss_policy = * every DHCP acquisition */ "\"captive_portal_detect\": {" -#if 1 - /* this does the actual test */ "\"endpoint\": \"connectivitycheck.android.com\"," "\"http_url\": \"generate_204\"," "\"port\": 80," -#endif -#if 0 - /* this looks like a captive portal due to redirect */ - "\"endpoint\": \"google.com\"," - "\"http_url\": \"/\"," - "\"port\": 80," -#endif -#if 0 - /* this looks like no internet */ - "\"endpoint\": \"warmcat.com\"," - "\"http_url\": \"/\"," - "\"port\": 999," -#endif "\"protocol\": \"h1\"," "\"http_method\": \"GET\"," "\"opportunistic\": true," @@ -309,6 +295,38 @@ app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, * state wait while we trigger the dependent action. */ switch (target) { + + case LWS_SYSTATE_INITIALIZED: /* overlay on the hardcoded policy */ + case LWS_SYSTATE_POLICY_VALID: /* overlay on the loaded policy */ + + if (target != current) + break; + + if (force_cpd_fail_portal) + + /* this makes it look like we're behind a captive portal + * because the overriden address does a redirect */ + + lws_ss_policy_overlay(context, + "{\"s\": [{\"captive_portal_detect\": {" + "\"endpoint\": \"google.com\"," + "\"http_url\": \"/\"," + "\"port\": 80" + "}}]}"); + + if (force_cpd_fail_no_internet) + + /* this looks like no internet, because the overridden + * port doesn't have anything that will connect to us */ + + lws_ss_policy_overlay(context, + "{\"s\": [{\"captive_portal_detect\": {" + "\"endpoint\": \"warmcat.com\"," + "\"http_url\": \"/\"," + "\"port\": 999" + "}}]}"); + break; + case LWS_SYSTATE_REGISTERED: size = lws_system_blob_get_size(ab); if (size) @@ -372,6 +390,14 @@ int main(int argc, const char **argv) lwsl_user("LWS secure streams test client [-d]\n"); + /* these options are mutually exclusive if given */ + + if (lws_cmdline_option(argc, argv, "--force-portal")) + force_cpd_fail_portal = 1; + + if (lws_cmdline_option(argc, argv, "--force-no-internet")) + force_cpd_fail_no_internet = 1; + info.fd_limit_per_thread = 1 + 6 + 1; info.port = CONTEXT_PORT_NO_LISTEN; #if defined(LWS_SS_USE_SSPC) -- Gitee From 14027781cc45abfe27715b78ac520ace7d178d6a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 13 Mar 2020 07:25:33 +0000 Subject: [PATCH 0012/1062] lws_struct: conditional prototypes make trouble with visibility Although the code is correct and the symbols should be defined, making some prototypes conditional on cmake defines breaks their visibility when the library is built. They're conditional here to get around use of sqlite3 type in the prototypes where we may not be including sqlite3 headers. Replace the conditional with a grauitous typedef as a forward ref, since it's only referred to via pointer types. --- include/libwebsockets/lws-struct.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/libwebsockets/lws-struct.h b/include/libwebsockets/lws-struct.h index 4468fdfc..3091feae 100644 --- a/include/libwebsockets/lws-struct.h +++ b/include/libwebsockets/lws-struct.h @@ -242,7 +242,7 @@ LWS_VISIBLE LWS_EXTERN lws_struct_json_serialize_result_t lws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, size_t len, size_t *written); -#if defined(LWS_WITH_STRUCT_SQLITE3) +typedef struct sqlite3 sqlite3; LWS_VISIBLE LWS_EXTERN int lws_struct_sq3_serialize(sqlite3 *pdb, const lws_struct_map_t *schema, @@ -263,4 +263,3 @@ lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, LWS_VISIBLE LWS_EXTERN int lws_struct_sq3_close(sqlite3 **pdb); -#endif -- Gitee From 65a3d40d74e5e6d1b916f4ccc3b8e571e5dee956 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 13 Mar 2020 07:42:25 +0000 Subject: [PATCH 0013/1062] ss: support metadata string expansion in endpoint string This lets you set metadata symbols exposed by the streamtype policy into the endpoint address. No ABI change --- lib/secure-streams/README.md | 9 +- lib/secure-streams/secure-streams.c | 18 +- .../CMakeLists.txt | 92 +++++ .../minimal-secure-streams-metadata/README.md | 66 ++++ .../minimal-secure-streams.c | 370 ++++++++++++++++++ 5 files changed, 552 insertions(+), 3 deletions(-) create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-metadata/README.md create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index cde5aa67..d0540f69 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -119,7 +119,14 @@ These are an array of policies for the supported stream type names. ### `endpoint` -The DNS address the secure stream should connect to +The DNS address the secure stream should connect to. + +This may contain string symbols which will be replaced with the +corresponding streamtype metadata value at runtime. Eg, if the +streamtype lists a metadata name "region", it's then possible to +define the endpoint as, eg, `${region}.mysite.com`, and before +attempting the connection setting the stream's metadata item +"region" to the desired value, eg, "uk". ### `port` diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index b5eb4033..f8e7b2ae 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -187,8 +187,10 @@ lws_ss_client_connect(lws_ss_handle_t *h) { struct lws_client_connect_info i; const struct ss_pcols *ssp; + size_t used_in, used_out; union lws_ss_contemp ct; - char path[128]; + char path[128], ep[96]; + lws_strexp_t exp; if (!h->policy) { lwsl_err("%s: ss with no policy\n", __func__); @@ -226,7 +228,19 @@ lws_ss_client_connect(lws_ss_handle_t *h) } } - i.address = h->policy->endpoint; + /* expand metadata ${symbols} that may be inside the endpoint string */ + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, ep, sizeof(ep)); + + if (lws_strexp_expand(&exp, h->policy->endpoint, + strlen(h->policy->endpoint), + &used_in, &used_out) != LSTRX_DONE) { + lwsl_err("%s: address strexp failed\n", __func__); + + return -1; + } + + i.address = ep; i.port = h->policy->port; i.host = i.address; i.origin = i.address; diff --git a/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt new file mode 100644 index 00000000..2b1b4b1c --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt @@ -0,0 +1,92 @@ +project(minimal-secure-streams-metadata) +cmake_minimum_required(VERSION 2.8) +include(CheckCSourceCompiles) + +set(SAMP lws-minimal-secure-streams-metadata) + +# If we are being built as part of lws, confirm current build config supports +# reqconfig, else skip building ourselves. +# +# If we are being built externally, confirm installed lws was configured to +# support reqconfig, else error out with a helpful message about the problem. +# +MACRO(require_lws_config reqconfig _val result) + + if (DEFINED ${reqconfig}) + if (${reqconfig}) + set (rq 1) + else() + set (rq 0) + endif() + else() + set(rq 0) + endif() + + if (${_val} EQUAL ${rq}) + set(SAME 1) + else() + set(SAME 0) + endif() + + if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) + if (${_val}) + message("${SAMP}: skipping as lws being built without ${reqconfig}") + else() + message("${SAMP}: skipping as lws built with ${reqconfig}") + endif() + set(${result} 0) + else() + if (LWS_WITH_MINIMAL_EXAMPLES) + set(MET ${SAME}) + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) + if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) + set(HAS_${reqconfig} 0) + else() + set(HAS_${reqconfig} 1) + endif() + if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) + set(MET 1) + else() + set(MET 0) + endif() + endif() + if (NOT MET) + if (${_val}) + message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") + else() + message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") + endif() + endif() + endif() +ENDMACRO() + + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) + +if (requirements) + add_executable(${SAMP} minimal-secure-streams.c) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets) + endif() + + if (LWS_WITH_SECURE_STREAMS_PROXY_API) + add_compile_options(-DLWS_SS_USE_SSPC) + + add_executable(${SAMP}-client minimal-secure-streams.c) + if (websockets_shared) + target_link_libraries(${SAMP}-client websockets_shared) + add_dependencies(${SAMP}-client websockets_shared) + else() + target_link_libraries(${SAMP}-client websockets) + endif() + endif() + +endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-metadata/README.md b/minimal-examples/secure-streams/minimal-secure-streams-metadata/README.md new file mode 100644 index 00000000..cb9b3b36 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-metadata/README.md @@ -0,0 +1,66 @@ +# lws minimal secure streams + +The application goes to https://warmcat.com and reads index.html there. + +It does it using Secure Streams... the main code in minimal-secure-streams.c +just sets up the context and opens a secure stream of type "mintest". + +The handler for state changes and payloads for "mintest" is in ss-myss.c + +The information about how a "mintest" stream should connect and the +protocol it uses is kept separated in policy-database.c + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 +-f| Force connecting to the wrong endpoint to check backoff retry flow +-p| Run as proxy server for clients to connect to over unix domain socket +--force-portal|Force the SS Captive Portal Detection to feel it's behind a portal +--force-no-internet|Force the SS Captive Portal Detection to feel it can't reach the internet + +``` +[2019/08/12 07:16:11:0045] USR: LWS minimal secure streams [-d] [-f] +[2019/08/12 07:16:12:6102] USR: myss_state: LWSSSCS_CREATING, ord 0x0 +[2019/08/12 07:16:12:6107] USR: myss_state: LWSSSCS_POLL, ord 0x0 +[2019/08/12 07:16:12:6117] N: lws_ss_client_connect: connecting h1get warmcat.com / +[2019/08/12 07:16:12:6118] USR: myss_state: LWSSSCS_CONNECTING, ord 0x0 +[2019/08/12 07:16:13:4171] USR: myss_state: LWSSSCS_CONNECTED, ord 0x0 +[2019/08/12 07:16:13:4222] USR: myss_rx: len 1024, flags: 1 +[2019/08/12 07:16:13:4243] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4244] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4244] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4245] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4246] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4247] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4252] USR: myss_rx: len 1015, flags: 0 +[2019/08/12 07:16:13:4264] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4265] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4266] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4267] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4268] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4268] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4269] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4270] USR: myss_rx: len 1015, flags: 0 +[2019/08/12 07:16:13:4278] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4279] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4280] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4281] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4282] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4283] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4283] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4284] USR: myss_rx: len 1015, flags: 0 +[2019/08/12 07:16:13:4287] USR: myss_rx: len 1024, flags: 0 +[2019/08/12 07:16:13:4288] USR: myss_rx: len 947, flags: 0 +[2019/08/12 07:16:13:4293] USR: myss_rx: len 0, flags: 2 +[2019/08/12 07:16:13:4399] USR: myss_state: LWSSSCS_DISCONNECTED, ord 0x0 +[2019/08/12 07:16:13:4761] USR: myss_state: LWSSSCS_DESTROYING, ord 0x0 +[2019/08/12 07:16:13:4781] USR: Completed: OK +``` diff --git a/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c new file mode 100644 index 00000000..1481ec14 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c @@ -0,0 +1,370 @@ +/* + * lws-minimal-secure-streams-metadata + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * + * This demonstrates a minimal http client using secure streams api. + * + * It visits https://warmcat.com/ and receives the html page there. + * + * This example is built two different ways from the same source... one includes + * the policy everything needed to fulfil the stream directly. The other -client + * variant has no policy itself and some other minor init changes, and connects + * to the -proxy example to actually get the connection done. + * + * In the -client build case, the example does not even init the tls libraries + * since the proxy part will take care of all that. + */ + +#include +#include +#include + +/* + * uncomment to force network traffic through 127.0.0.1:1080 + * + * On your local machine, you can run a SOCKS5 proxy like this + * + * $ ssh -N -D 0.0.0.0:1080 localhost -v + * + * If enabled, this also fetches a remote policy that also + * specifies that all traffic should go through the remote + * proxy. + */ +// #define VIA_LOCALHOST_SOCKS + +static int interrupted, bad = 1, force_cpd_fail_portal, + force_cpd_fail_no_internet; +static lws_state_notify_link_t nl; + +/* + * If the -proxy app is fulfilling our connection, then we don't need to have + * the policy in the client. + * + * When we build with LWS_SS_USE_SSPC, the apis hook up to a proxy process over + * a Unix Domain Socket. To test that, you need to separately run the + * ./lws-minimal-secure-streams-proxy test app on the same machine. + */ + +#if !defined(LWS_SS_USE_SSPC) +static const char * const default_ss_policy = + "{" + "\"release\":" "\"01234567\"," + "\"product\":" "\"myproduct\"," + "\"schema-version\":" "1," +#if defined(VIA_LOCALHOST_SOCKS) + "\"via-socks5\":" "\"127.0.0.1:1080\"," +#endif + + "\"retry\": [" /* named backoff / retry strategies */ + "{\"default\": {" + "\"backoff\": [" "1000," + "2000," + "3000," + "5000," + "10000" + "]," + "\"conceal\":" "5," + "\"jitterpc\":" "20," + "\"svalidping\":" "30," + "\"svalidhup\":" "35" + "}}" + "]," + "\"certs\": [" /* named individual certificates in BASE64 DER */ + /* + * Let's Encrypt certs for warmcat.com / libwebsockets.org + * + * We fetch the real policy from there using SS and switch to + * using that. + */ + "{\"isrg_root_x1\": \"" /* ISRG ROOT X1 */ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4" + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu" + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY" + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc" + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+" + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U" + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW" + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH" + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC" + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv" + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn" + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn" + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw" + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI" + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV" + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq" + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL" + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ" + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK" + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5" + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur" + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC" + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc" + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq" + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA" + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d" + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + "\"}," + "{\"LEX3_isrg_root_x1\": \"" /* LE X3 signed by ISRG X1 root */ + "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1" + "WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg" + "RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi" + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX" + "NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf" + "89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl" + "Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc" + "Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz" + "uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB" + "AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU" + "BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB" + "FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo" + "SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js" + "LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF" + "BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG" + "AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD" + "VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB" + "ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx" + "A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM" + "UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2" + "DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1" + "eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu" + "OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw" + "p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY" + "2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0" + "ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR" + "PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b" + "rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + "\"}" + "]," + "\"trust_stores\": [" /* named cert chains */ + "{" + "\"name\": \"le_via_isrg\"," + "\"stack\": [" + "\"isrg_root_x1\"," + "\"LEX3_isrg_root_x1\"" + "]" + "}" + "]," + "\"s\": [" + "{\"mintest\": {" + "\"endpoint\":" "\"${servername}\"," + "\"port\":" "443," + "\"protocol\":" "\"h1\"," + "\"http_method\":" "\"GET\"," + "\"http_url\":" "\"\"," + "\"tls\":" "true," + "\"opportunistic\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"le_via_isrg\"," + "\"metadata\": [" + "{\"servername\": \"\"}" + "]" + "}}" + "]}" +; + +#endif + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + lws_sorted_usec_list_t sul; +} myss_t; + +/* secure streams payload interface */ + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_info(buf, len); + + /* + * If we received the whole message, for our example it means + * we are done. + */ + if (flags & LWSSS_FLAG_EOM) { + bad = 0; + interrupted = 1; + } + + return 0; +} + +static int +myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + //myss_t *m = (myss_t *)userobj; + + return 0; +} + +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_set_metadata(m->ss, "servername", "warmcat.com", 11); + lws_ss_client_connect(m->ss); + break; + case LWSSSCS_ALL_RETRIES_FAILED: + /* if we're out of retries, we want to close the app and FAIL */ + interrupted = 1; + break; + case LWSSSCS_QOS_ACK_REMOTE: + lwsl_notice("%s: LWSSSCS_QOS_ACK_REMOTE\n", __func__); + break; + default: + break; + } + + return 0; +} + +static int +app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + struct lws_context *context = lws_system_context_from_system_mgr(mgr); + + /* + * For the things we care about, let's notice if we are trying to get + * past them when we haven't solved them yet, and make the system + * state wait while we trigger the dependent action. + */ + switch (target) { + + case LWS_SYSTATE_OPERATIONAL: + if (current == LWS_SYSTATE_OPERATIONAL) { + lws_ss_info_t ssi; + + /* We're making an outgoing secure stream ourselves */ + + memset(&ssi, 0, sizeof(ssi)); + ssi.handle_offset = offsetof(myss_t, ss); + ssi.opaque_user_data_offset = offsetof(myss_t, + opaque_data); + ssi.rx = myss_rx; + ssi.tx = myss_tx; + ssi.state = myss_state; + ssi.user_alloc = sizeof(myss_t); + ssi.streamtype = "mintest"; + + if (lws_ss_create(context, 0, &ssi, NULL, NULL, + NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + break; + } + + return 0; +} + +static lws_state_notify_link_t * const app_notifier_list[] = { + &nl, NULL +}; + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + int n = 0; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS secure streams test client [-d]\n"); + + /* these options are mutually exclusive if given */ + + if (lws_cmdline_option(argc, argv, "--force-portal")) + force_cpd_fail_portal = 1; + + if (lws_cmdline_option(argc, argv, "--force-no-internet")) + force_cpd_fail_no_internet = 1; + + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; + +#if defined(LWS_SS_USE_SSPC) + info.protocols = lws_sspc_protocols; + { + const char *p; + + /* connect to ssproxy via UDS by default, else via + * tcp connection to this port */ + if ((p = lws_cmdline_option(argc, argv, "-p"))) + info.ss_proxy_port = atoi(p); + + /* UDS "proxy.ss.lws" in abstract namespace, else this socket + * path; when -p given this can specify the network interface + * to bind to */ + if ((p = lws_cmdline_option(argc, argv, "-i"))) + info.ss_proxy_bind = p; + + /* if -p given, -a specifies the proxy address to connect to */ + if ((p = lws_cmdline_option(argc, argv, "-a"))) + info.ss_proxy_address = p; + } +#else + info.pss_policies_json = default_ss_policy; + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#endif + + /* integrate us with lws system state management when context created */ + + nl.name = "app"; + nl.notify_cb = app_system_state_nf; + info.register_notifier_list = app_notifier_list; + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + + /* the event loop */ + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} -- Gitee From 8adcdbb189c5fc7ebcf7c649820490494fb0f95d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 14 Mar 2020 07:04:14 +0000 Subject: [PATCH 0014/1062] lws_spa: avoid reading past table Didn't check the lenghts of the NUL-terminated header table properly. https://github.com/warmcat/libwebsockets/issues/1859 --- lib/core/context.c | 6 ++-- lib/roles/http/server/lws-spa.c | 64 +++++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index be5e70d8..5b5bb1c9 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -538,11 +538,13 @@ lws_create_context(const struct lws_context_creation_info *info) else context->max_http_header_pool = context->max_fds; + if (info->fd_limit_per_thread) context->fd_limit_per_thread = lpf; else - context->fd_limit_per_thread = context->max_fds / - context->count_threads; + if (context->count_threads) + context->fd_limit_per_thread = context->max_fds / + context->count_threads; #if defined(LWS_WITH_NETWORK) diff --git a/lib/roles/http/server/lws-spa.c b/lib/roles/http/server/lws-spa.c index 7e79eb00..1bbf77a6 100644 --- a/lib/roles/http/server/lws-spa.c +++ b/lib/roles/http/server/lws-spa.c @@ -42,10 +42,13 @@ enum urldecode_stateful { MT_COMPLETED, }; -static const char * const mp_hdr[] = { - "content-disposition: ", - "content-type: ", - "\x0d\x0a" +static struct mp_hdr { + const char * const hdr; + uint8_t hdr_len; +} mp_hdrs[] = { + { "content-disposition: ", 21 }, + { "content-type: ", 14 }, + { "\x0d\x0a", 2 } }; struct lws_spa; @@ -69,10 +72,12 @@ struct lws_urldecode_stateful { int mp; int sum; - unsigned int multipart_form_data:1; - unsigned int inside_quote:1; - unsigned int subname:1; - unsigned int boundary_real_crlf:1; + uint8_t matchable; + + uint8_t multipart_form_data:1; + uint8_t inside_quote:1; + uint8_t subname:1; + uint8_t boundary_real_crlf:1; enum urldecode_stateful state; @@ -150,7 +155,7 @@ static int lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, int len) { - int n, m, hit = 0; + int n, hit; char c; while (len--) { @@ -281,29 +286,52 @@ retry_as_first: break; case MT_HNAME: - m = 0; c =*in; if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; - for (n = 0; n < (int)LWS_ARRAY_SIZE(mp_hdr); n++) - if (c == mp_hdr[n][s->mp]) { - m++; + if (!s->mp) + /* initially, any of them might match */ + s->matchable = (1 << LWS_ARRAY_SIZE(mp_hdrs)) - 1; + + hit = -1; + for (n = 0; n < (int)LWS_ARRAY_SIZE(mp_hdrs); n++) { + + if (!(s->matchable & (1 << n))) + continue; + /* this guy is still in contention... */ + + if (s->mp >= mp_hdrs[n].hdr_len) { + /* he went past the end of it */ + s->matchable &= ~(1 << n); + continue; + } + + if (c != mp_hdrs[n].hdr[s->mp]) { + /* mismatched a char */ + s->matchable &= ~(1 << n); + continue; + } + + if (s->mp + 1 == mp_hdrs[n].hdr_len) { + /* we have a winner... */ hit = n; + break; } + } + in++; - if (!m) { - /* Unknown header - ignore it */ + if (hit == -1 && !s->matchable) { + /* We ruled them all out */ s->state = MT_IGNORE1; s->mp = 0; continue; } s->mp++; - if (m != 1) + if (hit < 0) continue; - if (mp_hdr[hit][s->mp]) - continue; + /* we matched the one in hit */ s->mp = 0; s->temp[0] = '\0'; -- Gitee From 2cd8f599ebbefdc04805bbfd9103cbb442c21daf Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 14 Mar 2020 06:56:41 +0000 Subject: [PATCH 0015/1062] ss: allow url style endpoint addresses The endpoint field in streamtype policy may continue to just be the hostname, like "warmcat.com". But it's also possible now to be a url-formatted string, like, eg, "https://warmcat.com:444/mailman/listinfo" If so (ie, if it contains a : ) then the decoded elements may override if tls is enabled, the endpoint address, the port, and the url path. No ABI change. --- .../libwebsockets/lws-secure-streams-client.h | 2 +- include/libwebsockets/lws-secure-streams.h | 2 +- lib/core/context.c | 4 +- lib/secure-streams/policy.c | 4 +- lib/secure-streams/protocols/ss-h1.c | 11 ++- lib/secure-streams/protocols/ss-h2.c | 19 ++++- lib/secure-streams/protocols/ss-ws.c | 21 ++++- lib/secure-streams/secure-streams-client.c | 4 +- lib/secure-streams/secure-streams.c | 82 +++++++++++++------ .../minimal-secure-streams.c | 42 +++++----- 10 files changed, 134 insertions(+), 57 deletions(-) diff --git a/include/libwebsockets/lws-secure-streams-client.h b/include/libwebsockets/lws-secure-streams-client.h index b7244158..35cb8873 100644 --- a/include/libwebsockets/lws-secure-streams-client.h +++ b/include/libwebsockets/lws-secure-streams-client.h @@ -163,7 +163,7 @@ lws_sspc_rideshare(struct lws_sspc_handle *h); */ LWS_VISIBLE LWS_EXTERN int lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, - void *value, size_t len); + const void *value, size_t len); LWS_VISIBLE LWS_EXTERN int lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t add); diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index afd8bee1..f0b2b403 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -463,7 +463,7 @@ lws_ss_rideshare(struct lws_ss_handle *h); */ LWS_VISIBLE LWS_EXTERN int lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, - void *value, size_t len); + const void *value, size_t len); /** diff --git a/lib/core/context.c b/lib/core/context.c index 5b5bb1c9..27b1d11f 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -949,7 +949,9 @@ lws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result) cx->captive_portal_detect = (uint8_t)result; /* if nothing is there to intercept anything, go all the way */ - lws_state_transition_steps(&cx->mgr_system, LWS_SYSTATE_OPERATIONAL); + if (cx->mgr_system.state != LWS_SYSTATE_POLICY_INVALID) + lws_state_transition_steps(&cx->mgr_system, + LWS_SYSTATE_OPERATIONAL); } lws_cpd_result_t diff --git a/lib/secure-streams/policy.c b/lib/secure-streams/policy.c index d12f6f80..6991e528 100644 --- a/lib/secure-streams/policy.c +++ b/lib/secure-streams/policy.c @@ -242,7 +242,7 @@ lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index) int lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, - void *value, size_t len) + const void *value, size_t len) { lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); @@ -252,7 +252,7 @@ lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, } h->metadata[omd->length].name = name; - h->metadata[omd->length].value = value; + h->metadata[omd->length].value = (void *)value; h->metadata[omd->length].length = len; return 0; diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 1de0868f..81065a33 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -543,10 +543,16 @@ secstream_connect_munge_h1(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *pbasis = h->policy->u.http.url; size_t used_in, used_out; lws_strexp_t exp; - if (!h->policy->u.http.url) + /* i.path on entry is used to override the policy urlpath if not "" */ + + if (i->path[0]) + pbasis = i->path; + + if (!pbasis) return 0; #if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) @@ -564,8 +570,7 @@ secstream_connect_munge_h1(lws_ss_handle_t *h, char *buf, size_t len, lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); - if (lws_strexp_expand(&exp, h->policy->u.http.url, - strlen(h->policy->u.http.url), + if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), &used_in, &used_out) != LSTRX_DONE) return 1; diff --git a/lib/secure-streams/protocols/ss-h2.c b/lib/secure-streams/protocols/ss-h2.c index 941183c1..06332485 100644 --- a/lib/secure-streams/protocols/ss-h2.c +++ b/lib/secure-streams/protocols/ss-h2.c @@ -112,6 +112,15 @@ secstream_connect_munge_h2(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *pbasis = h->policy->u.http.url; + size_t used_in, used_out; + lws_strexp_t exp; + + /* i.path on entry is used to override the policy urlpath if not "" */ + + if (i->path[0]) + pbasis = i->path; + if (h->policy->flags & LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM) i->ssl_connection |= LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; @@ -137,13 +146,19 @@ secstream_connect_munge_h2(lws_ss_handle_t *h, char *buf, size_t len, i->manual_initial_tx_credit); } - if (!h->policy->u.http.url) + if (!pbasis) return 0; /* protocol aux is the path part */ i->path = buf; - lws_snprintf(buf, len, "/%s", h->policy->u.http.url); + buf[0] = '/'; + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); + + if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), + &used_in, &used_out) != LSTRX_DONE) + return 1; return 0; } diff --git a/lib/secure-streams/protocols/ss-ws.c b/lib/secure-streams/protocols/ss-ws.c index ac1dc32a..91d36a58 100644 --- a/lib/secure-streams/protocols/ss-ws.c +++ b/lib/secure-streams/protocols/ss-ws.c @@ -143,15 +143,30 @@ secstream_connect_munge_ws(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *pbasis = h->policy->u.http.url; + size_t used_in, used_out; + lws_strexp_t exp; + lwsl_notice("%s\n", __func__); - if (!h->policy->u.http.url) + /* i.path on entry is used to override the policy urlpath if not "" */ + + if (i->path[0]) + pbasis = i->path; + + if (!pbasis) return 0; /* protocol aux is the path part ; ws subprotocol name */ - i->path = h->policy->u.http.url; - lws_snprintf(buf, len, "/%s", h->policy->u.http.url); + i->path = buf; + buf[0] = '/'; + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); + + if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), + &used_in, &used_out) != LSTRX_DONE) + return 1; i->protocol = h->policy->u.http.u.ws.subprotocol; diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index 67d73be6..57d7ca0d 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -493,7 +493,7 @@ lws_sspc_rideshare(struct lws_sspc_handle *h) static int _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, - void *value, size_t len, int tx_cr_adjust) + const void *value, size_t len, int tx_cr_adjust) { lws_sspc_metadata_t *md; @@ -555,7 +555,7 @@ _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, int lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, - void *value, size_t len) + const void *value, size_t len) { return _lws_sspc_set_metadata(h, name, value, len, 0); } diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index f8e7b2ae..b93158ac 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -185,11 +185,13 @@ lws_ss_backoff(lws_ss_handle_t *h) int lws_ss_client_connect(lws_ss_handle_t *h) { + const char *prot, *_prot, *ipath, *_ipath, *ads, *_ads; struct lws_client_connect_info i; const struct ss_pcols *ssp; size_t used_in, used_out; union lws_ss_contemp ct; char path[128], ep[96]; + int port, _port, tls; lws_strexp_t exp; if (!h->policy) { @@ -205,10 +207,53 @@ lws_ss_client_connect(lws_ss_handle_t *h) if (h->h_sink) return 0; + /* + * We're going to substitute ${metadata} in the endpoint at connection- + * time, so this can be set dynamically... + */ + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, ep, sizeof(ep)); + + if (lws_strexp_expand(&exp, h->policy->endpoint, + strlen(h->policy->endpoint), + &used_in, &used_out) != LSTRX_DONE) { + lwsl_err("%s: address strexp failed\n", __func__); + + return -1; + } + + /* + * ... in some cases, we might want the user to be able to override + * some policy settings by what he provided in there. For example, + * if he set the endpoint to "https://myendpoint.com:4443/mypath" it + * might be quite convenient to override the policy to follow the info + * that was given for at least server, port and the url path. + */ + + _port = port = h->policy->port; + _prot = prot = NULL; + _ipath = ipath = ""; + _ads = ads = ep; + + if (strchr(ep, ':') && + !lws_parse_uri(ep, &_prot, &_ads, &_port, &_ipath)) { + lwsl_debug("%s: using uri parse results '%s' '%s' %d '%s'\n", + __func__, _prot, _ads, _port, _ipath); + prot = _prot; + ads = _ads; + port = _port; + ipath = _ipath; + } + memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ i.context = h->context; + tls = !!(h->policy->flags & LWSSSPOLF_TLS); - if (h->policy->flags & LWSSSPOLF_TLS) { + if (prot && (!strcmp(prot, "http") || !strcmp(prot, "ws") || + !strcmp(prot, "mqtt"))) + tls = 0; + + if (tls) { lwsl_info("%s: using tls\n", __func__); i.ssl_connection = LCCSCF_USE_SSL; @@ -228,28 +273,19 @@ lws_ss_client_connect(lws_ss_handle_t *h) } } - /* expand metadata ${symbols} that may be inside the endpoint string */ - - lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, ep, sizeof(ep)); - - if (lws_strexp_expand(&exp, h->policy->endpoint, - strlen(h->policy->endpoint), - &used_in, &used_out) != LSTRX_DONE) { - lwsl_err("%s: address strexp failed\n", __func__); - - return -1; - } - - i.address = ep; - i.port = h->policy->port; - i.host = i.address; - i.origin = i.address; - i.opaque_user_data = h; - i.seq = h->seq; - i.retry_and_idle_policy = h->policy->retry_bo; - i.sys_tls_client_cert = h->policy->client_cert; - - i.path = ""; + i.address = ads; + i.port = port; + i.host = i.address; + i.origin = i.address; + i.opaque_user_data = h; + i.seq = h->seq; + i.retry_and_idle_policy = h->policy->retry_bo; + i.sys_tls_client_cert = h->policy->client_cert; + + i.path = ipath; + /* if this is not "", munge should use it instead of policy + * url path + */ ssp = ss_pcols[(int)h->policy->protocol]; if (!ssp) { diff --git a/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c index 1481ec14..d9214801 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c @@ -40,6 +40,7 @@ static int interrupted, bad = 1, force_cpd_fail_portal, force_cpd_fail_no_internet; static lws_state_notify_link_t nl; +static const char *server_name_or_url = "warmcat.com"; /* * If the -proxy app is fulfilling our connection, then we don't need to have @@ -223,7 +224,9 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: - lws_ss_set_metadata(m->ss, "servername", "warmcat.com", 11); + lwsl_notice("%s: CREATING: setting servername metadata to %s\n", + __func__, server_name_or_url); + lws_ss_set_metadata(m->ss, "servername", server_name_or_url, strlen(server_name_or_url)); lws_ss_client_connect(m->ss); break; case LWSSSCS_ALL_RETRIES_FAILED: @@ -296,6 +299,7 @@ int main(int argc, const char **argv) { struct lws_context_creation_info info; struct lws_context *context; + const char *p; int n = 0; signal(SIGINT, sigint_handler); @@ -318,30 +322,30 @@ int main(int argc, const char **argv) #if defined(LWS_SS_USE_SSPC) info.protocols = lws_sspc_protocols; - { - const char *p; - - /* connect to ssproxy via UDS by default, else via - * tcp connection to this port */ - if ((p = lws_cmdline_option(argc, argv, "-p"))) - info.ss_proxy_port = atoi(p); - - /* UDS "proxy.ss.lws" in abstract namespace, else this socket - * path; when -p given this can specify the network interface - * to bind to */ - if ((p = lws_cmdline_option(argc, argv, "-i"))) - info.ss_proxy_bind = p; - - /* if -p given, -a specifies the proxy address to connect to */ - if ((p = lws_cmdline_option(argc, argv, "-a"))) - info.ss_proxy_address = p; - } + + /* connect to ssproxy via UDS by default, else via + * tcp connection to this port */ + if ((p = lws_cmdline_option(argc, argv, "-p"))) + info.ss_proxy_port = atoi(p); + + /* UDS "proxy.ss.lws" in abstract namespace, else this socket + * path; when -p given this can specify the network interface + * to bind to */ + if ((p = lws_cmdline_option(argc, argv, "-i"))) + info.ss_proxy_bind = p; + + /* if -p given, -a specifies the proxy address to connect to */ + if ((p = lws_cmdline_option(argc, argv, "-a"))) + info.ss_proxy_address = p; #else info.pss_policies_json = default_ss_policy; info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; #endif + if ((p = lws_cmdline_option(argc, argv, "-u"))) + server_name_or_url = p; + /* integrate us with lws system state management when context created */ nl.name = "app"; -- Gitee From f843668db99444e1cc7a070662a9dcb51901ff9d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 15 Mar 2020 04:40:30 +0000 Subject: [PATCH 0016/1062] ss: add lws_ss_to_user_object The ss handle is opaque, so if you need to get the user allocation from the handle outside of a callback, a helper is needed. ABI change. --- include/libwebsockets/lws-secure-streams.h | 12 ++++++++++++ lib/secure-streams/secure-streams.c | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index f0b2b403..eafdb136 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -420,6 +420,18 @@ lws_ss_state_name(int state); LWS_VISIBLE LWS_EXTERN struct lws_context * lws_ss_get_context(struct lws_ss_handle *h); +/** + * lws_ss_to_user_object() - convenience helper to get user object from handle + * + * \param h: secure streams handle + * + * Returns the user allocation related to the handle. Normally you won't need + * this since it's available in the rx, tx and state callbacks as "userdata" + * already. + */ +LWS_VISIBLE LWS_EXTERN void * +lws_ss_to_user_object(struct lws_ss_handle *h); + /** * lws_ss_rideshare() - find the current streamtype when types rideshare * diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index b93158ac..3c8eff3f 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -480,6 +480,12 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, return 0; } +void * +lws_ss_to_user_object(struct lws_ss_handle *h) +{ + return (void *)&h[1]; +} + void lws_ss_destroy(lws_ss_handle_t **ppss) { -- Gitee From 99e6aff5374ebdddd36ebbc8c33f3472692dd07a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 15 Mar 2020 04:55:21 +0000 Subject: [PATCH 0017/1062] ss: use system trust store if none given in policy For general OpenSSL case, we leave connection validity to system trust store bundle to decide; even for mbedtls it may have been passed a bundle externally and we don't want to have to list the x.509 stack explicitly for a server we don't have any control over. Instead of erroring out, allow the case no trust store is specified, just use vhost[0] and let the system trust store decide if it likes the server's cert or not. No ABI change. --- lib/secure-streams/secure-streams.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 3c8eff3f..407137f2 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -257,19 +257,17 @@ lws_ss_client_connect(lws_ss_handle_t *h) lwsl_info("%s: using tls\n", __func__); i.ssl_connection = LCCSCF_USE_SSL; - if (!h->policy->trust_store) { - lwsl_err("%s: tls required but no policy trust store\n", - __func__); + if (!h->policy->trust_store) + lwsl_info("%s: using platform trust store\n", __func__); + else { - return -1; - } - - i.vhost = lws_get_vhost_by_name(h->context, - h->policy->trust_store->name); - if (!i.vhost) { - lwsl_err("%s: missing vh for policy ca\n", __func__); + i.vhost = lws_get_vhost_by_name(h->context, + h->policy->trust_store->name); + if (!i.vhost) { + lwsl_err("%s: missing vh for policy ca\n", __func__); - return -1; + return -1; + } } } -- Gitee From af207215009d33dab3f42ba378402716bdf0128b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 16 Mar 2020 13:58:07 +0000 Subject: [PATCH 0018/1062] threadpool: enable to use secure streams as well as direct wsi This extends threadpool slightly so it can bind enqueued tasks to a secure streams handle as well as a straight wsi. Either the .wsi must be set as before, or the .ss handle if you are using secure streams, when enqueuing a task on the taskpool. A couple of other helpers get ss-aware wrappers if LWS_WITH_SECURE_STREAMS Although threadpool was originally designed for server (gitohashi) actually it's also fine working with client wsi / Secure Streams, if you have a situation a client connection is associated with heavy processing. --- include/libwebsockets/lws-threadpool.h | 17 ++++- lib/misc/threadpool/threadpool.c | 91 ++++++++++++++++++++------ 2 files changed, 87 insertions(+), 21 deletions(-) diff --git a/include/libwebsockets/lws-threadpool.h b/include/libwebsockets/lws-threadpool.h index 94440d02..5b6cf080 100644 --- a/include/libwebsockets/lws-threadpool.h +++ b/include/libwebsockets/lws-threadpool.h @@ -71,7 +71,11 @@ struct lws_threadpool_create_args { }; struct lws_threadpool_task_args { - struct lws *wsi; /**< user must set to wsi task is bound to */ +#if defined(LWS_WITH_SECURE_STREAMS) + struct lws_ss_handle *ss; /**< either wsi or ss must be set */ +#endif + struct lws *wsi; /**< either wsi or ss must be set */ + void *user; /**< user may set (user-private pointer) */ const char *name; /**< user may set to describe task */ char async_task; /**< set to allow the task to shrug off the loss @@ -177,6 +181,11 @@ lws_threadpool_enqueue(struct lws_threadpool *tp, LWS_VISIBLE LWS_EXTERN int lws_threadpool_dequeue(struct lws *wsi); +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_dequeue_ss(struct lws_ss_handle *ss); +#endif + /** * lws_threadpool_task_status() - Dequeue or try to stop a running task * @@ -198,6 +207,12 @@ LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status lws_threadpool_task_status_wsi(struct lws *wsi, struct lws_threadpool_task **task, void **user); +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status +lws_threadpool_task_status_ss(struct lws_ss_handle *ss, + struct lws_threadpool_task **task, void **user); +#endif + /** * lws_threadpool_task_sync() - Indicate to a stalled task it may continue * diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index 2a8bcbea..f12d980c 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -232,17 +232,27 @@ state_transition(struct lws_threadpool_task *task, task->status = status; } +static struct lws * +task_to_wsi(struct lws_threadpool_task *task) +{ +#if defined(LWS_WITH_SECURE_STREAMS) + if (task->args.ss) + return task->args.ss->wsi; +#endif + return task->args.wsi; +} + static void lws_threadpool_task_cleanup_destroy(struct lws_threadpool_task *task) { if (task->args.cleanup) - task->args.cleanup(task->args.wsi, task->args.user); + task->args.cleanup(task_to_wsi(task), task->args.user); - if (task->args.wsi) - task->args.wsi->tp_task = NULL; + if (task_to_wsi(task)) + task_to_wsi(task)->tp_task = NULL; lwsl_thread("%s: tp %p: cleaned finished task for wsi %p\n", - __func__, task->tp, task->args.wsi); + __func__, task->tp, task_to_wsi(task)); lws_free(task); } @@ -265,7 +275,7 @@ __lws_threadpool_reap(struct lws_threadpool_task *task) tp->done_queue_depth--; lwsl_thread("%s: tp %s: reaped task wsi %p\n", __func__, - tp->name, task->args.wsi); + tp->name, task_to_wsi(task)); break; } @@ -308,7 +318,7 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) if (!task) continue; - wsi = task->args.wsi; + wsi = task_to_wsi(task); if (!wsi || wsi->tsi != tsi || !task->wanted_writeable_cb) continue; @@ -331,7 +341,7 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) while (*c) { task = *c; - wsi = task->args.wsi; + wsi = task_to_wsi(task); if (wsi && wsi->tsi == tsi && task->wanted_writeable_cb) { @@ -373,12 +383,12 @@ lws_threadpool_worker_sync(struct lws_pool *pool, pthread_mutex_lock(&pool->lock); /* ======================= pool lock */ lwsl_info("%s: %s: task %p (%s): syncing with wsi %p\n", __func__, - pool->tp->name, task, task->name, task->args.wsi); + pool->tp->name, task, task->name, task_to_wsi(task)); temp = task->status; state_transition(task, LWS_TP_STATUS_SYNCING); while (tries--) { - wsi = task->args.wsi; + wsi = task_to_wsi(task); /* * if the wsi is no longer attached to this task, there is @@ -431,7 +441,7 @@ lws_threadpool_worker_sync(struct lws_pool *pool, lwsl_err("%s: %s: task %p (%s): SYNC timed out " "(associated wsi %p)\n", __func__, pool->tp->name, task, - task->name, task->args.wsi); + task->name, task_to_wsi(task)); state_transition(task, LWS_TP_STATUS_STOPPING); goto done; @@ -547,7 +557,7 @@ lws_threadpool_worker(void *d) lws_usec_t then; int n; - if (tp->destroying || !task->args.wsi) { + if (tp->destroying || !task_to_wsi(task)) { lwsl_info("%s: stopping on wsi gone\n", __func__); state_transition(task, LWS_TP_STATUS_STOPPING); } @@ -563,7 +573,7 @@ lws_threadpool_worker(void *d) /* if not destroying the tp, continue */ break; case LWS_TP_RETURN_SYNC: - if (!task->args.wsi) { + if (!task_to_wsi(task)) { lwsl_debug("%s: task that wants to " "outlive lost wsi asked " "to sync: bypassed\n", @@ -623,11 +633,11 @@ lws_threadpool_worker(void *d) /* signal the associated wsi to take a fresh look at * task status */ - if (pool->task->args.wsi) { + if (task_to_wsi(pool->task)) { task->wanted_writeable_cb = 1; lws_cancel_service( - lws_get_context(pool->task->args.wsi)); + lws_get_context(task_to_wsi(pool->task))); } } @@ -812,6 +822,9 @@ lws_threadpool_dequeue(struct lws *wsi) wsi->tp_task = NULL; task->args.wsi = NULL; +#if defined(LWS_WITH_SECURE_STREAMS) + task->args.ss = NULL; +#endif goto bail; } @@ -833,7 +846,7 @@ lws_threadpool_dequeue(struct lws *wsi) task->done = lws_now_usecs(); lwsl_debug("%s: tp %p: removed queued task wsi %p\n", - __func__, tp, task->args.wsi); + __func__, tp, task_to_wsi(task)); break; } @@ -877,11 +890,14 @@ lws_threadpool_dequeue(struct lws *wsi) task->args.wsi->tp_task = NULL; task->args.wsi = NULL; +#if defined(LWS_WITH_SECURE_STREAMS) + task->args.ss = NULL; +#endif pthread_mutex_unlock(&tp->pool_list[n].lock); lwsl_debug("%s: tp %p: request stop running task " - "for wsi %p\n", __func__, tp, task->args.wsi); + "for wsi %p\n", __func__, tp, task_to_wsi(task)); break; } @@ -889,9 +905,12 @@ lws_threadpool_dequeue(struct lws *wsi) if (n == tp->threads_in_pool) { /* can't find it */ lwsl_notice("%s: tp %p: no task for wsi %p, decoupling\n", - __func__, tp, task->args.wsi); + __func__, tp, task_to_wsi(task)); task->args.wsi->tp_task = NULL; task->args.wsi = NULL; +#if defined(LWS_WITH_SECURE_STREAMS) + task->args.ss = NULL; +#endif } bail: @@ -900,6 +919,17 @@ bail: return 0; } +#if defined(LWS_WITH_SECURE_STREAMS) +int +lws_threadpool_dequeue_ss(struct lws_ss_handle *ss) +{ + if (ss) + return lws_threadpool_dequeue(ss->wsi); + + return 0; +} +#endif + struct lws_threadpool_task * lws_threadpool_enqueue(struct lws_threadpool *tp, const struct lws_threadpool_task_args *args, @@ -911,6 +941,10 @@ lws_threadpool_enqueue(struct lws_threadpool *tp, if (tp->destroying) return NULL; +#if defined(LWS_WITH_SECURE_STREAMS) + assert(args->ss || args->wsi); +#endif + pthread_mutex_lock(&tp->lock); /* ======================== tpool lock */ /* @@ -957,10 +991,15 @@ lws_threadpool_enqueue(struct lws_threadpool *tp, * whatever reason can clean up) */ - args->wsi->tp_task = task; +#if defined(LWS_WITH_SECURE_STREAMS) + if (args->ss) + args->ss->wsi->tp_task = task; + else +#endif + args->wsi->tp_task = task; lwsl_thread("%s: tp %s: enqueued task %p (%s) for wsi %p, depth %d\n", - __func__, tp->name, task, task->name, args->wsi, + __func__, tp->name, task, task->name, task_to_wsi(task), tp->queue_depth); /* alert any idle thread there's something new on the task list */ @@ -1007,6 +1046,18 @@ lws_threadpool_task_status_wsi(struct lws *wsi, return status; } +#if defined(LWS_WITH_SECURE_STREAMS) +enum lws_threadpool_task_status +lws_threadpool_task_status_ss(struct lws_ss_handle *ss, + struct lws_threadpool_task **task, void **user) +{ + if (ss) + return lws_threadpool_task_status_wsi(ss->wsi, task, user); + + return -1; +} +#endif + void lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop) { -- Gitee From ed837acda0b887a31a57035a604b1598f0f0acf8 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 18 Mar 2020 12:19:51 +0000 Subject: [PATCH 0019/1062] lws_set_wsi_user: allow setting to override existing internal allocation --- lib/core-net/wsi.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index 21305253..ab3fee3e 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -637,14 +637,11 @@ lws_wsi_user(struct lws *wsi) void lws_set_wsi_user(struct lws *wsi, void *data) { - /* client and user owns it... */ - if (wsi->user_space_externally_allocated || - /* server, and protocol can never own it, user can control it... */ - (wsi->protocol && !wsi->protocol->per_session_data_size)) - wsi->user_space = data; - else - lwsl_err("%s: Cannot set internally-allocated user_space\n", - __func__); + if (!wsi->user_space_externally_allocated && wsi->user_space) + lws_free(wsi->user_space); + + wsi->user_space_externally_allocated = 1; + wsi->user_space = data; } struct lws * -- Gitee From c6165f8680f33f9635e722ef5470cf05e50729ea Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 18 Mar 2020 12:20:41 +0000 Subject: [PATCH 0020/1062] lws_spawn: get result to temp si We pass the temp si to the reap callback, we delete the lsp one beforehand. But we were collecting the spawn retcode into the lsp one... --- lib/misc/spawn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/misc/spawn.c b/lib/misc/spawn.c index d219a117..e8ce6dff 100644 --- a/lib/misc/spawn.c +++ b/lib/misc/spawn.c @@ -188,7 +188,7 @@ lws_spawn_reap(struct lws_spawn_piped *lsp) } temp = *lsp; - waitid(P_PID, lsp->child_pid, &lsp->si, WEXITED | WNOHANG); + waitid(P_PID, lsp->child_pid, &temp.si, WEXITED | WNOHANG); lsp->child_pid = -1; /* destroy the lsp itself first (it's freed and plsp set NULL */ -- Gitee From b95ff02f53e61ffab311504157b0b4bed2910d8e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 19 Mar 2020 10:04:33 +0000 Subject: [PATCH 0021/1062] example: convert ws ping example to use validity --- .../minimal-ws-client-ping/README.md | 103 ++++++++++++--- .../minimal-ws-client-ping.c | 124 +++--------------- 2 files changed, 109 insertions(+), 118 deletions(-) diff --git a/minimal-examples/ws-client/minimal-ws-client-ping/README.md b/minimal-examples/ws-client/minimal-ws-client-ping/README.md index 014e67a2..4cfc0ec6 100644 --- a/minimal-examples/ws-client/minimal-ws-client-ping/README.md +++ b/minimal-examples/ws-client/minimal-ws-client-ping/README.md @@ -2,7 +2,8 @@ This connects to libwebsockets.org using the lws-mirror-protocol. -It then sends a ws PING every 5s and records any PONG coming back. +It sets a validity regime of testing validity with PING every 3s and failing +if it didn't get the PONG back within 10s. ## build @@ -14,12 +15,10 @@ It then sends a ws PING every 5s and records any PONG coming back. Option|Meaning ---|--- --d|Set logging verbosity +-d|Set logging verbosity (you want 1039 to see the validity ping / pong) --server|Use a specific server instead of libwebsockets.org, eg `--server localhost`. Implies LCCSCF_ALLOW_SELFSIGNED --port|Use a specific port instead of 443, eg `--port 7681` --z|Send zero-length pings for testing --protocol|Use a specific ws subprotocol rather than lws-mirror-protocol, eg, `--protocol myprotocol` --v|Connection validity use 3s / 10s instead of default 5m / 5m10s ## usage @@ -28,17 +27,91 @@ Just run it, wait for the connect and then there will be PINGs sent at 5s intervals. ``` - $ ./lws-minimal-ws-client-ping -[2018/05/09 16:55:03:1160] USER: LWS minimal ws client PING -[2018/05/09 16:55:03:1379] NOTICE: Creating Vhost 'default' (serving disabled), 1 protocols, IPv6 off -[2018/05/09 16:55:03:1715] NOTICE: client loaded CA for verification ./libwebsockets.org.cer -[2018/05/09 16:55:03:1717] NOTICE: created client ssl context for default -[2018/05/09 16:55:04:8332] USER: callback_minimal_broker: established -[2018/05/09 16:55:09:8389] USER: Sending PING 10... -[2018/05/09 16:55:10:1491] USER: LWS_CALLBACK_CLIENT_RECEIVE_PONG -[2018/05/09 16:55:10:1494] NOTICE: -[2018/05/09 16:55:10:1514] NOTICE: 0000: 70 69 6E 67 20 62 6F 64 79 21 ping body! -[2018/05/09 16:55:10:1515] NOTICE: + $ ./lws-minimal-ws-client-ping -d1039 +[2020/03/18 13:13:47:1114] U: LWS minimal ws client PING +[2020/03/18 13:13:47:1503] I: Initial logging level 1039 +[2020/03/18 13:13:47:1507] I: Libwebsockets version: 4.0.99 v4.0.0-20-gc6165f868 +[2020/03/18 13:13:47:1508] I: IPV6 not compiled in +[2020/03/18 13:13:47:1512] I: LWS_DEF_HEADER_LEN : 4096 +[2020/03/18 13:13:47:1514] I: LWS_MAX_SMP : 1 +[2020/03/18 13:13:47:1519] I: sizeof (*info) : 720 +[2020/03/18 13:13:47:1520] I: SYSTEM_RANDOM_FILEPATH: '/dev/urandom' +[2020/03/18 13:13:47:1522] I: HTTP2 support : available +[2020/03/18 13:13:47:1552] N: lws_create_context: using ss proxy bind '(null)', port 0, ads '(null)' +[2020/03/18 13:13:47:1557] I: context created +[2020/03/18 13:13:47:1575] I: Using event loop: poll +[2020/03/18 13:13:47:1583] I: Default ALPN advertisment: h2,http/1.1 +[2020/03/18 13:13:47:1585] I: default timeout (secs): 20 +[2020/03/18 13:13:47:1614] I: Threads: 1 each 5 fds +[2020/03/18 13:13:47:1623] I: mem: context: 8152 B (4056 ctx + (1 thr x 4096)) +[2020/03/18 13:13:47:1625] I: mem: http hdr size: (4096 + 976), max count 5 +[2020/03/18 13:13:47:1629] I: mem: pollfd map: 40 B +[2020/03/18 13:13:47:1633] I: mem: platform fd map: 40 B +[2020/03/18 13:13:47:1692] I: Compiled with OpenSSL support +[2020/03/18 13:13:47:1695] I: Doing SSL library init +[2020/03/18 13:13:47:3103] I: canonical_hostname = constance +[2020/03/18 13:13:47:3140] I: Creating Vhost 'default' (serving disabled), 4 protocols, IPv6 off +[2020/03/18 13:13:47:4072] I: lws_tls_client_create_vhost_context: vh default: created new client ctx 0 +[2020/03/18 13:13:47:7468] I: created client ssl context for default +[2020/03/18 13:13:47:7482] I: Creating Vhost 'default' (serving disabled), 4 protocols, IPv6 off +[2020/03/18 13:13:47:7490] I: lws_tls_client_create_vhost_context: vh default: reusing client ctx 0: use 2 +[2020/03/18 13:13:47:7491] I: created client ssl context for default +[2020/03/18 13:13:47:7494] I: mem: per-conn: 792 bytes + protocol rx buf +[2020/03/18 13:13:47:7497] I: lws_plat_drop_app_privileges: not changing group +[2020/03/18 13:13:47:7499] I: lws_plat_drop_app_privileges: not changing user +[2020/03/18 13:13:47:7512] I: lws_cancel_service +[2020/03/18 13:13:47:7568] I: lws_state_notify_protocol_init: LWS_SYSTATE_CPD_PRE_TIME +[2020/03/18 13:13:47:7577] N: lws_ss_create: unknown stream type captive_portal_detect +[2020/03/18 13:13:47:7580] I: lws_ss_sys_cpd: Create stream failed (policy?) +[2020/03/18 13:13:47:7582] I: lws_state_notify_protocol_init: LWS_SYSTATE_CPD_PRE_TIME +[2020/03/18 13:13:47:7582] N: lws_ss_create: unknown stream type captive_portal_detect +[2020/03/18 13:13:47:7583] I: lws_ss_sys_cpd: Create stream failed (policy?) +[2020/03/18 13:13:47:7585] I: lws_state_notify_protocol_init: doing protocol init on POLICY_VALID +[2020/03/18 13:13:47:7588] I: lws_protocol_init +[2020/03/18 13:13:47:7623] I: lws_state_transition_steps: CONTEXT_CREATED -> OPERATIONAL +[2020/03/18 13:13:47:7628] N: connect_cb: connecting +[2020/03/18 13:13:47:7656] I: lws_client_connect_via_info: role binding to h1 +[2020/03/18 13:13:47:7662] I: lws_client_connect_via_info: protocol binding to lws-ping-test +[2020/03/18 13:13:47:7699] I: lws_client_connect_via_info: wsi 0x5669090: h1 lws-ping-test entry +[2020/03/18 13:13:47:7720] I: lws_header_table_attach: wsi 0x5669090: ah (nil) (tsi 0, count = 0) in +[2020/03/18 13:13:47:7729] I: _lws_create_ah: created ah 0x5669620 (size 4096): pool length 1 +[2020/03/18 13:13:47:7735] I: lws_header_table_attach: did attach wsi 0x5669090: ah 0x5669620: count 1 (on exit) +[2020/03/18 13:13:47:7780] I: lws_client_connect_2_dnsreq: 0x5669090: lookup libwebsockets.org:443 +[2020/03/18 13:13:47:8784] I: lws_getaddrinfo46: getaddrinfo 'libwebsockets.org' says 0 +[2020/03/18 13:13:47:8804] I: lws_client_connect_3_connect: libwebsockets.org ipv4 46.105.127.147 +[2020/03/18 13:13:47:9176] I: lws_client_connect_3_connect: getsockopt check: conn OK +[2020/03/18 13:13:47:9179] I: lws_client_connect_3_connect: Connection started 0x5682cc0 +[2020/03/18 13:13:47:9197] I: lws_client_connect_4_established: wsi 0x5669090: h1 lws-ping-test client created own conn (raw 0) vh defaultm st 0x202 +[2020/03/18 13:13:47:9418] I: h1 client conn using alpn list 'http/1.1' +[2020/03/18 13:13:48:4523] I: lws_role_call_alpn_negotiated: 'http/1.1' +[2020/03/18 13:13:48:4531] I: client connect OK +[2020/03/18 13:13:48:4543] I: lws_openssl_describe_cipher: wsi 0x5669090: TLS_AES_256_GCM_SHA384, TLS_AES_256_GCM_SHA384, 256 bits, TLSv1.3 +[2020/03/18 13:13:48:4717] I: lws_client_socket_service: HANDSHAKE2: 0x5669090: sending headers (wsistate 0x10000204), w sock 5 +[2020/03/18 13:13:48:4992] I: lws_buflist_aware_read: wsi 0x5669090: lws_client_socket_service: ssl_capable_read -4 +[2020/03/18 13:13:48:5005] I: lws_buflist_aware_read: wsi 0x5669090: lws_client_socket_service: ssl_capable_read 174 +[2020/03/18 13:13:48:5166] I: __lws_header_table_detach: wsi 0x5669090: ah 0x5669620 (tsi=0, count = 1) +[2020/03/18 13:13:48:5171] I: __lws_header_table_detach: nobody usable waiting +[2020/03/18 13:13:48:5175] I: _lws_destroy_ah: freed ah 0x5669620 : pool length 0 +[2020/03/18 13:13:48:5180] I: __lws_header_table_detach: wsi 0x5669090: ah 0x5669620 (tsi=0, count = 0) +[2020/03/18 13:13:48:5197] I: _lws_validity_confirmed_role: wsi 0x5669090: setting validity timer 3s (hup 0) +[2020/03/18 13:13:48:5208] U: callback_minimal_broker: established +[2020/03/18 13:13:51:5218] I: lws_validity_cb: wsi 0x5669090: scheduling validity check +[2020/03/18 13:13:51:5325] I: rops_handle_POLLOUT_ws: issuing ping on wsi 0x5669090: ws lws-ping-test h2: 0 +[2020/03/18 13:13:51:5504] I: lws_issue_raw: ssl_capable_write (6) says 6 +[2020/03/18 13:13:51:5809] I: lws_ws_client_rx_sm: client 0x5669090 received pong +[2020/03/18 13:13:51:5819] I: _lws_validity_confirmed_role: wsi 0x5669090: setting validity timer 3s (hup 0) +[2020/03/18 13:13:51:5831] I: Client doing pong callback +[2020/03/18 13:13:54:5821] I: lws_validity_cb: wsi 0x5669090: scheduling validity check +[2020/03/18 13:13:54:5825] I: rops_handle_POLLOUT_ws: issuing ping on wsi 0x5669090: ws lws-ping-test h2: 0 +[2020/03/18 13:13:54:5833] I: lws_issue_raw: ssl_capable_write (6) says 6 +[2020/03/18 13:13:54:6258] I: lws_ws_client_rx_sm: client 0x5669090 received pong +[2020/03/18 13:13:54:6261] I: _lws_validity_confirmed_role: wsi 0x5669090: setting validity timer 3s (hup 0) +[2020/03/18 13:13:54:6263] I: Client doing pong callback +[2020/03/18 13:13:57:6263] I: lws_validity_cb: wsi 0x5669090: scheduling validity check +[2020/03/18 13:13:57:6267] I: rops_handle_POLLOUT_ws: issuing ping on wsi 0x5669090: ws lws-ping-test h2: 0 +[2020/03/18 13:13:57:6275] I: lws_issue_raw: ssl_capable_write (6) says 6 +[2020/03/18 13:13:58:0034] I: lws_ws_client_rx_sm: client 0x5669090 received pong + ... ``` diff --git a/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c b/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c index 63279ff2..a8589f0e 100644 --- a/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c +++ b/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c @@ -1,13 +1,14 @@ /* * lws-minimal-ws-client-ping * - * Written in 2010-2019 by Andy Green + * Written in 2010-2020 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. * - * This demonstrates a ws client that sends pings from time to time and - * shows when it receives the PONG + * This demonstrates keeping a ws connection validated by the lws validity + * timer stuff without having to do anything in the code. Use debug logging + * -d1039 to see lws doing the pings / pongs in the background. */ #include @@ -17,24 +18,22 @@ static struct lws_context *context; static struct lws *client_wsi; -static int interrupted, zero_length_ping, port = 443, quick_pings, no_user_ping, - ssl_connection = LCCSCF_USE_SSL; +static int interrupted, port = 443, ssl_connection = LCCSCF_USE_SSL; static const char *server_address = "libwebsockets.org", *pro = "lws-mirror-protocol"; - -struct pss { - int send_a_ping; -}; +static lws_sorted_usec_list_t sul; static const lws_retry_bo_t retry = { .secs_since_valid_ping = 3, .secs_since_valid_hangup = 10, }; -static int -connect_client(void) +static void +connect_cb(lws_sorted_usec_list_t *_sul) { struct lws_client_connect_info i; + lwsl_notice("%s: connecting\n", __func__); + memset(&i, 0, sizeof(i)); i.context = context; @@ -45,95 +44,30 @@ connect_client(void) i.origin = i.address; i.ssl_connection = ssl_connection; i.protocol = pro; + i.alpn = "h2;http/1.1"; i.local_protocol_name = "lws-ping-test"; i.pwsi = &client_wsi; - if (quick_pings) - i.retry_and_idle_policy = &retry; + i.retry_and_idle_policy = &retry; - return !lws_client_connect_via_info(&i); + if (!lws_client_connect_via_info(&i)) + lws_sul_schedule(context, 0, _sul, connect_cb, 5 * LWS_USEC_PER_SEC); } static int -callback_minimal_broker(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) +callback_minimal_pingtest(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) { - struct pss *pss = (struct pss *)user; - int n; switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: - goto try; - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); - client_wsi = NULL; - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), LWS_CALLBACK_USER, 1); + lws_sul_schedule(context, 0, &sul, connect_cb, 5 * LWS_USEC_PER_SEC); break; - /* --- client callbacks --- */ - case LWS_CALLBACK_CLIENT_ESTABLISHED: lwsl_user("%s: established\n", __func__); - lws_set_timer_usecs(wsi, 5 * LWS_USEC_PER_SEC); - break; - - case LWS_CALLBACK_CLIENT_WRITEABLE: - if (pss->send_a_ping) { - uint8_t ping[LWS_PRE + 125]; - int m; - - pss->send_a_ping = 0; - n = 0; - if (!zero_length_ping) - n = lws_snprintf((char *)ping + LWS_PRE, 125, - "ping body!"); - - lwsl_user("Sending PING %d...\n", n); - - m = lws_write(wsi, ping + LWS_PRE, n, LWS_WRITE_PING); - if (m < n) { - lwsl_err("sending ping failed: %d\n", m); - - return -1; - } - - lws_callback_on_writable(wsi); - } - break; - - case LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL: - client_wsi = NULL; - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); - break; - - case LWS_CALLBACK_CLIENT_RECEIVE_PONG: - lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE_PONG\n"); - lwsl_hexdump_notice(in, len); - break; - - case LWS_CALLBACK_TIMER: - if (no_user_ping) - break; - /* we want to send a ws PING every few seconds */ - pss->send_a_ping = 1; - lws_callback_on_writable(wsi); - lws_set_timer_usecs(wsi, 10 * LWS_USEC_PER_SEC); - break; - - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); -try: - if (connect_client()) - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); break; default: @@ -146,8 +80,8 @@ try: static const struct lws_protocols protocols[] = { { "lws-ping-test", - callback_minimal_broker, - sizeof(struct pss), + callback_minimal_pingtest, + 0, 0, }, { NULL, NULL, 0, 0 } @@ -191,12 +125,6 @@ int main(int argc, const char **argv) info.client_ssl_ca_filepath = "./libwebsockets.org.cer"; #endif - if (lws_cmdline_option(argc, argv, "-z")) - zero_length_ping = 1; - - if (lws_cmdline_option(argc, argv, "-n")) - no_user_ping = 1; - if ((p = lws_cmdline_option(argc, argv, "--protocol"))) pro = p; @@ -209,18 +137,6 @@ int main(int argc, const char **argv) if ((p = lws_cmdline_option(argc, argv, "--port"))) port = atoi(p); - /* the default validity check is 5m / 5m10s... -v = 5s / 10s */ - - if (lws_cmdline_option(argc, argv, "-v")) - quick_pings = 1; - - /* - * since we know this lws context is only ever going to be used with - * one client wsis / fds / sockets at a time, let lws know it doesn't - * have to use the default allocations for fd tables up to ulimit -n. - * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we - * will use. - */ info.fd_limit_per_thread = 1 + 1 + 1; context = lws_create_context(&info); @@ -229,6 +145,8 @@ int main(int argc, const char **argv) return 1; } + lws_sul_schedule(context, 0, &sul, connect_cb, 100); + while (n >= 0 && !interrupted) n = lws_service(context, 0); -- Gitee From 11837db0e0ba0a9d5b919e40fbe100453a0b9582 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 19 Mar 2020 10:14:25 +0000 Subject: [PATCH 0022/1062] mbedtls: support older versions without net_sockets.h --- CMakeLists.txt | 4 ++++ cmake/lws_config.h.in | 1 + lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dd4cbcc..9c04250f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2228,6 +2228,10 @@ endif() CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE\n#include \nint main(void) {int fd[2];\n return pipe2(fd, 0);\n}\n" LWS_HAVE_PIPE2) +# old mbedtls has everything in mbedtls/net.h + +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return 0;}\n" LWS_HAVE_MBEDTLS_NET_SOCKETS) + # tcp keepalive needs this on linux to work practically... but it only exists # after kernel 2.6.37 diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 56691a30..ecfd8f4d 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -53,6 +53,7 @@ #cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_ca_chain #cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_own_cert #cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_authmode +#cmakedefine LWS_HAVE_MBEDTLS_NET_SOCKETS #cmakedefine LWS_HAVE_NEW_UV_VERSION_H #cmakedefine LWS_HAVE_OPENSSL_ECDH_H #cmakedefine LWS_HAVE_PIPE2 diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 776abf57..15f2b962 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -18,7 +18,11 @@ /* mbedtls include */ #include "mbedtls/platform.h" +#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) #include "mbedtls/net_sockets.h" +#else +#include "mbedtls/net.h" +#endif #include "mbedtls/debug.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" -- Gitee From 93d6ab929b01ef2f62caec3061166e5027196d2d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 19 Mar 2020 14:05:18 +0000 Subject: [PATCH 0023/1062] ss: reduce logging of unknown streamtypes There are a few automatic things that look for streamtypes that may or may not exist now - captive_portal_detect - fetch_policy - api_amazon_com_auth logging them as notice every startup is pretty intrusive, change to info. --- lib/secure-streams/secure-streams.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 407137f2..743d7beb 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -350,8 +350,8 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, pol = lws_ss_policy_lookup(context, ssi->streamtype); if (!pol) { - lwsl_notice("%s: unknown stream type %s\n", __func__, - ssi->streamtype); + lwsl_info("%s: unknown stream type %s\n", __func__, + ssi->streamtype); return 1; } -- Gitee From 44fa7e39e32682a4a3f5d83f7dff4c1e0802191e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 19 Mar 2020 14:34:29 +0000 Subject: [PATCH 0024/1062] lws_dir: uv: clean up temp loop on fail --- lib/misc/dir.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/misc/dir.c b/lib/misc/dir.c index 4c8ca64f..5c4b00cf 100644 --- a/lib/misc/dir.c +++ b/lib/misc/dir.c @@ -48,25 +48,28 @@ lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) ir = uv_loop_init(&loop); if (ir) { lwsl_err("%s: loop init failed %d\n", __func__, ir); + return 1; } ir = uv_fs_scandir(&loop, &req, dirpath, 0, NULL); if (ir < 0) { lwsl_err("Scandir on %s failed, errno %d\n", dirpath, LWS_ERRNO); - return 2; + ret = 2; + goto bail; } while (uv_fs_scandir_next(&req, &dent) != UV_EOF) { lde.name = dent.name; lde.type = (int)dent.type; if (cb(dirpath, user, &lde)) - goto bail; + goto bail1; } ret = 0; -bail: +bail1: uv_fs_req_cleanup(&req); +bail: while (uv_loop_close(&loop)) ; -- Gitee From 5c657e0865251a8efb7585d962d431e1d78719eb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 20 Mar 2020 09:35:54 +0000 Subject: [PATCH 0025/1062] wolfssl: build fixes Solve wolfssl wrappers being defines and header path availability for cmake tests --- CMakeLists.txt | 54 +++++++++++++++++--------------- lib/tls/openssl/openssl-client.c | 15 ++++++++- lib/tls/openssl/openssl-ssl.c | 2 +- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c04250f..1daf7b84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1954,13 +1954,17 @@ if (LWS_WITH_SSL) if (LWS_WITH_CYASSL) foreach(inc ${WOLFSSL_INCLUDE_DIRS}) + set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/cyassl) include_directories("${inc}" "${inc}/cyassl") endforeach() else() foreach(inc ${WOLFSSL_INCLUDE_DIRS}) + set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/wolfssl) include_directories("${inc}" "${inc}/wolfssl") endforeach() endif() + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) + set(VARIA wolfSSL_) list(APPEND LIB_LIST "${WOLFSSL_LIBRARIES}") set(chose_ssl 1) @@ -2174,35 +2178,35 @@ if (LWS_WITH_ZLIB) endif() endif() -CHECK_FUNCTION_EXISTS(SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param) -CHECK_FUNCTION_EXISTS(SSL_set_info_callback LWS_HAVE_SSL_SET_INFO_CALLBACK) -CHECK_FUNCTION_EXISTS(X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host) -CHECK_FUNCTION_EXISTS(RSA_set0_key LWS_HAVE_RSA_SET0_KEY) -CHECK_FUNCTION_EXISTS(X509_get_key_usage LWS_HAVE_X509_get_key_usage) -CHECK_FUNCTION_EXISTS(EVP_PKEY_new_raw_private_key LWS_HAVE_SSL_CTX_EVP_PKEY_new_raw_private_key) -CHECK_FUNCTION_EXISTS(SSL_CTX_get0_certificate LWS_HAVE_SSL_CTX_get0_certificate) -CHECK_FUNCTION_EXISTS(SSL_get0_alpn_selected LWS_HAVE_SSL_get0_alpn_selected) -CHECK_FUNCTION_EXISTS(SSL_set_alpn_protos LWS_HAVE_SSL_set_alpn_protos) -CHECK_FUNCTION_EXISTS(EVP_aes_128_cfb8 LWS_HAVE_EVP_aes_128_cfb8) -CHECK_FUNCTION_EXISTS(EVP_aes_128_cfb128 LWS_HAVE_EVP_aes_128_cfb128) -CHECK_FUNCTION_EXISTS(EVP_aes_192_cfb8 LWS_HAVE_EVP_aes_192_cfb8) -CHECK_FUNCTION_EXISTS(EVP_aes_192_cfb128 LWS_HAVE_EVP_aes_192_cfb128) -CHECK_FUNCTION_EXISTS(EVP_aes_256_cfb8 LWS_HAVE_EVP_aes_256_cfb8) -CHECK_FUNCTION_EXISTS(EVP_aes_256_cfb128 LWS_HAVE_EVP_aes_256_cfb128) -CHECK_FUNCTION_EXISTS(EVP_aes_128_xts LWS_HAVE_EVP_aes_128_xts) -CHECK_FUNCTION_EXISTS(RSA_verify_pss_mgf1 LWS_HAVE_RSA_verify_pss_mgf1) -CHECK_FUNCTION_EXISTS(HMAC_CTX_new LWS_HAVE_HMAC_CTX_new) -CHECK_FUNCTION_EXISTS(SSL_CTX_set_ciphersuites LWS_HAVE_SSL_CTX_set_ciphersuites) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_info_callback LWS_HAVE_SSL_SET_INFO_CALLBACK) +CHECK_FUNCTION_EXISTS(${VARIA}X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host) +CHECK_FUNCTION_EXISTS(${VARIA}RSA_set0_key LWS_HAVE_RSA_SET0_KEY) +CHECK_FUNCTION_EXISTS(${VARIA}X509_get_key_usage LWS_HAVE_X509_get_key_usage) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_PKEY_new_raw_private_key LWS_HAVE_SSL_CTX_EVP_PKEY_new_raw_private_key) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_get0_certificate LWS_HAVE_SSL_CTX_get0_certificate) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_get0_alpn_selected LWS_HAVE_SSL_get0_alpn_selected) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_alpn_protos LWS_HAVE_SSL_set_alpn_protos) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb8 LWS_HAVE_EVP_aes_128_cfb8) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb128 LWS_HAVE_EVP_aes_128_cfb128) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb8 LWS_HAVE_EVP_aes_192_cfb8) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb128 LWS_HAVE_EVP_aes_192_cfb128) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb8 LWS_HAVE_EVP_aes_256_cfb8) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb128 LWS_HAVE_EVP_aes_256_cfb128) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_xts LWS_HAVE_EVP_aes_128_xts) +CHECK_FUNCTION_EXISTS(${VARIA}RSA_verify_pss_mgf1 LWS_HAVE_RSA_verify_pss_mgf1) +CHECK_FUNCTION_EXISTS(${VARIA}HMAC_CTX_new LWS_HAVE_HMAC_CTX_new) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set_ciphersuites LWS_HAVE_SSL_CTX_set_ciphersuites) if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) if (UNIX) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) endif() CHECK_C_SOURCE_COMPILES("#include \nint main(void) { STACK_OF(X509) *c = NULL; SSL_CTX *ctx = NULL; return (int)SSL_CTX_get_extra_chain_certs_only(ctx, &c); }\n" LWS_HAVE_SSL_EXTRA_CHAIN_CERTS) CHECK_C_SOURCE_COMPILES("#include \nint main(void) { EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX_free(md_ctx); return 0; }\n" LWS_HAVE_EVP_MD_CTX_free) -CHECK_FUNCTION_EXISTS(ECDSA_SIG_set0 LWS_HAVE_ECDSA_SIG_set0) -CHECK_FUNCTION_EXISTS(BN_bn2binpad LWS_HAVE_BN_bn2binpad) -CHECK_FUNCTION_EXISTS(EVP_aes_128_wrap LWS_HAVE_EVP_aes_128_wrap) -CHECK_FUNCTION_EXISTS(EC_POINT_get_affine_coordinates LWS_HAVE_EC_POINT_get_affine_coordinates) +CHECK_FUNCTION_EXISTS(${VARIA}ECDSA_SIG_set0 LWS_HAVE_ECDSA_SIG_set0) +CHECK_FUNCTION_EXISTS(${VARIA}BN_bn2binpad LWS_HAVE_BN_bn2binpad) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_wrap LWS_HAVE_EVP_aes_128_wrap) +CHECK_FUNCTION_EXISTS(${VARIA}EC_POINT_get_affine_coordinates LWS_HAVE_EC_POINT_get_affine_coordinates) endif() if (LWS_WITH_MBEDTLS) set(LWS_HAVE_TLS_CLIENT_METHOD 1) @@ -2220,8 +2224,8 @@ if (LWS_WITH_MBEDTLS) CHECK_FUNCTION_EXISTS(mbedtls_net_init LWS_HAVE_mbedtls_net_init) else() -CHECK_FUNCTION_EXISTS(TLS_client_method LWS_HAVE_TLS_CLIENT_METHOD) -CHECK_FUNCTION_EXISTS(TLSv1_2_client_method LWS_HAVE_TLSV1_2_CLIENT_METHOD) +CHECK_FUNCTION_EXISTS(${VARIA}TLS_client_method LWS_HAVE_TLS_CLIENT_METHOD) +CHECK_FUNCTION_EXISTS(${VARIA}TLSv1_2_client_method LWS_HAVE_TLSV1_2_CLIENT_METHOD) endif() # ideally we want to use pipe2() diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 7d435806..9a258b10 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -189,9 +189,11 @@ lws_ssl_client_bio_create(struct lws *wsi) if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { X509_VERIFY_PARAM *param = SSL_get0_param(wsi->tls.ssl); +#if !defined(USE_WOLFSSL) /* Enable automatic hostname checks */ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); +#endif // Handle the case where the hostname is an IP address. if (!X509_VERIFY_PARAM_set1_ip_asc(param, hostname)) X509_VERIFY_PARAM_set1_host(param, hostname, 0); @@ -313,7 +315,11 @@ lws_ssl_client_bio_create(struct lws *wsi) if (lws_system_blob_get_single_ptr(b, &data)) goto no_client_cert; - if (SSL_use_certificate_ASN1(wsi->tls.ssl, data, (int)size) != 1) { + if (SSL_use_certificate_ASN1(wsi->tls.ssl, +#if defined(USE_WOLFSSL) + (unsigned char *) +#endif + data, (int)size) != 1) { lwsl_err("%s: use_certificate failed\n", __func__); lws_tls_err_describe_clear(); goto no_client_cert; @@ -333,8 +339,15 @@ lws_ssl_client_bio_create(struct lws *wsi) goto no_client_cert; if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, wsi->tls.ssl, +#if defined(USE_WOLFSSL) + (unsigned char *) +#endif + data, (int)size) != 1 && SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, wsi->tls.ssl, +#if defined(USE_WOLFSSL) + (unsigned char *) +#endif data, (int)size) != 1) { lwsl_err("%s: use_privkey failed\n", __func__); lws_tls_err_describe_clear(); diff --git a/lib/tls/openssl/openssl-ssl.c b/lib/tls/openssl/openssl-ssl.c index 2a6ff952..1f2fd825 100644 --- a/lib/tls/openssl/openssl-ssl.c +++ b/lib/tls/openssl/openssl-ssl.c @@ -36,7 +36,7 @@ int openssl_websocket_private_data_index, int lws_openssl_describe_cipher(struct lws *wsi) { -#if !defined(LWS_WITH_NO_LOGS) +#if !defined(LWS_WITH_NO_LOGS) && !defined(USE_WOLFSSL) int np = -1; SSL *s = wsi->tls.ssl; -- Gitee From 54029c48967063316f2553a51843eb961c9b31f9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 20 Mar 2020 19:44:10 +0000 Subject: [PATCH 0026/1062] lws_struct: sqlite: order defaults to _lws_idx but may be overridden The internal order that a dll2 of structs was written might or might not be what the guy deserializing it cares about --- lib/misc/lws-struct-sqlite.c | 7 +++++-- lib/misc/threadpool/threadpool.c | 31 +++++++++++++++++-------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/lib/misc/lws-struct-sqlite.c b/lib/misc/lws-struct-sqlite.c index b0599681..327537c1 100644 --- a/lib/misc/lws-struct-sqlite.c +++ b/lib/misc/lws-struct-sqlite.c @@ -185,6 +185,9 @@ lws_struct_sq3_deserialize(sqlite3 *pdb, const char *filter, const char *order, lws_struct_args_t a; int limit = _limit < 0 ? -_limit : _limit; + if (!order) + order = "_lws_idx"; + memset(&a, 0, sizeof(a)); a.cb_arg = o; /* lws_dll2_owner tracking query result objects */ a.map_st[0] = schema->child_map; @@ -199,8 +202,8 @@ lws_struct_sq3_deserialize(sqlite3 *pdb, const char *filter, const char *order, (unsigned long long)start, filter ? filter : ""); lws_snprintf(s, sizeof(s) - 1, "select * " - "from %s %s order by _lws_idx%s %slimit %d;", - schema->colname, where, order ? order : "", + "from %s %s order by %s %slimit %d;", + schema->colname, where, order, _limit < 0 ? "desc " : "", limit); if (sqlite3_exec(pdb, s, lws_struct_sq3_deser_cb, &a, NULL) != SQLITE_OK) { diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index f12d980c..e5394fbe 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -265,25 +265,28 @@ __lws_threadpool_reap(struct lws_threadpool_task *task) /* remove the task from the done queue */ - c = &tp->task_done_head; + if (tp) { + c = &tp->task_done_head; - while (*c) { - if ((*c) == task) { - t = *c; - *c = t->task_queue_next; - t->task_queue_next = NULL; - tp->done_queue_depth--; + while (*c) { + if ((*c) == task) { + t = *c; + *c = t->task_queue_next; + t->task_queue_next = NULL; + tp->done_queue_depth--; - lwsl_thread("%s: tp %s: reaped task wsi %p\n", __func__, - tp->name, task_to_wsi(task)); + lwsl_thread("%s: tp %s: reaped task wsi %p\n", __func__, + tp->name, task_to_wsi(task)); - break; + break; + } + c = &(*c)->task_queue_next; } - c = &(*c)->task_queue_next; - } - if (!t) - lwsl_err("%s: task %p not in done queue\n", __func__, task); + if (!t) + lwsl_err("%s: task %p not in done queue\n", __func__, task); + } else + lwsl_err("%s: task->tp NULL already\n", __func__); /* call the task's cleanup and delete the task itself */ -- Gitee From 6d5ebd237c16f3cebf790840b80abe1211c97c0d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 21 Mar 2020 13:12:25 +0000 Subject: [PATCH 0027/1062] threadpool: lack of task when getting status should be taken as FINISHED --- lib/misc/threadpool/threadpool.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index e5394fbe..6a4a38bc 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -1026,8 +1026,10 @@ lws_threadpool_task_status_wsi(struct lws *wsi, struct lws_threadpool *tp; *task = wsi->tp_task; - if (!*task) - return -1; + if (!*task) { + lwsl_notice("%s: wsi has NULL tp_task, ~=FINISHED\n", __func__); + return LWS_TP_STATUS_FINISHED; + } tp = (*task)->tp; *user = (*task)->args.user; -- Gitee From 47ea968e160acfc0add04f72b9b935153e838ab9 Mon Sep 17 00:00:00 2001 From: Akira Tsukamoto Date: Sat, 21 Mar 2020 14:37:19 +0900 Subject: [PATCH 0028/1062] jws: lws_gencrypto_jws_alg_to_definition needs sentinel Otherwise segfault when end of array reached. --- lib/tls/lws-gencrypto-common.c | 2 ++ 1 file changed, 2 insertions(+) mode change 100755 => 100644 lib/tls/lws-gencrypto-common.c diff --git a/lib/tls/lws-gencrypto-common.c b/lib/tls/lws-gencrypto-common.c old mode 100755 new mode 100644 index aaa7b74d..917a5f12 --- a/lib/tls/lws-gencrypto-common.c +++ b/lib/tls/lws-gencrypto-common.c @@ -238,6 +238,8 @@ static const struct lws_jose_jwe_alg lws_gencrypto_jws_alg_map[] = { "PS512", NULL, 2048, 4096, 0 }, #endif + /* list terminator */ + { 0, 0, 0, 0, NULL, NULL, 0, 0, 0} }; /* -- Gitee From 2a7a92f4d5cdebbcf26e5383c7a191e27e566b8d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 21 Mar 2020 10:20:05 +0000 Subject: [PATCH 0029/1062] mbedtls: support old 2.2-era version from xenial --- CMakeLists.txt | 4 +++- cmake/lws_config.h.in | 3 +++ lib/tls/mbedtls/lws-genaes.c | 7 +++++++ lib/tls/mbedtls/lws-genhash.c | 5 +++++ lib/tls/mbedtls/lws-genrsa.c | 17 +++++++++++++++++ 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1daf7b84..11b0d585 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2222,7 +2222,9 @@ if (LWS_WITH_MBEDTLS) CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_own_cert LWS_HAVE_mbedtls_ssl_set_hs_own_cert) CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_authmode LWS_HAVE_mbedtls_ssl_set_hs_authmode) CHECK_FUNCTION_EXISTS(mbedtls_net_init LWS_HAVE_mbedtls_net_init) - + CHECK_FUNCTION_EXISTS(mbedtls_md_setup LWS_HAVE_mbedtls_md_setup) # not on xenial 2.2 + CHECK_FUNCTION_EXISTS(mbedtls_rsa_complete LWS_HAVE_mbedtls_rsa_complete) # not on xenial 2.2 + CHECK_FUNCTION_EXISTS(mbedtls_internal_aes_encrypt LWS_HAVE_mbedtls_internal_aes_encrypt) # not on xenial 2.2 else() CHECK_FUNCTION_EXISTS(${VARIA}TLS_client_method LWS_HAVE_TLS_CLIENT_METHOD) CHECK_FUNCTION_EXISTS(${VARIA}TLSv1_2_client_method LWS_HAVE_TLSV1_2_CLIENT_METHOD) diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index ecfd8f4d..1af2f023 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -46,7 +46,10 @@ #cmakedefine LWS_HAVE_MALLOC_H #cmakedefine LWS_HAVE_MALLOC_TRIM #cmakedefine LWS_HAVE_MALLOC_USABLE_SIZE +#cmakedefine LWS_HAVE_mbedtls_md_setup #cmakedefine LWS_HAVE_mbedtls_net_init +#cmakedefine LWS_HAVE_mbedtls_rsa_complete +#cmakedefine LWS_HAVE_mbedtls_internal_aes_encrypt #cmakedefine LWS_HAVE_mbedtls_ssl_conf_alpn_protocols #cmakedefine LWS_HAVE_mbedtls_ssl_get_alpn_protocol #cmakedefine LWS_HAVE_mbedtls_ssl_conf_sni diff --git a/lib/tls/mbedtls/lws-genaes.c b/lib/tls/mbedtls/lws-genaes.c index d7766062..a74a1696 100644 --- a/lib/tls/mbedtls/lws-genaes.c +++ b/lib/tls/mbedtls/lws-genaes.c @@ -161,6 +161,7 @@ lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen) return 0; } +#if defined(LWS_HAVE_mbedtls_internal_aes_encrypt) static int lws_genaes_rfc3394_wrap(int wrap, int cek_bits, const uint8_t *kek, int kek_bits, const uint8_t *in, uint8_t *out) @@ -271,6 +272,7 @@ bail: return ret; } +#endif int lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len, @@ -282,6 +284,7 @@ lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len, switch (ctx->mode) { case LWS_GAESM_KW: +#if defined(LWS_HAVE_mbedtls_internal_aes_encrypt) /* a key of length ctx->k->len is wrapped by a 128-bit KEK */ n = lws_genaes_rfc3394_wrap(ctx->op == MBEDTLS_AES_ENCRYPT, ctx->op == MBEDTLS_AES_ENCRYPT ? len * 8 : @@ -289,6 +292,10 @@ lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len, ctx->k->len * 8, in, out); break; +#else + lwsl_err("%s: your mbedtls is too old\n", __func__); + return -1; +#endif case LWS_GAESM_CBC: memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16); diff --git a/lib/tls/mbedtls/lws-genhash.c b/lib/tls/mbedtls/lws-genhash.c index 396f8b13..a32d2152 100644 --- a/lib/tls/mbedtls/lws-genhash.c +++ b/lib/tls/mbedtls/lws-genhash.c @@ -148,8 +148,13 @@ lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, if (!ctx->hmac) return -1; +#if !defined(LWS_HAVE_mbedtls_md_setup) if (mbedtls_md_init_ctx(&ctx->ctx, ctx->hmac)) return -1; +#else + if (mbedtls_md_setup(&ctx->ctx, ctx->hmac, 1)) + return -1; +#endif if (mbedtls_md_hmac_starts(&ctx->ctx, key, key_len)) { mbedtls_md_free(&ctx->ctx); diff --git a/lib/tls/mbedtls/lws-genrsa.c b/lib/tls/mbedtls/lws-genrsa.c index 5b3b234a..5269d126 100644 --- a/lib/tls/mbedtls/lws-genrsa.c +++ b/lib/tls/mbedtls/lws-genrsa.c @@ -85,8 +85,13 @@ lws_genrsa_create(struct lws_genrsa_ctx *ctx, struct lws_gencrypto_keyelem *el, if ( el[LWS_GENCRYPTO_RSA_KEYEL_D].len && !el[LWS_GENCRYPTO_RSA_KEYEL_P].len && !el[LWS_GENCRYPTO_RSA_KEYEL_Q].len) { +#if defined(LWS_HAVE_mbedtls_rsa_complete) if (mbedtls_rsa_complete(ctx->ctx)) { lwsl_notice("mbedtls_rsa_complete failed\n"); +#else + { + lwsl_notice("%s: you have to provide P and Q\n", __func__); +#endif lws_free_set_NULL(ctx->ctx); return -1; @@ -176,7 +181,9 @@ lws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, ctx->ctx->len = in_len; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -214,7 +221,9 @@ lws_genrsa_private_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, ctx->ctx->len = in_len; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -249,7 +258,9 @@ lws_genrsa_public_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, { int n; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -284,7 +295,9 @@ lws_genrsa_private_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in, { int n; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -323,7 +336,9 @@ lws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in, if (h < 0) return -1; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif switch(ctx->mode) { case LGRSAM_PKCS1_1_5: @@ -358,7 +373,9 @@ lws_genrsa_hash_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in, if (h < 0) return -1; +#if defined(LWS_HAVE_mbedtls_rsa_complete) mbedtls_rsa_complete(ctx->ctx); +#endif /* * The "sig" buffer must be as large as the size of ctx->N -- Gitee From f684daefda55722e230fd45b1085091cc63f697a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 21 Mar 2020 15:20:41 +0000 Subject: [PATCH 0030/1062] glibc: support older versions Ubuntu Xenial's version lacks this helper define, add it if missing so it can build --- lib/event-libs/glib/glib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/event-libs/glib/glib.c b/lib/event-libs/glib/glib.c index 4adea145..ada7627d 100644 --- a/lib/event-libs/glib/glib.c +++ b/lib/event-libs/glib/glib.c @@ -26,6 +26,10 @@ #include +#if !defined(G_SOURCE_FUNC) +#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) +#endif + #define wsi_to_subclass(_w) ((_w)->w_read.glib.source) #define wsi_to_gsource(_w) ((GSource *)wsi_to_subclass(_w)) #define pt_to_loop(_pt) ((_pt)->glib.loop) -- Gitee From 6440521992879c34093407d00f7450985088ea10 Mon Sep 17 00:00:00 2001 From: Karl Rupp Date: Mon, 23 Mar 2020 11:26:23 +0100 Subject: [PATCH 0031/1062] http server: Using default filename also for subdirectories. If a user sets a default filename for a http mount (.def in lws_http_mount), eg. 'default.html', then a GET request for '/' correctly forwards to '/default.html'. However, without this commit the default filename is not taken into account for subdirectories. Thus, GET subdir/ will forward to 'subdir/index.html' instead of the expected 'subdir/default.html' This commit changes the behavior such that the user-provided default filename is also used for subdirectories. --- lib/roles/http/server/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index e6205c9c..0baba256 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -587,8 +587,8 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin, #endif if ((S_IFMT & st.st_mode) == S_IFDIR) { lwsl_debug("default filename append to dir\n"); - lws_snprintf(path, sizeof(path) - 1, "%s/%s/index.html", - origin, uri); + lws_snprintf(path, sizeof(path) - 1, "%s/%s/%s", + origin, uri, m->def ? m->def : "index.html"); } } while ((S_IFMT & st.st_mode) != S_IFREG && spin < 5); -- Gitee From c261f5a90e6c34bebc7af9d35643d07cd5e7973c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 24 Mar 2020 06:27:35 +0000 Subject: [PATCH 0032/1062] spawn: on OSX only waitpid can get return code --- lib/misc/spawn.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/misc/spawn.c b/lib/misc/spawn.c index e8ce6dff..f9c4a86f 100644 --- a/lib/misc/spawn.c +++ b/lib/misc/spawn.c @@ -188,7 +188,11 @@ lws_spawn_reap(struct lws_spawn_piped *lsp) } temp = *lsp; - waitid(P_PID, lsp->child_pid, &temp.si, WEXITED | WNOHANG); + n = waitid(P_PID, lsp->child_pid, &temp.si, WEXITED | WNOHANG); + temp.si.si_status &= 0xff; /* we use b8 + for flags */ + lwsl_notice("%s: waitd says %d, process exit %d\n", + __func__, n, temp.si.si_status); + lsp->child_pid = -1; /* destroy the lsp itself first (it's freed and plsp set NULL */ -- Gitee From 9b637c17b98107ff0e1232290e8fc3711bbcbf2b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 24 Mar 2020 12:31:02 +0000 Subject: [PATCH 0033/1062] glib: osx: brew symlink workaround --- lib/event-libs/glib/private-lib-event-libs-glib.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/event-libs/glib/private-lib-event-libs-glib.h b/lib/event-libs/glib/private-lib-event-libs-glib.h index b021ad6d..00bbf551 100644 --- a/lib/event-libs/glib/private-lib-event-libs-glib.h +++ b/lib/event-libs/glib/private-lib-event-libs-glib.h @@ -23,7 +23,11 @@ */ #if defined(LWS_WITH_GLIB) +#if defined(__APPLE__) +#include +#else #include +#endif #endif /* LWS_WITH_GLIB */ struct lws_pt_eventlibs_glib { -- Gitee From e783a6ca6e9504b9dc482e46aa881e378691b3cf Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 24 Mar 2020 18:59:36 +0000 Subject: [PATCH 0034/1062] minimal: rediscover event loop lib paths Building the examples may face the same situations as building lws with the same dependencies, bring over the same CMakeLists.txt approach --- .../CMakeLists.txt | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt index 748a6b84..2e3b6d65 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt @@ -76,13 +76,28 @@ CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defin if (LWS_WITH_LIBUV) - set(extralibs ${extralibs} uv) + find_path(LIBUV_INCLUDE_DIRS NAMES uv.h) + find_library(LIBUV_LIBRARIES NAMES uv) + message("libuv include dir: ${LIBUV_INCLUDE_DIRS}") + message("libuv libraries: ${LIBUV_LIBRARIES}") + include_directories("${LIBUV_INCLUDE_DIRS}") + set(extralibs ${extralibs} ${LIBUV_LIBRARIES}) endif() if (LWS_WITH_LIBEVENT) - set(extralibs ${extralibs} event) + find_path(LIBEVENT_INCLUDE_DIRS NAMES event2/event.h) + find_library(LIBEVENT_LIBRARIES NAMES event) + message("libevent include dir: ${LIBEVENT_INCLUDE_DIRS}") + message("libevent libraries: ${LIBEVENT_LIBRARIES}") + include_directories("${LIBEVENT_INCLUDE_DIRS}") + set(extralibs ${extralibs} ${LIBEVENT_LIBRARIES}) endif() if (LWS_WITH_LIBEV) - set(extralibs ${extralibs} ev) + find_path(LIBEV_INCLUDE_DIRS NAMES ev.h) + find_library(LIBEV_LIBRARIES NAMES ev) + message("libev include dir: ${LIBEV_INCLUDE_DIRS}") + message("libev libraries: ${LIBEV_LIBRARIES}") + include_directories("${LIBEV_INCLUDE_DIRS}") + set(extralibs ${extralibs} ${LIBEV_LIBRARIES}) endif() if (LWS_WITH_GLIB) set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory") -- Gitee From 4cc7f4ed02ad483dcb48f90baa5cc48a33a76a9a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 26 Mar 2020 06:48:34 +0000 Subject: [PATCH 0035/1062] ss: add static policy as a build option In some cases devices may be too constrained to handle JSON policies but still want to use SS apis and methodology. This introduces an off-by-default cmake option LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY, if enabled the JSON parsing part is excluded and it's assumed the user code provides its policy as hardcoded policy structs. --- CMakeLists.txt | 10 +- cmake/lws_config.h.in | 1 + include/libwebsockets/lws-context-vhost.h | 5 + .../libwebsockets/lws-secure-streams-policy.h | 26 +- lib/core/context.c | 22 + lib/core/private-lib-core.h | 6 +- lib/secure-streams/README.md | 27 + lib/secure-streams/policy-common.c | 279 +++ .../{policy.c => policy-json.c} | 281 +-- .../private-lib-secure-streams.h | 40 + .../CMakeLists.txt | 1 + .../minimal-secure-streams-avs/CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../CMakeLists.txt | 82 + .../minimal-secure-streams-policy2c/README.md | 49 + .../minimal-secure-streams.c | 570 +++++++ .../CMakeLists.txt | 1 + .../minimal-secure-streams-seq/CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../CMakeLists.txt | 80 + .../README.md | 61 + .../minimal-secure-streams.c | 291 ++++ .../static-policy.h | 1511 +++++++++++++++++ .../minimal-secure-streams/CMakeLists.txt | 1 + 24 files changed, 3081 insertions(+), 267 deletions(-) create mode 100644 lib/secure-streams/policy-common.c rename lib/secure-streams/{policy.c => policy-json.c} (77%) create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-policy2c/README.md create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/README.md create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 11b0d585..50b90e6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,7 @@ option(LWS_WITH_HTTP_UNCOMMON_HEADERS "Include less common http header support" option(LWS_WITH_SECURE_STREAMS "Secure Streams protocol-agnostic API" OFF) option(LWS_WITH_SECURE_STREAMS_PROXY_API "Secure Streams support to work across processes" OFF) option(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM "Auth support for api.amazon.com" OFF) +option(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY "Secure Streams Policy is hardcoded only" OFF) # # TLS library options... all except mbedTLS are basically OpenSSL variants. @@ -1176,10 +1177,15 @@ if (LWS_WITH_NETWORK) if (LWS_WITH_SECURE_STREAMS) list(APPEND SOURCES lib/secure-streams/secure-streams.c - lib/secure-streams/policy.c - lib/secure-streams/system/fetch-policy/fetch-policy.c + lib/secure-streams/policy-common.c lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c ) + if (NOT LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + list(APPEND SOURCES + lib/secure-streams/policy-json.c + lib/secure-streams/system/fetch-policy/fetch-policy.c + ) + endif() if (LWS_ROLE_H1) list(APPEND SOURCES lib/secure-streams/protocols/ss-h1.c diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 1af2f023..17885768 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -154,6 +154,7 @@ #cmakedefine LWS_WITH_SECURE_STREAMS #cmakedefine LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM #cmakedefine LWS_WITH_SECURE_STREAMS_PROXY_API +#cmakedefine LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY #cmakedefine LWS_WITH_SELFTESTS #cmakedefine LWS_WITH_SEQUENCER #cmakedefine LWS_WITH_SERVER_STATUS diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index 33143b92..c0c61a0b 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -712,9 +712,14 @@ struct lws_context_creation_info { /**< CONTEXT: percentage of udp reads we actually received * to make disappear, in order to simulate and test udp retry flow */ #if defined(LWS_WITH_SECURE_STREAMS) +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + const struct lws_ss_policy *pss_policies; /**< CONTEXT: point to first + * in a linked-list of streamtype policies prepared by user code */ +#else const char *pss_policies_json; /**< CONTEXT: point to a string * containing a JSON description of the secure streams policies. Set * to NULL if not using Secure Streams. */ +#endif const struct lws_ss_plugin **pss_plugins; /**< CONTEXT: point to an array * of pointers to plugin structs here, terminated with a NULL ptr. * Set to NULL if not using Secure Streams. */ diff --git a/include/libwebsockets/lws-secure-streams-policy.h b/include/libwebsockets/lws-secure-streams-policy.h index 02122fff..86ed2de0 100644 --- a/include/libwebsockets/lws-secure-streams-policy.h +++ b/include/libwebsockets/lws-secure-streams-policy.h @@ -122,7 +122,7 @@ typedef struct lws_ss_trust_store { struct lws_ss_trust_store *next; const char *name; - lws_ss_x509_t *ssx509[8]; + const lws_ss_x509_t *ssx509[6]; int count; } lws_ss_trust_store_t; @@ -130,6 +130,7 @@ enum { LWSSSP_H1, LWSSSP_H2, LWSSSP_WS, + LWSSSP_MQTT, LWSSS_HBI_AUTH = 0, @@ -179,6 +180,8 @@ typedef struct lws_ss_policy { union { +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) || defined(LWS_ROLE_WS) + /* details for http-related protocols... */ struct { @@ -211,6 +214,10 @@ typedef struct lws_ss_policy { uint8_t fail_redirect:1; } http; +#endif + +#if defined(LWS_ROLE_MQTT) + struct { const char *topic; /* stream sends on this topic */ const char *subscribe; /* stream subscribes to this topic */ @@ -226,6 +233,8 @@ typedef struct lws_ss_policy { } mqtt; +#endif + /* details for non-http related protocols... */ } u; @@ -248,6 +257,12 @@ typedef struct lws_ss_policy { 0 = none, 1+ = cc 0+ */ } lws_ss_policy_t; +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + +/* + * These only exist / have meaning if there's a dynamic JSON policy enabled + */ + LWS_VISIBLE LWS_EXTERN int lws_ss_policy_parse_begin(struct lws_context *context, int overlay); @@ -259,3 +274,12 @@ lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len) LWS_VISIBLE LWS_EXTERN int lws_ss_policy_overlay(struct lws_context *context, const char *overlay); + +/* + * You almost certainly don't want this, it returns the first policy object + * in a linked-list of objects created by lws_ss_policy_parse above + */ +LWS_VISIBLE LWS_EXTERN const lws_ss_policy_t * +lws_ss_policy_get(struct lws_context *context); + +#endif diff --git a/lib/core/context.c b/lib/core/context.c index 27b1d11f..8c357d7e 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -161,6 +161,7 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, /* it failed, eg, no streamtype for it in the policy */ } +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) /* * Skip this if we are running something without the policy for it */ @@ -173,6 +174,7 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, if (!lws_ss_sys_fetch_policy(context)) return 1; } +#endif #endif /* protocol part */ @@ -295,6 +297,11 @@ lws_create_context(const struct lws_context_creation_info *info) __func__, context->udp_loss_sim_tx_pc, context->udp_loss_sim_rx_pc); +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + /* directly use the user-provided policy object list */ + context->pss_policies = info->pss_policies; +#endif + #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) context->ss_proxy_bind = info->ss_proxy_bind; context->ss_proxy_port = info->ss_proxy_port; @@ -318,7 +325,9 @@ lws_create_context(const struct lws_context_creation_info *info) #endif #if defined(LWS_WITH_SECURE_STREAMS) +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) context->pss_policies_json = info->pss_policies_json; +#endif context->pss_plugins = info->pss_plugins; #endif @@ -822,6 +831,7 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_SECURE_STREAMS) +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) if (context->pss_policies_json) { /* * You must create your context with the explicit vhosts flag @@ -844,6 +854,16 @@ lws_create_context(const struct lws_context_creation_info *info) goto bail; } } else +#else + if (context->pss_policies) { + /* user code set the policy objects directly, no parsing step */ + + if (lws_ss_policy_set(context, "hardcoded")) { + lwsl_err("%s: policy set failed\n", __func__); + goto bail; + } + } else +#endif lws_create_vhost(context, info); #endif @@ -1096,9 +1116,11 @@ lws_context_destroy2(struct lws_context *context) #if defined(LWS_WITH_SECURE_STREAMS) lws_dll2_foreach_safe(&pt->ss_owner, NULL, lws_ss_destroy_dll); +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) if (context->ac_policy) lwsac_free(&context->ac_policy); #endif +#endif #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) lws_dll2_foreach_safe(&pt->ss_client_owner, NULL, lws_sspc_destroy_dll); diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 77380456..49ea3f6b 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -358,7 +358,6 @@ struct lws_context { #endif #if defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) - void *pol_args; struct lws_ss_handle *hss_auth; struct lws_ss_handle *hss_fetch_policy; lws_sorted_usec_list_t sul_api_amazon_com; @@ -440,10 +439,13 @@ struct lws_context { const lws_system_ops_t *system_ops; #if defined(LWS_WITH_SECURE_STREAMS) +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) const char *pss_policies_json; + struct lwsac *ac_policy; + void *pol_args; +#endif const lws_ss_policy_t *pss_policies; const lws_ss_plugin_t **pss_plugins; - struct lwsac *ac_policy; #endif void *external_baggage_free_on_destroy; diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index d0540f69..7508cac2 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -528,3 +528,30 @@ socks_proxy=127.0.0.1:1337 ./bin/lws-minimal-secure-streams-client -p 1234 -i 12 You can confirm this goes through the ssh socks5 proxy to get to the SS proxy and fulfil the connection. + +## Using static policies + +If one of your targets is too constrained to make use of dynamic JSON policies, but +using SS and the policies is attractive for wider reasons, you can use a static policy +built into the firmware for the constrained target. + +The secure-streams example "policy2c" (which runs on the build machine, not the device) + +https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-policy2c + +accepts a normal JSON policy on stdin, and emits a C code representation that can be +included directly in the firmware. + +https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h + +Using this technique it's possible to standardize on maintaining JSON policies across a +range of devices with different contraints, and use the C conversion of the policy on devices +that are too small. + +The Cmake option `LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY` should be enabled to use this +mode, it will not build the JSON parser (and the option for LEJP can also be disabled if +you're not otherwise using it, saving an additional couple of KB). + +Notice policy2c example tool must be built with `LWS_ROLE_H1`, `LWS_ROLE_H2`, `LWS_ROLE_WS` +and `LWS_ROLE_MQTT` enabled so it can handle any kind of policy. + diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c new file mode 100644 index 00000000..98102dfc --- /dev/null +++ b/lib/secure-streams/policy-common.c @@ -0,0 +1,279 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This file contains the stuff related to secure streams policy, it's always + * built if LWS_WITH_SECURE_STREAMS enabled. + */ + +#include + +const lws_ss_policy_t * +lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype) +{ + const lws_ss_policy_t *p = context->pss_policies; + + if (!streamtype) + return NULL; + + while (p) { + if (!strcmp(p->streamtype, streamtype)) + return p; + p = p->next; + } + + return NULL; +} + +int +lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, + const void *value, size_t len) +{ + lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); + + if (!omd) { + lwsl_err("%s: unknown metadata %s\n", __func__, name); + return 1; + } + + h->metadata[omd->length].name = name; + h->metadata[omd->length].value = (void *)value; + h->metadata[omd->length].length = len; + + return 0; +} + +lws_ss_metadata_t * +lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name) +{ + lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); + + if (!omd) + return NULL; + + return &h->metadata[omd->length]; +} + +lws_ss_metadata_t * +lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name) +{ + lws_ss_metadata_t *pmd = p->metadata; + + while (pmd) { + if (pmd->name && !strcmp(name, pmd->name)) + return pmd; + pmd = pmd->next; + } + + return NULL; +} + +lws_ss_metadata_t * +lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index) +{ + lws_ss_metadata_t *pmd = p->metadata; + + while (pmd) { + if (pmd->length == index) + return pmd; + pmd = pmd->next; + } + + return NULL; +} + +int +lws_ss_policy_set(struct lws_context *context, const char *name) +{ +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; + lws_ss_x509_t *x; + char buf[16]; + int m; +#endif + const lws_ss_policy_t *pol; + struct lws_vhost *v; + int ret = 0; + +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + /* + * Parsing seems to have succeeded, and we're going to use the new + * policy that's laid out in args->ac + */ + + lejp_destruct(&args->jctx); + + if (context->ac_policy) { + + /* + * So this is a bit fun-filled, we already had a policy in + * force, perhaps it was the default policy that's just good for + * fetching the real policy, and we're doing that now. + * + * We can destroy all the policy-related direct allocations + * easily because they're cleanly in a single lwsac... + */ + lwsac_free(&context->ac_policy); + + /* + * ...but when we did the trust stores, we created vhosts for + * each. We need to destroy those now too, and recreate new + * ones from the new policy, perhaps with different X.509s. + */ + + v = context->vhost_list; + while (v) { + if (v->from_ss_policy) { + struct lws_vhost *vh = v->vhost_next; + lwsl_debug("%s: destroying vh %p\n", __func__, v); + lws_vhost_destroy(v); + v = vh; + continue; + } + v = v->vhost_next; + } + + lws_check_deferred_free(context, 0, 1); + } + + context->pss_policies = args->heads[LTY_POLICY].p; + context->ac_policy = args->ac; + + lws_humanize(buf, sizeof(buf), lwsac_total_alloc(args->ac), + humanize_schema_si_bytes); + if (lwsac_total_alloc(args->ac)) + m = (int)((lwsac_total_overhead(args->ac) * 100) / + lwsac_total_alloc(args->ac)); + else + m = 0; + + lwsl_notice("%s: %s, pad %d%c: %s\n", __func__, buf, m, '%', name); +#endif + + /* Create vhosts for each type of trust store */ + + pol = context->pss_policies; + while (pol) { + struct lws_context_creation_info i; + int n; + + memset(&i, 0, sizeof(i)); + + /* + * We get called from context creation... instantiates + * vhosts with client tls contexts set up for each unique CA. + * + * For compatibility with static policy, we create the vhosts + * by walking streamtype list and create vhosts using trust + * store name if it doesn't already exist. + */ + + if (!pol->trust_store) { + pol = pol->next; + continue; + } + v = lws_get_vhost_by_name(context, pol->trust_store->name); + if (v) { + /* vhost for this trust store already exists, skip */ + pol = pol->next; + continue; + } + + i.options = context->options; + i.vhost_name = pol->trust_store->name; + lwsl_debug("%s: %s\n", __func__, i.vhost_name); + i.client_ssl_ca_mem = pol->trust_store->ssx509[0]->ca_der; + i.client_ssl_ca_mem_len = pol->trust_store->ssx509[0]->ca_der_len; + i.port = CONTEXT_PORT_NO_LISTEN; + lwsl_info("%s: %s trust store initial '%s'\n", __func__, + i.vhost_name, pol->trust_store->ssx509[0]->vhost_name); + + v = lws_create_vhost(context, &i); + if (!v) { + lwsl_err("%s: failed to create vhost %s\n", + __func__, i.vhost_name); + ret = 1; + } else + v->from_ss_policy = 1; + + for (n = 1; v && n < pol->trust_store->count; n++) { + lwsl_info("%s: add '%s' to trust store\n", __func__, + pol->trust_store->ssx509[n]->vhost_name); + if (lws_tls_client_vhost_extra_cert_mem(v, + pol->trust_store->ssx509[n]->ca_der, + pol->trust_store->ssx509[n]->ca_der_len)) { + lwsl_err("%s: add extra cert failed\n", + __func__); + ret = 1; + } + } + + pol = pol->next; + } + +#if defined(LWS_WITH_SOCKS5) + + /* + * ... we need to go through every vhost updating its understanding of + * which socks5 proxy to use... + */ + + v = context->vhost_list; + while (v) { + lws_set_socks(v, args->socks5_proxy); + v = v->vhost_next; + } + if (context->vhost_system) + lws_set_socks(context->vhost_system, args->socks5_proxy); + + if (args->socks5_proxy) + lwsl_notice("%s: global socks5 proxy: %s\n", __func__, + args->socks5_proxy); +#endif + +#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + + /* + * For dynamic policy case, now we processed the x.509 CAs, we can free + * all of our originals. For static policy, they're in .rodata, nothing + * to free. + */ + + x = args->heads[LTY_X509].x; + while (x) { + /* + * Free all the DER buffers now they have been parsed into + * tls library X.509 objects + */ + lws_free((void *)x->ca_der); + x->ca_der = NULL; + x = x->next; + } + + /* and we can discard the parsing args object now, invalidating args */ + + lws_free_set_NULL(context->pol_args); +#endif + + return ret; +} + diff --git a/lib/secure-streams/policy.c b/lib/secure-streams/policy-json.c similarity index 77% rename from lib/secure-streams/policy.c rename to lib/secure-streams/policy-json.c index 6991e528..09e5a0c7 100644 --- a/lib/secure-streams/policy.c +++ b/lib/secure-streams/policy-json.c @@ -20,16 +20,13 @@ * 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. + * + * This file contains the stuff related to JSON-provided policy, it's not built + * if LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY enabled. */ #include -typedef struct backoffs { - struct backoffs *next; - const char *name; - lws_retry_bo_t r; -} backoff_t; - static const char * const lejp_tokens_policy[] = { "release", "product", @@ -161,39 +158,6 @@ typedef enum { LSSPPT_STREAMTYPES } policy_token_t; -union u { - backoff_t *b; - lws_ss_x509_t *x; - lws_ss_trust_store_t *t; - lws_ss_policy_t *p; -}; - -enum { - LTY_BACKOFF, - LTY_X509, - LTY_TRUSTSTORE, - LTY_POLICY, - - _LTY_COUNT /* always last */ -}; - -struct policy_cb_args { - struct lejp_ctx jctx; - struct lws_context *context; - struct lwsac *ac; - - const char *socks5_proxy; - - struct lws_b64state b64; - - union u heads[_LTY_COUNT]; - union u curr[_LTY_COUNT]; - - uint8_t *p; - - int count; -}; - #define POL_AC_INITIAL 2048 #define POL_AC_GRAIN 800 #define MAX_CERT_TEMP 2048 /* used to discover actual cert size for realloc */ @@ -212,63 +176,6 @@ static const char *protonames[] = { "mqtt", /* LWSSSP_MQTT */ }; -lws_ss_metadata_t * -lws_ss_policy_metadata(const lws_ss_policy_t *p, const char *name) -{ - lws_ss_metadata_t *pmd = p->metadata; - - while (pmd) { - if (pmd->name && !strcmp(name, pmd->name)) - return pmd; - pmd = pmd->next; - } - - return NULL; -} - -lws_ss_metadata_t * -lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index) -{ - lws_ss_metadata_t *pmd = p->metadata; - - while (pmd) { - if (pmd->length == index) - return pmd; - pmd = pmd->next; - } - - return NULL; -} - -int -lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, - const void *value, size_t len) -{ - lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); - - if (!omd) { - lwsl_err("%s: unknown metadata %s\n", __func__, name); - return 1; - } - - h->metadata[omd->length].name = name; - h->metadata[omd->length].value = (void *)value; - h->metadata[omd->length].length = len; - - return 0; -} - -lws_ss_metadata_t * -lws_ss_get_handle_metadata(struct lws_ss_handle *h, const char *name) -{ - lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); - - if (!omd) - return NULL; - - return &h->metadata[omd->length]; -} - static signed char lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) { @@ -645,6 +552,7 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->metadata_count++; break; +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) case LSSPPT_HTTP_AUTH_HEADER: case LSSPPT_HTTP_DSN_HEADER: case LSSPPT_HTTP_FWV_HEADER: @@ -690,6 +598,9 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->u.http.fail_redirect = reason == LEJPCB_VAL_TRUE; break; +#endif + +#if defined(LWS_ROLE_WS) case LSSPPT_WS_SUBPROTOCOL: pp = (char **)&a->curr[LTY_POLICY].p->u.http.u.ws.subprotocol; @@ -699,11 +610,14 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->u.http.u.ws.binary = reason == LEJPCB_VAL_TRUE; break; +#endif + case LSSPPT_LOCAL_SINK: if (reason == LEJPCB_VAL_TRUE) a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_LOCAL_SINK; break; +#if defined(LWS_ROLE_MQTT) case LSSPPT_MQTT_TOPIC: pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.topic; goto string2; @@ -739,6 +653,7 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->u.mqtt.will_retain = reason == LEJPCB_VAL_TRUE; break; +#endif case LSSPPT_PROTOCOL: a->curr[LTY_POLICY].p->protocol = 0xff; @@ -752,6 +667,9 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar)); lwsl_err("%s: unknown protocol name %s\n", __func__, dotstar); return -1; + + default: + break; } return 0; @@ -835,6 +753,7 @@ lws_ss_policy_parse_abandon(struct lws_context *context) struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; lejp_destruct(&args->jctx); + lwsac_free(&args->ac); lws_free_set_NULL(context->pol_args); return 0; @@ -865,175 +784,13 @@ lws_ss_policy_overlay(struct lws_context *context, const char *overlay) strlen(overlay)); } -int -lws_ss_policy_set(struct lws_context *context, const char *name) -{ - struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; - lws_ss_trust_store_t *ts; - struct lws_vhost *v; - lws_ss_x509_t *x; - char buf[16]; - int m, ret = 0; - - /* - * Parsing seems to have succeeded, and we're going to use the new - * policy that's laid out in args->ac - */ - - lejp_destruct(&args->jctx); - - if (context->ac_policy) { - - /* - * So this is a bit fun-filled, we already had a policy in - * force, perhaps it was the default policy that's just good for - * fetching the real policy, and we're doing that now. - * - * We can destroy all the policy-related direct allocations - * easily because they're cleanly in a single lwsac... - */ - lwsac_free(&context->ac_policy); - - /* - * ...but when we did the trust stores, we created vhosts for - * each. We need to destroy those now too, and recreate new - * ones from the new policy, perhaps with different X.509s. - */ - - v = context->vhost_list; - while (v) { - if (v->from_ss_policy) { - struct lws_vhost *vh = v->vhost_next; - lwsl_debug("%s: destroying vh %p\n", __func__, v); - lws_vhost_destroy(v); - v = vh; - continue; - } - v = v->vhost_next; - } - - lws_check_deferred_free(context, 0, 1); - } - - context->pss_policies = args->heads[LTY_POLICY].p; - context->ac_policy = args->ac; - - lws_humanize(buf, sizeof(buf), lwsac_total_alloc(args->ac), - humanize_schema_si_bytes); - if (lwsac_total_alloc(args->ac)) - m = (int)((lwsac_total_overhead(args->ac) * 100) / - lwsac_total_alloc(args->ac)); - else - m = 0; - - lwsl_notice("%s: %s, pad %d%c: %s\n", __func__, buf, m, '%', name); - - /* Create vhosts for each type of trust store */ - - ts = args->heads[LTY_TRUSTSTORE].t; - while (ts) { - struct lws_context_creation_info i; - - memset(&i, 0, sizeof(i)); - - /* - * We get called from context creation... instantiates - * vhosts with client tls contexts set up for each unique CA. - * - * Create the vhost with the first (mandatory) entry in the - * trust store... - */ - - v = lws_get_vhost_by_name(context, ts->name); - if (!v) { - int n; - - i.options = context->options; - i.vhost_name = ts->name; - lwsl_debug("%s: %s\n", __func__, i.vhost_name); - i.client_ssl_ca_mem = ts->ssx509[0]->ca_der; - i.client_ssl_ca_mem_len = ts->ssx509[0]->ca_der_len; - i.port = CONTEXT_PORT_NO_LISTEN; - lwsl_info("%s: %s trust store initial '%s'\n", __func__, - ts->name, ts->ssx509[0]->vhost_name); - - v = lws_create_vhost(context, &i); - if (!v) { - lwsl_err("%s: failed to create vhost %s\n", - __func__, ts->name); - ret = 1; - } else - v->from_ss_policy = 1; - - for (n = 1; v && n < ts->count; n++) { - lwsl_info("%s: add '%s' to trust store\n", - __func__, ts->ssx509[n]->vhost_name); - if (lws_tls_client_vhost_extra_cert_mem(v, - ts->ssx509[n]->ca_der, - ts->ssx509[n]->ca_der_len)) { - lwsl_err("%s: add extra cert failed\n", - __func__); - ret = 1; - } - } - } - - ts = ts->next; - } - -#if defined(LWS_WITH_SOCKS5) - - /* - * ... we need to go through every vhost updating its understanding of - * which socks5 proxy to use... - */ - - v = context->vhost_list; - while (v) { - lws_set_socks(v, args->socks5_proxy); - v = v->vhost_next; - } - if (context->vhost_system) - lws_set_socks(context->vhost_system, args->socks5_proxy); - - if (args->socks5_proxy) - lwsl_notice("%s: global socks5 proxy: %s\n", __func__, - args->socks5_proxy); -#endif - - /* now we processed the x.509 CAs, we can free all of our originals */ - - x = args->heads[LTY_X509].x; - while (x) { - /* - * Free all the DER buffers now they have been parsed into - * tls library X.509 objects - */ - lws_free((void *)x->ca_der); - x->ca_der = NULL; - x = x->next; - } - - /* and we can discard the parsing args object now, invalidating args */ - - lws_free_set_NULL(context->pol_args); - - return ret; -} - const lws_ss_policy_t * -lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype) +lws_ss_policy_get(struct lws_context *context) { - const lws_ss_policy_t *p = context->pss_policies; + struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; - if (!streamtype) + if (!args) return NULL; - while (p) { - if (!strcmp(p->streamtype, streamtype)) - return p; - p = p->next; - } - - return NULL; + return args->heads[LTY_POLICY].p; } diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 90dd4458..9d9044e2 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -242,6 +242,46 @@ typedef struct lws_sspc_handle { uint8_t destroying:1; } lws_sspc_handle_t; +typedef struct backoffs { + struct backoffs *next; + const char *name; + lws_retry_bo_t r; +} backoff_t; + +union u { + backoff_t *b; + lws_ss_x509_t *x; + lws_ss_trust_store_t *t; + lws_ss_policy_t *p; +}; + +enum { + LTY_BACKOFF, + LTY_X509, + LTY_TRUSTSTORE, + LTY_POLICY, + + _LTY_COUNT /* always last */ +}; + + +struct policy_cb_args { + struct lejp_ctx jctx; + struct lws_context *context; + struct lwsac *ac; + + const char *socks5_proxy; + + struct lws_b64state b64; + + union u heads[_LTY_COUNT]; + union u curr[_LTY_COUNT]; + + uint8_t *p; + + int count; +}; + int lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, struct lws_context *context, diff --git a/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt index b28d84e0..0fb81078 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt @@ -66,6 +66,7 @@ set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) require_lws_config(LWS_WITH_ALSA 1 requirements) if (requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt index 7e58274a..e336dad3 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt @@ -65,6 +65,7 @@ set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${SAMP} main.c avs.c) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt index 2b1b4b1c..b53fb9bb 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt @@ -66,6 +66,7 @@ set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${SAMP} minimal-secure-streams.c) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt new file mode 100644 index 00000000..5aec9b00 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt @@ -0,0 +1,82 @@ +cmake_minimum_required(VERSION 2.8) +include(CheckCSourceCompiles) + +set(SAMP lws-minimal-secure-streams-policy2c) + +# If we are being built as part of lws, confirm current build config supports +# reqconfig, else skip building ourselves. +# +# If we are being built externally, confirm installed lws was configured to +# support reqconfig, else error out with a helpful message about the problem. +# +MACRO(require_lws_config reqconfig _val result) + + if (DEFINED ${reqconfig}) + if (${reqconfig}) + set (rq 1) + else() + set (rq 0) + endif() + else() + set(rq 0) + endif() + + if (${_val} EQUAL ${rq}) + set(SAME 1) + else() + set(SAME 0) + endif() + + if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) + if (${_val}) + message("${SAMP}: skipping as lws being built without ${reqconfig}") + else() + message("${SAMP}: skipping as lws built with ${reqconfig}") + endif() + set(${result} 0) + else() + if (LWS_WITH_MINIMAL_EXAMPLES) + set(MET ${SAME}) + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) + if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) + set(HAS_${reqconfig} 0) + else() + set(HAS_${reqconfig} 1) + endif() + if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) + set(MET 1) + else() + set(MET 0) + endif() + endif() + if (NOT MET) + if (${_val}) + message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") + else() + message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") + endif() + endif() + endif() +ENDMACRO() + + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_ROLE_H2 1 requirements) +require_lws_config(LWS_ROLE_MQTT 1 requirements) +require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) + +if (requirements) + add_executable(${SAMP} minimal-secure-streams.c) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets) + endif() + +endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/README.md b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/README.md new file mode 100644 index 00000000..8e093ea6 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/README.md @@ -0,0 +1,49 @@ +# lws minimal secure streams policy2c + +This application parses a JSON policy passed on stdin and emits the +equivalent of it in C structs ready for compilation. + +This is useful in the case your platform doesn't use a dynamic JSON +policy and is space-constrained, you can still form and maintain the +policy in JSON, but with this utility convert it into compileable C. + +**Notice** this depends on LWS_ROLE_H1, LWS_ROLE_H2, LWS_ROLE_WS and +LWS_ROLE_MQTT build of lws, since it has to be able to work with any kind +of policy content. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` +$ cat mypolicy.json | lws-minimal-secure-streams-policy2c + +(on stdout) + +static const uint32_t _rbo_bo_0[] = { + 1000, 2000, 3000, 5000, 10000, +}; +static const lws_retry_bo_t _rbo_0 = { + .retry_ms_table = _rbo_bo_0, + .retry_ms_table_count = 5, + .conceal_count = 5, + .secs_since_valid_ping = 30, + .secs_since_valid_hangup = 35, + .jitter_percent = 20, +}; +static const uint8_t _ss_der_amazon_root_ca_1[] = { + /* 0x 0 */ 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x06, + /* 0x 10 */ 0x6C, 0x9F, 0xCF, 0x99, 0xBF, 0x8C, 0x0A, 0x39, + /* 0x 18 */ 0xE2, 0xF0, 0x78, 0x8A, 0x43, 0xE6, 0x96, 0x36, + /* 0x 20 */ 0x5B, 0xCA, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, +... +``` diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c new file mode 100644 index 00000000..0dfa5fa1 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c @@ -0,0 +1,570 @@ +/* + * lws-minimal-secure-streams-policy2c + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * + * This reads policy JSON on stdin and emits it as compileable + * C structs. + * + * It's useful if your platform is too space-constrained for a + * JSON policy and needs to build a static policy in C via + * LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY... this way you can + * still create and maintain the JSON policy but implement it directly + * as C structs in your code. + */ + +#include +#include +#include +#include + +static int interrupted, bad = 1; + + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +struct aggstr { + struct aggstr *next; + + const char *orig; + size_t offset; +}; + +static struct aggstr *rbomap, /* retry / backoff object map */ + *trustmap, /* trust store map */ + *certmap; /* x.509 cert map */ +static size_t last_offset; + + + +static const char * +purify_csymbol(const char *in, char *temp, size_t templen) +{ + const char *otemp = temp; + + assert (strlen(in) < templen); + + while (*in) { + if ((*in >= 'a' && *in <= 'z') || (*in >= 'A' && *in <= 'Z') || + (*in >= '0' && *in <= '9')) + *temp++ = *in; + else + *temp++ = '_'; + + in++; + } + + *temp = '\0'; + + return otemp; +} + +int main(int argc, const char **argv) +{ + const lws_ss_policy_t *pol, *lastpol = NULL; + struct lws_context_creation_info info; + size_t json_size = 0, est = 0; + struct lws_context *context; + char prev[128], curr[128]; + int unique_rbo = 0, m, n; + char buf[64], buf1[64]; + lws_ss_metadata_t *md; + struct aggstr *a, *a1; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS secure streams policy2c [-d]\n"); + + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; + + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + lws_ss_policy_parse_begin(context, 0); + + printf("/*\n * Autogenerated from the following JSON policy\n */\n\n#if 0\n"); + + do { + int m, n = read(0, buf, sizeof(buf)); + + if (n < 1) + break; + + m = lws_ss_policy_parse(context, (uint8_t *)buf, (size_t)n); + + printf("%.*s", n, buf); + json_size += n; + + if (m < 0 && m != LEJP_CONTINUE) { + lwsl_err("%s: policy parse failed... lws has WITH_ROLEs" + "for what's in the JSON?\n", __func__); + goto bail; + } + } while (1); + + printf("\n\n Original JSON size: %zu\n#endif\n\n", json_size); + + lwsl_notice("%s: parsed JSON\n", __func__); + + /* + * Well, this is fun, isn't it... we have parsed the JSON into in-memory + * policy objects, and it has set the context policy pointer to the head + * of those but has not set the new policy (which would free the x.509). + * + * We want to walk the streamtype list first discovering unique objects + * and strings referenced there and emitting them compactly as C data, + * and then second to emit the streamtype linked-list referring to those + * objects. + * + * For const strings, we aggregate them and avoid generating extra + * pointers by encoding the reference as &_lws_ss_staticpol_str[xxx] + * where xxx is the fixed offset in the aggregated monster-string. When + * doing that, we keep a map of original pointers to offsets. + * + * Although we want to minimize memory used by the emitted C, we don't + * have to sweat memory during this conversion since it's happening on a + * PC + */ + + pol = lws_ss_policy_get(context); + lwsl_notice("%s: pol %p\n", __func__, pol); + while (pol) { + + /* + * Walk the metadata list gathering strings and issuing the + * C struct + */ + + md = pol->metadata; + + if (md) { + int idx = 0; + + printf("\nstatic const lws_ss_metadata_t "); + + prev[0] = '\0'; + md = pol->metadata; + while (md) { + + est += sizeof(lws_ss_metadata_t); + + lws_snprintf(curr, sizeof(curr), "_md_%s_%s", + purify_csymbol(pol->streamtype, buf, + sizeof(buf)), + purify_csymbol(md->name, buf1, + sizeof(buf1))); + + printf("%s = {\n", curr); + if (prev[0]) + printf("\t.next = (void *)&%s, \n", prev); + + printf("\t.name = \"%s\",\n", (const char *)md->name); + if (md->value) + printf("\t.value = (void *)\"%s\",\n", (const char *)md->value); + + printf("\t.length = %d,\n", idx++); // md->length); + + printf("}"); + if (md->next) + printf(",\n"); + + lws_strncpy(prev, curr, sizeof(prev)); + + md = md->next; + } + + printf(";\n\n"); + } + + /* + * Create unique retry policies... have we seen this guy? + */ + + if (pol->retry_bo) { + a = rbomap; + while (a) { + if (a->orig == (const char *)pol->retry_bo) + break; + + a = a->next; + } + + if (!a) { + + /* We haven't seen it before and need to create it */ + + a = malloc(sizeof(*a)); + if (!a) + goto bail; + a->next = rbomap; + a->offset = unique_rbo++; + a->orig = (const char *)pol->retry_bo; + rbomap = a; + + printf("static const uint32_t _rbo_bo_%zu[] = {\n", + a->offset); + for (n = 0; n < pol->retry_bo->retry_ms_table_count; n++) + printf(" %u, ", (unsigned int) + pol->retry_bo->retry_ms_table[n]); + + est += sizeof(uint32_t) * + pol->retry_bo->retry_ms_table_count; + + printf("\n};\nstatic const " + "lws_retry_bo_t _rbo_%zu = {\n", a->offset); + + printf("\t.retry_ms_table = _rbo_bo_%zu,\n", + a->offset); + printf("\t.retry_ms_table_count = %u,\n", + pol->retry_bo->retry_ms_table_count); + printf("\t.conceal_count = %u,\n", + pol->retry_bo->conceal_count); + printf("\t.secs_since_valid_ping = %u,\n", + pol->retry_bo->secs_since_valid_ping); + printf("\t.secs_since_valid_hangup = %u,\n", + pol->retry_bo->secs_since_valid_hangup); + printf("\t.jitter_percent = %u,\n", + pol->retry_bo->jitter_percent); + printf("};\n"); + + est += sizeof(lws_retry_bo_t); + } + } + + /* + * How about his trust store, it's new to us? + */ + + if (pol->trust_store) { + a = trustmap; + while (a) { + if (a->orig == (const char *)pol->trust_store) + break; + + a = a->next; + } + + if (!a) { + + /* it's new to us... */ + + a = malloc(sizeof(*a)); + if (!a) + goto bail; + a->next = trustmap; + a->offset = 0; /* don't care, just track seen */ + a->orig = (const char *)pol->trust_store; + trustmap = a; + + /* + * Have a look through his x.509 stack... + * any that're new to us? + */ + + for (n = 0; n < pol->trust_store->count; n++) { + if (!pol->trust_store->ssx509[n]) + continue; + a1 = certmap; + while (a1) { + if (a1->orig == (const char *)pol->trust_store->ssx509[n]) + break; + a1 = a1->next; + } + + if (!a1) { + /* + * This x.509 cert is new to us... + * let's capture the DER + */ + + a1 = malloc(sizeof(*a1)); + if (!a1) + goto bail; + a1->next = certmap; + a1->offset = 0; /* don't care, just track seen */ + a1->orig = (const char *)pol->trust_store->ssx509[n]; + certmap = a1; + + printf("static const uint8_t _ss_der_%s[] = {\n", + purify_csymbol(pol->trust_store->ssx509[n]->vhost_name, + buf, sizeof(buf))); + + for (m = 0; m < (int)pol->trust_store->ssx509[n]->ca_der_len; m++) { + if ((m & 7) == 0) + printf("\t/* 0x%3x */ ", m); + + printf("0x%02X, ", pol->trust_store->ssx509[n]->ca_der[m]); + if ((m & 7) == 7) + printf("\n"); + } + + printf("\n};\nstatic const lws_ss_x509_t _ss_x509_%s = {\n", + purify_csymbol(pol->trust_store->ssx509[n]->vhost_name, + buf, sizeof(buf))); + printf("\t.vhost_name = \"%s\",\n", pol->trust_store->ssx509[n]->vhost_name); + printf("\t.ca_der = _ss_der_%s,\n", + purify_csymbol(pol->trust_store->ssx509[n]->vhost_name, + buf, sizeof(buf))); + printf("\t.ca_der_len = %zu,\n", pol->trust_store->ssx509[n]->ca_der_len); + printf("};\n"); + + est += sizeof(lws_ss_x509_t) + pol->trust_store->ssx509[n]->ca_der_len; + } + + } + + + printf("static const lws_ss_trust_store_t _ss_ts_%s = {\n", + purify_csymbol(pol->trust_store->name, + buf, sizeof(buf))); + + printf("\t.name = \"%s\",\n", pol->trust_store->name); + printf("\t.ssx509 = {\n"); + + for (n = pol->trust_store->count - 1; n >= 0 ; n--) + printf("\t\t&_ss_x509_%s,\n", + pol->trust_store->ssx509[n]->vhost_name); + + printf("\t}\n};\n"); + + est += sizeof(lws_ss_trust_store_t); + + } + } + + pol = pol->next; + } + + + + /* + * The streamtypes + */ + + pol = lws_ss_policy_get(context); + lwsl_notice("%s: pol %p\n", __func__, pol); + + printf("\nstatic const lws_ss_policy_t "); + prev[0] = '\0'; + + while (pol) { + + est += sizeof(*pol); + + lws_snprintf(curr, sizeof(curr), "_ssp_%s", + purify_csymbol(pol->streamtype, buf, sizeof(buf))); + printf("%s = {\n", curr); + + + if (prev[0]) + printf("\t.next = (void *)&%s,\n", prev); + + printf("\t.streamtype = \"%s\",\n", pol->streamtype); + if (pol->endpoint) + printf("\t.endpoint = \"%s\",\n", pol->endpoint); + if (pol->rideshare_streamtype) + printf("\t.rideshare_streamtype = \"%s\",\n", + pol->rideshare_streamtype); + if (pol->payload_fmt) + printf("\t.payload_fmt = \"%s\",\n", + pol->payload_fmt); + if (pol->socks5_proxy) + printf("\t.socks5_proxy = \"%s\",\n", + pol->socks5_proxy); + + { + lws_ss_metadata_t *nv = pol->metadata, *last = NULL; + + while (nv) { + last = nv; + nv = nv->next; + } + if (pol->metadata) + printf("\t.metadata = (void *)&_md_%s_%s,\n", + purify_csymbol(pol->streamtype, buf, sizeof(buf)), + purify_csymbol(last->name, buf1, sizeof(buf1))); + } + + + switch (pol->protocol) { + case LWSSSP_H1: + case LWSSSP_H2: + case LWSSSP_WS: + + printf("\t.u = {\n\t\t.http = {\n"); + + if (pol->u.http.method) + printf("\t\t\t.method = \"%s\",\n", + pol->u.http.method); + if (pol->u.http.url) + printf("\t\t\t.url = \"%s\",\n", + pol->u.http.url); + if (pol->u.http.multipart_name) + printf("\t\t\t.multipart_name = \"%s\",\n", + pol->u.http.multipart_name); + if (pol->u.http.multipart_filename) + printf("\t\t\t.multipart_filename = \"%s\",\n", + pol->u.http.multipart_filename); + if (pol->u.http.multipart_content_type) + printf("\t\t\t.multipart_content_type = \"%s\",\n", + pol->u.http.multipart_content_type); + if (pol->u.http.auth_preamble) + printf("\t\t\t.auth_preamble = \"%s\",\n", + pol->u.http.auth_preamble); + + if (pol->u.http.blob_header[0]) { + printf("\t\t\t.blob_header = {\n"); + for (n = 0; n < (int)LWS_ARRAY_SIZE(pol->u.http.blob_header); n++) + if (pol->u.http.blob_header[n]) + printf("\t\t\t\t\"%s\",\n", + pol->u.http.blob_header[n]); + + printf("\t\t\t},\n"); + } + + if (pol->protocol == LWSSSP_WS) { + printf("\t\t\t.u = {\n\t\t\t\t.ws = {\n"); + if (pol->u.http.u.ws.subprotocol) + printf("\t\t\t\t\t.subprotocol = \"%s\",\n", + pol->u.http.u.ws.subprotocol); + printf("\t\t\t\t\t.binary = %u\n", pol->u.http.u.ws.binary); + printf("\t\t\t\t}\n\t\t\t},\n"); + } + + if (pol->u.http.resp_expect) + printf("\t\t\t.resp_expect = %u,\n", pol->u.http.resp_expect); + if (pol->u.http.fail_redirect) + printf("\t\t\t.fail_redirect = %u,\n", pol->u.http.fail_redirect); + + printf("\t\t}\n\t},\n"); + + break; + case LWSSSP_MQTT: + + printf("\t.u = {\n\t\t.mqtt = {\n"); + + if (pol->u.mqtt.topic) + printf("\t\t\t.topic = \"%s\",\n", + pol->u.mqtt.topic); + if (pol->u.mqtt.subscribe) + printf("\t\t\t.subscribe = \"%s\",\n", + pol->u.mqtt.subscribe); + if (pol->u.mqtt.will_topic) + printf("\t\t\t.will_topic = \"%s\",\n", + pol->u.mqtt.will_topic); + if (pol->u.mqtt.will_message) + printf("\t\t\t.will_message = \"%s\",\n", + pol->u.mqtt.will_message); + + if (pol->u.mqtt.keep_alive) + printf("\t\t\t.keep_alive = %u,\n", + pol->u.mqtt.keep_alive); + if (pol->u.mqtt.qos) + printf("\t\t\t.qos = %u,\n", + pol->u.mqtt.qos); + if (pol->u.mqtt.clean_start) + printf("\t\t\t.clean_start = %u,\n", + pol->u.mqtt.clean_start); + if (pol->u.mqtt.will_qos) + printf("\t\t\t.will_qos = %u,\n", + pol->u.mqtt.will_qos); + if (pol->u.mqtt.will_retain) + printf("\t\t\t.will_retain = %u,\n", + pol->u.mqtt.will_retain); + + printf("\t\t}\n\t},\n"); + + break; + default: + lwsl_err("%s: unknown ss protocol index %d\n", __func__, + pol->protocol); + goto bail; + } + +#if 0 + const lws_ss_trust_store_t *trust_store; /**< CA certs needed for conn + validation, only set between policy parsing and vhost creation */ +#endif + + if (pol->retry_bo) { + a = rbomap; + while (a) { + if (a->orig == (const char *)pol->retry_bo) + break; + + a = a->next; + } + if (!a) + goto bail; + + printf("\t.retry_bo = &_rbo_%zu,\n", a->offset); + } + + if (pol->flags) + printf("\t.flags = 0x%x,\n", pol->flags); + if (pol->port) + printf("\t.port = %u,\n", pol->port); + if (pol->metadata_count) + printf("\t.metadata_count = %u,\n", pol->metadata_count); + printf("\t.protocol = %u,\n", pol->protocol); + if (pol->client_cert) + printf("\t.client_cert = %u,\n", pol->client_cert); + + if (pol->trust_store) + printf("\t.trust_store = &_ss_ts_%s,\n", + purify_csymbol(pol->trust_store->name, buf, sizeof(buf))); + + + printf("}"); + if (pol->next) + printf(",\n"); + + lws_strncpy(prev, curr, sizeof(prev)); + + lastpol = pol; + + pol = pol->next; + } + + printf(";\n"); + if (lastpol) + printf("#define _ss_static_policy_entry _ssp_%s\n", + purify_csymbol(lastpol->streamtype, buf, sizeof(buf))); + + est += last_offset; + + printf("/* estimated footprint %zu (when sizeof void * = %zu) */\n", + est, sizeof(void *)); + + lws_ss_policy_parse_abandon(context); + bad = 0; + +bail: + + + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} diff --git a/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt index 00c0c3d6..60e105ec 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt @@ -67,6 +67,7 @@ require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS_PROXY_API 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt index b55a3a00..cd466d90 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt @@ -66,6 +66,7 @@ set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt index 080ddeaa..e32bcbd7 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt @@ -66,6 +66,7 @@ set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt new file mode 100644 index 00000000..df7290f2 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required(VERSION 2.8) +include(CheckCSourceCompiles) + +set(SAMP lws-minimal-secure-streams-staticpolicy) + +# If we are being built as part of lws, confirm current build config supports +# reqconfig, else skip building ourselves. +# +# If we are being built externally, confirm installed lws was configured to +# support reqconfig, else error out with a helpful message about the problem. +# +MACRO(require_lws_config reqconfig _val result) + + if (DEFINED ${reqconfig}) + if (${reqconfig}) + set (rq 1) + else() + set (rq 0) + endif() + else() + set(rq 0) + endif() + + if (${_val} EQUAL ${rq}) + set(SAME 1) + else() + set(SAME 0) + endif() + + if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) + if (${_val}) + message("${SAMP}: skipping as lws being built without ${reqconfig}") + else() + message("${SAMP}: skipping as lws built with ${reqconfig}") + endif() + set(${result} 0) + else() + if (LWS_WITH_MINIMAL_EXAMPLES) + set(MET ${SAME}) + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) + if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) + set(HAS_${reqconfig} 0) + else() + set(HAS_${reqconfig} 1) + endif() + if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) + set(MET 1) + else() + set(MET 0) + endif() + endif() + if (NOT MET) + if (${_val}) + message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") + else() + message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") + endif() + endif() + endif() +ENDMACRO() + + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 1 requirements) + +if (requirements) + add_executable(${SAMP} minimal-secure-streams.c) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets) + endif() + +endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/README.md b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/README.md new file mode 100644 index 00000000..64002b20 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/README.md @@ -0,0 +1,61 @@ +# lws minimal secure streams static policy + +The application goes to https://warmcat.com and reads index.html there. + +It does it using a static Secure Streams policy generated from JSON by +policy2c example. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` +$ ./lws-minimal-secure-streams-staticpolicy +[2020/03/26 15:49:12:6640] U: LWS secure streams static policy test client [-d] +[2020/03/26 15:49:12:7067] N: lws_create_context: using ss proxy bind '(null)', port 0, ads '(null)' +[2020/03/26 15:49:12:7567] N: lws_tls_client_create_vhost_context: using mem client CA cert 914 +[2020/03/26 15:49:12:7597] N: lws_tls_client_create_vhost_context: using mem client CA cert 1011 +[2020/03/26 15:49:12:7603] N: lws_tls_client_create_vhost_context: using mem client CA cert 1425 +[2020/03/26 15:49:12:7605] N: lws_tls_client_create_vhost_context: using mem client CA cert 1011 +[2020/03/26 15:49:12:9713] N: lws_system_cpd_set: setting CPD result OK +[2020/03/26 15:49:13:9625] N: ss_api_amazon_auth_rx: acquired 588-byte api.amazon.com auth token, exp 3600s +[2020/03/26 15:49:13:9747] U: myss_state: LWSSSCS_CREATING, ord 0x0 +[2020/03/26 15:49:13:9774] U: myss_state: LWSSSCS_CONNECTING, ord 0x0 +[2020/03/26 15:49:14:1897] U: myss_state: LWSSSCS_CONNECTED, ord 0x0 +[2020/03/26 15:49:14:1926] U: myss_rx: len 1520, flags: 1 +[2020/03/26 15:49:14:1945] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:1946] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:1947] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:1948] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:1949] U: myss_rx: len 583, flags: 0 +[2020/03/26 15:49:14:2087] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2089] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2090] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2091] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2092] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2093] U: myss_rx: len 583, flags: 0 +[2020/03/26 15:49:14:2109] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2110] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2111] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2112] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2113] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2114] U: myss_rx: len 583, flags: 0 +[2020/03/26 15:49:14:2135] U: myss_rx: len 1520, flags: 0 +[2020/03/26 15:49:14:2136] U: myss_rx: len 1358, flags: 0 +[2020/03/26 15:49:14:2136] U: myss_rx: len 0, flags: 2 +[2020/03/26 15:49:14:2138] U: myss_state: LWSSSCS_QOS_ACK_REMOTE, ord 0x0 +[2020/03/26 15:49:14:2139] N: myss_state: LWSSSCS_QOS_ACK_REMOTE +[2020/03/26 15:49:14:2170] U: myss_state: LWSSSCS_DISCONNECTED, ord 0x0 +[2020/03/26 15:49:14:2192] U: myss_state: LWSSSCS_DESTROYING, ord 0x0 +[2020/03/26 15:49:14:2265] E: lws_context_destroy3 +[2020/03/26 15:49:14:2282] U: Completed: OK + +``` diff --git a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c new file mode 100644 index 00000000..3febea07 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/minimal-secure-streams.c @@ -0,0 +1,291 @@ +/* + * lws-minimal-secure-streams + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * + * This demonstrates a minimal http client using secure streams api. + * + * It visits https://warmcat.com/ and receives the html page there. + * + * This example is built two different ways from the same source... one includes + * the policy everything needed to fulfil the stream directly. The other -client + * variant has no policy itself and some other minor init changes, and connects + * to the -proxy example to actually get the connection done. + * + * In the -client build case, the example does not even init the tls libraries + * since the proxy part will take care of all that. + */ + +#include +#include +#include + +static int interrupted, bad = 1, force_cpd_fail_portal, + force_cpd_fail_no_internet; +static lws_state_notify_link_t nl; + +/* + * This is example builds with a static policy autogenerated from a JSON + * policy... + */ +#include "static-policy.h" + + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + lws_sorted_usec_list_t sul; +} myss_t; + +static const char *canned_root_token_payload = + "grant_type=refresh_token" + "&refresh_token=Atzr|IwEBIJedGXjDqsU_vMxykqOMg" + "SHfYe3CPcedueWEMWSDMaDnEmiW8RlR1Kns7Cb4B-TOSnqp7ifVsY4BMY2B8tpHfO39XP" + "zfu9HapGjTR458IyHX44FE71pWJkGZ79uVBpljP4sazJuk8XS3Oe_yLnm_DIO6fU1nU3Y" + "0flYmsOiOAQE_gRk_pdlmEtHnpMA-9rLw3mkY5L89Ty9kUygBsiFaYatouROhbsTn8-jW" + "k1zZLUDpT6ICtBXSnrCIg0pUbZevPFhTwdXd6eX-u4rq0W-XaDvPWFO7au-iPb4Zk5eZE" + "iX6sissYrtNmuEXc2uHu7MnQO1hHCaTdIO2CANVumf-PHSD8xseamyh04sLV5JgFzY45S" + "KvKMajiUZuLkMokOx86rjC2Hdkx5DO7G-dbG1ufBDG-N79pFMSs7Ck5pc283IdLoJkCQc" + "AGvTX8o8I29QqkcGou-9TKhOJmpX8As94T61ok0UqqEKPJ7RhfQHHYdCtsdwxgvfVr9qI" + "xL_hDCcTho8opCVX-6QhJHl6SQFlTw13" + "&client_id=" + "amzn1.application-oa2-client.4823334c434b4190a2b5a42c07938a2d"; + +/* secure streams payload interface */ + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_info(buf, len); + + /* + * If we received the whole message, for our example it means + * we are done. + */ + if (flags & LWSSS_FLAG_EOM) { + bad = 0; + interrupted = 1; + } + + return 0; +} + +static int +myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + //myss_t *m = (myss_t *)userobj; + + return 0; +} + +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10); + lws_ss_set_metadata(m->ss, "ctype", "myctype", 7); + lws_ss_client_connect(m->ss); + break; + case LWSSSCS_ALL_RETRIES_FAILED: + /* if we're out of retries, we want to close the app and FAIL */ + interrupted = 1; + break; + case LWSSSCS_QOS_ACK_REMOTE: + lwsl_notice("%s: LWSSSCS_QOS_ACK_REMOTE\n", __func__); + break; + default: + break; + } + + return 0; +} + +static int +app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + struct lws_context *context = lws_system_context_from_system_mgr(mgr); + lws_system_blob_t *ab = lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_AUTH, 1 /* AUTH_IDX_ROOT */); + size_t size; + + /* + * For the things we care about, let's notice if we are trying to get + * past them when we haven't solved them yet, and make the system + * state wait while we trigger the dependent action. + */ + switch (target) { + + case LWS_SYSTATE_REGISTERED: + size = lws_system_blob_get_size(ab); + if (size) + break; + + /* let's register our canned root token so auth can use it */ + lws_system_blob_direct_set(ab, + (const uint8_t *)canned_root_token_payload, + strlen(canned_root_token_payload)); + break; + + case LWS_SYSTATE_OPERATIONAL: + if (current == LWS_SYSTATE_OPERATIONAL) { + lws_ss_info_t ssi; + + /* We're making an outgoing secure stream ourselves */ + + memset(&ssi, 0, sizeof(ssi)); + ssi.handle_offset = offsetof(myss_t, ss); + ssi.opaque_user_data_offset = offsetof(myss_t, + opaque_data); + ssi.rx = myss_rx; + ssi.tx = myss_tx; + ssi.state = myss_state; + ssi.user_alloc = sizeof(myss_t); + ssi.streamtype = "mintest"; + + if (lws_ss_create(context, 0, &ssi, NULL, NULL, + NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + break; + } + + return 0; +} + +static lws_state_notify_link_t * const app_notifier_list[] = { + &nl, NULL +}; + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + int n = 0; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS secure streams static policy test client [-d]\n"); + + /* these options are mutually exclusive if given */ + + if (lws_cmdline_option(argc, argv, "--force-portal")) + force_cpd_fail_portal = 1; + + if (lws_cmdline_option(argc, argv, "--force-no-internet")) + force_cpd_fail_no_internet = 1; + + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; +#if defined(LWS_SS_USE_SSPC) + info.protocols = lws_sspc_protocols; + { + const char *p; + + /* connect to ssproxy via UDS by default, else via + * tcp connection to this port */ + if ((p = lws_cmdline_option(argc, argv, "-p"))) + info.ss_proxy_port = atoi(p); + + /* UDS "proxy.ss.lws" in abstract namespace, else this socket + * path; when -p given this can specify the network interface + * to bind to */ + if ((p = lws_cmdline_option(argc, argv, "-i"))) + info.ss_proxy_bind = p; + + /* if -p given, -a specifies the proxy address to connect to */ + if ((p = lws_cmdline_option(argc, argv, "-a"))) + info.ss_proxy_address = p; + } +#else + info.pss_policies = &_ss_static_policy_entry; + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#endif +#if defined(LWS_WITH_DETAILED_LATENCY) + info.detailed_latency_cb = lws_det_lat_plot_cb; + info.detailed_latency_filepath = "/tmp/lws-latency-ssproxy"; +#endif + + /* integrate us with lws system state management when context created */ + + nl.name = "app"; + nl.notify_cb = app_system_state_nf; + info.register_notifier_list = app_notifier_list; + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + /* + * Set the related lws_system blobs + * + * ...direct_set() sets a pointer, so the thing pointed to has to have + * a suitable lifetime, eg, something that already exists on the heap or + * a const string in .rodata like this + */ + + lws_system_blob_direct_set(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_DEVICE_SERIAL, 0), + (const uint8_t *)"SN12345678", 10); + lws_system_blob_direct_set(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION, 0), + (const uint8_t *)"v0.01", 5); + + /* + * ..._heap_append() appends to a buflist kind of arrangement on heap, + * just one block is fine, otherwise it will concatenate the fragments + * in the order they were appended (and take care of freeing them at + * context destroy time). ..._heap_empty() is also available to remove + * everything that was already allocated. + * + * Here we use _heap_append() just so it's tested as well as direct set. + */ + + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_DEVICE_TYPE, 0), + (const uint8_t *)"spacerocket", 11); + + /* the event loop */ + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} diff --git a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h new file mode 100644 index 00000000..d2b1bede --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h @@ -0,0 +1,1511 @@ +/* + * Autogenerated from the following JSON policy + */ + +#if 0 +{ + "release": "01234567", + "product": "myproduct", + "schema-version": 1, + "retry": [{ + "default": { + "backoff": [1000, 2000, 3000, 5000, 10000], + "conceal": 5, + "jitterpc": 20, + "svalidping": 30, + "svalidhup": 35 + } + }], + "certs": [{ + "isrg_root_x1": "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZLubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + }, { + "LEX3_isrg_root_x1": "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3MgRW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrXNSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHlNpi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7DcGu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgzuEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMBAAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEFBQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsGAQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYDVR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIBABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGxA/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRMUM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOuOsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vwp7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKRPB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5brUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + }, { + "amazon_root_ca_1": "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5" + }, { + "digicert_global_root_g2": "MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTflMrY=" + }, { + "digicert_global_ca_g2": "MIIEizCCA3OgAwIBAgIQDI7gyQ1qiRWIBAYe4kH5rzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0yODA4MDExMjAwMDBaMEQxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxHjAcBgNVBAMTFURpZ2lDZXJ0IEdsb2JhbCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNIfL7zBYZdW9UvhU5L4IatFaxhz1uvPmoKR/uadpFgC4przc/cV35gmAvkVNlW7SHMArZagV+Xau4CLyMnuG3UsOcGAngLH1ypmTb+u6wbBfpXzYEQQGfWMItYNdSWYb7QjHqXnxr5IuYUL6nG6AEfq/gmD6yOTSwyOR2Bm40cZbIc22GoiS9g5+vCShjEbyrpEJIJ7RfRACvmfe8EiRROM6GyD5eHn7OgzS+8LOy4g2gxPR/VSpAQGQuBldYpdlH5NnbQtwl6OErXb4y/E3w57bqukPyV93t4CTZedJMeJfD/1K2uaGvG/w/VNfFVbkhJ+Pi474j48V4Rd6rfArMCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMi5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFCRuKy3QapJRUSVpAaqaR6aJ50AgMB8GA1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485MA0GCSqGSIb3DQEBCwUAA4IBAQALOYSR+ZfrqoGvhOlaOJL84mxZvzbIRacxAxHhBsCsMsdaVSnaT0AC9aHesO3ewPj2dZ12uYf+QYB6z13jAMZbAuabeGLJ3LhimnftiQjXS8X9Q9ViIyfEBFltcT8jW+rZ8uckJ2/0lYDblizkVIvP6hnZf1WZUXoOLRg9eFhSvGNoVwvdRLNXSmDmyHBwW4coatc7TlJFGa8kBpJIERqLrqwYElesA8u49L3KJg6nwd3jM+/AVTANlVlOnAM2BvjAjxSZnE0qnsHhfTuvcqdFuhOWKU4Z0BqYBvQ3lBetoxi6PrABDJXWKTUgNX31EGDk92hiHuwZ4STyhxGs6QiA" + }, { + "starfield_services_root_ca": "MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkdiEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6" + }, { + "starfield_class_2_ca": "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJlxy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=" + }], + "trust_stores": [{ + "name": "le_via_isrg", + "stack": ["isrg_root_x1", "LEX3_isrg_root_x1"] + }, { + "name": "api_amazon_com", + "stack": ["digicert_global_ca_g2", "digicert_global_root_g2"] + }, { + "name": "avs_via_starfield", + "stack": ["starfield_class_2_ca", "starfield_services_root_ca"] + }, { + "name": "mqtt_amz_iot", + "stack": ["amazon_root_ca_1", "starfield_class_2_ca", "starfield_services_root_ca"] + }], + "s": [{ + "api_amazon_com_auth": { + "endpoint": "api.amazon.com", + "port": 443, + "protocol": "h1", + "http_method": "POST", + "http_url": "auth/o2/token", + "plugins": [], + "opportunistic": true, + "tls": true, + "h2q_oflow_txcr": true, + "http_www_form_urlencoded": true, + "http_no_content_length": true, + "retry": "default", + "tls_trust_store": "api_amazon_com" + } + }, { + "avs_event": { + "endpoint": "alexa.na.gateway.devices.a2z.com", + "port": 443, + "protocol": "h2", + "http_method": "GET", + "http_url": "v20160207/directives", + "h2q_oflow_txcr": true, + "http_auth_header": "authorization:", + "http_auth_preamble": "Bearer ", + "http_no_content_length": true, + "nailed_up": true, + "long_poll": true, + "retry": "default", + "plugins": [], + "tls": true, + "tls_trust_store": "avs_via_starfield" + } + }, { + "avs_metadata": { + "endpoint": "alexa.na.gateway.devices.a2z.com", + "port": 443, + "protocol": "h2", + "http_method": "POST", + "http_url": "v20160207/events", + "opportunistic": true, + "h2q_oflow_txcr": true, + "http_auth_header": "authorization:", + "http_auth_preamble": "Bearer ", + "http_multipart_name": "metadata", + "http_mime_content_type": "application/json; charset=UTF-8", + "http_no_content_length": true, + "rideshare": "avs_audio", + "retry": "default", + "plugins": [], + "tls": true, + "tls_trust_store": "avs_via_starfield" + } + }, { + "avs_audio": { + "endpoint": "alexa.na.gateway.devices.a2z.com", + "port": 443, + "protocol": "h2", + "http_method": "POST", + "http_url": "v20160207/events", + "plugins": [], + "tls": true, + "h2q_oflow_txcr": true, + "http_auth_header": "authorization:", + "http_auth_preamble": "Bearer ", + "http_multipart_name": "audio", + "http_mime_content_type": "application/octet-stream", + "http_no_content_length": true, + "retry": "default", + "tls_trust_store": "avs_via_starfield" + } + }, { + "mintest": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h1", + "http_method": "GET", + "http_url": "index.html?uptag=${uptag}", + "http_dsn_header": "x-dsn:", + "http_fwv_header": "x-fw-version:", + "http_devtype_header": "x-devtype:", + "metadata": [{ + "uptag": "X-Upload-Tag:" + }, { + "ctype": "Content-Type:" + }, { + "xctype": "X-Content-Type:" + }], + "plugins": [], + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "h2longpolltest": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h2", + "http_method": "GET", + "http_url": "index.html", + "plugins": [], + "tls": true, + "nailed_up": true, + "long_poll": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "mintest-fail": { + "endpoint": "warmcat.com", + "port": 22, + "protocol": "h1", + "http_method": "GET", + "http_url": "index.html", + "plugins": [], + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "minpost": { + "endpoint": "warmcat.com", + "port": 443, + "protocol": "h1", + "http_method": "POST", + "http_url": "testserver/formtest", + "plugins": [], + "tls": true, + "opportunistic": true, + "retry": "default", + "tls_trust_store": "le_via_isrg" + } + }, { + "mqtt_test": { + "endpoint": "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + "port": 443, + "tls": true, + "client_cert": 0, + "tls_trust_store": "mqtt_amz_iot", + "protocol": "mqtt", + "mqtt_topic": "test/topic0", + "mqtt_subscribe": "test/topic0", + "mqtt_qos": 0, + "retry": "default" + } + }, { + "mqtt_test1": { + "endpoint": "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + "port": 443, + "tls": true, + "client_cert": 0, + "tls_trust_store": "mqtt_amz_iot", + "protocol": "mqtt", + "mqtt_topic": "test/topic1", + "mqtt_subscribe": "test/topic1", + "mqtt_qos": 1, + "retry": "default" + } + }, { + "captive_portal_detect": { + "endpoint": "connectivitycheck.android.com", + "port": 80, + "protocol": "h1", + "http_method": "GET", + "http_url": "generate_204", + "opportunistic": true, + "http_expect": 204, + "http_fail_redirect": true + } + } + ] +} + + + Original JSON size: 15491 +#endif + +static const uint32_t _rbo_bo_0[] = { + 1000, 2000, 3000, 5000, 10000, +}; +static const lws_retry_bo_t _rbo_0 = { + .retry_ms_table = _rbo_bo_0, + .retry_ms_table_count = 5, + .conceal_count = 5, + .secs_since_valid_ping = 30, + .secs_since_valid_hangup = 35, + .jitter_percent = 20, +}; +static const uint8_t _ss_der_amazon_root_ca_1[] = { + /* 0x 0 */ 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x06, + /* 0x 10 */ 0x6C, 0x9F, 0xCF, 0x99, 0xBF, 0x8C, 0x0A, 0x39, + /* 0x 18 */ 0xE2, 0xF0, 0x78, 0x8A, 0x43, 0xE6, 0x96, 0x36, + /* 0x 20 */ 0x5B, 0xCA, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + /* 0x 28 */ 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + /* 0x 30 */ 0x00, 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, + /* 0x 38 */ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + /* 0x 40 */ 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + /* 0x 48 */ 0x0A, 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + /* 0x 50 */ 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + /* 0x 58 */ 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, + /* 0x 60 */ 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + /* 0x 68 */ 0x43, 0x41, 0x20, 0x31, 0x30, 0x1E, 0x17, 0x0D, + /* 0x 70 */ 0x31, 0x35, 0x30, 0x35, 0x32, 0x36, 0x30, 0x30, + /* 0x 78 */ 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, + /* 0x 80 */ 0x38, 0x30, 0x31, 0x31, 0x37, 0x30, 0x30, 0x30, + /* 0x 88 */ 0x30, 0x30, 0x30, 0x5A, 0x30, 0x39, 0x31, 0x0B, + /* 0x 90 */ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + /* 0x 98 */ 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, + /* 0x a0 */ 0x03, 0x55, 0x04, 0x0A, 0x13, 0x06, 0x41, 0x6D, + /* 0x a8 */ 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + /* 0x b0 */ 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, + /* 0x b8 */ 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x20, 0x52, 0x6F, + /* 0x c0 */ 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x30, + /* 0x c8 */ 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x d0 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + /* 0x d8 */ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, + /* 0x e0 */ 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, + /* 0x e8 */ 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, + /* 0x f0 */ 0x71, 0xAF, 0x47, 0x80, 0x50, 0x74, 0x7D, 0x6E, + /* 0x f8 */ 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + /* 0x100 */ 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, + /* 0x108 */ 0xAC, 0x02, 0x2D, 0x86, 0xD3, 0xA0, 0x43, 0x7A, + /* 0x110 */ 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + /* 0x118 */ 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, + /* 0x120 */ 0xF4, 0xEE, 0x88, 0x23, 0xC7, 0x3E, 0xEB, 0x37, + /* 0x128 */ 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + /* 0x130 */ 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, + /* 0x138 */ 0xFE, 0x82, 0x36, 0xA5, 0xE5, 0x4A, 0x56, 0xE4, + /* 0x140 */ 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + /* 0x148 */ 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, + /* 0x150 */ 0x20, 0x50, 0x06, 0x6C, 0x7A, 0xD0, 0x80, 0xB2, + /* 0x158 */ 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + /* 0x160 */ 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, + /* 0x168 */ 0xBA, 0xD5, 0xA9, 0xF9, 0x48, 0x67, 0x30, 0x96, + /* 0x170 */ 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + /* 0x178 */ 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, + /* 0x180 */ 0x54, 0xEB, 0xA3, 0xC3, 0x91, 0xF9, 0x48, 0xDC, + /* 0x188 */ 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + /* 0x190 */ 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, + /* 0x198 */ 0x59, 0x6E, 0xBB, 0x73, 0x87, 0x17, 0xF2, 0x32, + /* 0x1a0 */ 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + /* 0x1a8 */ 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, + /* 0x1b0 */ 0xF7, 0x71, 0x5C, 0x5E, 0x69, 0xFF, 0xEA, 0x95, + /* 0x1b8 */ 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + /* 0x1c0 */ 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, + /* 0x1c8 */ 0x54, 0xE1, 0x77, 0xE0, 0x67, 0xC8, 0x0F, 0x9C, + /* 0x1d0 */ 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + /* 0x1d8 */ 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, + /* 0x1e0 */ 0x8E, 0x04, 0xAE, 0x6C, 0x9A, 0xC8, 0xAA, 0x0D, + /* 0x1e8 */ 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x42, 0x30, + /* 0x1f0 */ 0x40, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, + /* 0x1f8 */ 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, + /* 0x200 */ 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, + /* 0x208 */ 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, + /* 0x210 */ 0x01, 0x86, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, + /* 0x218 */ 0x0E, 0x04, 0x16, 0x04, 0x14, 0x84, 0x18, 0xCC, + /* 0x220 */ 0x85, 0x34, 0xEC, 0xBC, 0x0C, 0x94, 0x94, 0x2E, + /* 0x228 */ 0x08, 0x59, 0x9C, 0xC7, 0xB2, 0x10, 0x4E, 0x0A, + /* 0x230 */ 0x08, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + /* 0x238 */ 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + /* 0x240 */ 0x03, 0x82, 0x01, 0x01, 0x00, 0x98, 0xF2, 0x37, + /* 0x248 */ 0x5A, 0x41, 0x90, 0xA1, 0x1A, 0xC5, 0x76, 0x51, + /* 0x250 */ 0x28, 0x20, 0x36, 0x23, 0x0E, 0xAE, 0xE6, 0x28, + /* 0x258 */ 0xBB, 0xAA, 0xF8, 0x94, 0xAE, 0x48, 0xA4, 0x30, + /* 0x260 */ 0x7F, 0x1B, 0xFC, 0x24, 0x8D, 0x4B, 0xB4, 0xC8, + /* 0x268 */ 0xA1, 0x97, 0xF6, 0xB6, 0xF1, 0x7A, 0x70, 0xC8, + /* 0x270 */ 0x53, 0x93, 0xCC, 0x08, 0x28, 0xE3, 0x98, 0x25, + /* 0x278 */ 0xCF, 0x23, 0xA4, 0xF9, 0xDE, 0x21, 0xD3, 0x7C, + /* 0x280 */ 0x85, 0x09, 0xAD, 0x4E, 0x9A, 0x75, 0x3A, 0xC2, + /* 0x288 */ 0x0B, 0x6A, 0x89, 0x78, 0x76, 0x44, 0x47, 0x18, + /* 0x290 */ 0x65, 0x6C, 0x8D, 0x41, 0x8E, 0x3B, 0x7F, 0x9A, + /* 0x298 */ 0xCB, 0xF4, 0xB5, 0xA7, 0x50, 0xD7, 0x05, 0x2C, + /* 0x2a0 */ 0x37, 0xE8, 0x03, 0x4B, 0xAD, 0xE9, 0x61, 0xA0, + /* 0x2a8 */ 0x02, 0x6E, 0xF5, 0xF2, 0xF0, 0xC5, 0xB2, 0xED, + /* 0x2b0 */ 0x5B, 0xB7, 0xDC, 0xFA, 0x94, 0x5C, 0x77, 0x9E, + /* 0x2b8 */ 0x13, 0xA5, 0x7F, 0x52, 0xAD, 0x95, 0xF2, 0xF8, + /* 0x2c0 */ 0x93, 0x3B, 0xDE, 0x8B, 0x5C, 0x5B, 0xCA, 0x5A, + /* 0x2c8 */ 0x52, 0x5B, 0x60, 0xAF, 0x14, 0xF7, 0x4B, 0xEF, + /* 0x2d0 */ 0xA3, 0xFB, 0x9F, 0x40, 0x95, 0x6D, 0x31, 0x54, + /* 0x2d8 */ 0xFC, 0x42, 0xD3, 0xC7, 0x46, 0x1F, 0x23, 0xAD, + /* 0x2e0 */ 0xD9, 0x0F, 0x48, 0x70, 0x9A, 0xD9, 0x75, 0x78, + /* 0x2e8 */ 0x71, 0xD1, 0x72, 0x43, 0x34, 0x75, 0x6E, 0x57, + /* 0x2f0 */ 0x59, 0xC2, 0x02, 0x5C, 0x26, 0x60, 0x29, 0xCF, + /* 0x2f8 */ 0x23, 0x19, 0x16, 0x8E, 0x88, 0x43, 0xA5, 0xD4, + /* 0x300 */ 0xE4, 0xCB, 0x08, 0xFB, 0x23, 0x11, 0x43, 0xE8, + /* 0x308 */ 0x43, 0x29, 0x72, 0x62, 0xA1, 0xA9, 0x5D, 0x5E, + /* 0x310 */ 0x08, 0xD4, 0x90, 0xAE, 0xB8, 0xD8, 0xCE, 0x14, + /* 0x318 */ 0xC2, 0xD0, 0x55, 0xF2, 0x86, 0xF6, 0xC4, 0x93, + /* 0x320 */ 0x43, 0x77, 0x66, 0x61, 0xC0, 0xB9, 0xE8, 0x41, + /* 0x328 */ 0xD7, 0x97, 0x78, 0x60, 0x03, 0x6E, 0x4A, 0x72, + /* 0x330 */ 0xAE, 0xA5, 0xD1, 0x7D, 0xBA, 0x10, 0x9E, 0x86, + /* 0x338 */ 0x6C, 0x1B, 0x8A, 0xB9, 0x59, 0x33, 0xF8, 0xEB, + /* 0x340 */ 0xC4, 0x90, 0xBE, 0xF1, 0xB9, +}; +static const lws_ss_x509_t _ss_x509_amazon_root_ca_1 = { + .vhost_name = "amazon_root_ca_1", + .ca_der = _ss_der_amazon_root_ca_1, + .ca_der_len = 837, +}; +static const uint8_t _ss_der_starfield_class_2_ca[] = { + /* 0x 0 */ 0x30, 0x82, 0x04, 0x0F, 0x30, 0x82, 0x02, 0xF7, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, + /* 0x 10 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 18 */ 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + /* 0x 20 */ 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + /* 0x 28 */ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x25, + /* 0x 30 */ 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 38 */ 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + /* 0x 40 */ 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + /* 0x 48 */ 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x2C, + /* 0x 50 */ 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, + /* 0x 58 */ 0x30, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x29, + /* 0x 60 */ 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, + /* 0x 68 */ 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, + /* 0x 70 */ 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + /* 0x 78 */ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, + /* 0x 80 */ 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + /* 0x 88 */ 0x79, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x34, 0x30, + /* 0x 90 */ 0x36, 0x32, 0x39, 0x31, 0x37, 0x33, 0x39, 0x31, + /* 0x 98 */ 0x36, 0x5A, 0x17, 0x0D, 0x33, 0x34, 0x30, 0x36, + /* 0x a0 */ 0x32, 0x39, 0x31, 0x37, 0x33, 0x39, 0x31, 0x36, + /* 0x a8 */ 0x5A, 0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, + /* 0x b0 */ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + /* 0x b8 */ 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + /* 0x c0 */ 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, + /* 0x c8 */ 0x69, 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, + /* 0x d0 */ 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, + /* 0x d8 */ 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, + /* 0x e0 */ 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0B, + /* 0x e8 */ 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + /* 0x f0 */ 0x65, 0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, + /* 0x f8 */ 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, + /* 0x100 */ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, + /* 0x108 */ 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, + /* 0x110 */ 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x20, 0x30, + /* 0x118 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x120 */ 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + /* 0x128 */ 0x01, 0x0D, 0x00, 0x30, 0x82, 0x01, 0x08, 0x02, + /* 0x130 */ 0x82, 0x01, 0x01, 0x00, 0xB7, 0x32, 0xC8, 0xFE, + /* 0x138 */ 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11, + /* 0x140 */ 0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, + /* 0x148 */ 0x87, 0x3F, 0xA1, 0xAB, 0xFB, 0x3C, 0xA6, 0x9F, + /* 0x150 */ 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B, + /* 0x158 */ 0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, + /* 0x160 */ 0x9E, 0xE8, 0x5F, 0xEC, 0xE5, 0x27, 0x44, 0xF5, + /* 0x168 */ 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0, + /* 0x170 */ 0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, + /* 0x178 */ 0x93, 0x1E, 0x8F, 0x66, 0x1C, 0x39, 0xA7, 0x4D, + /* 0x180 */ 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB, + /* 0x188 */ 0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, + /* 0x190 */ 0x14, 0x54, 0xEB, 0x26, 0xC7, 0xF3, 0x7F, 0x19, + /* 0x198 */ 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A, + /* 0x1a0 */ 0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, + /* 0x1a8 */ 0x04, 0x87, 0xA3, 0xD4, 0xF9, 0x89, 0xA5, 0x34, + /* 0x1b0 */ 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66, + /* 0x1b8 */ 0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, + /* 0x1c0 */ 0x3E, 0x10, 0xC8, 0x3B, 0xEF, 0x06, 0x65, 0x66, + /* 0x1c8 */ 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51, + /* 0x1d0 */ 0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, + /* 0x1d8 */ 0xB2, 0x5D, 0x06, 0x6C, 0xC3, 0x23, 0x56, 0x9A, + /* 0x1e0 */ 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3, + /* 0x1e8 */ 0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, + /* 0x1f0 */ 0x36, 0x3D, 0xEA, 0x9C, 0xD3, 0x35, 0xB3, 0xBC, + /* 0x1f8 */ 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64, + /* 0x200 */ 0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, + /* 0x208 */ 0x99, 0xC9, 0x1E, 0x87, 0xB4, 0x9D, 0x1A, 0xC0, + /* 0x210 */ 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B, + /* 0x218 */ 0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, + /* 0x220 */ 0x3E, 0xBB, 0x78, 0x0D, 0x1C, 0x42, 0x67, 0x6B, + /* 0x228 */ 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2, + /* 0x230 */ 0x44, 0xA0, 0x01, 0xAB, 0x02, 0x01, 0x03, 0xA3, + /* 0x238 */ 0x81, 0xC5, 0x30, 0x81, 0xC2, 0x30, 0x1D, 0x06, + /* 0x240 */ 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, + /* 0x248 */ 0xBF, 0x5F, 0xB7, 0xD1, 0xCE, 0xDD, 0x1F, 0x86, + /* 0x250 */ 0xF4, 0x5B, 0x55, 0xAC, 0xDC, 0xD7, 0x10, 0xC2, + /* 0x258 */ 0x0E, 0xA9, 0x88, 0xE7, 0x30, 0x81, 0x92, 0x06, + /* 0x260 */ 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0x8A, 0x30, + /* 0x268 */ 0x81, 0x87, 0x80, 0x14, 0xBF, 0x5F, 0xB7, 0xD1, + /* 0x270 */ 0xCE, 0xDD, 0x1F, 0x86, 0xF4, 0x5B, 0x55, 0xAC, + /* 0x278 */ 0xDC, 0xD7, 0x10, 0xC2, 0x0E, 0xA9, 0x88, 0xE7, + /* 0x280 */ 0xA1, 0x6C, 0xA4, 0x6A, 0x30, 0x68, 0x31, 0x0B, + /* 0x288 */ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + /* 0x290 */ 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, + /* 0x298 */ 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, + /* 0x2a0 */ 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, + /* 0x2a8 */ 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, + /* 0x2b0 */ 0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, + /* 0x2b8 */ 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, + /* 0x2c0 */ 0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, + /* 0x2c8 */ 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x43, + /* 0x2d0 */ 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, + /* 0x2d8 */ 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + /* 0x2e0 */ 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, + /* 0x2e8 */ 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x82, 0x01, + /* 0x2f0 */ 0x00, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, + /* 0x2f8 */ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, + /* 0x300 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x308 */ 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, + /* 0x310 */ 0x01, 0x01, 0x00, 0x05, 0x9D, 0x3F, 0x88, 0x9D, + /* 0x318 */ 0xD1, 0xC9, 0x1A, 0x55, 0xA1, 0xAC, 0x69, 0xF3, + /* 0x320 */ 0xF3, 0x59, 0xDA, 0x9B, 0x01, 0x87, 0x1A, 0x4F, + /* 0x328 */ 0x57, 0xA9, 0xA1, 0x79, 0x09, 0x2A, 0xDB, 0xF7, + /* 0x330 */ 0x2F, 0xB2, 0x1E, 0xCC, 0xC7, 0x5E, 0x6A, 0xD8, + /* 0x338 */ 0x83, 0x87, 0xA1, 0x97, 0xEF, 0x49, 0x35, 0x3E, + /* 0x340 */ 0x77, 0x06, 0x41, 0x58, 0x62, 0xBF, 0x8E, 0x58, + /* 0x348 */ 0xB8, 0x0A, 0x67, 0x3F, 0xEC, 0xB3, 0xDD, 0x21, + /* 0x350 */ 0x66, 0x1F, 0xC9, 0x54, 0xFA, 0x72, 0xCC, 0x3D, + /* 0x358 */ 0x4C, 0x40, 0xD8, 0x81, 0xAF, 0x77, 0x9E, 0x83, + /* 0x360 */ 0x7A, 0xBB, 0xA2, 0xC7, 0xF5, 0x34, 0x17, 0x8E, + /* 0x368 */ 0xD9, 0x11, 0x40, 0xF4, 0xFC, 0x2C, 0x2A, 0x4D, + /* 0x370 */ 0x15, 0x7F, 0xA7, 0x62, 0x5D, 0x2E, 0x25, 0xD3, + /* 0x378 */ 0x00, 0x0B, 0x20, 0x1A, 0x1D, 0x68, 0xF9, 0x17, + /* 0x380 */ 0xB8, 0xF4, 0xBD, 0x8B, 0xED, 0x28, 0x59, 0xDD, + /* 0x388 */ 0x4D, 0x16, 0x8B, 0x17, 0x83, 0xC8, 0xB2, 0x65, + /* 0x390 */ 0xC7, 0x2D, 0x7A, 0xA5, 0xAA, 0xBC, 0x53, 0x86, + /* 0x398 */ 0x6D, 0xDD, 0x57, 0xA4, 0xCA, 0xF8, 0x20, 0x41, + /* 0x3a0 */ 0x0B, 0x68, 0xF0, 0xF4, 0xFB, 0x74, 0xBE, 0x56, + /* 0x3a8 */ 0x5D, 0x7A, 0x79, 0xF5, 0xF9, 0x1D, 0x85, 0xE3, + /* 0x3b0 */ 0x2D, 0x95, 0xBE, 0xF5, 0x71, 0x90, 0x43, 0xCC, + /* 0x3b8 */ 0x8D, 0x1F, 0x9A, 0x00, 0x0A, 0x87, 0x29, 0xE9, + /* 0x3c0 */ 0x55, 0x22, 0x58, 0x00, 0x23, 0xEA, 0xE3, 0x12, + /* 0x3c8 */ 0x43, 0x29, 0x5B, 0x47, 0x08, 0xDD, 0x8C, 0x41, + /* 0x3d0 */ 0x6A, 0x65, 0x06, 0xA8, 0xE5, 0x21, 0xAA, 0x41, + /* 0x3d8 */ 0xB4, 0x95, 0x21, 0x95, 0xB9, 0x7D, 0xD1, 0x34, + /* 0x3e0 */ 0xAB, 0x13, 0xD6, 0xAD, 0xBC, 0xDC, 0xE2, 0x3D, + /* 0x3e8 */ 0x39, 0xCD, 0xBD, 0x3E, 0x75, 0x70, 0xA1, 0x18, + /* 0x3f0 */ 0x59, 0x03, 0xC9, 0x22, 0xB4, 0x8F, 0x9C, 0xD5, + /* 0x3f8 */ 0x5E, 0x2A, 0xD7, 0xA5, 0xB6, 0xD4, 0x0A, 0x6D, + /* 0x400 */ 0xF8, 0xB7, 0x40, 0x11, 0x46, 0x9A, 0x1F, 0x79, + /* 0x408 */ 0x0E, 0x62, 0xBF, 0x0F, 0x97, 0xEC, 0xE0, 0x2F, + /* 0x410 */ 0x1F, 0x17, 0x94, +}; +static const lws_ss_x509_t _ss_x509_starfield_class_2_ca = { + .vhost_name = "starfield_class_2_ca", + .ca_der = _ss_der_starfield_class_2_ca, + .ca_der_len = 1043, +}; +static const uint8_t _ss_der_starfield_services_root_ca[] = { + /* 0x 0 */ 0x30, 0x82, 0x03, 0xEF, 0x30, 0x82, 0x02, 0xD7, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, + /* 0x 10 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 18 */ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + /* 0x 20 */ 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + /* 0x 28 */ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + /* 0x 30 */ 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, + /* 0x 38 */ 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, + /* 0x 40 */ 0x61, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + /* 0x 48 */ 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F, 0x74, + /* 0x 50 */ 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, + /* 0x 58 */ 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 60 */ 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + /* 0x 68 */ 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, + /* 0x 70 */ 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x2C, + /* 0x 78 */ 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B, 0x30, + /* 0x 80 */ 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, + /* 0x 88 */ 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, + /* 0x 90 */ 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + /* 0x 98 */ 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, + /* 0x a0 */ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + /* 0x a8 */ 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, + /* 0x b0 */ 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, + /* 0x b8 */ 0x47, 0x32, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x39, + /* 0x c0 */ 0x30, 0x39, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + /* 0x c8 */ 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x37, 0x31, + /* 0x d0 */ 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, + /* 0x d8 */ 0x39, 0x5A, 0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, + /* 0x e0 */ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + /* 0x e8 */ 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + /* 0x f0 */ 0x55, 0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, + /* 0x f8 */ 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13, 0x30, 0x11, + /* 0x100 */ 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, + /* 0x108 */ 0x63, 0x6F, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, + /* 0x110 */ 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, + /* 0x118 */ 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, + /* 0x120 */ 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, + /* 0x128 */ 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, + /* 0x130 */ 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, + /* 0x138 */ 0x31, 0x3B, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, + /* 0x140 */ 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, 0x72, 0x66, + /* 0x148 */ 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, + /* 0x150 */ 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, + /* 0x158 */ 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + /* 0x160 */ 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, + /* 0x168 */ 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, + /* 0x170 */ 0x20, 0x2D, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, + /* 0x178 */ 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + /* 0x180 */ 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, + /* 0x188 */ 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + /* 0x190 */ 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xD5, 0x0C, + /* 0x198 */ 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, + /* 0x1a0 */ 0x19, 0x97, 0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, + /* 0x1a8 */ 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13, 0x6D, 0x29, + /* 0x1b0 */ 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, + /* 0x1b8 */ 0x38, 0x63, 0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, + /* 0x1c0 */ 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59, 0x7F, 0xF6, + /* 0x1c8 */ 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, + /* 0x1d0 */ 0x52, 0x9A, 0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, + /* 0x1d8 */ 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49, 0xD9, 0xB6, + /* 0x1e0 */ 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, + /* 0x1e8 */ 0xEB, 0xCF, 0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, + /* 0x1f0 */ 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94, 0x89, 0x47, + /* 0x1f8 */ 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, + /* 0x200 */ 0xDA, 0x84, 0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, + /* 0x208 */ 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A, 0x1D, 0x4A, + /* 0x210 */ 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, + /* 0x218 */ 0x00, 0x70, 0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, + /* 0x220 */ 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45, 0xF6, 0xC2, + /* 0x228 */ 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, + /* 0x230 */ 0x34, 0x47, 0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, + /* 0x238 */ 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6, 0xE7, 0xDE, + /* 0x240 */ 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, + /* 0x248 */ 0x6D, 0xA9, 0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, + /* 0x250 */ 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB, 0xB1, 0x6B, + /* 0x258 */ 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, + /* 0x260 */ 0x46, 0x32, 0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, + /* 0x268 */ 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73, 0xBB, 0x64, + /* 0x270 */ 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, + /* 0x278 */ 0x87, 0x2F, 0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, + /* 0x280 */ 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE, 0x2A, 0x2F, + /* 0x288 */ 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, + /* 0x290 */ 0x02, 0x55, 0x39, 0x8B, 0x7F, 0x05, 0x02, 0x03, + /* 0x298 */ 0x01, 0x00, 0x01, 0xA3, 0x42, 0x30, 0x40, 0x30, + /* 0x2a0 */ 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, + /* 0x2a8 */ 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + /* 0x2b0 */ 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, + /* 0x2b8 */ 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, + /* 0x2c0 */ 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + /* 0x2c8 */ 0x16, 0x04, 0x14, 0x9C, 0x5F, 0x00, 0xDF, 0xAA, + /* 0x2d0 */ 0x01, 0xD7, 0x30, 0x2B, 0x38, 0x88, 0xA2, 0xB8, + /* 0x2d8 */ 0x6D, 0x4A, 0x9C, 0xF2, 0x11, 0x91, 0x83, 0x30, + /* 0x2e0 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x2e8 */ 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, + /* 0x2f0 */ 0x01, 0x01, 0x00, 0x4B, 0x36, 0xA6, 0x84, 0x77, + /* 0x2f8 */ 0x69, 0xDD, 0x3B, 0x19, 0x9F, 0x67, 0x23, 0x08, + /* 0x300 */ 0x6F, 0x0E, 0x61, 0xC9, 0xFD, 0x84, 0xDC, 0x5F, + /* 0x308 */ 0xD8, 0x36, 0x81, 0xCD, 0xD8, 0x1B, 0x41, 0x2D, + /* 0x310 */ 0x9F, 0x60, 0xDD, 0xC7, 0x1A, 0x68, 0xD9, 0xD1, + /* 0x318 */ 0x6E, 0x86, 0xE1, 0x88, 0x23, 0xCF, 0x13, 0xDE, + /* 0x320 */ 0x43, 0xCF, 0xE2, 0x34, 0xB3, 0x04, 0x9D, 0x1F, + /* 0x328 */ 0x29, 0xD5, 0xBF, 0xF8, 0x5E, 0xC8, 0xD5, 0xC1, + /* 0x330 */ 0xBD, 0xEE, 0x92, 0x6F, 0x32, 0x74, 0xF2, 0x91, + /* 0x338 */ 0x82, 0x2F, 0xBD, 0x82, 0x42, 0x7A, 0xAD, 0x2A, + /* 0x340 */ 0xB7, 0x20, 0x7D, 0x4D, 0xBC, 0x7A, 0x55, 0x12, + /* 0x348 */ 0xC2, 0x15, 0xEA, 0xBD, 0xF7, 0x6A, 0x95, 0x2E, + /* 0x350 */ 0x6C, 0x74, 0x9F, 0xCF, 0x1C, 0xB4, 0xF2, 0xC5, + /* 0x358 */ 0x01, 0xA3, 0x85, 0xD0, 0x72, 0x3E, 0xAD, 0x73, + /* 0x360 */ 0xAB, 0x0B, 0x9B, 0x75, 0x0C, 0x6D, 0x45, 0xB7, + /* 0x368 */ 0x8E, 0x94, 0xAC, 0x96, 0x37, 0xB5, 0xA0, 0xD0, + /* 0x370 */ 0x8F, 0x15, 0x47, 0x0E, 0xE3, 0xE8, 0x83, 0xDD, + /* 0x378 */ 0x8F, 0xFD, 0xEF, 0x41, 0x01, 0x77, 0xCC, 0x27, + /* 0x380 */ 0xA9, 0x62, 0x85, 0x33, 0xF2, 0x37, 0x08, 0xEF, + /* 0x388 */ 0x71, 0xCF, 0x77, 0x06, 0xDE, 0xC8, 0x19, 0x1D, + /* 0x390 */ 0x88, 0x40, 0xCF, 0x7D, 0x46, 0x1D, 0xFF, 0x1E, + /* 0x398 */ 0xC7, 0xE1, 0xCE, 0xFF, 0x23, 0xDB, 0xC6, 0xFA, + /* 0x3a0 */ 0x8D, 0x55, 0x4E, 0xA9, 0x02, 0xE7, 0x47, 0x11, + /* 0x3a8 */ 0x46, 0x3E, 0xF4, 0xFD, 0xBD, 0x7B, 0x29, 0x26, + /* 0x3b0 */ 0xBB, 0xA9, 0x61, 0x62, 0x37, 0x28, 0xB6, 0x2D, + /* 0x3b8 */ 0x2A, 0xF6, 0x10, 0x86, 0x64, 0xC9, 0x70, 0xA7, + /* 0x3c0 */ 0xD2, 0xAD, 0xB7, 0x29, 0x70, 0x79, 0xEA, 0x3C, + /* 0x3c8 */ 0xDA, 0x63, 0x25, 0x9F, 0xFD, 0x68, 0xB7, 0x30, + /* 0x3d0 */ 0xEC, 0x70, 0xFB, 0x75, 0x8A, 0xB7, 0x6D, 0x60, + /* 0x3d8 */ 0x67, 0xB2, 0x1E, 0xC8, 0xB9, 0xE9, 0xD8, 0xA8, + /* 0x3e0 */ 0x6F, 0x02, 0x8B, 0x67, 0x0D, 0x4D, 0x26, 0x57, + /* 0x3e8 */ 0x71, 0xDA, 0x20, 0xFC, 0xC1, 0x4A, 0x50, 0x8D, + /* 0x3f0 */ 0xB1, 0x28, 0xBA, +}; +static const lws_ss_x509_t _ss_x509_starfield_services_root_ca = { + .vhost_name = "starfield_services_root_ca", + .ca_der = _ss_der_starfield_services_root_ca, + .ca_der_len = 1011, +}; +static const lws_ss_trust_store_t _ss_ts_mqtt_amz_iot = { + .name = "mqtt_amz_iot", + .ssx509 = { + &_ss_x509_starfield_services_root_ca, + &_ss_x509_starfield_class_2_ca, + &_ss_x509_amazon_root_ca_1, + } +}; +static const uint8_t _ss_der_isrg_root_x1[] = { + /* 0x 0 */ 0x30, 0x82, 0x05, 0x6B, 0x30, 0x82, 0x03, 0x53, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, + /* 0x 10 */ 0x82, 0x10, 0xCF, 0xB0, 0xD2, 0x40, 0xE3, 0x59, + /* 0x 18 */ 0x44, 0x63, 0xE0, 0xBB, 0x63, 0x82, 0x8B, 0x00, + /* 0x 20 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 28 */ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + /* 0x 30 */ 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + /* 0x 38 */ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x29, + /* 0x 40 */ 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 48 */ 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, + /* 0x 50 */ 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + /* 0x 58 */ 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, + /* 0x 60 */ 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, + /* 0x 68 */ 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + /* 0x 70 */ 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, 0x47, + /* 0x 78 */ 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31, + /* 0x 80 */ 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x36, + /* 0x 88 */ 0x30, 0x34, 0x31, 0x31, 0x30, 0x34, 0x33, 0x38, + /* 0x 90 */ 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x36, 0x30, + /* 0x 98 */ 0x34, 0x31, 0x31, 0x30, 0x34, 0x33, 0x38, 0x5A, + /* 0x a0 */ 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + /* 0x a8 */ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + /* 0x b0 */ 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + /* 0x b8 */ 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, + /* 0x c0 */ 0x65, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, + /* 0x c8 */ 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + /* 0x d0 */ 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, + /* 0x d8 */ 0x75, 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + /* 0x e0 */ 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + /* 0x e8 */ 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, + /* 0x f0 */ 0x31, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0D, 0x06, + /* 0x f8 */ 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + /* 0x100 */ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0F, + /* 0x108 */ 0x00, 0x30, 0x82, 0x02, 0x0A, 0x02, 0x82, 0x02, + /* 0x110 */ 0x01, 0x00, 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, + /* 0x118 */ 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, 0x28, 0x1C, + /* 0x120 */ 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, + /* 0x128 */ 0x6E, 0x3C, 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, + /* 0x130 */ 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, 0xF6, 0x00, + /* 0x138 */ 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, + /* 0x140 */ 0x93, 0xB6, 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, + /* 0x148 */ 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, 0x21, 0x7E, + /* 0x150 */ 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, + /* 0x158 */ 0xDF, 0xB3, 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, + /* 0x160 */ 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, 0x4A, 0x66, + /* 0x168 */ 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, + /* 0x170 */ 0x29, 0x22, 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, + /* 0x178 */ 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, 0x7E, 0x94, + /* 0x180 */ 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, + /* 0x188 */ 0x23, 0x53, 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, + /* 0x190 */ 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, 0x80, 0x74, + /* 0x198 */ 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, + /* 0x1a0 */ 0x70, 0x21, 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, + /* 0x1a8 */ 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, 0xEB, 0x16, + /* 0x1b0 */ 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, + /* 0x1b8 */ 0xE8, 0xFF, 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, + /* 0x1c0 */ 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, 0x70, 0x8D, + /* 0x1c8 */ 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, + /* 0x1d0 */ 0xD9, 0xEE, 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, + /* 0x1d8 */ 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, 0xAC, 0x87, + /* 0x1e0 */ 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, + /* 0x1e8 */ 0x6F, 0x5B, 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, + /* 0x1f0 */ 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, 0x62, 0x79, + /* 0x1f8 */ 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, + /* 0x200 */ 0x10, 0xE1, 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, + /* 0x208 */ 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, 0xE5, 0x02, + /* 0x210 */ 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, + /* 0x218 */ 0x37, 0x96, 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, + /* 0x220 */ 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, 0xF9, 0x49, + /* 0x228 */ 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, + /* 0x230 */ 0x41, 0xE9, 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, + /* 0x238 */ 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, 0x35, 0x2F, + /* 0x240 */ 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, + /* 0x248 */ 0x64, 0x77, 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, + /* 0x250 */ 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, 0xD6, 0x89, + /* 0x258 */ 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, + /* 0x260 */ 0x26, 0xF5, 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, + /* 0x268 */ 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, 0xB5, 0xA7, + /* 0x270 */ 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, + /* 0x278 */ 0xA7, 0x12, 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, + /* 0x280 */ 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, 0xD0, 0x2F, + /* 0x288 */ 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, + /* 0x290 */ 0x05, 0x12, 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, + /* 0x298 */ 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, 0x74, 0xE7, + /* 0x2a0 */ 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, + /* 0x2a8 */ 0x71, 0x36, 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, + /* 0x2b0 */ 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, 0xA6, 0x7D, + /* 0x2b8 */ 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, + /* 0x2c0 */ 0xBD, 0x83, 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, + /* 0x2c8 */ 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, 0xB6, 0xF0, + /* 0x2d0 */ 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, + /* 0x2d8 */ 0x88, 0xDC, 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, + /* 0x2e0 */ 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, 0xF3, 0x64, + /* 0x2e8 */ 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, + /* 0x2f0 */ 0xDB, 0xE2, 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, + /* 0x2f8 */ 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, 0x70, 0x88, + /* 0x300 */ 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, + /* 0x308 */ 0x27, 0x51, 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, + /* 0x310 */ 0x43, 0x4F, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, + /* 0x318 */ 0x42, 0x30, 0x40, 0x30, 0x0E, 0x06, 0x03, 0x55, + /* 0x320 */ 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, + /* 0x328 */ 0x02, 0x01, 0x06, 0x30, 0x0F, 0x06, 0x03, 0x55, + /* 0x330 */ 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, + /* 0x338 */ 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1D, 0x06, 0x03, + /* 0x340 */ 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x79, + /* 0x348 */ 0xB4, 0x59, 0xE6, 0x7B, 0xB6, 0xE5, 0xE4, 0x01, + /* 0x350 */ 0x73, 0x80, 0x08, 0x88, 0xC8, 0x1A, 0x58, 0xF6, + /* 0x358 */ 0xE9, 0x9B, 0x6E, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x360 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + /* 0x368 */ 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x55, + /* 0x370 */ 0x1F, 0x58, 0xA9, 0xBC, 0xB2, 0xA8, 0x50, 0xD0, + /* 0x378 */ 0x0C, 0xB1, 0xD8, 0x1A, 0x69, 0x20, 0x27, 0x29, + /* 0x380 */ 0x08, 0xAC, 0x61, 0x75, 0x5C, 0x8A, 0x6E, 0xF8, + /* 0x388 */ 0x82, 0xE5, 0x69, 0x2F, 0xD5, 0xF6, 0x56, 0x4B, + /* 0x390 */ 0xB9, 0xB8, 0x73, 0x10, 0x59, 0xD3, 0x21, 0x97, + /* 0x398 */ 0x7E, 0xE7, 0x4C, 0x71, 0xFB, 0xB2, 0xD2, 0x60, + /* 0x3a0 */ 0xAD, 0x39, 0xA8, 0x0B, 0xEA, 0x17, 0x21, 0x56, + /* 0x3a8 */ 0x85, 0xF1, 0x50, 0x0E, 0x59, 0xEB, 0xCE, 0xE0, + /* 0x3b0 */ 0x59, 0xE9, 0xBA, 0xC9, 0x15, 0xEF, 0x86, 0x9D, + /* 0x3b8 */ 0x8F, 0x84, 0x80, 0xF6, 0xE4, 0xE9, 0x91, 0x90, + /* 0x3c0 */ 0xDC, 0x17, 0x9B, 0x62, 0x1B, 0x45, 0xF0, 0x66, + /* 0x3c8 */ 0x95, 0xD2, 0x7C, 0x6F, 0xC2, 0xEA, 0x3B, 0xEF, + /* 0x3d0 */ 0x1F, 0xCF, 0xCB, 0xD6, 0xAE, 0x27, 0xF1, 0xA9, + /* 0x3d8 */ 0xB0, 0xC8, 0xAE, 0xFD, 0x7D, 0x7E, 0x9A, 0xFA, + /* 0x3e0 */ 0x22, 0x04, 0xEB, 0xFF, 0xD9, 0x7F, 0xEA, 0x91, + /* 0x3e8 */ 0x2B, 0x22, 0xB1, 0x17, 0x0E, 0x8F, 0xF2, 0x8A, + /* 0x3f0 */ 0x34, 0x5B, 0x58, 0xD8, 0xFC, 0x01, 0xC9, 0x54, + /* 0x3f8 */ 0xB9, 0xB8, 0x26, 0xCC, 0x8A, 0x88, 0x33, 0x89, + /* 0x400 */ 0x4C, 0x2D, 0x84, 0x3C, 0x82, 0xDF, 0xEE, 0x96, + /* 0x408 */ 0x57, 0x05, 0xBA, 0x2C, 0xBB, 0xF7, 0xC4, 0xB7, + /* 0x410 */ 0xC7, 0x4E, 0x3B, 0x82, 0xBE, 0x31, 0xC8, 0x22, + /* 0x418 */ 0x73, 0x73, 0x92, 0xD1, 0xC2, 0x80, 0xA4, 0x39, + /* 0x420 */ 0x39, 0x10, 0x33, 0x23, 0x82, 0x4C, 0x3C, 0x9F, + /* 0x428 */ 0x86, 0xB2, 0x55, 0x98, 0x1D, 0xBE, 0x29, 0x86, + /* 0x430 */ 0x8C, 0x22, 0x9B, 0x9E, 0xE2, 0x6B, 0x3B, 0x57, + /* 0x438 */ 0x3A, 0x82, 0x70, 0x4D, 0xDC, 0x09, 0xC7, 0x89, + /* 0x440 */ 0xCB, 0x0A, 0x07, 0x4D, 0x6C, 0xE8, 0x5D, 0x8E, + /* 0x448 */ 0xC9, 0xEF, 0xCE, 0xAB, 0xC7, 0xBB, 0xB5, 0x2B, + /* 0x450 */ 0x4E, 0x45, 0xD6, 0x4A, 0xD0, 0x26, 0xCC, 0xE5, + /* 0x458 */ 0x72, 0xCA, 0x08, 0x6A, 0xA5, 0x95, 0xE3, 0x15, + /* 0x460 */ 0xA1, 0xF7, 0xA4, 0xED, 0xC9, 0x2C, 0x5F, 0xA5, + /* 0x468 */ 0xFB, 0xFF, 0xAC, 0x28, 0x02, 0x2E, 0xBE, 0xD7, + /* 0x470 */ 0x7B, 0xBB, 0xE3, 0x71, 0x7B, 0x90, 0x16, 0xD3, + /* 0x478 */ 0x07, 0x5E, 0x46, 0x53, 0x7C, 0x37, 0x07, 0x42, + /* 0x480 */ 0x8C, 0xD3, 0xC4, 0x96, 0x9C, 0xD5, 0x99, 0xB5, + /* 0x488 */ 0x2A, 0xE0, 0x95, 0x1A, 0x80, 0x48, 0xAE, 0x4C, + /* 0x490 */ 0x39, 0x07, 0xCE, 0xCC, 0x47, 0xA4, 0x52, 0x95, + /* 0x498 */ 0x2B, 0xBA, 0xB8, 0xFB, 0xAD, 0xD2, 0x33, 0x53, + /* 0x4a0 */ 0x7D, 0xE5, 0x1D, 0x4D, 0x6D, 0xD5, 0xA1, 0xB1, + /* 0x4a8 */ 0xC7, 0x42, 0x6F, 0xE6, 0x40, 0x27, 0x35, 0x5C, + /* 0x4b0 */ 0xA3, 0x28, 0xB7, 0x07, 0x8D, 0xE7, 0x8D, 0x33, + /* 0x4b8 */ 0x90, 0xE7, 0x23, 0x9F, 0xFB, 0x50, 0x9C, 0x79, + /* 0x4c0 */ 0x6C, 0x46, 0xD5, 0xB4, 0x15, 0xB3, 0x96, 0x6E, + /* 0x4c8 */ 0x7E, 0x9B, 0x0C, 0x96, 0x3A, 0xB8, 0x52, 0x2D, + /* 0x4d0 */ 0x3F, 0xD6, 0x5B, 0xE1, 0xFB, 0x08, 0xC2, 0x84, + /* 0x4d8 */ 0xFE, 0x24, 0xA8, 0xA3, 0x89, 0xDA, 0xAC, 0x6A, + /* 0x4e0 */ 0xE1, 0x18, 0x2A, 0xB1, 0xA8, 0x43, 0x61, 0x5B, + /* 0x4e8 */ 0xD3, 0x1F, 0xDC, 0x3B, 0x8D, 0x76, 0xF2, 0x2D, + /* 0x4f0 */ 0xE8, 0x8D, 0x75, 0xDF, 0x17, 0x33, 0x6C, 0x3D, + /* 0x4f8 */ 0x53, 0xFB, 0x7B, 0xCB, 0x41, 0x5F, 0xFF, 0xDC, + /* 0x500 */ 0xA2, 0xD0, 0x61, 0x38, 0xE1, 0x96, 0xB8, 0xAC, + /* 0x508 */ 0x5D, 0x8B, 0x37, 0xD7, 0x75, 0xD5, 0x33, 0xC0, + /* 0x510 */ 0x99, 0x11, 0xAE, 0x9D, 0x41, 0xC1, 0x72, 0x75, + /* 0x518 */ 0x84, 0xBE, 0x02, 0x41, 0x42, 0x5F, 0x67, 0x24, + /* 0x520 */ 0x48, 0x94, 0xD1, 0x9B, 0x27, 0xBE, 0x07, 0x3F, + /* 0x528 */ 0xB9, 0xB8, 0x4F, 0x81, 0x74, 0x51, 0xE1, 0x7A, + /* 0x530 */ 0xB7, 0xED, 0x9D, 0x23, 0xE2, 0xBE, 0xE0, 0xD5, + /* 0x538 */ 0x28, 0x04, 0x13, 0x3C, 0x31, 0x03, 0x9E, 0xDD, + /* 0x540 */ 0x7A, 0x6C, 0x8F, 0xC6, 0x07, 0x18, 0xC6, 0x7F, + /* 0x548 */ 0xDE, 0x47, 0x8E, 0x3F, 0x28, 0x9E, 0x04, 0x06, + /* 0x550 */ 0xCF, 0xA5, 0x54, 0x34, 0x77, 0xBD, 0xEC, 0x89, + /* 0x558 */ 0x9B, 0xE9, 0x17, 0x43, 0xDF, 0x5B, 0xDB, 0x5F, + /* 0x560 */ 0xFE, 0x8E, 0x1E, 0x57, 0xA2, 0xCD, 0x40, 0x9D, + /* 0x568 */ 0x7E, 0x62, 0x22, 0xDA, 0xDE, 0x18, 0x27, +}; +static const lws_ss_x509_t _ss_x509_isrg_root_x1 = { + .vhost_name = "isrg_root_x1", + .ca_der = _ss_der_isrg_root_x1, + .ca_der_len = 1391, +}; +static const uint8_t _ss_der_LEX3_isrg_root_x1[] = { + /* 0x 0 */ 0x30, 0x82, 0x05, 0x8D, 0x30, 0x82, 0x03, 0x75, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, + /* 0x 10 */ 0xD3, 0xB1, 0x72, 0x26, 0x34, 0x23, 0x32, 0xDC, + /* 0x 18 */ 0xF4, 0x05, 0x28, 0x51, 0x2A, 0xEC, 0x9C, 0x6A, + /* 0x 20 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x 28 */ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + /* 0x 30 */ 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + /* 0x 38 */ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x29, + /* 0x 40 */ 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + /* 0x 48 */ 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, + /* 0x 50 */ 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + /* 0x 58 */ 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, + /* 0x 60 */ 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, + /* 0x 68 */ 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, + /* 0x 70 */ 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, 0x47, + /* 0x 78 */ 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31, + /* 0x 80 */ 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x31, 0x30, + /* 0x 88 */ 0x30, 0x36, 0x31, 0x35, 0x34, 0x33, 0x35, 0x35, + /* 0x 90 */ 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x31, 0x30, 0x30, + /* 0x 98 */ 0x36, 0x31, 0x35, 0x34, 0x33, 0x35, 0x35, 0x5A, + /* 0x a0 */ 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + /* 0x a8 */ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + /* 0x b0 */ 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, + /* 0x b8 */ 0x13, 0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, + /* 0x c0 */ 0x45, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x31, + /* 0x c8 */ 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, + /* 0x d0 */ 0x13, 0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, + /* 0x d8 */ 0x45, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, + /* 0x e0 */ 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + /* 0x e8 */ 0x79, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, + /* 0x f0 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x f8 */ 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + /* 0x100 */ 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, + /* 0x108 */ 0x02, 0x82, 0x01, 0x01, 0x00, 0x9C, 0xD3, 0x0C, + /* 0x110 */ 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, + /* 0x118 */ 0x37, 0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, + /* 0x120 */ 0x35, 0x26, 0x19, 0x25, 0xE1, 0xBD, 0xBE, 0x35, + /* 0x128 */ 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, + /* 0x130 */ 0x05, 0xAB, 0xA9, 0x9E, 0x35, 0x08, 0x58, 0xEC, + /* 0x138 */ 0xB1, 0x2A, 0xC4, 0x68, 0x87, 0x0B, 0xA3, 0xE3, + /* 0x140 */ 0x75, 0xE4, 0xE6, 0xF3, 0xA7, 0x62, 0x71, 0xBA, + /* 0x148 */ 0x79, 0x81, 0x60, 0x1F, 0xD7, 0x91, 0x9A, 0x9F, + /* 0x150 */ 0xF3, 0xD0, 0x78, 0x67, 0x71, 0xC8, 0x69, 0x0E, + /* 0x158 */ 0x95, 0x91, 0xCF, 0xFE, 0xE6, 0x99, 0xE9, 0x60, + /* 0x160 */ 0x3C, 0x48, 0xCC, 0x7E, 0xCA, 0x4D, 0x77, 0x12, + /* 0x168 */ 0x24, 0x9D, 0x47, 0x1B, 0x5A, 0xEB, 0xB9, 0xEC, + /* 0x170 */ 0x1E, 0x37, 0x00, 0x1C, 0x9C, 0xAC, 0x7B, 0xA7, + /* 0x178 */ 0x05, 0xEA, 0xCE, 0x4A, 0xEB, 0xBD, 0x41, 0xE5, + /* 0x180 */ 0x36, 0x98, 0xB9, 0xCB, 0xFD, 0x6D, 0x3C, 0x96, + /* 0x188 */ 0x68, 0xDF, 0x23, 0x2A, 0x42, 0x90, 0x0C, 0x86, + /* 0x190 */ 0x74, 0x67, 0xC8, 0x7F, 0xA5, 0x9A, 0xB8, 0x52, + /* 0x198 */ 0x61, 0x14, 0x13, 0x3F, 0x65, 0xE9, 0x82, 0x87, + /* 0x1a0 */ 0xCB, 0xDB, 0xFA, 0x0E, 0x56, 0xF6, 0x86, 0x89, + /* 0x1a8 */ 0xF3, 0x85, 0x3F, 0x97, 0x86, 0xAF, 0xB0, 0xDC, + /* 0x1b0 */ 0x1A, 0xEF, 0x6B, 0x0D, 0x95, 0x16, 0x7D, 0xC4, + /* 0x1b8 */ 0x2B, 0xA0, 0x65, 0xB2, 0x99, 0x04, 0x36, 0x75, + /* 0x1c0 */ 0x80, 0x6B, 0xAC, 0x4A, 0xF3, 0x1B, 0x90, 0x49, + /* 0x1c8 */ 0x78, 0x2F, 0xA2, 0x96, 0x4F, 0x2A, 0x20, 0x25, + /* 0x1d0 */ 0x29, 0x04, 0xC6, 0x74, 0xC0, 0xD0, 0x31, 0xCD, + /* 0x1d8 */ 0x8F, 0x31, 0x38, 0x95, 0x16, 0xBA, 0xA8, 0x33, + /* 0x1e0 */ 0xB8, 0x43, 0xF1, 0xB1, 0x1F, 0xC3, 0x30, 0x7F, + /* 0x1e8 */ 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, + /* 0x1f0 */ 0xE3, 0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, + /* 0x1f8 */ 0xC5, 0xAF, 0xC4, 0x8D, 0x0D, 0x1D, 0x64, 0x16, + /* 0x200 */ 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, + /* 0x208 */ 0xC0, 0xD8, 0x7D, 0xC3, 0x93, 0x02, 0x03, 0x01, + /* 0x210 */ 0x00, 0x01, 0xA3, 0x82, 0x01, 0x67, 0x30, 0x82, + /* 0x218 */ 0x01, 0x63, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, + /* 0x220 */ 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, + /* 0x228 */ 0x01, 0x86, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, + /* 0x230 */ 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, + /* 0x238 */ 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x54, + /* 0x240 */ 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04, 0x4D, 0x30, + /* 0x248 */ 0x4B, 0x30, 0x08, 0x06, 0x06, 0x67, 0x81, 0x0C, + /* 0x250 */ 0x01, 0x02, 0x01, 0x30, 0x3F, 0x06, 0x0B, 0x2B, + /* 0x258 */ 0x06, 0x01, 0x04, 0x01, 0x82, 0xDF, 0x13, 0x01, + /* 0x260 */ 0x01, 0x01, 0x30, 0x30, 0x30, 0x2E, 0x06, 0x08, + /* 0x268 */ 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, + /* 0x270 */ 0x16, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, + /* 0x278 */ 0x2F, 0x63, 0x70, 0x73, 0x2E, 0x72, 0x6F, 0x6F, + /* 0x280 */ 0x74, 0x2D, 0x78, 0x31, 0x2E, 0x6C, 0x65, 0x74, + /* 0x288 */ 0x73, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, + /* 0x290 */ 0x2E, 0x6F, 0x72, 0x67, 0x30, 0x1D, 0x06, 0x03, + /* 0x298 */ 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xA8, + /* 0x2a0 */ 0x4A, 0x6A, 0x63, 0x04, 0x7D, 0xDD, 0xBA, 0xE6, + /* 0x2a8 */ 0xD1, 0x39, 0xB7, 0xA6, 0x45, 0x65, 0xEF, 0xF3, + /* 0x2b0 */ 0xA8, 0xEC, 0xA1, 0x30, 0x33, 0x06, 0x03, 0x55, + /* 0x2b8 */ 0x1D, 0x1F, 0x04, 0x2C, 0x30, 0x2A, 0x30, 0x28, + /* 0x2c0 */ 0xA0, 0x26, 0xA0, 0x24, 0x86, 0x22, 0x68, 0x74, + /* 0x2c8 */ 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, + /* 0x2d0 */ 0x2E, 0x72, 0x6F, 0x6F, 0x74, 0x2D, 0x78, 0x31, + /* 0x2d8 */ 0x2E, 0x6C, 0x65, 0x74, 0x73, 0x65, 0x6E, 0x63, + /* 0x2e0 */ 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72, 0x67, + /* 0x2e8 */ 0x30, 0x72, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, + /* 0x2f0 */ 0x05, 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, + /* 0x2f8 */ 0x30, 0x30, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, + /* 0x300 */ 0x05, 0x07, 0x30, 0x01, 0x86, 0x24, 0x68, 0x74, + /* 0x308 */ 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6F, 0x63, 0x73, + /* 0x310 */ 0x70, 0x2E, 0x72, 0x6F, 0x6F, 0x74, 0x2D, 0x78, + /* 0x318 */ 0x31, 0x2E, 0x6C, 0x65, 0x74, 0x73, 0x65, 0x6E, + /* 0x320 */ 0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72, + /* 0x328 */ 0x67, 0x2F, 0x30, 0x30, 0x06, 0x08, 0x2B, 0x06, + /* 0x330 */ 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x24, + /* 0x338 */ 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, + /* 0x340 */ 0x65, 0x72, 0x74, 0x2E, 0x72, 0x6F, 0x6F, 0x74, + /* 0x348 */ 0x2D, 0x78, 0x31, 0x2E, 0x6C, 0x65, 0x74, 0x73, + /* 0x350 */ 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, + /* 0x358 */ 0x6F, 0x72, 0x67, 0x2F, 0x30, 0x1F, 0x06, 0x03, + /* 0x360 */ 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + /* 0x368 */ 0x14, 0x79, 0xB4, 0x59, 0xE6, 0x7B, 0xB6, 0xE5, + /* 0x370 */ 0xE4, 0x01, 0x73, 0x80, 0x08, 0x88, 0xC8, 0x1A, + /* 0x378 */ 0x58, 0xF6, 0xE9, 0x9B, 0x6E, 0x30, 0x0D, 0x06, + /* 0x380 */ 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + /* 0x388 */ 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, + /* 0x390 */ 0x00, 0x19, 0xCF, 0x75, 0x20, 0x34, 0x2D, 0x3A, + /* 0x398 */ 0xA6, 0x45, 0xFF, 0xD0, 0xD5, 0xE6, 0x8C, 0xDA, + /* 0x3a0 */ 0x32, 0xE8, 0x9C, 0x6E, 0x1B, 0x41, 0xD1, 0x27, + /* 0x3a8 */ 0xA8, 0xE2, 0x50, 0xF2, 0x70, 0xAA, 0xC4, 0xE7, + /* 0x3b0 */ 0x93, 0x46, 0xB4, 0xE8, 0x10, 0xAB, 0x70, 0x4F, + /* 0x3b8 */ 0xEF, 0xB7, 0xEA, 0x04, 0xD2, 0x94, 0x11, 0xB1, + /* 0x3c0 */ 0x03, 0xFE, 0x5D, 0xBA, 0xDF, 0x36, 0x8C, 0x94, + /* 0x3c8 */ 0x36, 0x8F, 0x13, 0x7C, 0x44, 0x8F, 0x0B, 0xF5, + /* 0x3d0 */ 0x01, 0x57, 0xAD, 0x68, 0xB8, 0xC5, 0x79, 0xC0, + /* 0x3d8 */ 0xD8, 0x4A, 0x80, 0xD7, 0x4C, 0xA3, 0x1E, 0x24, + /* 0x3e0 */ 0x7A, 0x1F, 0xD7, 0x23, 0xE8, 0xC1, 0x62, 0x3A, + /* 0x3e8 */ 0x76, 0xF9, 0x22, 0x7D, 0x5E, 0x5A, 0xC4, 0x4C, + /* 0x3f0 */ 0x50, 0xCD, 0xAF, 0xDD, 0xEF, 0x6D, 0x36, 0xC0, + /* 0x3f8 */ 0x80, 0x80, 0x1B, 0xA4, 0x3C, 0x70, 0x20, 0xD6, + /* 0x400 */ 0x54, 0x21, 0xD3, 0xBA, 0xEF, 0x14, 0xA9, 0xBF, + /* 0x408 */ 0x07, 0x3F, 0x41, 0x0A, 0x36, 0xB1, 0xA2, 0xB0, + /* 0x410 */ 0x0B, 0x20, 0xD5, 0x1F, 0x67, 0xD0, 0xC3, 0xEB, + /* 0x418 */ 0x88, 0xF6, 0x8A, 0x02, 0xC8, 0xC6, 0x57, 0xB6, + /* 0x420 */ 0x0C, 0xFC, 0x56, 0xF1, 0xD2, 0x3F, 0x17, 0x69, + /* 0x428 */ 0x68, 0x1C, 0xC8, 0xD7, 0x66, 0x3A, 0x86, 0xF1, + /* 0x430 */ 0x19, 0x2A, 0x65, 0x47, 0x68, 0xC6, 0xD2, 0x03, + /* 0x438 */ 0xE7, 0xEF, 0x74, 0x16, 0x0B, 0x06, 0x21, 0xF9, + /* 0x440 */ 0x0C, 0xA6, 0xA8, 0x11, 0x4B, 0x4E, 0x5F, 0xE3, + /* 0x448 */ 0x33, 0xDB, 0x08, 0x41, 0xEA, 0x09, 0x79, 0x75, + /* 0x450 */ 0x78, 0xEE, 0x47, 0xC8, 0x42, 0xD3, 0x81, 0xC5, + /* 0x458 */ 0x65, 0x2D, 0x75, 0xD0, 0x0E, 0x00, 0x16, 0x9D, + /* 0x460 */ 0x1C, 0xEE, 0xB7, 0x58, 0x45, 0x25, 0xE7, 0x33, + /* 0x468 */ 0x63, 0x5B, 0x63, 0x41, 0x09, 0xE8, 0xE9, 0xFE, + /* 0x470 */ 0xAC, 0xFA, 0x73, 0x32, 0x74, 0xB3, 0x76, 0xE9, + /* 0x478 */ 0x6B, 0x94, 0xE2, 0xCD, 0xD4, 0x62, 0xF3, 0xAE, + /* 0x480 */ 0x3A, 0xC5, 0x31, 0x46, 0x52, 0x6E, 0xED, 0x34, + /* 0x488 */ 0x91, 0x1E, 0xA0, 0xC2, 0xDE, 0x54, 0x84, 0xE5, + /* 0x490 */ 0x78, 0x20, 0x56, 0x4C, 0xDD, 0x68, 0xF9, 0x2E, + /* 0x498 */ 0x28, 0x64, 0x1B, 0x1A, 0x99, 0xF2, 0xFB, 0x4D, + /* 0x4a0 */ 0x7F, 0xE3, 0xB8, 0x5F, 0x5D, 0x73, 0x41, 0xEC, + /* 0x4a8 */ 0x79, 0xED, 0x58, 0xD6, 0x7A, 0x37, 0x65, 0x70, + /* 0x4b0 */ 0xA7, 0xB1, 0xBA, 0x39, 0xF6, 0x3E, 0x61, 0x0A, + /* 0x4b8 */ 0xD9, 0xC0, 0x86, 0x90, 0x9A, 0x1A, 0xC8, 0xA8, + /* 0x4c0 */ 0x96, 0x6E, 0x8A, 0x0B, 0x2B, 0x6D, 0xED, 0xD6, + /* 0x4c8 */ 0xFA, 0x07, 0x67, 0xE7, 0x29, 0x04, 0xF7, 0xE2, + /* 0x4d0 */ 0xB2, 0xD1, 0x58, 0x15, 0x52, 0xC7, 0xF1, 0xA3, + /* 0x4d8 */ 0x9D, 0xA6, 0xC0, 0x56, 0x2C, 0xD4, 0x92, 0x98, + /* 0x4e0 */ 0xD8, 0xF1, 0x83, 0xB9, 0x6C, 0x7C, 0x33, 0xA0, + /* 0x4e8 */ 0xE5, 0x4B, 0xAA, 0x90, 0x92, 0xF1, 0xDA, 0x45, + /* 0x4f0 */ 0x4A, 0x34, 0x14, 0xC7, 0x7C, 0x4E, 0xC4, 0xA5, + /* 0x4f8 */ 0x6C, 0x5D, 0x3F, 0xBF, 0xDE, 0xB9, 0xA8, 0x61, + /* 0x500 */ 0x4A, 0x85, 0x20, 0xDE, 0x42, 0x83, 0x29, 0x62, + /* 0x508 */ 0x7C, 0x1C, 0x99, 0x08, 0xA5, 0x46, 0x1F, 0xF4, + /* 0x510 */ 0x6B, 0x22, 0xD3, 0x86, 0x51, 0xCB, 0x37, 0xCD, + /* 0x518 */ 0x60, 0x4A, 0x42, 0x63, 0x56, 0xB3, 0xC8, 0xD1, + /* 0x520 */ 0x8F, 0x31, 0x09, 0x53, 0xC1, 0xE2, 0xDC, 0x1B, + /* 0x528 */ 0xD4, 0xF1, 0x54, 0x77, 0x67, 0xCF, 0x33, 0x7B, + /* 0x530 */ 0x00, 0xD6, 0xD2, 0x7C, 0xDE, 0xC6, 0x79, 0xBF, + /* 0x538 */ 0xCB, 0xE0, 0x16, 0xFD, 0xB2, 0xA1, 0xF2, 0x91, + /* 0x540 */ 0x3C, 0x1D, 0x2D, 0xE8, 0x9C, 0xD4, 0x03, 0xCD, + /* 0x548 */ 0x66, 0x4A, 0xA3, 0x37, 0x93, 0x19, 0x79, 0x7B, + /* 0x550 */ 0xE2, 0x19, 0xC2, 0x16, 0x00, 0xC8, 0xED, 0x0E, + /* 0x558 */ 0x4E, 0x0D, 0xFF, 0x7E, 0xCF, 0x07, 0xA8, 0x64, + /* 0x560 */ 0xCD, 0x29, 0xDF, 0x41, 0xAA, 0x85, 0x30, 0x49, + /* 0x568 */ 0x10, 0x73, 0xA7, 0x4E, 0x89, 0x32, 0x0E, 0x5B, + /* 0x570 */ 0xAD, 0x40, 0x86, 0xC1, 0xB0, 0x94, 0x0C, 0x8D, + /* 0x578 */ 0x26, 0xC5, 0xA7, 0x49, 0xDC, 0x1C, 0xF8, 0x5B, + /* 0x580 */ 0x14, 0x7A, 0x7F, 0x23, 0x69, 0x04, 0xAD, 0xB2, + /* 0x588 */ 0x02, 0x29, 0xD6, 0x12, 0xC8, 0xA4, 0xC6, 0xA1, + /* 0x590 */ 0x2D, +}; +static const lws_ss_x509_t _ss_x509_LEX3_isrg_root_x1 = { + .vhost_name = "LEX3_isrg_root_x1", + .ca_der = _ss_der_LEX3_isrg_root_x1, + .ca_der_len = 1425, +}; +static const lws_ss_trust_store_t _ss_ts_le_via_isrg = { + .name = "le_via_isrg", + .ssx509 = { + &_ss_x509_LEX3_isrg_root_x1, + &_ss_x509_isrg_root_x1, + } +}; + +static const lws_ss_metadata_t _md_mintest_xctype = { + .name = "xctype", + .value = (void *)"X-Content-Type:", + .length = 0, +}, +_md_mintest_ctype = { + .next = (void *)&_md_mintest_xctype, + .name = "ctype", + .value = (void *)"Content-Type:", + .length = 1, +}, +_md_mintest_uptag = { + .next = (void *)&_md_mintest_ctype, + .name = "uptag", + .value = (void *)"X-Upload-Tag:", + .length = 2, +}; + +static const lws_ss_trust_store_t _ss_ts_avs_via_starfield = { + .name = "avs_via_starfield", + .ssx509 = { + &_ss_x509_starfield_services_root_ca, + &_ss_x509_starfield_class_2_ca, + } +}; +static const uint8_t _ss_der_digicert_global_ca_g2[] = { + /* 0x 0 */ 0x30, 0x82, 0x04, 0x8B, 0x30, 0x82, 0x03, 0x73, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x0C, + /* 0x 10 */ 0x8E, 0xE0, 0xC9, 0x0D, 0x6A, 0x89, 0x15, 0x88, + /* 0x 18 */ 0x04, 0x06, 0x1E, 0xE2, 0x41, 0xF9, 0xAF, 0x30, + /* 0x 20 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x 28 */ 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x61, + /* 0x 30 */ 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + /* 0x 38 */ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, + /* 0x 40 */ 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, + /* 0x 48 */ 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + /* 0x 50 */ 0x20, 0x49, 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, + /* 0x 58 */ 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x77, + /* 0x 60 */ 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, + /* 0x 68 */ 0x65, 0x72, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + /* 0x 70 */ 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + /* 0x 78 */ 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, + /* 0x 80 */ 0x72, 0x74, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + /* 0x 88 */ 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, + /* 0x 90 */ 0x32, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x33, 0x30, + /* 0x 98 */ 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, + /* 0x a0 */ 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x38, 0x30, 0x38, + /* 0x a8 */ 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, + /* 0x b0 */ 0x5A, 0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, + /* 0x b8 */ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + /* 0x c0 */ 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, + /* 0x c8 */ 0x0A, 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, + /* 0x d0 */ 0x65, 0x72, 0x74, 0x20, 0x49, 0x6E, 0x63, 0x31, + /* 0x d8 */ 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, + /* 0x e0 */ 0x13, 0x15, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, + /* 0x e8 */ 0x72, 0x74, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + /* 0x f0 */ 0x6C, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32, 0x30, + /* 0x f8 */ 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x100 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + /* 0x108 */ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, + /* 0x110 */ 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, + /* 0x118 */ 0xD3, 0x48, 0x7C, 0xBE, 0xF3, 0x05, 0x86, 0x5D, + /* 0x120 */ 0x5B, 0xD5, 0x2F, 0x85, 0x4E, 0x4B, 0xE0, 0x86, + /* 0x128 */ 0xAD, 0x15, 0xAC, 0x61, 0xCF, 0x5B, 0xAF, 0x3E, + /* 0x130 */ 0x6A, 0x0A, 0x47, 0xFB, 0x9A, 0x76, 0x91, 0x60, + /* 0x138 */ 0x0B, 0x8A, 0x6B, 0xCD, 0xCF, 0xDC, 0x57, 0x7E, + /* 0x140 */ 0x60, 0x98, 0x0B, 0xE4, 0x54, 0xD9, 0x56, 0xED, + /* 0x148 */ 0x21, 0xCC, 0x02, 0xB6, 0x5A, 0x81, 0x5F, 0x97, + /* 0x150 */ 0x6A, 0xEE, 0x02, 0x2F, 0x23, 0x27, 0xB8, 0x6D, + /* 0x158 */ 0xD4, 0xB0, 0xE7, 0x06, 0x02, 0x78, 0x0B, 0x1F, + /* 0x160 */ 0x5C, 0xA9, 0x99, 0x36, 0xFE, 0xBB, 0xAC, 0x1B, + /* 0x168 */ 0x05, 0xFA, 0x57, 0xCD, 0x81, 0x10, 0x40, 0x67, + /* 0x170 */ 0xD6, 0x30, 0x8B, 0x58, 0x35, 0xD4, 0x96, 0x61, + /* 0x178 */ 0xBE, 0xD0, 0x8C, 0x7A, 0x97, 0x9F, 0x1A, 0xF9, + /* 0x180 */ 0x22, 0xE6, 0x14, 0x2F, 0xA9, 0xC6, 0xE8, 0x01, + /* 0x188 */ 0x1F, 0xAB, 0xF8, 0x26, 0x0F, 0xAC, 0x8E, 0x4D, + /* 0x190 */ 0x2C, 0x32, 0x39, 0x1D, 0x81, 0x9B, 0x8D, 0x1C, + /* 0x198 */ 0x65, 0xB2, 0x1C, 0xDB, 0x61, 0xA8, 0x89, 0x2F, + /* 0x1a0 */ 0x60, 0xE7, 0xEB, 0xC2, 0x4A, 0x18, 0xC4, 0x6F, + /* 0x1a8 */ 0x2A, 0xE9, 0x10, 0x92, 0x09, 0xED, 0x17, 0xD1, + /* 0x1b0 */ 0x00, 0x2B, 0xE6, 0x7D, 0xEF, 0x04, 0x89, 0x14, + /* 0x1b8 */ 0x4E, 0x33, 0xA1, 0xB2, 0x0F, 0x97, 0x87, 0x9F, + /* 0x1c0 */ 0xB3, 0xA0, 0xCD, 0x2F, 0xBC, 0x2C, 0xEC, 0xB8, + /* 0x1c8 */ 0x83, 0x68, 0x31, 0x3D, 0x1F, 0xD5, 0x4A, 0x90, + /* 0x1d0 */ 0x10, 0x19, 0x0B, 0x81, 0x95, 0xD6, 0x29, 0x76, + /* 0x1d8 */ 0x51, 0xF9, 0x36, 0x76, 0xD0, 0xB7, 0x09, 0x7A, + /* 0x1e0 */ 0x38, 0x4A, 0xD7, 0x6F, 0x8C, 0xBF, 0x13, 0x7C, + /* 0x1e8 */ 0x39, 0xED, 0xBA, 0xAE, 0x90, 0xFC, 0x95, 0xF7, + /* 0x1f0 */ 0x7B, 0x78, 0x09, 0x36, 0x5E, 0x74, 0x93, 0x1E, + /* 0x1f8 */ 0x25, 0xF0, 0xFF, 0xD4, 0xAD, 0xAE, 0x68, 0x6B, + /* 0x200 */ 0xC6, 0xFF, 0x0F, 0xD5, 0x35, 0xF1, 0x55, 0x6E, + /* 0x208 */ 0x48, 0x49, 0xF8, 0xF8, 0xB8, 0xEF, 0x88, 0xF8, + /* 0x210 */ 0xF1, 0x5E, 0x11, 0x77, 0xAA, 0xDF, 0x02, 0xB3, + /* 0x218 */ 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, + /* 0x220 */ 0x5A, 0x30, 0x82, 0x01, 0x56, 0x30, 0x12, 0x06, + /* 0x228 */ 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, + /* 0x230 */ 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, + /* 0x238 */ 0x00, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, + /* 0x240 */ 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, + /* 0x248 */ 0x86, 0x30, 0x34, 0x06, 0x08, 0x2B, 0x06, 0x01, + /* 0x250 */ 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x28, 0x30, + /* 0x258 */ 0x26, 0x30, 0x24, 0x06, 0x08, 0x2B, 0x06, 0x01, + /* 0x260 */ 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, + /* 0x268 */ 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6F, 0x63, + /* 0x270 */ 0x73, 0x70, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, + /* 0x278 */ 0x65, 0x72, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x30, + /* 0x280 */ 0x7B, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x74, + /* 0x288 */ 0x30, 0x72, 0x30, 0x37, 0xA0, 0x35, 0xA0, 0x33, + /* 0x290 */ 0x86, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, + /* 0x298 */ 0x2F, 0x63, 0x72, 0x6C, 0x34, 0x2E, 0x64, 0x69, + /* 0x2a0 */ 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2E, 0x63, + /* 0x2a8 */ 0x6F, 0x6D, 0x2F, 0x44, 0x69, 0x67, 0x69, 0x43, + /* 0x2b0 */ 0x65, 0x72, 0x74, 0x47, 0x6C, 0x6F, 0x62, 0x61, + /* 0x2b8 */ 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x47, 0x32, 0x2E, + /* 0x2c0 */ 0x63, 0x72, 0x6C, 0x30, 0x37, 0xA0, 0x35, 0xA0, + /* 0x2c8 */ 0x33, 0x86, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3A, + /* 0x2d0 */ 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x33, 0x2E, 0x64, + /* 0x2d8 */ 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2E, + /* 0x2e0 */ 0x63, 0x6F, 0x6D, 0x2F, 0x44, 0x69, 0x67, 0x69, + /* 0x2e8 */ 0x43, 0x65, 0x72, 0x74, 0x47, 0x6C, 0x6F, 0x62, + /* 0x2f0 */ 0x61, 0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x47, 0x32, + /* 0x2f8 */ 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x3D, 0x06, 0x03, + /* 0x300 */ 0x55, 0x1D, 0x20, 0x04, 0x36, 0x30, 0x34, 0x30, + /* 0x308 */ 0x32, 0x06, 0x04, 0x55, 0x1D, 0x20, 0x00, 0x30, + /* 0x310 */ 0x2A, 0x30, 0x28, 0x06, 0x08, 0x2B, 0x06, 0x01, + /* 0x318 */ 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1C, 0x68, + /* 0x320 */ 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x77, + /* 0x328 */ 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, + /* 0x330 */ 0x65, 0x72, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, + /* 0x338 */ 0x43, 0x50, 0x53, 0x30, 0x1D, 0x06, 0x03, 0x55, + /* 0x340 */ 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x24, 0x6E, + /* 0x348 */ 0x2B, 0x2D, 0xD0, 0x6A, 0x92, 0x51, 0x51, 0x25, + /* 0x350 */ 0x69, 0x01, 0xAA, 0x9A, 0x47, 0xA6, 0x89, 0xE7, + /* 0x358 */ 0x40, 0x20, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, + /* 0x360 */ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4E, + /* 0x368 */ 0x22, 0x54, 0x20, 0x18, 0x95, 0xE6, 0xE3, 0x6E, + /* 0x370 */ 0xE6, 0x0F, 0xFA, 0xFA, 0xB9, 0x12, 0xED, 0x06, + /* 0x378 */ 0x17, 0x8F, 0x39, 0x30, 0x0D, 0x06, 0x09, 0x2A, + /* 0x380 */ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + /* 0x388 */ 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x0B, + /* 0x390 */ 0x39, 0x84, 0x91, 0xF9, 0x97, 0xEB, 0xAA, 0x81, + /* 0x398 */ 0xAF, 0x84, 0xE9, 0x5A, 0x38, 0x92, 0xFC, 0xE2, + /* 0x3a0 */ 0x6C, 0x59, 0xBF, 0x36, 0xC8, 0x45, 0xA7, 0x31, + /* 0x3a8 */ 0x03, 0x11, 0xE1, 0x06, 0xC0, 0xAC, 0x32, 0xC7, + /* 0x3b0 */ 0x5A, 0x55, 0x29, 0xDA, 0x4F, 0x40, 0x02, 0xF5, + /* 0x3b8 */ 0xA1, 0xDE, 0xB0, 0xED, 0xDE, 0xC0, 0xF8, 0xF6, + /* 0x3c0 */ 0x75, 0x9D, 0x76, 0xB9, 0x87, 0xFE, 0x41, 0x80, + /* 0x3c8 */ 0x7A, 0xCF, 0x5D, 0xE3, 0x00, 0xC6, 0x5B, 0x02, + /* 0x3d0 */ 0xE6, 0x9B, 0x78, 0x62, 0xC9, 0xDC, 0xB8, 0x62, + /* 0x3d8 */ 0x9A, 0x77, 0xED, 0x89, 0x08, 0xD7, 0x4B, 0xC5, + /* 0x3e0 */ 0xFD, 0x43, 0xD5, 0x62, 0x23, 0x27, 0xC4, 0x04, + /* 0x3e8 */ 0x59, 0x6D, 0x71, 0x3F, 0x23, 0x5B, 0xEA, 0xD9, + /* 0x3f0 */ 0xF2, 0xE7, 0x24, 0x27, 0x6F, 0xF4, 0x95, 0x80, + /* 0x3f8 */ 0xDB, 0x96, 0x2C, 0xE4, 0x54, 0x8B, 0xCF, 0xEA, + /* 0x400 */ 0x19, 0xD9, 0x7F, 0x55, 0x99, 0x51, 0x7A, 0x0E, + /* 0x408 */ 0x2D, 0x18, 0x3D, 0x78, 0x58, 0x52, 0xBC, 0x63, + /* 0x410 */ 0x68, 0x57, 0x0B, 0xDD, 0x44, 0xB3, 0x57, 0x4A, + /* 0x418 */ 0x60, 0xE6, 0xC8, 0x70, 0x70, 0x5B, 0x87, 0x28, + /* 0x420 */ 0x6A, 0xD7, 0x3B, 0x4E, 0x52, 0x45, 0x19, 0xAF, + /* 0x428 */ 0x24, 0x06, 0x92, 0x48, 0x11, 0x1A, 0x8B, 0xAE, + /* 0x430 */ 0xAC, 0x18, 0x12, 0x57, 0xAC, 0x03, 0xCB, 0xB8, + /* 0x438 */ 0xF4, 0xBD, 0xCA, 0x26, 0x0E, 0xA7, 0xC1, 0xDD, + /* 0x440 */ 0xE3, 0x33, 0xEF, 0xC0, 0x55, 0x30, 0x0D, 0x95, + /* 0x448 */ 0x59, 0x4E, 0x9C, 0x03, 0x36, 0x06, 0xF8, 0xC0, + /* 0x450 */ 0x8F, 0x14, 0x99, 0x9C, 0x4D, 0x2A, 0x9E, 0xC1, + /* 0x458 */ 0xE1, 0x7D, 0x3B, 0xAF, 0x72, 0xA7, 0x45, 0xBA, + /* 0x460 */ 0x13, 0x96, 0x29, 0x4E, 0x19, 0xD0, 0x1A, 0x98, + /* 0x468 */ 0x06, 0xF4, 0x37, 0x94, 0x17, 0xAD, 0xA3, 0x18, + /* 0x470 */ 0xBA, 0x3E, 0xB0, 0x01, 0x0C, 0x95, 0xD6, 0x29, + /* 0x478 */ 0x35, 0x20, 0x35, 0x7D, 0xF5, 0x10, 0x60, 0xE4, + /* 0x480 */ 0xF7, 0x68, 0x62, 0x1E, 0xEC, 0x19, 0xE1, 0x24, + /* 0x488 */ 0xF2, 0x87, 0x11, 0xAC, 0xE9, 0x08, 0x80, +}; +static const lws_ss_x509_t _ss_x509_digicert_global_ca_g2 = { + .vhost_name = "digicert_global_ca_g2", + .ca_der = _ss_der_digicert_global_ca_g2, + .ca_der_len = 1167, +}; +static const uint8_t _ss_der_digicert_global_root_g2[] = { + /* 0x 0 */ 0x30, 0x82, 0x03, 0x8E, 0x30, 0x82, 0x02, 0x76, + /* 0x 8 */ 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x03, + /* 0x 10 */ 0x3A, 0xF1, 0xE6, 0xA7, 0x11, 0xA9, 0xA0, 0xBB, + /* 0x 18 */ 0x28, 0x64, 0xB1, 0x1D, 0x09, 0xFA, 0xE5, 0x30, + /* 0x 20 */ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + /* 0x 28 */ 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x61, + /* 0x 30 */ 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + /* 0x 38 */ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, + /* 0x 40 */ 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, + /* 0x 48 */ 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + /* 0x 50 */ 0x20, 0x49, 0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, + /* 0x 58 */ 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x77, + /* 0x 60 */ 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, + /* 0x 68 */ 0x65, 0x72, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + /* 0x 70 */ 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, + /* 0x 78 */ 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, + /* 0x 80 */ 0x72, 0x74, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, + /* 0x 88 */ 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, + /* 0x 90 */ 0x32, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x33, 0x30, + /* 0x 98 */ 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, + /* 0x a0 */ 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x31, + /* 0x a8 */ 0x31, 0x35, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, + /* 0x b0 */ 0x5A, 0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, + /* 0x b8 */ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + /* 0x c0 */ 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, + /* 0x c8 */ 0x0A, 0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, + /* 0x d0 */ 0x65, 0x72, 0x74, 0x20, 0x49, 0x6E, 0x63, 0x31, + /* 0x d8 */ 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, + /* 0x e0 */ 0x13, 0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, + /* 0x e8 */ 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2E, 0x63, + /* 0x f0 */ 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, + /* 0x f8 */ 0x55, 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, + /* 0x100 */ 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6C, + /* 0x108 */ 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, + /* 0x110 */ 0x74, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, + /* 0x118 */ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + /* 0x120 */ 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + /* 0x128 */ 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, + /* 0x130 */ 0x02, 0x82, 0x01, 0x01, 0x00, 0xBB, 0x37, 0xCD, + /* 0x138 */ 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, + /* 0x140 */ 0xAD, 0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, + /* 0x148 */ 0x08, 0x8D, 0xF5, 0x19, 0x54, 0xC9, 0xFB, 0x88, + /* 0x150 */ 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, + /* 0x158 */ 0x7A, 0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, + /* 0x160 */ 0x2D, 0xE8, 0x5E, 0x09, 0x24, 0x44, 0xBA, 0x62, + /* 0x168 */ 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, + /* 0x170 */ 0x75, 0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, + /* 0x178 */ 0x1A, 0x6C, 0x30, 0xDC, 0xDA, 0x1F, 0x19, 0xB1, + /* 0x180 */ 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, + /* 0x188 */ 0x83, 0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, + /* 0x190 */ 0x7B, 0x2C, 0xD2, 0xBD, 0x2E, 0xA5, 0x2F, 0xE4, + /* 0x198 */ 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, + /* 0x1a0 */ 0x25, 0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, + /* 0x1a8 */ 0xFF, 0x4F, 0x21, 0x49, 0x18, 0xF7, 0x67, 0x90, + /* 0x1b0 */ 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, + /* 0x1b8 */ 0xB4, 0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, + /* 0x1c0 */ 0xE8, 0x5D, 0x1B, 0xCD, 0x8C, 0x1D, 0xAB, 0x95, + /* 0x1c8 */ 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, + /* 0x1d0 */ 0x49, 0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, + /* 0x1d8 */ 0xB4, 0xAC, 0x55, 0x07, 0xA9, 0x8F, 0x95, 0xB3, + /* 0x1e0 */ 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, + /* 0x1e8 */ 0xA9, 0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, + /* 0x1f0 */ 0x8C, 0x27, 0x4A, 0x57, 0x14, 0x7C, 0x82, 0x9D, + /* 0x1f8 */ 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, + /* 0x200 */ 0x8C, 0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, + /* 0x208 */ 0xA1, 0xE6, 0x21, 0xCA, 0xFD, 0x83, 0xE5, 0x10, + /* 0x210 */ 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, + /* 0x218 */ 0x73, 0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, + /* 0x220 */ 0x14, 0x89, 0x21, 0x34, 0x4D, 0xAF, 0x0F, 0x45, + /* 0x228 */ 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, + /* 0x230 */ 0xB1, 0x33, 0x83, 0x29, 0x85, 0x02, 0x03, 0x01, + /* 0x238 */ 0x00, 0x01, 0xA3, 0x42, 0x30, 0x40, 0x30, 0x0F, + /* 0x240 */ 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, + /* 0x248 */ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, + /* 0x250 */ 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, + /* 0x258 */ 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, + /* 0x260 */ 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + /* 0x268 */ 0x04, 0x14, 0x4E, 0x22, 0x54, 0x20, 0x18, 0x95, + /* 0x270 */ 0xE6, 0xE3, 0x6E, 0xE6, 0x0F, 0xFA, 0xFA, 0xB9, + /* 0x278 */ 0x12, 0xED, 0x06, 0x17, 0x8F, 0x39, 0x30, 0x0D, + /* 0x280 */ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + /* 0x288 */ 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, + /* 0x290 */ 0x01, 0x00, 0x60, 0x67, 0x28, 0x94, 0x6F, 0x0E, + /* 0x298 */ 0x48, 0x63, 0xEB, 0x31, 0xDD, 0xEA, 0x67, 0x18, + /* 0x2a0 */ 0xD5, 0x89, 0x7D, 0x3C, 0xC5, 0x8B, 0x4A, 0x7F, + /* 0x2a8 */ 0xE9, 0xBE, 0xDB, 0x2B, 0x17, 0xDF, 0xB0, 0x5F, + /* 0x2b0 */ 0x73, 0x77, 0x2A, 0x32, 0x13, 0x39, 0x81, 0x67, + /* 0x2b8 */ 0x42, 0x84, 0x23, 0xF2, 0x45, 0x67, 0x35, 0xEC, + /* 0x2c0 */ 0x88, 0xBF, 0xF8, 0x8F, 0xB0, 0x61, 0x0C, 0x34, + /* 0x2c8 */ 0xA4, 0xAE, 0x20, 0x4C, 0x84, 0xC6, 0xDB, 0xF8, + /* 0x2d0 */ 0x35, 0xE1, 0x76, 0xD9, 0xDF, 0xA6, 0x42, 0xBB, + /* 0x2d8 */ 0xC7, 0x44, 0x08, 0x86, 0x7F, 0x36, 0x74, 0x24, + /* 0x2e0 */ 0x5A, 0xDA, 0x6C, 0x0D, 0x14, 0x59, 0x35, 0xBD, + /* 0x2e8 */ 0xF2, 0x49, 0xDD, 0xB6, 0x1F, 0xC9, 0xB3, 0x0D, + /* 0x2f0 */ 0x47, 0x2A, 0x3D, 0x99, 0x2F, 0xBB, 0x5C, 0xBB, + /* 0x2f8 */ 0xB5, 0xD4, 0x20, 0xE1, 0x99, 0x5F, 0x53, 0x46, + /* 0x300 */ 0x15, 0xDB, 0x68, 0x9B, 0xF0, 0xF3, 0x30, 0xD5, + /* 0x308 */ 0x3E, 0x31, 0xE2, 0x8D, 0x84, 0x9E, 0xE3, 0x8A, + /* 0x310 */ 0xDA, 0xDA, 0x96, 0x3E, 0x35, 0x13, 0xA5, 0x5F, + /* 0x318 */ 0xF0, 0xF9, 0x70, 0x50, 0x70, 0x47, 0x41, 0x11, + /* 0x320 */ 0x57, 0x19, 0x4E, 0xC0, 0x8F, 0xAE, 0x06, 0xC4, + /* 0x328 */ 0x95, 0x13, 0x17, 0x2F, 0x1B, 0x25, 0x9F, 0x75, + /* 0x330 */ 0xF2, 0xB1, 0x8E, 0x99, 0xA1, 0x6F, 0x13, 0xB1, + /* 0x338 */ 0x41, 0x71, 0xFE, 0x88, 0x2A, 0xC8, 0x4F, 0x10, + /* 0x340 */ 0x20, 0x55, 0xD7, 0xF3, 0x14, 0x45, 0xE5, 0xE0, + /* 0x348 */ 0x44, 0xF4, 0xEA, 0x87, 0x95, 0x32, 0x93, 0x0E, + /* 0x350 */ 0xFE, 0x53, 0x46, 0xFA, 0x2C, 0x9D, 0xFF, 0x8B, + /* 0x358 */ 0x22, 0xB9, 0x4B, 0xD9, 0x09, 0x45, 0xA4, 0xDE, + /* 0x360 */ 0xA4, 0xB8, 0x9A, 0x58, 0xDD, 0x1B, 0x7D, 0x52, + /* 0x368 */ 0x9F, 0x8E, 0x59, 0x43, 0x88, 0x81, 0xA4, 0x9E, + /* 0x370 */ 0x26, 0xD5, 0x6F, 0xAD, 0xDD, 0x0D, 0xC6, 0x37, + /* 0x378 */ 0x7D, 0xED, 0x03, 0x92, 0x1B, 0xE5, 0x77, 0x5F, + /* 0x380 */ 0x76, 0xEE, 0x3C, 0x8D, 0xC4, 0x5D, 0x56, 0x5B, + /* 0x388 */ 0xA2, 0xD9, 0x66, 0x6E, 0xB3, 0x35, 0x37, 0xE5, + /* 0x390 */ 0x32, 0xB6, +}; +static const lws_ss_x509_t _ss_x509_digicert_global_root_g2 = { + .vhost_name = "digicert_global_root_g2", + .ca_der = _ss_der_digicert_global_root_g2, + .ca_der_len = 914, +}; +static const lws_ss_trust_store_t _ss_ts_api_amazon_com = { + .name = "api_amazon_com", + .ssx509 = { + &_ss_x509_digicert_global_root_g2, + &_ss_x509_digicert_global_ca_g2, + } +}; + +static const lws_ss_policy_t _ssp_captive_portal_detect = { + .streamtype = "captive_portal_detect", + .endpoint = "connectivitycheck.android.com", + .u = { + .http = { + .method = "GET", + .url = "generate_204", + .resp_expect = 204, + .fail_redirect = 1, + } + }, + .flags = 0x1, + .port = 80, + .protocol = 0, +}, +_ssp_mqtt_test1 = { + .next = (void *)&_ssp_captive_portal_detect, + .streamtype = "mqtt_test1", + .endpoint = "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + .u = { + .mqtt = { + .topic = "test/topic1", + .subscribe = "test/topic1", + .qos = 1, + } + }, + .retry_bo = &_rbo_0, + .flags = 0x10, + .port = 443, + .protocol = 3, + .client_cert = 1, + .trust_store = &_ss_ts_mqtt_amz_iot, +}, +_ssp_mqtt_test = { + .next = (void *)&_ssp_mqtt_test1, + .streamtype = "mqtt_test", + .endpoint = "a1ygonr3im5cv2-ats.iot.us-west-2.amazonaws.com", + .u = { + .mqtt = { + .topic = "test/topic0", + .subscribe = "test/topic0", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x10, + .port = 443, + .protocol = 3, + .client_cert = 1, + .trust_store = &_ss_ts_mqtt_amz_iot, +}, +_ssp_minpost = { + .next = (void *)&_ssp_mqtt_test, + .streamtype = "minpost", + .endpoint = "warmcat.com", + .u = { + .http = { + .method = "POST", + .url = "testserver/formtest", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x11, + .port = 443, + .protocol = 0, + .trust_store = &_ss_ts_le_via_isrg, +}, +_ssp_mintest_fail = { + .next = (void *)&_ssp_minpost, + .streamtype = "mintest-fail", + .endpoint = "warmcat.com", + .u = { + .http = { + .method = "GET", + .url = "index.html", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x11, + .port = 22, + .protocol = 0, + .trust_store = &_ss_ts_le_via_isrg, +}, +_ssp_h2longpolltest = { + .next = (void *)&_ssp_mintest_fail, + .streamtype = "h2longpolltest", + .endpoint = "warmcat.com", + .u = { + .http = { + .method = "GET", + .url = "index.html", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x32, + .port = 443, + .protocol = 1, + .trust_store = &_ss_ts_le_via_isrg, +}, +_ssp_mintest = { + .next = (void *)&_ssp_h2longpolltest, + .streamtype = "mintest", + .endpoint = "warmcat.com", + .metadata = (void *)&_md_mintest_uptag, + .u = { + .http = { + .method = "GET", + .url = "index.html?uptag=${uptag}", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x11, + .port = 443, + .metadata_count = 3, + .protocol = 0, + .trust_store = &_ss_ts_le_via_isrg, +}, +_ssp_avs_audio = { + .next = (void *)&_ssp_mintest, + .streamtype = "avs_audio", + .endpoint = "alexa.na.gateway.devices.a2z.com", + .u = { + .http = { + .method = "POST", + .url = "v20160207/events", + .multipart_name = "audio", + .multipart_content_type = "application/octet-stream", + .auth_preamble = "Bearer ", + .blob_header = { + "authorization:", + }, + } + }, + .retry_bo = &_rbo_0, + .flags = 0xa90, + .port = 443, + .protocol = 1, + .trust_store = &_ss_ts_avs_via_starfield, +}, +_ssp_avs_metadata = { + .next = (void *)&_ssp_avs_audio, + .streamtype = "avs_metadata", + .endpoint = "alexa.na.gateway.devices.a2z.com", + .rideshare_streamtype = "avs_audio", + .u = { + .http = { + .method = "POST", + .url = "v20160207/events", + .multipart_name = "metadata", + .multipart_content_type = "application/json; charset=UTF-8", + .auth_preamble = "Bearer ", + .blob_header = { + "authorization:", + }, + } + }, + .retry_bo = &_rbo_0, + .flags = 0xa91, + .port = 443, + .protocol = 1, + .trust_store = &_ss_ts_avs_via_starfield, +}, +_ssp_avs_event = { + .next = (void *)&_ssp_avs_metadata, + .streamtype = "avs_event", + .endpoint = "alexa.na.gateway.devices.a2z.com", + .u = { + .http = { + .method = "GET", + .url = "v20160207/directives", + .auth_preamble = "Bearer ", + .blob_header = { + "authorization:", + }, + } + }, + .retry_bo = &_rbo_0, + .flags = 0x2b2, + .port = 443, + .protocol = 1, + .trust_store = &_ss_ts_avs_via_starfield, +}, +_ssp_api_amazon_com_auth = { + .next = (void *)&_ssp_avs_event, + .streamtype = "api_amazon_com_auth", + .endpoint = "api.amazon.com", + .u = { + .http = { + .method = "POST", + .url = "auth/o2/token", + } + }, + .retry_bo = &_rbo_0, + .flags = 0x1291, + .port = 443, + .protocol = 0, + .trust_store = &_ss_ts_api_amazon_com, +}; +#define _ss_static_policy_entry _ssp_api_amazon_com_auth +/* estimated footprint 10928 (when sizeof void * = 8) */ diff --git a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt index 675e5238..f24d2a87 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt @@ -65,6 +65,7 @@ set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${SAMP} minimal-secure-streams.c) -- Gitee From 2f6e0ed10baf9d000d18cc5831b8d7b40aac60f5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 26 Mar 2020 18:07:48 +0000 Subject: [PATCH 0036/1062] h1: handle LRS_FLUSHING_BEFORE_CLOSE at ops read read has a tight leash on the states it's happy to turn up there, it's good to be like that but it turns out LRS_FLUSHING_BEFORE_CLOSE should be whitelisted since it can happen under some transient conditions and is valid. https://github.com/warmcat/libwebsockets/issues/1872 --- lib/roles/h1/ops-h1.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index bc9de63d..8e100808 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -256,6 +256,9 @@ ws_mode: case LRS_SSL_ACK_PENDING: break; + case LRS_FLUSHING_BEFORE_CLOSE: + break; + case LRS_DEAD_SOCKET: lwsl_err("%s: Unhandled state LRS_DEAD_SOCKET\n", __func__); goto bail; -- Gitee From be32d0554eee4197344915b0c5bbc9ba54aa5df6 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 27 Mar 2020 13:24:44 +0000 Subject: [PATCH 0037/1062] mbedtls: attempt to remove dependency on net_sockets.c The mbedtls openssl wrapper wants to use exports from mbedtls' net_sockets.c, but this is only supposed to work on *nix and windows. Typically people are using mbedtls on RTOS type platforms and to use it, net_sockets.c needs some hacking. Try to avoid that situation by porting the two exports we need into the lws plat code and call from the wrapper. --- lib/core-net/private-lib-core-net.h | 7 +++ lib/plat/freertos/freertos-sockets.c | 61 +++++++++++++++++++++++ lib/plat/optee/network.c | 58 +++++++++++++++++++++ lib/plat/unix/unix-sockets.c | 60 +++++++++++++++++++++- lib/plat/windows/windows-sockets.c | 53 ++++++++++++++++++++ lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 5 +- 6 files changed, 242 insertions(+), 2 deletions(-) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 0d1556a5..5e7dcbc2 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -1408,6 +1408,13 @@ lws_socks5c_handle_state(struct lws *wsi, struct lws_pollfd *pollfd, int lws_socks5c_greet(struct lws *wsi, const char **pcce); +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len); + +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len); + + enum { LW5CHS_RET_RET0, LW5CHS_RET_BAIL3, diff --git a/lib/plat/freertos/freertos-sockets.c b/lib/plat/freertos/freertos-sockets.c index 2a977578..4efdd07f 100644 --- a/lib/plat/freertos/freertos-sockets.c +++ b/lib/plat/freertos/freertos-sockets.c @@ -24,6 +24,14 @@ #include "private-lib-core.h" +#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) +#include "mbedtls/net_sockets.h" +#else +#include "mbedtls/net.h" +#endif +#endif + int lws_send_pipe_choked(struct lws *wsi) { @@ -259,3 +267,56 @@ lws_plat_ifconfig_ip(const char *ifname, int fd, uint8_t *ip, uint8_t *mask_ip, return -1; } + +#if defined(LWS_WITH_MBEDTLS) +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = write(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if( errno == EINTR ) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + return MBEDTLS_ERR_NET_SEND_FAILED; +} + +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = (int)read(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_READ; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if (errno == EINTR) + return MBEDTLS_ERR_SSL_WANT_READ; + + return MBEDTLS_ERR_NET_RECV_FAILED; +} +#endif + diff --git a/lib/plat/optee/network.c b/lib/plat/optee/network.c index 487e9f48..767c2549 100644 --- a/lib/plat/optee/network.c +++ b/lib/plat/optee/network.c @@ -24,6 +24,13 @@ #include "private-lib-core.h" +#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) +#include "mbedtls/net_sockets.h" +#else +#include "mbedtls/net.h" +#endif +#endif int lws_plat_pipe_create(struct lws *wsi) @@ -247,4 +254,55 @@ lws_plat_inet_pton(int af, const char *src, void *dst) return 1; } +#if defined(LWS_WITH_MBEDTLS) +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = write(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if( errno == EINTR ) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + return MBEDTLS_ERR_NET_SEND_FAILED; +} +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = (int)read(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_READ; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if (errno == EINTR) + return MBEDTLS_ERR_SSL_WANT_READ; + + return MBEDTLS_ERR_NET_RECV_FAILED; +} + +#endif diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index 5e7a68ac..abdb07f9 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -34,7 +34,13 @@ #include #include - +#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) +#include "mbedtls/net_sockets.h" +#else +#include "mbedtls/net.h" +#endif +#endif int lws_send_pipe_choked(struct lws *wsi) @@ -455,3 +461,55 @@ lws_plat_ifconfig_ip(const char *ifname, int fd, uint8_t *ip, uint8_t *mask_ip, return -1; #endif } + +#if defined(LWS_WITH_MBEDTLS) +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = write(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if( errno == EINTR ) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + return MBEDTLS_ERR_NET_SEND_FAILED; +} + +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = (int)read(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_READ; + + if (errno == EPIPE || errno == ECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + if (errno == EINTR) + return MBEDTLS_ERR_SSL_WANT_READ; + + return MBEDTLS_ERR_NET_RECV_FAILED; +} +#endif diff --git a/lib/plat/windows/windows-sockets.c b/lib/plat/windows/windows-sockets.c index f3d3ec20..e52dd62d 100644 --- a/lib/plat/windows/windows-sockets.c +++ b/lib/plat/windows/windows-sockets.c @@ -27,6 +27,13 @@ #endif #include "private-lib-core.h" +#if defined(LWS_WITH_MBEDTLS) +#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) +#include "mbedtls/net_sockets.h" +#else +#include "mbedtls/net.h" +#endif +#endif int lws_send_pipe_choked(struct lws *wsi) @@ -380,3 +387,49 @@ lws_plat_ifconfig_ip(const char *ifname, int fd, uint8_t *ip, uint8_t *mask_ip, return -1; } +#if defined(LWS_WITH_MBEDTLS) +int +lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = write(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_WRITE; + + if (WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + return MBEDTLS_ERR_NET_SEND_FAILED; +} + +int +lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) +{ + int fd = ((mbedtls_net_context *) ctx)->fd; + int ret; + + if (fd < 0) + return MBEDTLS_ERR_NET_INVALID_CONTEXT; + + ret = (int)read(fd, buf, len); + if (ret >= 0) + return ret; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + return MBEDTLS_ERR_SSL_WANT_READ; + + if (WSAGetLastError() == WSAECONNRESET) + return MBEDTLS_ERR_NET_CONN_RESET; + + return MBEDTLS_ERR_NET_RECV_FAILED; +} +#endif + diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 15f2b962..a5bddea2 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -67,6 +67,7 @@ struct pkey_pm unsigned int max_content_len; + /*********************************************************************************************/ /************************************ SSL arch interface *************************************/ @@ -185,7 +186,9 @@ int ssl_pm_new(SSL *ssl) goto mbedtls_err2; } - mbedtls_ssl_set_bio(&ssl_pm->ssl, &ssl_pm->fd, mbedtls_net_send, mbedtls_net_recv, NULL); + mbedtls_ssl_set_bio(&ssl_pm->ssl, &ssl_pm->fd, + lws_plat_mbedtls_net_send, + lws_plat_mbedtls_net_recv, NULL); ssl->ssl_pm = ssl_pm; -- Gitee From e0383324249e29ddc514a7fe904926d17df647e7 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 27 Mar 2020 18:35:23 +0000 Subject: [PATCH 0038/1062] gcc: support -fanalyzer static analysis Starting with gcc 10 (in fedora 32) there's a new static analyzer built into gcc you can enable with -fanalyzer. It doesn't slow compilation much, but it's a bit hit and miss, it only analyzes each compilation unit standalone so it reports issues that can never happen. Enable it if the option LWS_WITH_FANALYZER is enabled and cmake can see the actual compiler supports it. --- CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50b90e6c..9253181c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -166,7 +166,7 @@ option(LWS_WITH_DETAILED_LATENCY "Record detailed latency stats for each read an option(LWS_WITH_UDP "Platform supports UDP" ON) option(LWS_WITH_SPAWN "Spawn subprocesses with piped stdin/out/stderr" OFF) option(LWS_WITH_FSMOUNT "Overlayfs and fallback mounting apis" OFF) - +option(LWS_WITH_FANALYZER "Enable gcc -fanalyzer if compiler supports" OFF) # # to use miniz, enable both LWS_WITH_ZLIB and LWS_WITH_MINIZ @@ -1724,6 +1724,9 @@ endif() if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) include (CheckCCompilerFlag) CHECK_C_COMPILER_FLAG(-fvisibility=hidden LWS_HAVE_VISIBILITY) + if (LWS_WITH_FANALYZER) + CHECK_C_COMPILER_FLAG(-fanalyzer LWS_HAVE_FANALYZER) + endif() if (LWS_HAVE_VISIBILITY) set(VISIBILITY_FLAG -fvisibility=hidden) endif() @@ -1750,6 +1753,10 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) set(CMAKE_C_FLAGS "-Wtype-limits ${CMAKE_C_FLAGS}" ) endif() + if (LWS_WITH_FANALYZER AND LWS_HAVE_FANALYZER) + set(CMAKE_C_FLAGS "-fanalyzer ${CMAKE_C_FLAGS}" ) + endif() + if (UNIX AND NOT LWS_PLAT_FREERTOS) set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wstrict-aliasing -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" ) else() -- Gitee From ee9ab7c1fca1b470123acad222bab8c2f79d6904 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 27 Mar 2020 19:10:40 +0000 Subject: [PATCH 0039/1062] fanalyzer: workarounds and fixes GCC -fanalyzer did find a real issue (unchecked malloc return) but it mainly reported things that weren't true due to what was happening outside of the particular compilation unit that it could see. --- lib/core-net/wsi.c | 5 +++++ lib/roles/http/parsers.c | 6 +++--- lib/secure-streams/secure-streams-client.c | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index ab3fee3e..7eefe47a 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -1036,6 +1036,8 @@ lws_mux_mark_immortal(struct lws *wsi) } nwsi = lws_get_network_wsi(wsi); + if (!nwsi) + return; lwsl_debug("%s: %p %p %d\n", __func__, wsi, nwsi, nwsi->immortal_substream_count); @@ -1051,6 +1053,9 @@ lws_mux_mark_immortal(struct lws *wsi) int lws_http_mark_sse(struct lws *wsi) { + if (!wsi) + return 0; + lws_http_headers_detach(wsi); lws_mux_mark_immortal(wsi); diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index 7abedb6a..78956539 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -1414,9 +1414,9 @@ set_parsing_complete: if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) { #if defined(LWS_ROLE_WS) - if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION)) - wsi->rx_frame_type = /* temp for ws version index */ - atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION)); + const char *pv = lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION); + if (pv) + wsi->rx_frame_type = atoi(pv); lwsl_parser("v%02d hdrs done\n", wsi->rx_frame_type); #endif diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index 57d7ca0d..e9c849ec 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -337,6 +337,8 @@ lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, h = malloc(sizeof(lws_sspc_handle_t) + ssi->user_alloc + strlen(ssi->streamtype) + 1); + if (!h) + return 1; memset(h, 0, sizeof(*h)); memcpy(&h->ssi, ssi, sizeof(*ssi)); ua = (uint8_t *)&h[1]; -- Gitee From e26f83bd83f74931b38e183970321ec25e5cc20b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 28 Mar 2020 16:20:50 +0000 Subject: [PATCH 0040/1062] ss: add support for raw-skt protocol --- CMakeLists.txt | 1 + lib/core-net/vhost.c | 1 + lib/secure-streams/README.md | 8 + lib/secure-streams/policy-json.c | 1 + .../private-lib-secure-streams.h | 2 + lib/secure-streams/protocols/ss-raw.c | 143 ++++++++++++++++++ lib/secure-streams/secure-streams.c | 5 +- 7 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 lib/secure-streams/protocols/ss-raw.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9253181c..511b1e15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1179,6 +1179,7 @@ if (LWS_WITH_NETWORK) lib/secure-streams/secure-streams.c lib/secure-streams/policy-common.c lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c + lib/secure-streams/protocols/ss-raw.c ) if (NOT LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) list(APPEND SOURCES diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index dd9e5260..ecd42843 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -85,6 +85,7 @@ const struct lws_protocols *available_secstream_protocols[] = { #if defined(LWS_ROLE_MQTT) &protocol_secstream_mqtt, #endif + &protocol_secstream_raw, NULL }; #endif diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index 7508cac2..d015d730 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -143,6 +143,14 @@ streamtypes are |h2|http/2| |ws|http/1 Websockets| |mqtt|mqtt 3.1.1| +|raw|| + +Raw protocol is a bit different than the others in that there is no protocol framing, +whatever is received on the connection is passed to the user rx callback and whatever +the tx callback provides is issued on to the connection. Because tcp can be +arbitrarily fragmented by any intermediary, such streams have to be regarded as an +ordered bytestream that may be fragmented at any byte without any meaning in terms +of message boundaries, for that reason SOM and EOM are ignored with raw. ### `plugins` diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 09e5a0c7..49eb0e5e 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -174,6 +174,7 @@ static const char *protonames[] = { "h2", /* LWSSSP_H2 */ "ws", /* LWSSSP_WS */ "mqtt", /* LWSSSP_MQTT */ + "raw", /* LWSSSP_RAW */ }; static signed char diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 9d9044e2..514307f7 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -372,9 +372,11 @@ extern const struct ss_pcols ss_pcol_h1; extern const struct ss_pcols ss_pcol_h2; extern const struct ss_pcols ss_pcol_ws; extern const struct ss_pcols ss_pcol_mqtt; +extern const struct ss_pcols ss_pcol_raw; extern const struct lws_protocols protocol_secstream_h1; extern const struct lws_protocols protocol_secstream_h2; extern const struct lws_protocols protocol_secstream_ws; extern const struct lws_protocols protocol_secstream_mqtt; +extern const struct lws_protocols protocol_secstream_raw; diff --git a/lib/secure-streams/protocols/ss-raw.c b/lib/secure-streams/protocols/ss-raw.c new file mode 100644 index 00000000..05dc8248 --- /dev/null +++ b/lib/secure-streams/protocols/ss-raw.c @@ -0,0 +1,143 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is the glue that wires up raw-socket to Secure Streams. + */ + +#include + +int +secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, + void *in, size_t len) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], + *end = &buf[sizeof(buf) - 1]; + int f = 0; + size_t buflen; + + switch (reason) { + + case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: + assert(h); + assert(h->policy); + lwsl_info("%s: h: %p, %s CLIENT_CONNECTION_ERROR: %s\n", __func__, + h, h->policy->streamtype, in ? (char *)in : "(null)"); + lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + h->wsi = NULL; + lws_ss_backoff(h); + break; + + case LWS_CALLBACK_RAW_CLOSE: + if (!h) + break; + lwsl_info("%s: h: %p, %s LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", + __func__, h, + h->policy ? h->policy->streamtype : "no policy"); + h->wsi = NULL; + if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && + !h->txn_ok && !wsi->context->being_destroyed) + lws_ss_backoff(h); + if (lws_ss_event_helper(h, LWSSSCS_DISCONNECTED)) + lws_ss_destroy(&h); + break; + + case LWS_CALLBACK_RAW_CONNECTED: + lwsl_info("%s: RAW_CONNECTED\n", __func__); + + h->retry = 0; + h->seqstate = SSSEQ_CONNECTED; + lws_ss_set_timeout_us(h, LWS_SET_TIMER_USEC_CANCEL); + lws_ss_event_helper(h, LWSSSCS_CONNECTED); + + lws_validity_confirmed(wsi); + break; + + /* chunks of chunked content, with header removed */ + case LWS_CALLBACK_RAW_RX: + if (!h) + return 0; + + h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, 0); + + return 0; /* don't passthru */ + + case LWS_CALLBACK_RAW_WRITEABLE: + lwsl_info("%s: RAW_WRITEABLE\n", __func__); + if (!h) + return 0; + + buflen = lws_ptr_diff(end, p); + if (h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f)) { + /* don't want to send anything */ + lwsl_debug("%s: dont want to write\n", __func__); + return 0; + } + + /* + * flags are ignored with raw, there are no protocol payload + * boundaries, just an arbitrarily-fragmented bytestream + */ + + p += buflen; + if (lws_write(wsi, buf + LWS_PRE, lws_ptr_diff(p, buf + LWS_PRE), + LWS_WRITE_HTTP) != (int)lws_ptr_diff(p, buf + LWS_PRE)) { + lwsl_err("%s: write failed\n", __func__); + return -1; + } + + lws_set_timeout(wsi, 0, 0); + break; + + default: + break; + } + + return lws_callback_http_dummy(wsi, reason, user, in, len); +} + +static int +secstream_connect_munge_raw(lws_ss_handle_t *h, char *buf, size_t len, + struct lws_client_connect_info *i, + union lws_ss_contemp *ct) +{ + i->method = "RAW"; + + return 0; +} + + +const struct lws_protocols protocol_secstream_raw = { + "lws-secstream-raw", + secstream_raw, + 0, + 0, +}; + +const struct ss_pcols ss_pcol_raw = { + "raw", + "", + "lws-secstream-raw", + secstream_connect_munge_raw, + NULL +}; diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 743d7beb..f9b5fc1d 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -45,6 +45,8 @@ static const struct ss_pcols *ss_pcols[] = { #else NULL, #endif + &ss_pcol_raw, /* LWSSSP_RAW */ + NULL, }; static const char *state_names[] = { @@ -301,7 +303,8 @@ lws_ss_client_connect(lws_ss_handle_t *h) i.protocol = ssp->protocol_name; /* lws protocol name */ i.local_protocol_name = i.protocol; - ssp->munge(h, path, sizeof(path), &i, &ct); + if (ssp->munge) /* eg, raw doesn't use; endpoint strexp already done */ + ssp->munge(h, path, sizeof(path), &i, &ct); i.pwsi = &h->wsi; -- Gitee From d9f249f39faecac82942cc2c568e050dcb940544 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 28 Mar 2020 17:18:28 +0000 Subject: [PATCH 0041/1062] ss-document-support-for-unix-domain Explain how to use unix domain connection with secure streams --- lib/secure-streams/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index d015d730..6098008e 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -128,6 +128,13 @@ define the endpoint as, eg, `${region}.mysite.com`, and before attempting the connection setting the stream's metadata item "region" to the desired value, eg, "uk". +If the endpoint string begins with `+`, then it's understood to +mean a connection to a Unix Domain Socket, for Linux `+@` means +the following Unix Domain Socket is in the Linux Abstract +Namespace and doesn't have a filesystem footprint. This is only +supported on unix-type and windows platforms and when lws was +configured with `-DLWS_UNIX_SOCK=1` + ### `port` The port number as an integer on the endpoint to connect to -- Gitee From a0a1c9c65fe56e6b6cc485178ca0662099987327 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 31 Mar 2020 07:17:34 +0100 Subject: [PATCH 0042/1062] linkit: set cross base to use opt --- contrib/cross-linkit.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/cross-linkit.cmake b/contrib/cross-linkit.cmake index f33fa30f..596cd0af 100644 --- a/contrib/cross-linkit.cmake +++ b/contrib/cross-linkit.cmake @@ -16,7 +16,7 @@ # # if your sdk lives somewhere else, this is the only place that should need changing -set(CROSS_BASE /projects/linkit/sdk) +set(CROSS_BASE /opt/linkit/sdk) set(CROSS_PATH ${CROSS_BASE}/tools/gcc/gcc-arm-none-eabi) # -- Gitee From 39b05e7db3b1fd44ca5092132bb82a3799df7a9f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 31 Mar 2020 11:36:47 +0100 Subject: [PATCH 0043/1062] mbedtls: remove mbedtls_x509_crt_info reference Nobody uses this from the wrapper... it brings in mbedtls_x509_crt_info() even if you're using -ffunctionsections for a loss of about 1.7KB on Arm. Let's chop it out... --- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index a5bddea2..eb4a088e 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -551,6 +551,7 @@ OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl) int x509_pm_show_info(X509 *x) { +#if 0 int ret; char *buf; mbedtls_x509_crt *x509_crt; @@ -590,6 +591,9 @@ mbedtls_err1: ssl_mem_free(buf); no_mem: return -1; +#else + return 0; +#endif } int x509_pm_new(X509 *x, X509 *m_x) -- Gitee From 4caeb56bec1fcb721504e9e9e6c74b5d55cbe152 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 1 Apr 2020 05:56:45 +0100 Subject: [PATCH 0044/1062] vfork There's a subtle difference between fork and vfork... when doing the dup() before the exec, with cfork we are still dealing with the parent process "possessed" by the forked process briefly inbetween the vfork() and the exec(). That matters because when we close the duplicated fds for the stdxxx pipes, with vfork we're closing the fd we still want to hold in the parent process. --- lib/misc/spawn.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/misc/spawn.c b/lib/misc/spawn.c index f9c4a86f..1a41eae7 100644 --- a/lib/misc/spawn.c +++ b/lib/misc/spawn.c @@ -362,7 +362,7 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) if (lws_change_pollfd(lsp->stdwsi[LWS_STDERR], LWS_POLLOUT, LWS_POLLIN)) goto bail3; - lwsl_debug("%s: fds in %d, out %d, err %d\n", __func__, + lwsl_notice("%s: fds in %d, out %d, err %d\n", __func__, lsp->stdwsi[LWS_STDIN]->desc.sockfd, lsp->stdwsi[LWS_STDOUT]->desc.sockfd, lsp->stdwsi[LWS_STDERR]->desc.sockfd); @@ -448,8 +448,18 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) lwsl_err("%s: stdin dup2 failed\n", __func__); goto bail3; } - close(lsp->pipe_fds[m][0]); - close(lsp->pipe_fds[m][1]); + /* + * If we used fork(), then we can close both sides of the + * original pipe now we bound it to fd 0, 1, 2. + * + * But if we used vfork(), until the exec() we have hijacked + * the original process temporarily and we are (ab)using its + * identity during this pre-exec() time + */ + close(lsp->pipe_fds[m][!(m == 0)]); +#if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) + close(lsp->pipe_fds[m][!!(m == 0)]); +#endif } // lwsl_notice("%s: child cd %s, exec %s\n", __func__, wd, i->exec_array[0]); -- Gitee From fb3fd499e336a18c92a0a648f617ad7385ec2986 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 4 Apr 2020 10:47:11 +0100 Subject: [PATCH 0045/1062] threadpool: allow multiple threadpool tasks to bind to same wsi --- include/libwebsockets/lws-threadpool.h | 52 ++++- lib/core-net/private-lib-core-net.h | 2 +- lib/misc/spawn.c | 2 +- lib/misc/threadpool/threadpool.c | 214 ++++++++++++------ .../protocol_lws_minimal_threadpool.c | 5 +- 5 files changed, 185 insertions(+), 90 deletions(-) diff --git a/include/libwebsockets/lws-threadpool.h b/include/libwebsockets/lws-threadpool.h index 5b6cf080..a12c92d3 100644 --- a/include/libwebsockets/lws-threadpool.h +++ b/include/libwebsockets/lws-threadpool.h @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -177,17 +177,21 @@ lws_threadpool_enqueue(struct lws_threadpool *tp, * This doesn't free the task. It only shortcuts it to state * LWS_TP_STATUS_STOPPED. lws_threadpool_task_status() must be performed on * the task separately once it is in LWS_TP_STATUS_STOPPED to free the task. + * + * DEPRECATED: You should use lws_threadpool_dequeue_task() with + * lws_threadpool_get_task_wsi() / _ss() if you know there can only be one task + * per connection, or call it via lws_threadpool_foreach_task_wsi() / _ss() to + * get the tasks bound to the connection. */ LWS_VISIBLE LWS_EXTERN int -lws_threadpool_dequeue(struct lws *wsi); +lws_threadpool_dequeue(struct lws *wsi) LWS_WARN_DEPRECATED; -#if defined(LWS_WITH_SECURE_STREAMS) LWS_VISIBLE LWS_EXTERN int -lws_threadpool_dequeue_ss(struct lws_ss_handle *ss); -#endif +lws_threadpool_dequeue_task(struct lws_threadpool_task *task); + /** - * lws_threadpool_task_status() - Dequeue or try to stop a running task + * lws_threadpool_task_status() - reap completed tasks * * \param wsi: the wsi to query the current task of * \param task: receives a pointer to the opaque task @@ -202,16 +206,18 @@ lws_threadpool_dequeue_ss(struct lws_ss_handle *ss); * * Its use is to make sure the service thread has seen the state of the task * before deleting it. + * + * DEPRECATED... use lws_threadpool_task_status() instead and get the task + * pointer from lws_threadpool_get_task_wsi() / _ss() if you know there can only + * be one, else call it via lws_threadpool_foreach_task_wsi() / _ss() */ LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status lws_threadpool_task_status_wsi(struct lws *wsi, - struct lws_threadpool_task **task, void **user); + struct lws_threadpool_task **task, void **user) + LWS_WARN_DEPRECATED; -#if defined(LWS_WITH_SECURE_STREAMS) LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status -lws_threadpool_task_status_ss(struct lws_ss_handle *ss, - struct lws_threadpool_task **task, void **user); -#endif +lws_threadpool_task_status(struct lws_threadpool_task *task, void **user); /** * lws_threadpool_task_sync() - Indicate to a stalled task it may continue @@ -244,4 +250,28 @@ lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop); LWS_VISIBLE LWS_EXTERN void lws_threadpool_dump(struct lws_threadpool *tp); + + + +LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task * +lws_threadpool_get_task_wsi(struct lws *wsi); + +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task * +lws_threadpool_get_task_ss(struct lws_ss_handle *ss); +#endif + + +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_foreach_task_wsi(struct lws *wsi, void *user, + int (*cb)(struct lws_threadpool_task *task, + void *user)); + +#if defined(LWS_WITH_SECURE_STREAMS) +LWS_VISIBLE LWS_EXTERN int +lws_threadpool_foreach_task_ss(struct lws_ss_handle *ss, void *user, + int (*cb)(struct lws_threadpool_task *task, void *user)); +#endif + + //@} diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 5e7dcbc2..b6540083 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -710,7 +710,7 @@ struct lws { const lws_retry_bo_t *retry_policy; #if defined(LWS_WITH_THREADPOOL) - struct lws_threadpool_task *tp_task; + lws_dll2_owner_t tp_task_owner; /* struct lws_threadpool_task */ #endif #if defined(LWS_WITH_PEER_LIMITS) diff --git a/lib/misc/spawn.c b/lib/misc/spawn.c index 1a41eae7..fdc61cd2 100644 --- a/lib/misc/spawn.c +++ b/lib/misc/spawn.c @@ -456,8 +456,8 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) * the original process temporarily and we are (ab)using its * identity during this pre-exec() time */ - close(lsp->pipe_fds[m][!(m == 0)]); #if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) + close(lsp->pipe_fds[m][!(m == 0)]); close(lsp->pipe_fds[m][!!(m == 0)]); #endif } diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index 6a4a38bc..deab7571 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -36,59 +36,61 @@ struct lws_threadpool; struct lws_threadpool_task { - struct lws_threadpool_task *task_queue_next; + struct lws_threadpool_task *task_queue_next; - struct lws_threadpool *tp; - char name[32]; + struct lws_threadpool *tp; + char name[32]; struct lws_threadpool_task_args args; - lws_usec_t created; - lws_usec_t acquired; - lws_usec_t done; - lws_usec_t entered_state; + lws_dll2_t list; + + lws_usec_t created; + lws_usec_t acquired; + lws_usec_t done; + lws_usec_t entered_state; - lws_usec_t acc_running; - lws_usec_t acc_syncing; + lws_usec_t acc_running; + lws_usec_t acc_syncing; - pthread_cond_t wake_idle; + pthread_cond_t wake_idle; enum lws_threadpool_task_status status; - int late_sync_retries; + int late_sync_retries; - char wanted_writeable_cb; - char outlive; + char wanted_writeable_cb; + char outlive; }; struct lws_pool { - struct lws_threadpool *tp; - pthread_t thread; - pthread_mutex_t lock; /* part of task wake_idle */ - struct lws_threadpool_task *task; - lws_usec_t acquired; - int worker_index; + struct lws_threadpool *tp; + pthread_t thread; + pthread_mutex_t lock; /* part of task wake_idle */ + struct lws_threadpool_task *task; + lws_usec_t acquired; + int worker_index; }; struct lws_threadpool { - pthread_mutex_t lock; /* protects all pool lists */ - pthread_cond_t wake_idle; - struct lws_pool *pool_list; + pthread_mutex_t lock; /* protects all pool lists */ + pthread_cond_t wake_idle; + struct lws_pool *pool_list; - struct lws_context *context; - struct lws_threadpool *tp_list; /* context list of threadpools */ + struct lws_context *context; + struct lws_threadpool *tp_list; /* context list of threadpools */ - struct lws_threadpool_task *task_queue_head; - struct lws_threadpool_task *task_done_head; + struct lws_threadpool_task *task_queue_head; + struct lws_threadpool_task *task_done_head; - char name[32]; + char name[32]; - int threads_in_pool; - int queue_depth; - int done_queue_depth; - int max_queue_depth; - int running_tasks; + int threads_in_pool; + int queue_depth; + int done_queue_depth; + int max_queue_depth; + int running_tasks; - unsigned int destroying:1; + unsigned int destroying:1; }; static int @@ -248,8 +250,7 @@ lws_threadpool_task_cleanup_destroy(struct lws_threadpool_task *task) if (task->args.cleanup) task->args.cleanup(task_to_wsi(task), task->args.user); - if (task_to_wsi(task)) - task_to_wsi(task)->tp_task = NULL; + lws_dll2_remove(&task->list); lwsl_thread("%s: tp %p: cleaned finished task for wsi %p\n", __func__, task->tp, task_to_wsi(task)); @@ -801,21 +802,16 @@ lws_threadpool_destroy(struct lws_threadpool *tp) } /* - * we want to stop and destroy the task and related priv. The wsi may no - * longer exist. + * We want to stop and destroy the tasks and related priv. */ int -lws_threadpool_dequeue(struct lws *wsi) +lws_threadpool_dequeue_task(struct lws_threadpool_task *task) { struct lws_threadpool *tp; - struct lws_threadpool_task **c, *task; + struct lws_threadpool_task **c; int n; - task = wsi->tp_task; - if (!task) - return 0; - tp = task->tp; pthread_mutex_lock(&tp->lock); /* ======================== tpool lock */ @@ -823,7 +819,7 @@ lws_threadpool_dequeue(struct lws *wsi) /* disconnect from wsi, and wsi from task */ - wsi->tp_task = NULL; + lws_dll2_remove(&task->list); task->args.wsi = NULL; #if defined(LWS_WITH_SECURE_STREAMS) task->args.ss = NULL; @@ -891,7 +887,7 @@ lws_threadpool_dequeue(struct lws *wsi) /* disconnect from wsi, and wsi from task */ - task->args.wsi->tp_task = NULL; + lws_dll2_remove(&task->list); task->args.wsi = NULL; #if defined(LWS_WITH_SECURE_STREAMS) task->args.ss = NULL; @@ -909,7 +905,7 @@ lws_threadpool_dequeue(struct lws *wsi) /* can't find it */ lwsl_notice("%s: tp %p: no task for wsi %p, decoupling\n", __func__, tp, task_to_wsi(task)); - task->args.wsi->tp_task = NULL; + lws_dll2_remove(&task->list); task->args.wsi = NULL; #if defined(LWS_WITH_SECURE_STREAMS) task->args.ss = NULL; @@ -922,16 +918,20 @@ bail: return 0; } -#if defined(LWS_WITH_SECURE_STREAMS) int -lws_threadpool_dequeue_ss(struct lws_ss_handle *ss) +lws_threadpool_dequeue(struct lws *wsi) /* deprecated */ { - if (ss) - return lws_threadpool_dequeue(ss->wsi); + struct lws_threadpool_task *task; - return 0; + if (!wsi->tp_task_owner.count) + return 0; + assert(wsi->tp_task_owner.count != 1); + + task = lws_container_of(wsi->tp_task_owner.head, + struct lws_threadpool_task, list); + + return lws_threadpool_dequeue_task(task); } -#endif struct lws_threadpool_task * lws_threadpool_enqueue(struct lws_threadpool *tp, @@ -996,10 +996,10 @@ lws_threadpool_enqueue(struct lws_threadpool *tp, #if defined(LWS_WITH_SECURE_STREAMS) if (args->ss) - args->ss->wsi->tp_task = task; + lws_dll2_add_tail(&task->list, &args->ss->wsi->tp_task_owner); else #endif - args->wsi->tp_task = task; + lws_dll2_add_tail(&task->list, &args->wsi->tp_task_owner); lwsl_thread("%s: tp %s: enqueued task %p (%s) for wsi %p, depth %d\n", __func__, tp->name, task, task->name, task_to_wsi(task), @@ -1019,31 +1019,23 @@ bail: /* this should be called from the service thread */ enum lws_threadpool_task_status -lws_threadpool_task_status_wsi(struct lws *wsi, - struct lws_threadpool_task **task, void **user) +lws_threadpool_task_status(struct lws_threadpool_task *task, void **user) { enum lws_threadpool_task_status status; - struct lws_threadpool *tp; - - *task = wsi->tp_task; - if (!*task) { - lwsl_notice("%s: wsi has NULL tp_task, ~=FINISHED\n", __func__); - return LWS_TP_STATUS_FINISHED; - } + struct lws_threadpool *tp = task->tp; - tp = (*task)->tp; - *user = (*task)->args.user; - status = (*task)->status; + *user = task->args.user; + status = task->status; if (status == LWS_TP_STATUS_FINISHED || status == LWS_TP_STATUS_STOPPED) { char buf[160]; pthread_mutex_lock(&tp->lock); /* ================ tpool lock */ - __lws_threadpool_task_dump(*task, buf, sizeof(buf)); + __lws_threadpool_task_dump(task, buf, sizeof(buf)); lwsl_thread("%s: %s: service thread REAPING: %s\n", __func__, tp->name, buf); - __lws_threadpool_reap(*task); + __lws_threadpool_reap(task); lws_memory_barrier(); pthread_mutex_unlock(&tp->lock); /* ------------ tpool unlock */ } @@ -1051,17 +1043,26 @@ lws_threadpool_task_status_wsi(struct lws *wsi, return status; } -#if defined(LWS_WITH_SECURE_STREAMS) enum lws_threadpool_task_status -lws_threadpool_task_status_ss(struct lws_ss_handle *ss, - struct lws_threadpool_task **task, void **user) +lws_threadpool_task_status_wsi(struct lws *wsi, + struct lws_threadpool_task **_task, void **user) { - if (ss) - return lws_threadpool_task_status_wsi(ss->wsi, task, user); + struct lws_threadpool_task *task; - return -1; + if (!wsi->tp_task_owner.count) { + lwsl_notice("%s: wsi has no task, ~=FINISHED\n", __func__); + return LWS_TP_STATUS_FINISHED; + } + + assert(wsi->tp_task_owner.count == 1); /* see deprecation docs in hdr */ + + task = lws_container_of(wsi->tp_task_owner.head, + struct lws_threadpool_task, list); + + *_task = task; + + return lws_threadpool_task_status(task, user); } -#endif void lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop) @@ -1073,3 +1074,66 @@ lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop) pthread_cond_signal(&task->wake_idle); } + +int +lws_threadpool_foreach_task_wsi(struct lws *wsi, void *user, + int (*cb)(struct lws_threadpool_task *task, + void *user)) +{ + struct lws_threadpool_task *task1; + + if (wsi->tp_task_owner.head == NULL) + return 0; + + task1 = lws_container_of(wsi->tp_task_owner.head, + struct lws_threadpool_task, list); + + pthread_mutex_lock(&task1->tp->lock); /* ================ tpool lock */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + wsi->tp_task_owner.head) { + struct lws_threadpool_task *task = lws_container_of(d, + struct lws_threadpool_task, list); + + if (cb(task, user)) { + pthread_mutex_unlock(&task1->tp->lock); /* ------------ tpool unlock */ + return 1; + } + + } lws_end_foreach_dll_safe(d, d1); + + pthread_mutex_unlock(&task1->tp->lock); /* ------------ tpool unlock */ + + return 0; +} + +#if defined(LWS_WITH_SECURE_STREAMS) +int +lws_threadpool_foreach_task_ss(struct lws_ss_handle *ss, void *user, + int (*cb)(struct lws_threadpool_task *task, + void *user)) +{ + if (!ss->wsi) + return 0; + + return lws_threadpool_foreach_task_wsi(ss->wsi, user, cb); +} +#endif + +struct lws_threadpool_task * +lws_threadpool_get_task_wsi(struct lws *wsi) +{ + if (wsi->tp_task_owner.head == NULL) + return NULL; + + return lws_container_of(wsi->tp_task_owner.head, + struct lws_threadpool_task, list); +} + +#if defined(LWS_WITH_SECURE_STREAMS) +struct lws_threadpool_task * +lws_threadpool_get_task_ss(struct lws_ss_handle *ss) +{ + return lws_threadpool_get_task_wsi(ss->wsi); +} +#endif diff --git a/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c b/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c index 9850072c..55998a79 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c +++ b/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c @@ -237,7 +237,7 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL: lwsl_debug("LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL: %p\n", wsi); - lws_threadpool_dequeue(wsi); + lws_threadpool_dequeue_task(lws_threadpool_get_task_wsi(wsi)); break; case LWS_CALLBACK_SERVER_WRITEABLE: @@ -253,7 +253,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, * private task data. */ - n = lws_threadpool_task_status_wsi(wsi, &task, &_user); + task = lws_threadpool_get_task_wsi(wsi); + n = lws_threadpool_task_status(task, &_user); lwsl_debug("%s: LWS_CALLBACK_SERVER_WRITEABLE: status %d\n", __func__, n); switch(n) { -- Gitee From 370ba6f5eda09b70fb4494fe82b6169859722034 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 5 Apr 2020 12:06:31 +0100 Subject: [PATCH 0046/1062] lws_struct: handle empty char array serialization --- lib/misc/lws-struct-lejp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/misc/lws-struct-lejp.c b/lib/misc/lws-struct-lejp.c index 7e94f26f..477bd55e 100644 --- a/lib/misc/lws-struct-lejp.c +++ b/lib/misc/lws-struct-lejp.c @@ -478,6 +478,10 @@ lws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, /* early check if the entry should be elided */ switch (map->type) { + case LSMT_STRING_CHAR_ARRAY: + if (!q) + goto up; + break; case LSMT_STRING_PTR: case LSMT_CHILD_PTR: q = (char *)*(char **)q; -- Gitee From 8385cb427fa35f7eb947d0b6622ae082b6b25f06 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 6 Apr 2020 09:58:03 +0100 Subject: [PATCH 0047/1062] sai.json Add initial Sai CI config for build --- .sai.json | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 .sai.json diff --git a/.sai.json b/.sai.json new file mode 100644 index 00000000..1f651a94 --- /dev/null +++ b/.sai.json @@ -0,0 +1,103 @@ +{ + "schema": "sai-1", + + "platforms": { + "linux-ubuntu-xenial-amd64": { + "build": "mkdir build destdir;cd build;cmake .. ${cmake};make -j;make -j DESTDIR=../destdir install" + }, + "linux-ubuntu-bionic-amd64": { + "build": "mkdir build destdir;cd build;cmake .. ${cmake};make -j;make -j DESTDIR=../destdir install" + }, + "linux-fedora-32-x86_64": { + "build": "mkdir build destdir;cd build;cmake .. ${cmake};make -j;make -j DESTDIR=../destdir install" + }, + "OSX-catalina": { + "build": "mkdir build destdir; cd build; cmake .. -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/openssl@1.1/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} && make -j" + }, + "linkit-cross": { + "build": "mkdir build;cd build;cmake .. ${cmake};make -j", + "default": false + } + }, + + "configurations": { + "default": { + "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", + "deps": "openssl" + }, + "linkit": { + "cmake": "-DCMAKE_INSTALL_PREFIX:PATH=/tmp -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake -DLWS_PLAT_FREERTOS=1 -DLWS_WITH_ZLIB=0 -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_HTTP_STREAM_COMPRESSION=0 -DLWS_WITH_MBEDTLS=1 -DLWS_WITH_FILE_OPS=0", + "deps": "linkit-sdk", + "platforms": "linkit-cross" + }, + "lwsws": { + "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", + "deps": "libz,openssl" + }, + "lwsws2": { + "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_LWS_DSH=1", + "deps": "libz,openssl" + }, + "mbedtls": { + "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG", + "deps": "mbedtls" + }, + "noserver": { + "cmake": "-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1", + "deps": "openssl" + }, + "noclient": { + "cmake": "-DLWS_WITHOUT_CLIENT=ON -DLWS_WITH_MINIMAL_EXAMPLES=1", + "deps": "openssl" + }, + "ext": { + "cmake": "-DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_MINIMAL_EXAMPLES=1", + "deps": "libz,openssl" + }, + "nonetwork": { + "cmake": "-DLWS_WITH_NETWORK=0" + }, + "libev": { + "cmake": "-DLWS_WITH_LIBEV=ON", + "deps": "libev" + }, + "libevent": { + "cmake": "-DLWS_WITH_LIBEVENT=ON", + "deps": "libevent" + }, + "libglib": { + "cmake": "-DLWS_WITH_GLIB=ON", + "deps": "libglib" + }, + "ipv6": { + "cmake": "-DLWS_IPV6=ON" + }, + "nossl": { + "cmake": "-DLWS_WITH_SSL=OFF" + }, + "daemon": { + "cmake": "-DLWS_WITHOUT_DAEMONIZE=OFF", + "deps": "openssl" + }, + "cgi": { + "cmake": "-DLWS_WITH_CGI=ON", + "deps": "openssl" + }, + "nologs": { + "cmake": "-DLWS_WITH_NO_LOGS=ON", + "deps": "openssl" + }, + "smp": { + "cmake": "-DLWS_MAX_SMP=32 -DLWS_WITH_MINIMAL_EXAMPLES=1", + "deps": "openssl" + }, + "nows": { + "cmake": "-DLWS_ROLE_WS=0", + "deps": "openssl" + }, + "threadpool": { + "cmake": "-DLWS_WITH_THREADPOOL=1 -DLWS_WITH_MINIMAL_EXAMPLES=1" + } + } +} + -- Gitee From 5e99b9f3eee05690e9b94b97e57dc42a4d8df442 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 6 Apr 2020 13:22:01 +0100 Subject: [PATCH 0048/1062] h2: take care to retain initial sid --- CMakeLists.txt | 2 +- lib/core-net/wsi.c | 10 ++++++++-- lib/roles/h2/http2.c | 24 +++++++++++++++++++++--- lib/roles/h2/ops-h2.c | 4 ++-- lib/roles/http/client/client-http.c | 2 +- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 511b1e15..5d093792 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -357,7 +357,7 @@ find_package(Git) if(GIT_EXECUTABLE) execute_process( WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMAND "${GIT_EXECUTABLE}" describe --tags + COMMAND "${GIT_EXECUTABLE}" describe --tags --always OUTPUT_VARIABLE GIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ) diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index 7eefe47a..d0b49af3 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -1088,6 +1088,12 @@ lws_wsi_client_stash_item(struct lws *wsi, int stash_idx, int hdr_idx) void lws_wsi_mux_insert(struct lws *wsi, struct lws *parent_wsi, int sid) { + lwsl_info("%s: wsi %p, par %p: assign sid %d (curr %d)\n", __func__, + wsi, parent_wsi, sid, wsi->mux.my_sid); + + if (wsi->mux.my_sid && wsi->mux.my_sid != (unsigned int)sid) + assert(0); + wsi->mux.my_sid = sid; wsi->mux.parent_wsi = parent_wsi; wsi->role_ops = parent_wsi->role_ops; @@ -1204,8 +1210,8 @@ lws_wsi_mux_mark_parents_needing_writeable(struct lws *wsi) wsi2 = wsi; while (wsi2) { wsi2->mux.requested_POLLOUT = 1; - lwsl_info("%s: mark %p (sid %u) pending writable\n", __func__, - wsi2, wsi2->mux.my_sid); + lwsl_info("%s: mark wsi: %p, sid %u, pending writable\n", + __func__, wsi2, wsi2->mux.my_sid); wsi2 = wsi2->mux.parent_wsi; } diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index d08084ae..931b453e 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -248,6 +248,8 @@ lws_wsi_server_new(struct lws_vhost *vh, struct lws *parent_wsi, h2n->highest_sid_opened = sid; lws_wsi_mux_insert(wsi, parent_wsi, sid); + if (sid >= h2n->highest_sid) + h2n->highest_sid = sid + 2; wsi->mux_substream = 1; wsi->seen_nonpseudoheader = 0; @@ -319,6 +321,9 @@ lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi) nwsi->h2.h2n->highest_sid += 2; } + lwsl_info("%s: binding wsi %p to sid %d (next %d)\n", __func__, + wsi, (int)wsi->mux.my_sid, (int)nwsi->h2.h2n->highest_sid); + lws_wsi_mux_insert(wsi, parent_wsi, wsi->mux.my_sid); wsi->txc.tx_cr = nwsi->h2.h2n->peer_set.s[H2SET_INITIAL_WINDOW_SIZE]; @@ -1219,6 +1224,9 @@ lws_h2_parse_frame_header(struct lws *wsi) return 1; } + if (h2n->sid >= h2n->highest_sid) + h2n->highest_sid = h2n->sid + 2; + h2n->swsi->h2.initialized = 1; if (lws_h2_update_peer_txcredit(h2n->swsi, @@ -1569,6 +1577,9 @@ lws_h2_parse_end_of_frame(struct lws *wsi) } switch (h2n->swsi->h2.h2_state) { + case LWS_H2_STATE_IDLE: + lws_h2_state(h2n->swsi, LWS_H2_STATE_OPEN); + break; case LWS_H2_STATE_OPEN: if (h2n->swsi->h2.END_STREAM) lws_h2_state(h2n->swsi, @@ -1582,7 +1593,8 @@ lws_h2_parse_end_of_frame(struct lws *wsi) #if defined(LWS_WITH_CLIENT) if (h2n->swsi->client_mux_substream) { - lwsl_info("%s: headers: client path\n", __func__); + lwsl_info("%s: wsi %p: headers: client path (h2 state %s)\n", + __func__, wsi, h2_state_names[h2n->swsi->h2.h2_state]); break; } #endif @@ -2318,7 +2330,13 @@ lws_h2_client_handshake(struct lws *wsi) lwsl_debug("%s\n", __func__); nwsi->h2.h2n->highest_sid_opened = sid; - wsi->mux.my_sid = sid; + if (!wsi->mux.my_sid) + wsi->mux.my_sid = sid; + else { + lwsl_debug("%s: %p already sid %d\n", + __func__, wsi, (int)wsi->mux.my_sid); + //assert(0); + } lwsl_info("%s: CLIENT_WAITING_TO_SEND_HEADERS: pollout (sid %d)\n", __func__, wsi->mux.my_sid); @@ -2430,7 +2448,7 @@ lws_h2_client_handshake(struct lws *wsi) wsi->txc.manual = 1; } - if (lws_h2_update_peer_txcredit(wsi, sid, n)) + if (lws_h2_update_peer_txcredit(wsi, wsi->mux.my_sid, n)) return 1; lws_h2_state(wsi, LWS_H2_STATE_OPEN); diff --git a/lib/roles/h2/ops-h2.c b/lib/roles/h2/ops-h2.c index 56f2a8d6..65b8f509 100644 --- a/lib/roles/h2/ops-h2.c +++ b/lib/roles/h2/ops-h2.c @@ -859,8 +859,8 @@ rops_perform_user_POLLOUT_h2(struct lws *wsi) goto next_child; } - lwsl_info("%s: child %p (wsistate 0x%x)\n", __func__, w, - (unsigned int)w->wsistate); + lwsl_info("%s: child wsi %p, sid %d, (wsistate 0x%x)\n", + __func__, w, w->mux.my_sid, (unsigned int)w->wsistate); /* priority 1: post compression-transform buffered output */ diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 009a918a..f34cbbc5 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -933,7 +933,7 @@ lws_client_interpret_server_handshake(struct lws *wsi) wsi->http.ah = ah1; - lwsl_info("%s: client connection up\n", __func__); + lwsl_info("%s: wsi %p: client connection up\n", __func__, wsi); /* * Did we get a response from the server with an explicit -- Gitee From 66d1f34846895dbe382444ee593d0bdb4b38e155 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 6 Apr 2020 14:06:33 +0100 Subject: [PATCH 0049/1062] ss: avs test: disable rate limiting Rate limiting does not work correctly with AVS server, the last block of rx data is not coming. Disable it for now so the returned data comes as rapidly as the server can send and the client receive. --- .../minimal-secure-streams-avs/avs.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c index fe8dd2ee..9fbd6aa4 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c @@ -46,7 +46,7 @@ typedef struct ss_avs_metadata { */ lws_sorted_usec_list_t sul; - uint8_t buf[8192]; + uint8_t buf[256 * 1024]; /* to test rate-limiting, set to 8 * 1024 */ int head; int tail; @@ -125,8 +125,9 @@ ss_avs_metadata_rx(void *userobj, const uint8_t *buf, size_t len, int flags) (int)len, (int)m->head, (int)m->tail, (int)n); lws_ss_get_est_peer_tx_credit(m->ss); if (len > n) { + lwsl_err("%s: bad len: len %d, n %d\n", __func__, (int)len, (int)n); assert(0); - lwsl_err("%s: bad len\n", __func__); + return 1; } @@ -159,11 +160,11 @@ ss_avs_metadata_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, if ((long)m->pos < 0) { *len = 0; - lwsl_notice("%s: skip tx\n", __func__); + lwsl_debug("%s: skip tx\n", __func__); return 1; } - lwsl_notice("%s: rideshare '%s'\n", __func__, lws_ss_rideshare(m->ss)); +// lwsl_notice("%s: rideshare '%s'\n", __func__, lws_ss_rideshare(m->ss)); if (!strcmp(lws_ss_rideshare(m->ss), "avs_audio")) { /* audio rideshare */ @@ -268,7 +269,7 @@ ss_avs_event_rx(void *userobj, const uint8_t *buf, size_t len, int flags) lwsl_notice("%s: rideshare %s, len %d, flags 0x%x\n", __func__, lws_ss_rideshare(m->ss), (int)len, flags); - //lwsl_hexdump_warn(buf, len); +// lwsl_hexdump_warn(buf, len); bad = 0; /* for this demo, receiving something here == success */ @@ -327,8 +328,9 @@ ss_avs_event_state(void *userobj, void *sh, * framing like multipart MIME and contains other parts */ - ssi.manual_initial_tx_credit = - sizeof(((ss_avs_metadata_t *)0)->buf) / 2; + /* uncomment to test rate-limiting, doesn't work with AVS servers */ +// ssi.manual_initial_tx_credit = +// sizeof(((ss_avs_metadata_t *)0)->buf) / 2; if (lws_ss_create(context, 0, &ssi, context, &hss_avs_sync, NULL, NULL)) { -- Gitee From 33c9a6da4c599a47dbdaff6823f2c9befc8e3d30 Mon Sep 17 00:00:00 2001 From: Jaco Kroon Date: Mon, 6 Apr 2020 18:29:25 +0200 Subject: [PATCH 0050/1062] vhost: Fix unused var warning with some SOCKS5 after 6bb116b8d8d59139416ceb8cb3ca522b3fa9adb3 the variable p could be declared without being used. https://bugs.gentoo.org/716386 refers. This just fixes that. --- lib/core-net/vhost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index ecd42843..3bdd7abf 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -477,8 +477,8 @@ lws_create_vhost(struct lws_context *context, struct lws_protocols *lwsp; int m, f = !info->pvo, fx = 0, abs_pcol_count = 0, sec_pcol_count = 0; char buf[96]; -#if ((defined(LWS_CLIENT_HTTP_PROXYING) && defined(LWS_WITH_CLIENT)) \ - || defined(LWS_WITH_SOCKS5)) && defined(LWS_HAVE_GETENV) +#if defined(LWS_CLIENT_HTTP_PROXYING) && defined(LWS_WITH_CLIENT) \ + && defined(LWS_HAVE_GETENV) char *p; #endif #if defined(LWS_WITH_SYS_ASYNC_DNS) -- Gitee From 2d55e18947fe68017984a2aa5971b8745cbb85bf Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 6 Apr 2020 20:25:06 +0100 Subject: [PATCH 0051/1062] ss: windows build adaptations Windows compiler finds various non-bug things to complain about when building with SS and other options, fix them up --- include/libwebsockets/lws-misc.h | 4 ++++ lib/misc/lws-struct-lejp.c | 2 +- lib/secure-streams/policy-common.c | 3 ++- lib/secure-streams/policy-json.c | 4 ++-- .../private-lib-secure-streams.h | 19 ++++++++++++++++--- lib/secure-streams/protocols/ss-h1.c | 7 ++++--- .../system/auth-api.amazon.com/auth.c | 4 ++-- 7 files changed, 31 insertions(+), 12 deletions(-) diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index 1d36923b..493218c1 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -723,6 +723,10 @@ lws_vbi_decode(const void *buf, uint64_t *value, size_t len); /* opaque internal struct */ struct lws_spawn_piped; +#if defined(WIN32) +typedef struct _lws_siginfo_t *siginfo_t; +#endif + typedef void (*lsp_cb_t)(void *opaque, lws_usec_t *accounting, siginfo_t *si, int we_killed_him); diff --git a/lib/misc/lws-struct-lejp.c b/lib/misc/lws-struct-lejp.c index 477bd55e..627a891f 100644 --- a/lib/misc/lws-struct-lejp.c +++ b/lib/misc/lws-struct-lejp.c @@ -675,7 +675,7 @@ lws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, * in "used". */ - lws_json_purify((char *)buf, q, len, &used); + lws_json_purify((char *)buf, q, (int)len, &used); m = strlen((const char *)buf); buf += m; len -= m; diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index 98102dfc..24fe833b 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -202,7 +202,8 @@ lws_ss_policy_set(struct lws_context *context, const char *name) i.vhost_name = pol->trust_store->name; lwsl_debug("%s: %s\n", __func__, i.vhost_name); i.client_ssl_ca_mem = pol->trust_store->ssx509[0]->ca_der; - i.client_ssl_ca_mem_len = pol->trust_store->ssx509[0]->ca_der_len; + i.client_ssl_ca_mem_len = (unsigned int) + pol->trust_store->ssx509[0]->ca_der_len; i.port = CONTEXT_PORT_NO_LISTEN; lwsl_info("%s: %s trust store initial '%s'\n", __func__, i.vhost_name, pol->trust_store->ssx509[0]->vhost_name); diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 49eb0e5e..51c05f1a 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -365,7 +365,7 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) lws_b64_decode_stateful(&a->b64, ctx->buf, &inl, a->p + a->count, &outl, reason == LEJPCB_VAL_STR_END); - a->count += outl; + a->count += (int)outl; if (inl != ctx->npos) { lwsl_err("%s: b64 decode fail\n", __func__); goto oom; @@ -766,7 +766,7 @@ lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len) struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; int m; - m = (int)(signed char)lejp_parse(&args->jctx, buf, len); + m = (int)(signed char)lejp_parse(&args->jctx, buf, (int)len); if (m == LEJP_CONTINUE || m >= 0) return m; diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 514307f7..02e607f6 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -92,10 +92,19 @@ typedef struct lws_ss_handle { union { struct { /* LWSSSP_H1 */ +#if defined(WIN32) + uint8_t dummy; +#endif } h1; struct { /* LWSSSP_H2 */ +#if defined(WIN32) + uint8_t dummy; +#endif } h2; struct { /* LWSSSP_WS */ +#if defined(WIN32) + uint8_t dummy; +#endif } ws; } u; } http; @@ -132,6 +141,10 @@ typedef struct lws_ss_handle { union lws_ss_contemp { #if defined(LWS_ROLE_MQTT) lws_mqtt_client_connect_param_t ccp; +#else +#if defined(WIN32) + uint8_t dummy; +#endif #endif }; @@ -363,9 +376,9 @@ struct ss_pcols { const char *name; const char *alpn; const char *protocol_name; - const secstream_protocol_connect_munge_t munge; - const secstream_protocol_add_txcr_t tx_cr_add; - const secstream_protocol_get_txcr_t tx_cr_est; + secstream_protocol_connect_munge_t munge; + secstream_protocol_add_txcr_t tx_cr_add; + secstream_protocol_get_txcr_t tx_cr_est; }; extern const struct ss_pcols ss_pcol_h1; diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 81065a33..2daf8747 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -272,7 +272,8 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_strnncpy(h->u.http.boundary + 4, ts.token, ts.token_len, sizeof(h->u.http.boundary) - 4); - h->u.http.boundary_len = ts.token_len + 4; + h->u.http.boundary_len = + (uint8_t)(ts.token_len + 4); h->u.http.boundary_seq = 2; h->u.http.boundary_dashes = 0; } @@ -334,7 +335,7 @@ malformed: if (lws_add_http_header_by_name(wsi, (uint8_t *)h->policy->u.http.blob_header[m], - buf, buflen + o, p, end)) + buf, (int)(buflen + o), p, end)) return -1; } @@ -357,7 +358,7 @@ malformed: if (lws_add_http_header_by_name(wsi, polmd->value, h->metadata[m].value, - h->metadata[m].length, p, end)) + (int)h->metadata[m].length, p, end)) return -1; } } diff --git a/lib/secure-streams/system/auth-api.amazon.com/auth.c b/lib/secure-streams/system/auth-api.amazon.com/auth.c index 697ae77b..7e3d6d4e 100644 --- a/lib/secure-streams/system/auth-api.amazon.com/auth.c +++ b/lib/secure-streams/system/auth-api.amazon.com/auth.c @@ -126,7 +126,7 @@ ss_api_amazon_auth_rx(void *userobj, const uint8_t *buf, size_t len, int flags) lws_system_blob_heap_empty(ab); } - n = (int)(signed char)lejp_parse(&m->jctx, buf, len); + n = (int)(signed char)lejp_parse(&m->jctx, buf, (int)len); if (n < 0) { lejp_destruct(&m->jctx); lws_system_blob_destroy( @@ -205,7 +205,7 @@ ss_api_amazon_auth_state(void *userobj, void *sh, lws_ss_constate_t state, s = lws_system_blob_get_size( lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, AUTH_IDX_ROOT)); - lws_ss_request_tx_len(m->ss, s); + lws_ss_request_tx_len(m->ss, (unsigned long)s); m->pos = 0; break; -- Gitee From 1a8833dcfdb197dd11d9fb2750973bca9e3e9d26 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 7 Apr 2020 10:09:00 +0100 Subject: [PATCH 0052/1062] windows: ipv6 compile fix Via turtiain https://github.com/warmcat/libwebsockets/issues/1880 --- lib/plat/windows/windows-sockets.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/plat/windows/windows-sockets.c b/lib/plat/windows/windows-sockets.c index e52dd62d..d211e0f2 100644 --- a/lib/plat/windows/windows-sockets.c +++ b/lib/plat/windows/windows-sockets.c @@ -149,6 +149,7 @@ int lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, size_t addrlen) { + long long address; #ifdef LWS_WITH_IPV6 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; @@ -159,7 +160,7 @@ lws_interface_to_sa(int ipv6, } #endif - long long address = inet_addr(ifname); + address = inet_addr(ifname); if (address == INADDR_NONE) { struct hostent *entry = gethostbyname(ifname); -- Gitee From 954fcf2bc32567f806ef947fd7d5be1355555e91 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 7 Apr 2020 09:13:46 +0100 Subject: [PATCH 0053/1062] windows: clean LWS_WITH_MINIMAL_EXAMPLES warnings Fix pthreads detection in the minimal examples and add it where needed. Fix unistd.h include to be conditional on not WIN32 With this, -DLWS_WITH_MINIMAL_EXAMPLES=1 is happy and warning-free on windows. --- .../api-tests/api-test-lws_struct-json/main.c | 2 +- .../minimal-http-client-attach/CMakeLists.txt | 3 ++- .../minimal-http-server-deaddrop/CMakeLists.txt | 2 +- .../minimal-http-server-eventlib-smp/CMakeLists.txt | 3 ++- .../minimal-http-server-form-post-file.c | 2 ++ .../minimal-http-server-smp/CMakeLists.txt | 3 ++- .../minimal-http-server-sse-ring/CMakeLists.txt | 3 ++- .../minimal-http-server-sse/CMakeLists.txt | 13 +++++++++++++ .../minimal-http-server-tls-mem.c | 8 ++++---- .../minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c | 2 ++ .../minimal-raw-adopt-udp/minimal-raw-adopt-udp.c | 6 ++++-- .../minimal-raw-fallback-http-server.c | 2 +- .../raw/minimal-raw-netcat/minimal-raw-netcat.c | 2 ++ .../raw/minimal-raw-serial/CMakeLists.txt | 2 +- .../raw/minimal-raw-vhost/minimal-raw-vhost.c | 2 +- .../secure-streams/minimal-secure-streams-avs/avs.c | 2 ++ .../ws-client/minimal-ws-client-ping/CMakeLists.txt | 3 ++- .../protocol_lws_minimal_pmd_bulk.c | 10 +++++----- .../ws-client/minimal-ws-client-spam/CMakeLists.txt | 3 ++- .../ws-client/minimal-ws-client-tx/CMakeLists.txt | 3 ++- .../ws-client/minimal-ws-client/minimal-ws-client.c | 1 - .../protocol_lws_minimal_pmd_bulk.c | 12 ++++++------ .../minimal-ws-server-ring/protocol_lws_minimal.c | 4 ++-- .../minimal-ws-server-threadpool/CMakeLists.txt | 3 ++- .../minimal-ws-server-threads-smp/CMakeLists.txt | 3 ++- .../minimal-ws-server-threads/CMakeLists.txt | 3 ++- 26 files changed, 67 insertions(+), 35 deletions(-) diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/main.c b/minimal-examples/api-tests/api-test-lws_struct-json/main.c index 7fcd84b9..7edfefb9 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/main.c +++ b/minimal-examples/api-tests/api-test-lws_struct-json/main.c @@ -346,7 +346,7 @@ int main(int argc, const char **argv) lws_struct_json_init_parse(&ctx, NULL, &a); n = (int)(signed char)lejp_parse(&ctx, (uint8_t *)json_tests[m], - strlen(json_tests[m])); + (int)strlen(json_tests[m])); if (n < 0) { lwsl_err("%s: notification JSON decode failed '%s'\n", __func__, lejp_error_to_string(n)); diff --git a/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt index 96441dac..a033c3d7 100644 --- a/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt @@ -11,7 +11,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() diff --git a/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt index 416576cb..dbdfcc3b 100644 --- a/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt @@ -72,7 +72,7 @@ require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) require_lws_config(LWS_WITH_HTTP_BASIC_AUTH 1 requirements) -if (requirements) +if (requirements AND UNIX) add_executable(${SAMP} ${SRCS}) if (LWS_PLUGINS_DIR) diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt index c6515a05..3611a79c 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt @@ -10,7 +10,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() diff --git a/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c b/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c index 14d78cd7..8d11aaae 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c +++ b/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c @@ -15,7 +15,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include #include #include diff --git a/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt index 08f839a3..b32eb709 100644 --- a/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt @@ -10,7 +10,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() diff --git a/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt index 596a9afd..be14a0d5 100644 --- a/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt @@ -10,7 +10,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() diff --git a/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt index 972fb901..35e819f8 100644 --- a/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt @@ -5,6 +5,18 @@ include(CheckCSourceCompiles) set(SAMP lws-minimal-http-server-sse) set(SRCS minimal-http-server-sse.c) +MACRO(require_pthreads result) + CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) + if (NOT LWS_HAVE_PTHREAD_H) + if (LWS_WITH_MINIMAL_EXAMPLES) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") + else() + message(FATAL_ERROR "threading support requires pthreads") + endif() + endif() +ENDMACRO() + # If we are being built as part of lws, confirm current build config supports # reqconfig, else skip building ourselves. # @@ -64,6 +76,7 @@ MACRO(require_lws_config reqconfig _val result) ENDMACRO() set(requirements 1) +require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-tls-mem/minimal-http-server-tls-mem.c b/minimal-examples/http-server/minimal-http-server-tls-mem/minimal-http-server-tls-mem.c index b3953fbd..56304bf9 100644 --- a/minimal-examples/http-server/minimal-http-server-tls-mem/minimal-http-server-tls-mem.c +++ b/minimal-examples/http-server/minimal-http-server-tls-mem/minimal-http-server-tls-mem.c @@ -429,9 +429,9 @@ int main(int argc, const char **argv) info.mounts = &mount; info.error_document_404 = "/404.html"; info.server_ssl_cert_mem = cert_pem; - info.server_ssl_cert_mem_len = strlen(cert_pem); + info.server_ssl_cert_mem_len = (unsigned int)strlen(cert_pem); info.server_ssl_private_key_mem = key_pem; - info.server_ssl_private_key_mem_len = strlen(key_pem); + info.server_ssl_private_key_mem_len = (unsigned int)strlen(key_pem); info.vhost_name = "first"; if (!lws_create_vhost(context, &info)) { @@ -443,9 +443,9 @@ int main(int argc, const char **argv) info.mounts = &mount; info.error_document_404 = "/404.html"; info.server_ssl_cert_mem = cert_der; - info.server_ssl_cert_mem_len = sizeof(cert_der); + info.server_ssl_cert_mem_len = (unsigned int)sizeof(cert_der); info.server_ssl_private_key_mem = key_der; - info.server_ssl_private_key_mem_len = sizeof(key_der); + info.server_ssl_private_key_mem_len = (unsigned int)sizeof(key_der); info.vhost_name = "second"; if (!lws_create_vhost(context, &info)) { diff --git a/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c b/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c index 11342345..725ff630 100644 --- a/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c +++ b/minimal-examples/raw/minimal-raw-adopt-tcp/minimal-raw-adopt-tcp.c @@ -31,7 +31,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include static int diff --git a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c index e85bb7d5..8af3804c 100644 --- a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c +++ b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c @@ -28,7 +28,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include static uint8_t sendbuf[4096]; @@ -40,7 +42,7 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { ssize_t n; - int fd; + lws_sockfd_type fd; switch (reason) { @@ -102,7 +104,7 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, #if defined(WIN32) (const char *) #endif - sendbuf, sendlen, 0, &udp.sa, udp.salen); + sendbuf, sendlen, 0, &udp.sa, (socklen_t)udp.salen); if (n < (ssize_t)len) lwsl_notice("%s: send returned %d\n", __func__, (int)n); break; diff --git a/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c b/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c index 1a7edaa8..5cb133ba 100644 --- a/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c +++ b/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c @@ -63,7 +63,7 @@ callback_raw_echo(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (len > sizeof(pss->buf)) len = sizeof(pss->buf); memcpy(pss->buf, in, len); - pss->len = len; + pss->len = (int)len; lws_callback_on_writable(wsi); break; diff --git a/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c b/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c index 1d8b59d9..ccdd5a54 100644 --- a/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c +++ b/minimal-examples/raw/minimal-raw-netcat/minimal-raw-netcat.c @@ -26,7 +26,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include static struct lws *raw_wsi, *stdin_wsi; diff --git a/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt b/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt index 523dc87a..2cbb66e7 100644 --- a/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt @@ -66,7 +66,7 @@ ENDMACRO() set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) -if (requirements) +if (requirements AND UNIX) add_executable(${SAMP} ${SRCS}) if (websockets_shared) diff --git a/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c b/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c index c5bb334d..e2fe529d 100644 --- a/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c +++ b/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c @@ -75,7 +75,7 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_RAW_RX: lwsl_user("LWS_CALLBACK_RAW_RX: %d\n", (int)len); - vhd->len = len; + vhd->len = (int)len; if (vhd->len > (int)sizeof(vhd->buf)) vhd->len = sizeof(vhd->buf); memcpy(vhd->buf, in, vhd->len); diff --git a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c index 9fbd6aa4..d7f268f7 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c @@ -17,7 +17,9 @@ #include #include #include +#if !defined(WIN32) #include +#endif #include #include diff --git a/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt index f3811eb7..f40d6309 100644 --- a/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt @@ -10,7 +10,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c index 6726ca5b..33e224bb 100644 --- a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c +++ b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c @@ -181,14 +181,14 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, if (s > (size_t)n) s = n; memcpy(p, &redundant_string[m], s); - pss->position_tx += s; + pss->position_tx += (int)s; p += s; - n -= s; + n -= (int)s; } } else { pss->position_tx += n; while (n--) - *p++ = rng(&pss->rng_tx); + *p++ = (uint8_t)rng(&pss->rng_tx); } n = lws_ptr_diff(p, start); @@ -227,13 +227,13 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, lwsl_user("echo'd data doesn't match\n"); return -1; } - pss->position_rx += s; + pss->position_rx += (int)s; in = ((unsigned char *)in) + s; len -= s; } } else { p = (uint8_t *)in; - pss->position_rx += len; + pss->position_rx += (int)len; while (len--) if (*p++ != (uint8_t)rng(&pss->rng_rx)) { lwsl_user("echo'd data doesn't match\n"); diff --git a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt index fa80cd47..da3c51b6 100644 --- a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt @@ -10,7 +10,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt index 3dc1b151..6d9c8181 100644 --- a/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt @@ -10,7 +10,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() diff --git a/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c b/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c index 35c3d3c2..a7e903bb 100644 --- a/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c +++ b/minimal-examples/ws-client/minimal-ws-client/minimal-ws-client.c @@ -13,7 +13,6 @@ #include #include #include -#include /* * This represents your object that "contains" the client connection and has diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c index 2ee48b0e..7c49f0ee 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/protocol_lws_minimal_pmd_bulk.c @@ -147,14 +147,14 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, if (s > (size_t)n) s = n; memcpy(p, &redundant_string[m], s); - pss->position_tx += s; + pss->position_tx += (int)s; p += s; - n -= s; + n -= (int)s; } } else { pss->position_tx += n; while (n--) - *p++ = rng(&pss->rng_tx); + *p++ = (uint8_t)rng(&pss->rng_tx); } n = lws_ptr_diff(p, start); @@ -172,7 +172,7 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, lwsl_user("LWS_CALLBACK_RECEIVE: %4d (pss->pos=%d, rpp %5d, last %d)\n", (int)len, (int)pss->position_rx, (int)lws_remaining_packet_payload(wsi), lws_is_final_fragment(wsi)); - olen = len; + olen = (int)len; if (*vhd->options & 1) { while (len) { @@ -185,13 +185,13 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, lwsl_user("echo'd data doesn't match\n"); return -1; } - pss->position_rx += s; + pss->position_rx += (int)s; in = ((char *)in) + s; len -= s; } } else { p = (uint8_t *)in; - pss->position_rx += len; + pss->position_rx += (int)len; while (len--) { if (*p++ != (uint8_t)rng(&pss->rng_rx)) { lwsl_user("echo'd data doesn't match: 0x%02X 0x%02X (%d)\n", diff --git a/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c b/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c index d8f68344..5370d53e 100644 --- a/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c +++ b/minimal-examples/ws-server/minimal-ws-server-ring/protocol_lws_minimal.c @@ -55,7 +55,7 @@ cull_lagging_clients(struct per_vhost_data__minimal *vhd) { uint32_t oldest_tail = lws_ring_get_oldest_tail(vhd->ring); struct per_session_data__minimal *old_pss = NULL; - int most = 0, before = lws_ring_get_count_waiting_elements(vhd->ring, + int most = 0, before = (int)lws_ring_get_count_waiting_elements(vhd->ring, &oldest_tail), m; /* @@ -111,7 +111,7 @@ cull_lagging_clients(struct per_vhost_data__minimal *vhd) * what is the largest number of pending ring elements * for any survivor. */ - m = lws_ring_get_count_waiting_elements(vhd->ring, + m = (int)lws_ring_get_count_waiting_elements(vhd->ring, &((*ppss)->tail)); if (m > most) most = m; diff --git a/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt index 00255da6..111ba701 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt @@ -10,7 +10,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt index 1a97437d..a6c798f5 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt @@ -10,7 +10,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt index 5194c70f..283a1828 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt @@ -10,7 +10,8 @@ MACRO(require_pthreads result) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) if (NOT LWS_HAVE_PTHREAD_H) if (LWS_WITH_MINIMAL_EXAMPLES) - set(result 0) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") else() message(FATAL_ERROR "threading support requires pthreads") endif() -- Gitee From d3308df40fcff457f23ed16d2485eb581a24fe18 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 7 Apr 2020 14:05:21 +0100 Subject: [PATCH 0054/1062] windows: pthreads Add support for external pthreads lib on windows and some docs about how to do. It can build with LWS_WITH_THREADPOOL and LWS_WITH_MINIMAL_EXAMPLES including the pthreads-dependent ones without warnings or errors on windows platform as well with this. pthreads_t can be anything, including a struct - not a pointer-to-a-struct but the struct itself. These can't be cast to a void * for printing as they can on linux, where the base type is a pointer. Let's fix all the usage of those to determine their own thread index in terms of the meaning to the program rather than as a tid. --- CMakeLists.txt | 31 +++++++++++++------ READMEs/README.build-windows.md | 19 ++++++++++++ cmake/lws_config.h.in | 2 ++ lib/misc/threadpool/threadpool.c | 10 ++++-- .../minimal-http-client-attach/CMakeLists.txt | 10 ++++-- .../minimal-http-client-attach.c | 12 ++++--- .../CMakeLists.txt | 12 +++++-- .../minimal-http-server-eventlib-smp.c | 7 +++++ .../minimal-http-server-smp/CMakeLists.txt | 12 +++++-- .../minimal-http-server-smp.c | 6 ++++ .../CMakeLists.txt | 10 ++++-- .../minimal-http-server-sse-ring.c | 22 ++++++++----- .../minimal-http-server-sse/CMakeLists.txt | 10 ++++-- .../minimal-http-server-sse.c | 6 ++++ .../minimal-mqtt-client-multi.c | 6 ++++ .../minimal-mqtt-client/minimal-mqtt-client.c | 6 ++++ .../minimal-ws-client-ping/CMakeLists.txt | 13 ++++++-- .../minimal-ws-client-ping.c | 6 ++++ .../minimal-ws-client-spam/CMakeLists.txt | 13 ++++++-- .../minimal-ws-client-spam.c | 6 ++++ .../minimal-ws-client-tx/CMakeLists.txt | 13 ++++++-- .../minimal-ws-client-tx/minimal-ws-client.c | 22 ++++++++----- .../CMakeLists.txt | 10 ++++-- .../minimal-ws-server-threadpool.c | 8 +++++ .../protocol_lws_minimal_threadpool.c | 8 ++++- .../CMakeLists.txt | 10 ++++-- .../minimal-ws-server.c | 6 ++++ .../protocol_lws_minimal.c | 22 +++++++------ .../minimal-ws-server-threads/CMakeLists.txt | 10 ++++-- .../minimal-ws-server.c | 6 ++++ .../protocol_lws_minimal.c | 12 ++++--- 31 files changed, 274 insertions(+), 72 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d093792..3f9bc52d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -497,7 +497,6 @@ endif() if (WIN32) set(LWS_MAX_SMP 1) -set(LWS_WITH_THREADPOOL 0) endif() if (LWS_WITHOUT_SERVER) @@ -592,6 +591,10 @@ set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory") set(LWS_GLIB_LIBRARIES CACHE PATH "Path to the glib library") set(LWS_LIBMOUNT_INCLUDE_DIRS CACHE PATH "Path to the libmount include directory") set(LWS_LIBMOUNT_LIBRARIES CACHE PATH "Path to the libmount library") +# on unix, these are in the toolchain. On win32 you have to put them somewhere +# yourself and point to them here +set(LWS_EXT_PTHREAD_INCLUDE_DIR CACHE PATH "Path to an external pthreads include directory") +set(LWS_EXT_PTHREAD_LIBRARIES CACHE PATH "Path to an external pthreads library") if (NOT LWS_WITH_SSL) @@ -911,6 +914,14 @@ if (NOT LWS_HAVE_GETIFADDRS) set(LWS_BUILTIN_GETIFADDRS 1) endif() +if (LWS_EXT_PTHREAD_INCLUDE_DIR) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_EXT_PTHREAD_INCLUDE_DIR}) + include_directories(${LWS_EXT_PTHREAD_INCLUDE_DIR}) + + list(APPEND LIB_LIST ${LWS_EXT_PTHREAD_LIBRARIES}) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} " -DHAVE_STRUCT_TIMESPEC=1") +endif() + CHECK_INCLUDE_FILE(dlfcn.h LWS_HAVE_DLFCN_H) CHECK_INCLUDE_FILE(fcntl.h LWS_HAVE_FCNTL_H) CHECK_INCLUDE_FILE(in6addr.h LWS_HAVE_IN6ADDR_H) @@ -1015,9 +1026,9 @@ CHECK_C_SOURCE_COMPILES("#include if (LWS_HAVE_PTHREAD_H) if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(CMAKE_REQUIRED_FLAGS "-pthread -Wno-error=unused-command-line-argument") + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-pthread -Wno-error=unused-command-line-argument") else() - set(CMAKE_REQUIRED_FLAGS "-pthread") + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-pthread") endif() CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE @@ -1103,8 +1114,6 @@ if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") list(APPEND SOURCES lib/misc/fsmount.c) endif() - - if (LWS_WITH_FILE_OPS) list(APPEND SOURCES lib/core/vfs.c) endif() @@ -1250,7 +1259,7 @@ if (LWS_ROLE_MQTT AND LWS_WITH_CLIENT) ) endif() -if (LWS_WITH_THREADPOOL AND UNIX AND LWS_HAVE_PTHREAD_H) +if (LWS_WITH_THREADPOOL AND LWS_HAVE_PTHREAD_H) list(APPEND SOURCES lib/misc/threadpool/threadpool.c) endif() @@ -1796,6 +1805,7 @@ source_group("Resources" FILES ${RESOURCES}) # set(LWS_LIBRARIES) + if (LWS_WITH_STATIC) if (LWS_STATIC_PIC) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -1896,6 +1906,9 @@ set(LIB_LIST) # # Find libraries. # +if (LWS_EXT_PTHREAD_INCLUDE_DIR) + list(APPEND LIB_LIST ${LWS_EXT_PTHREAD_LIBRARIES}) +endif() # # ZLIB (needed for deflate extension and if LWS_WITH_HTTP_STREAM_COMPRESSION) @@ -1977,7 +1990,7 @@ if (LWS_WITH_SSL) include_directories("${inc}" "${inc}/wolfssl") endforeach() endif() - set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) set(VARIA wolfSSL_) list(APPEND LIB_LIST "${WOLFSSL_LIBRARIES}") @@ -2020,7 +2033,7 @@ if (LWS_WITH_SSL) if (NOT LWS_WITH_MBEDTLS) # older (0.98) Openssl lacks this - set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) check_include_file(openssl/ecdh.h LWS_HAVE_OPENSSL_ECDH_H) if (LWS_SSL_SERVER_WITH_ECDH_CERT AND NOT LWS_HAVE_OPENSSL_ECDH_H) @@ -2181,7 +2194,7 @@ foreach (lib ${LWS_LIBRARIES}) endforeach() set (temp ${CMAKE_REQUIRED_LIBRARIES}) -set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) +set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST} ${CMAKE_REQUIRED_LIBRARIES}) if (LWS_WITH_ZLIB) if (LWS_WITH_BUNDLED_ZLIB) diff --git a/READMEs/README.build-windows.md b/READMEs/README.build-windows.md index 677e1f84..7b853694 100644 --- a/READMEs/README.build-windows.md +++ b/READMEs/README.build-windows.md @@ -73,3 +73,22 @@ there. ``` After that you can run the test apps OK. + +## pthreads + +It's amazing but after all these years windows doesn't offer pthreads compatibility +itself. Just like the many other missing POSIX bits like fork(). + +I downloaded the latest (2012) zip release of pthreads-win32 from here + +ftp://sourceware.org/pub/pthreads-win32 + +Then I created a dir "C:\Program Files (x86)\pthreads", and copied the `dll`, +`include` and `lib` subdirs from the `prebuilt` folder in the zip there. + +The cmake incantation to build against pthreads set up like that is + +``` + $ cmake .. -DLWS_EXT_PTHREAD_INCLUDE_DIR="C:\Program Files (x86)\pthreads\include" -DLWS_EXT_PTHREAD_LIBRARIES="C:\Program Files (x86)\pthreads\lib\x64\libpthreadGC2.a" -DLWS_WITH_MINIMAL_EXAMPLES=1 +``` + diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 17885768..de5e2f67 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -18,6 +18,8 @@ #cmakedefine LWS_LIBRARY_VERSION_NUMBER +#cmakedefine LWS_EXT_PTHREAD_LIBRARIES + #cmakedefine LWS_AVOID_SIGPIPE_IGN #cmakedefine LWS_BUILD_HASH "${LWS_BUILD_HASH}" #cmakedefine LWS_BUILTIN_GETIFADDRS diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index deab7571..61048ba9 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -26,6 +26,12 @@ #define _GNU_SOURCE #endif +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #include "private-lib-core.h" @@ -131,10 +137,10 @@ __lws_threadpool_task_dump(struct lws_threadpool_task *task, char *buf, int len) } if (task->acc_running) - runms = task->acc_running; + runms = (int)task->acc_running; if (task->acc_syncing) - syncms = task->acc_syncing; + syncms = (int)task->acc_syncing; if (!task->done) { buf += lws_snprintf(buf, end - buf, diff --git a/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt index a033c3d7..822bfbbe 100644 --- a/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt @@ -16,6 +16,12 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() @@ -88,9 +94,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c b/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c index dfd0032b..20a03523 100644 --- a/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c +++ b/minimal-examples/http-client/minimal-http-client-attach/minimal-http-client-attach.c @@ -15,6 +15,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include static struct lws_context *context; @@ -119,10 +125,7 @@ attach_callback(struct lws_context *context, int tsi, void *opaque) /* * Even though it was asked for from a different thread, we are called * back by lws from the lws event loop thread context - */ - lwsl_user("%s: called from tid %p\n", __func__, (void *)pthread_self()); - - /* + * * We can set up our operations on the lws event loop and return so * they can happen asynchronously */ @@ -218,7 +221,6 @@ int main(int argc, const char **argv) logs = atoi(p); lws_set_log_level(logs, NULL); - lwsl_user("%s: main thread tid %p\n", __func__, (void *)pthread_self()); lwsl_user("LWS minimal http client attach\n"); pthread_mutex_init(&lock, NULL); diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt index 3611a79c..25c0b314 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt @@ -15,6 +15,12 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() @@ -85,9 +91,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + add_dependencies(${SAMP} websockets_shared ${PTHREAD_LIB}) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c b/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c index 6ea9b6ea..f82fa048 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c +++ b/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c @@ -18,6 +18,13 @@ #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif + #include #define COUNT_THREADS 8 diff --git a/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt index b32eb709..ab9c8336 100644 --- a/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt @@ -15,6 +15,12 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() @@ -85,9 +91,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() \ No newline at end of file diff --git a/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c b/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c index ae07e4a8..b6a34415 100644 --- a/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c +++ b/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #define COUNT_THREADS 8 diff --git a/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt index be14a0d5..384f0a78 100644 --- a/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt @@ -15,6 +15,12 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() @@ -85,9 +91,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c b/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c index 2e51c2f9..1d4f210c 100644 --- a/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c +++ b/minimal-examples/http-server/minimal-http-server-sse-ring/minimal-http-server-sse-ring.c @@ -19,6 +19,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #include @@ -86,7 +92,11 @@ thread_spam(void *d) { struct vhd *vhd = (struct vhd *)d; struct msg amsg; - int len = 128, index = 1, n; + int len = 128, index = 1, n, whoami = 0; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_equal(pthread_self(), vhd->pthread_spam[n])) + whoami = n + 1; do { /* don't generate output if nobody connected */ @@ -108,10 +118,9 @@ thread_spam(void *d) goto wait_unlock; } n = lws_snprintf((char *)amsg.payload, len, - "%s: tid: %p, msg: %d", __func__, - (void *)pthread_self(), index++); + "%s: tid: %d, msg: %d", __func__, whoami, index++); amsg.len = n; - n = lws_ring_insert(vhd->ring, &amsg, 1); + n = (int)lws_ring_insert(vhd->ring, &amsg, 1); if (n != 1) { __minimal_destroy_message(&amsg); lwsl_user("dropping!\n"); @@ -131,7 +140,7 @@ wait: } while (!vhd->finished); - lwsl_notice("thread_spam %p exiting\n", (void *)pthread_self()); + lwsl_notice("thread_spam %d exiting\n", whoami); pthread_exit(NULL); @@ -186,8 +195,7 @@ callback_sse(struct lws *wsi, enum lws_callback_reasons reason, void *user, init_fail: vhd->finished = 1; for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) - if (vhd->pthread_spam[n]) - pthread_join(vhd->pthread_spam[n], &retval); + pthread_join(vhd->pthread_spam[n], &retval); if (vhd->ring) lws_ring_destroy(vhd->ring); diff --git a/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt index 35e819f8..781ae309 100644 --- a/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt @@ -14,6 +14,12 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() @@ -84,9 +90,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c b/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c index cb60774b..c7f8e7d3 100644 --- a/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c +++ b/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c @@ -19,6 +19,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include /* diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c index 1659a216..ab6967f8 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c +++ b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c @@ -11,6 +11,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #include diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c b/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c index d5fc448a..8cbce657 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c +++ b/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c @@ -11,6 +11,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #include diff --git a/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt index f40d6309..c6d11332 100644 --- a/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt @@ -15,8 +15,15 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() + # If we are being built as part of lws, confirm current build config supports # reqconfig, else skip building ourselves. # @@ -84,9 +91,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c b/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c index a8589f0e..ff6107b6 100644 --- a/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c +++ b/minimal-examples/ws-client/minimal-ws-client-ping/minimal-ws-client-ping.c @@ -14,6 +14,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include static struct lws_context *context; diff --git a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt index da3c51b6..42fd9706 100644 --- a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt @@ -15,8 +15,15 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() + # If we are being built as part of lws, confirm current build config supports # reqconfig, else skip building ourselves. # @@ -84,9 +91,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c b/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c index ec6f5234..3809ef50 100644 --- a/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c +++ b/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c @@ -13,6 +13,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include enum { diff --git a/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt index 6d9c8181..70fd5e27 100644 --- a/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt @@ -15,8 +15,15 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() + # If we are being built as part of lws, confirm current build config supports # reqconfig, else skip building ourselves. # @@ -84,9 +91,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) - add_dependencies(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() \ No newline at end of file diff --git a/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c b/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c index 137201d5..c83e23e9 100644 --- a/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c +++ b/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include static int interrupted; @@ -70,7 +76,11 @@ thread_spam(void *d) struct per_vhost_data__minimal *vhd = (struct per_vhost_data__minimal *)d; struct msg amsg; - int len = 128, index = 1, n; + int len = 128, index = 1, n, whoami = 0; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_equal(pthread_self(), vhd->pthread_spam[n])) + whoami = n + 1; do { /* don't generate output if client not connected */ @@ -92,10 +102,9 @@ thread_spam(void *d) goto wait_unlock; } n = lws_snprintf((char *)amsg.payload + LWS_PRE, len, - "tid: %p, msg: %d", - (void *)pthread_self(), index++); + "tid: %d, msg: %d", whoami, index++); amsg.len = n; - n = lws_ring_insert(vhd->ring, &amsg, 1); + n = (int)lws_ring_insert(vhd->ring, &amsg, 1); if (n != 1) { __minimal_destroy_message(&amsg); lwsl_user("dropping!\n"); @@ -114,7 +123,7 @@ wait: } while (!vhd->finished); - lwsl_notice("thread_spam %p exiting\n", (void *)pthread_self()); + lwsl_notice("thread_spam %d exiting\n", whoami); pthread_exit(NULL); @@ -188,8 +197,7 @@ callback_minimal_broker(struct lws *wsi, enum lws_callback_reasons reason, init_fail: vhd->finished = 1; for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) - if (vhd->pthread_spam[n]) - pthread_join(vhd->pthread_spam[n], &retval); + pthread_join(vhd->pthread_spam[n], &retval); if (vhd->ring) lws_ring_destroy(vhd->ring); diff --git a/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt index 111ba701..f557ca2b 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt @@ -15,6 +15,12 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() @@ -86,9 +92,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c b/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c index e0d8a9d0..61beb54d 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c +++ b/minimal-examples/ws-server/minimal-ws-server-threadpool/minimal-ws-server-threadpool.c @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #define LWS_PLUGIN_STATIC @@ -125,5 +131,7 @@ int main(int argc, const char **argv) lws_context_destroy(context); + lwsl_user("%s: exiting cleanly...\n", __func__); + return 0; } diff --git a/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c b/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c index 55998a79..5fd7d873 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c +++ b/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c @@ -43,6 +43,10 @@ struct task_data { uint64_t pos, end; }; +#if defined(WIN32) +static void usleep(unsigned long l) { Sleep(l / 1000); } +#endif + /* * Create the private data for the task * @@ -254,6 +258,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, */ task = lws_threadpool_get_task_wsi(wsi); + if (!task) + break; n = lws_threadpool_task_status(task, &_user); lwsl_debug("%s: LWS_CALLBACK_SERVER_WRITEABLE: status %d\n", __func__, n); @@ -277,7 +283,7 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, lws_set_timeout(wsi, PENDING_TIMEOUT_THREADPOOL_TASK, 5); - n = strlen(priv->result + LWS_PRE); + n = (int)strlen(priv->result + LWS_PRE); m = lws_write(wsi, (unsigned char *)priv->result + LWS_PRE, n, LWS_WRITE_TEXT); if (m < n) { diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt index a6c798f5..bf2ef9d5 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt @@ -15,6 +15,12 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() @@ -85,9 +91,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c index 8303f5cb..8a74eb74 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c +++ b/minimal-examples/ws-server/minimal-ws-server-threads-smp/minimal-ws-server.c @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #define LWS_PLUGIN_STATIC diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-smp/protocol_lws_minimal.c b/minimal-examples/ws-server/minimal-ws-server-threads-smp/protocol_lws_minimal.c index 375530c1..1ee7ce70 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads-smp/protocol_lws_minimal.c +++ b/minimal-examples/ws-server/minimal-ws-server-threads-smp/protocol_lws_minimal.c @@ -83,7 +83,11 @@ thread_spam(void *d) struct per_vhost_data__minimal *vhd = (struct per_vhost_data__minimal *)d; struct msg amsg; - int len = 128, index = 1, n; + int len = 128, index = 1, n, whoami = 0; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_equal(pthread_self(), vhd->pthread_spam[n])) + whoami = n + 1; do { /* don't generate output if nobody connected */ @@ -105,10 +109,10 @@ thread_spam(void *d) goto wait_unlock; } n = lws_snprintf((char *)amsg.payload + LWS_PRE, len, - "%s: spam tid: %p, msg: %d", vhd->config, - (void *)pthread_self(), index++); + "%s: spam tid: %d, msg: %d", vhd->config, + whoami, index++); amsg.len = n; - n = lws_ring_insert(vhd->ring, &amsg, 1); + n = (int)lws_ring_insert(vhd->ring, &amsg, 1); if (n != 1) { __minimal_destroy_message(&amsg); lwsl_user("dropping!\n"); @@ -127,7 +131,7 @@ wait: } while (!vhd->finished); - lwsl_notice("thread_spam %p exiting\n", (void *)pthread_self()); + lwsl_notice("thread_spam %d exiting\n", whoami); pthread_exit(NULL); @@ -199,8 +203,7 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, init_fail: vhd->finished = 1; for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) - if (vhd->pthread_spam[n]) - pthread_join(vhd->pthread_spam[n], &retval); + pthread_join(vhd->pthread_spam[n], &retval); if (vhd->ring) lws_ring_destroy(vhd->ring); @@ -231,7 +234,7 @@ init_fail: } n = lws_snprintf(temp + LWS_PRE, sizeof(temp) - LWS_PRE, - "svc tid:%p, %s", (void *)pthread_self(), + "svc, %s", (char *)pmsg->payload + LWS_PRE); /* notice we allowed for LWS_PRE in the payload already */ @@ -265,8 +268,7 @@ init_fail: break; case LWS_CALLBACK_EVENT_WAIT_CANCELLED: - lwsl_notice("LWS_CALLBACK_EVENT_WAIT_CANCELLED in svc tid %p\n", - (void *)pthread_self()); + lwsl_notice("LWS_CALLBACK_EVENT_WAIT_CANCELLED in svc\n"); if (!vhd) break; /* diff --git a/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt index 283a1828..c8bbb072 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt @@ -15,6 +15,12 @@ MACRO(require_pthreads result) else() message(FATAL_ERROR "threading support requires pthreads") endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() endif() ENDMACRO() @@ -88,9 +94,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c index 40d7fc78..fb96a1bf 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c +++ b/minimal-examples/ws-server/minimal-ws-server-threads/minimal-ws-server.c @@ -21,6 +21,12 @@ #include #include #include +#if defined(WIN32) +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif #include #define LWS_PLUGIN_STATIC diff --git a/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c b/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c index f3d83dac..8f230bbf 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c +++ b/minimal-examples/ws-server/minimal-ws-server-threads/protocol_lws_minimal.c @@ -83,7 +83,11 @@ thread_spam(void *d) struct per_vhost_data__minimal *vhd = (struct per_vhost_data__minimal *)d; struct msg amsg; - int len = 128, index = 1, n; + int len = 128, index = 1, n, whoami = 0; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(vhd->pthread_spam); n++) + if (pthread_equal(pthread_self(), vhd->pthread_spam[n])) + whoami = n + 1; do { /* don't generate output if nobody connected */ @@ -105,8 +109,8 @@ thread_spam(void *d) goto wait_unlock; } n = lws_snprintf((char *)amsg.payload + LWS_PRE, len, - "%s: tid: %p, msg: %d", vhd->config, - (void *)pthread_self(), index++); + "%s: tid: %d, msg: %d", vhd->config, + whoami, index++); amsg.len = n; n = lws_ring_insert(vhd->ring, &amsg, 1); if (n != 1) { @@ -127,7 +131,7 @@ wait: } while (!vhd->finished); - lwsl_notice("thread_spam %p exiting\n", (void *)pthread_self()); + lwsl_notice("thread_spam %d exiting\n", whoami); pthread_exit(NULL); -- Gitee From d7294a714ed1813208fb516b8ce5c88273e3f4c1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 8 Apr 2020 10:51:50 +0100 Subject: [PATCH 0055/1062] windows: import tronkko's dirent.h Win32 compatible version of dirent.h microsoft just don't seem to be able to include themselves. MIT license, same as lws, link to original github project in the header --- CMakeLists.txt | 5 +- lib/misc/dir.c | 13 +- win32port/dirent/dirent-win32.h | 1160 +++++++++++++++++++++++++++++++ 3 files changed, 1171 insertions(+), 7 deletions(-) create mode 100644 win32port/dirent/dirent-win32.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f9bc52d..726b3daf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,7 +129,7 @@ option(LWS_WITH_STRUCT_JSON "Generic struct serialization to and from JSON" OFF) option(LWS_WITH_STRUCT_SQLITE3 "Generic struct serialization to and from SQLITE3" OFF) # broken atm #option(LWS_WITH_SMTP "Provide SMTP support" OFF) -if (WIN32 OR LWS_WITH_ESP32) +if (LWS_WITH_ESP32) option(LWS_WITH_DIR "Directory scanning api support" OFF) option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" OFF) else() @@ -151,7 +151,6 @@ option(LWS_WITH_LWSAC "lwsac Chunk Allocation api" ON) option(LWS_WITH_CUSTOM_HEADERS "Store and allow querying custom HTTP headers (H1 only)" ON) option(LWS_WITH_DISKCACHE "Hashed cache directory with lazy LRU deletion to size limit" OFF) option(LWS_WITH_ASAN "Build with gcc runtime sanitizer options enabled (needs libasan)" OFF) -option(LWS_WITH_DIR "Directory scanning api support" OFF) option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" OFF) option(LWS_WITH_ZLIB "Include zlib support (required for extensions)" OFF) option(LWS_WITH_BUNDLED_ZLIB "Use bundled zlib version (Windows only)" ${LWS_WITH_BUNDLED_ZLIB_DEFAULT}) @@ -192,7 +191,7 @@ if (LWS_PLAT_FREERTOS OR LWS_PLAT_OPTEE) set(LWS_WITH_UDP 0) endif() -if (WIN32 OR LWS_PLAT_FREERTOS) +if (LWS_PLAT_FREERTOS) message(STATUS "No LWS_WITH_DIR or LWS_WITH_LEJP_CONF") set(LWS_WITH_DIR OFF) set(LWS_WITH_LEJP_CONF OFF) diff --git a/lib/misc/dir.c b/lib/misc/dir.c index 5c4b00cf..d2011e28 100644 --- a/lib/misc/dir.c +++ b/lib/misc/dir.c @@ -78,9 +78,13 @@ bail: #else -#if !defined(_WIN32) && !defined(LWS_PLAT_FREERTOS) +#if !defined(LWS_PLAT_FREERTOS) +#if defined(WIN32) +#include "../../win32port/dirent/dirent-win32.h" +#else #include +#endif static int filter(const struct dirent *ent) { @@ -153,15 +157,19 @@ lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) case DT_FIFO: lde.type = LDOT_FIFO; break; +#if !defined(WIN32) case DT_LNK: lde.type = LDOT_LINK; break; +#endif case DT_REG: lde.type = LDOT_FILE; break; +#if !defined(WIN32) case DT_SOCK: lde.type = LDOTT_SOCKET; break; +#endif default: lde.type = LDOT_UNKNOWN; break; @@ -183,8 +191,5 @@ bail: return ret; } - -#else -#error "If you want lws_dir on windows, you need libuv" #endif #endif diff --git a/win32port/dirent/dirent-win32.h b/win32port/dirent/dirent-win32.h new file mode 100644 index 00000000..f7a46daf --- /dev/null +++ b/win32port/dirent/dirent-win32.h @@ -0,0 +1,1160 @@ +/* + * Dirent interface for Microsoft Visual Studio + * + * Copyright (C) 1998-2019 Toni Ronkko + * This file is part of dirent. Dirent may be freely distributed + * under the MIT license. For all details and documentation, see + * https://github.com/tronkko/dirent + */ +#ifndef DIRENT_H +#define DIRENT_H + +/* Hide warnings about unreferenced local functions */ +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#elif defined(_MSC_VER) +# pragma warning(disable:4505) +#elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of the file name without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return the maximum size of a file name */ +#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX+1]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +/* Multi-byte character version */ +struct dirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX+1]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + + +/* Dirent functions */ +static DIR *opendir (const char *dirname); +static _WDIR *_wopendir (const wchar_t *dirname); + +static struct dirent *readdir (DIR *dirp); +static struct _wdirent *_wreaddir (_WDIR *dirp); + +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result); +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); + +static int closedir (DIR *dirp); +static int _wclosedir (_WDIR *dirp); + +static void rewinddir (DIR* dirp); +static void _wrewinddir (_WDIR* dirp); + +static int scandir (const char *dirname, struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)); + +static int alphasort (const struct dirent **a, const struct dirent **b); + +static int versionsort (const struct dirent **a, const struct dirent **b); + + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); + +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + +static void dirent_set_errno (int error); + + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir( + const wchar_t *dirname) +{ + _WDIR *dirp; + DWORD n; + wchar_t *p; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); + if (!dirp) { + return NULL; + } + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* + * Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, 0, NULL, NULL); +#else + /* WinRT */ + n = wcslen (dirname); +#endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); + if (dirp->patt == NULL) { + goto exit_closedir; + } + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, n, dirp->patt, NULL); + if (n <= 0) { + goto exit_closedir; + } +#else + /* WinRT */ + wcsncpy_s (dirp->patt, n+1, dirname, n); +#endif + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (!dirent_first (dirp)) { + goto exit_closedir; + } + + /* Success */ + return dirp; + + /* Failure */ +exit_closedir: + _wclosedir (dirp); + return NULL; +} + +/* + * Read next directory entry. + * + * Returns pointer to static directory entry which may be overwritten by + * subsequent calls to _wreaddir(). + */ +static struct _wdirent* +_wreaddir( + _WDIR *dirp) +{ + struct _wdirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) _wreaddir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry. + * + * Returns zero on success. If end of directory stream is reached, then sets + * result to NULL and returns zero. + */ +static int +_wreaddir_r( + _WDIR *dirp, + struct _wdirent *entry, + struct _wdirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp); + if (datap) { + size_t n; + DWORD attr; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n < PATH_MAX && datap->cFileName[n] != 0) { + entry->d_name[n] = datap->cFileName[n]; + n++; + } + entry->d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct _wdirent); + + /* Set result address */ + *result = entry; + + } else { + + /* Return NULL to indicate end of directory */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int +_wclosedir( + _WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Release search pattern */ + free (dirp->patt); + + /* Release directory structure */ + free (dirp); + ok = /*success*/0; + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void +_wrewinddir( + _WDIR* dirp) +{ + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Open new search handle */ + dirent_first (dirp); + } +} + +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + DWORD error; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } else { + + /* Failed to open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + /* Set error code */ + error = GetLastError (); + switch (error) { + case ERROR_ACCESS_DENIED: + /* No read access to directory */ + dirent_set_errno (EACCES); + break; + + case ERROR_DIRECTORY: + /* Directory name is invalid */ + dirent_set_errno (ENOTDIR); + break; + + case ERROR_PATH_NOT_FOUND: + default: + /* Cannot find the file */ + dirent_set_errno (ENOENT); + } + + } + return datap; +} + +/* + * Get next directory entry (internal). + * + * Returns + */ +static WIN32_FIND_DATAW* +dirent_next( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed or an error occurred */ + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; +} + +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir( + const char *dirname) +{ + struct DIR *dirp; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (!dirp) { + return NULL; + } + { + int error; + wchar_t wname[PATH_MAX + 1]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s( + &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1); + if (error) { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + goto exit_free; + } + + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir (wname); + if (!dirp->wdirp) { + goto exit_free; + } + + } + + /* Success */ + return dirp; + + /* Failure */ +exit_free: + free (dirp); + return NULL; +} + +/* + * Read next directory entry. + */ +static struct dirent* +readdir( + DIR *dirp) +{ + struct dirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) readdir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry into called-allocated buffer. + * + * Returns zero on success. If the end of directory stream is reached, then + * sets result to NULL and returns zero. + */ +static int +readdir_r( + DIR *dirp, + struct dirent *entry, + struct dirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cAlternateFileName, PATH_MAX + 1); + } + + if (!error) { + DWORD attr; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct dirent); + + } else { + + /* + * Cannot convert file name to multi-byte string so construct + * an erroneous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entry->d_name[0] = '?'; + entry->d_name[1] = '\0'; + entry->d_namlen = 1; + entry->d_type = DT_UNKNOWN; + entry->d_ino = 0; + entry->d_off = -1; + entry->d_reclen = 0; + + } + + /* Return pointer to directory entry */ + *result = entry; + + } else { + + /* No more directory entries */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream. + */ +static int +closedir( + DIR *dirp) +{ + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir (dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free (dirp); + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream to beginning. + */ +static void +rewinddir( + DIR* dirp) +{ + /* Rewind wide-character string directory stream */ + _wrewinddir (dirp->wdirp); +} + +/* + * Scan directory for entries. + */ +static int +scandir( + const char *dirname, + struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)) +{ + struct dirent **files = NULL; + size_t size = 0; + size_t allocated = 0; + const size_t init_size = 1; + DIR *dir = NULL; + struct dirent *entry; + struct dirent *tmp = NULL; + size_t i; + int result = 0; + + /* Open directory stream */ + dir = opendir (dirname); + if (dir) { + + /* Read directory entries to memory */ + while (1) { + + /* Enlarge pointer table to make room for another pointer */ + if (size >= allocated) { + void *p; + size_t num_entries; + + /* Compute number of entries in the enlarged pointer table */ + if (size < init_size) { + /* Allocate initial pointer table */ + num_entries = init_size; + } else { + /* Double the size */ + num_entries = size * 2; + } + + /* Allocate first pointer table or enlarge existing table */ + p = realloc (files, sizeof (void*) * num_entries); + if (p != NULL) { + /* Got the memory */ + files = (dirent**) p; + allocated = num_entries; + } else { + /* Out of memory */ + result = -1; + break; + } + + } + + /* Allocate room for temporary directory entry */ + if (tmp == NULL) { + tmp = (struct dirent*) malloc (sizeof (struct dirent)); + if (tmp == NULL) { + /* Cannot allocate temporary directory entry */ + result = -1; + break; + } + } + + /* Read directory entry to temporary area */ + if (readdir_r (dir, tmp, &entry) == /*OK*/0) { + + /* Did we get an entry? */ + if (entry != NULL) { + int pass; + + /* Determine whether to include the entry in result */ + if (filter) { + /* Let the filter function decide */ + pass = filter (tmp); + } else { + /* No filter function, include everything */ + pass = 1; + } + + if (pass) { + /* Store the temporary entry to pointer table */ + files[size++] = tmp; + tmp = NULL; + + /* Keep up with the number of files */ + result++; + } + + } else { + + /* + * End of directory stream reached => sort entries and + * exit. + */ + qsort (files, size, sizeof (void*), + (int (*) (const void*, const void*)) compare); + break; + + } + + } else { + /* Error reading directory entry */ + result = /*Error*/ -1; + break; + } + + } + + } else { + /* Cannot open directory */ + result = /*Error*/ -1; + } + + /* Release temporary directory entry */ + free (tmp); + + /* Release allocated memory on error */ + if (result < 0) { + for (i = 0; i < size; i++) { + free (files[i]); + } + free (files); + files = NULL; + } + + /* Close directory stream */ + if (dir) { + closedir (dir); + } + + /* Pass pointer table to caller */ + if (namelist) { + *namelist = files; + } + return result; +} + +/* Alphabetical sorting */ +static int +alphasort( + const struct dirent **a, const struct dirent **b) +{ + return strcoll ((*a)->d_name, (*b)->d_name); +} + +/* Sort versions */ +static int +versionsort( + const struct dirent **a, const struct dirent **b) +{ + /* FIXME: implement strverscmp and use that */ + return alphasort (a, b); +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs (wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resulting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Could not convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs (mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Set errno variable */ +static void +dirent_set_errno( + int error) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno (error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif +} + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ -- Gitee From 83c5bdc95f575b5db293f87ebbe1bcc461a2bfc4 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 9 Apr 2020 05:38:12 +0100 Subject: [PATCH 0056/1062] windows: msvc toolchain warnings to errors This may cause some dust to start with since there are many versions of msvc in use out there. --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 726b3daf..e64473f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1773,6 +1773,11 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) endif() endif () +if (MSVC) + # Fail the build if any warnings + add_compile_options(/W3 /WX) +endif() + if (LWS_PLAT_OPTEE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot ../../../../lib/libutils/isoc/include -I../../../../lib/libutils/isoc/include -I../../../../lib/libutils/ext/include" ) endif() -- Gitee From ff53a89db2263006e55df6fd5a10fd6e12073a01 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 10 Apr 2020 16:25:42 +0100 Subject: [PATCH 0057/1062] windows: async dns: fix typo --- CMakeLists.txt | 3 +++ lib/plat/windows/windows-resolv.c | 4 ++-- lib/system/async-dns/async-dns-parse.c | 12 ++++++------ lib/system/async-dns/async-dns.c | 4 ++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e64473f3..7592ac8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1525,6 +1525,9 @@ if (WIN32) lib/plat/windows/windows-service.c lib/plat/windows/windows-sockets.c ) + if (LWS_WITH_SYS_ASYNC_DNS) + list(APPEND SOURCES lib/plat/windows/windows-resolv.c) + endif() else() if (LWS_PLAT_OPTEE) diff --git a/lib/plat/windows/windows-resolv.c b/lib/plat/windows/windows-resolv.c index 1cfbcc63..541cc0ae 100644 --- a/lib/plat/windows/windows-resolv.c +++ b/lib/plat/windows/windows-resolv.c @@ -39,7 +39,7 @@ lws_async_dns_server_check_t lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) { - char subkey[512], dhcpns[512], ns[512], value[128], *key = + char subkey[512], value[128], *key = "SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"; HKEY hKey, hSub; LONG err; @@ -59,7 +59,7 @@ lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) &type, value, &len) == ERROR_SUCCESS || RegQueryValueEx(hSub, "DhcpNameServer", 0, &type, value, &len) == ERROR_SUCCESS)) { - n = lws_sa46_parse_numeric_address(value, sa46) + n = lws_sa46_parse_numeric_address(value, sa46); RegCloseKey(hSub); RegCloseKey(hKey); return n == 0 ? LADNS_CONF_SERVER_CHANGED : diff --git a/lib/system/async-dns/async-dns-parse.c b/lib/system/async-dns/async-dns-parse.c index 48bc56a7..c4068cfc 100644 --- a/lib/system/async-dns/async-dns-parse.c +++ b/lib/system/async-dns/async-dns-parse.c @@ -122,7 +122,7 @@ again1: ls++; - return ls - ols; + return lws_ptr_diff(ls, ols); } typedef int (*lws_async_dns_find_t)(const char *name, void *opaque, @@ -160,7 +160,7 @@ lws_adns_iterate(lws_adns_q_t *q, const uint8_t *pkt, int len, uint32_t ttl; lws_strncpy(stack[0].name, expname, sizeof(stack[0].name)); - stack[0].enl = strlen(expname); + stack[0].enl = (int)strlen(expname); start: ansc = lws_ser_ru16be(pkt + DHO_NANSWERS); @@ -583,11 +583,11 @@ lws_adns_parse_udp(lws_async_dns_t *dns, const uint8_t *pkt, size_t len) * char []: copy of resolved name */ - ncname = strlen(nmcname) + 1; + ncname = (int)strlen(nmcname) + 1; est = sizeof(lws_adns_cache_t) + ncname; if (lws_ser_ru16be(pkt + DHO_NANSWERS)) { - int ir = lws_adns_iterate(q, pkt, len, nmcname, + int ir = lws_adns_iterate(q, pkt, (int)len, nmcname, lws_async_dns_estimate, &est); if (ir < 0) goto fail_out; @@ -599,7 +599,7 @@ lws_adns_parse_udp(lws_async_dns_t *dns, const uint8_t *pkt, size_t len) /* but we want to create the cache entry against the original request */ nm = ((const char *)&q[1]) + DNS_MAX; - n = strlen(nm) + 1; + n = (int)strlen(nm) + 1; lwsl_info("%s: create cache entry for %s, %zu\n", __func__, nm, est - sizeof(lws_adns_cache_t)); @@ -632,7 +632,7 @@ lws_adns_parse_udp(lws_async_dns_t *dns, const uint8_t *pkt, size_t len) */ if (lws_ser_ru16be(pkt + DHO_NANSWERS) && - lws_adns_iterate(q, pkt, len, nmcname, lws_async_dns_store, &adst) < 0) { + lws_adns_iterate(q, pkt, (int)len, nmcname, lws_async_dns_store, &adst) < 0) { lws_free(c); goto fail_out; } diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index 81c34e0b..c1332d14 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -483,7 +483,7 @@ check_tid(struct lws_dll2 *d, void *user) { lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list); - return q->tid == (uint16_t)(long)user; + return q->tid == (uint16_t)(intptr_t)user; } int @@ -502,7 +502,7 @@ lws_async_dns_get_new_tid(struct lws_context *context, lws_adns_q_t *q) return -1; if (lws_dll2_foreach_safe(&dns->waiting, - (void *)(long)tid, check_tid)) + (void *)(intptr_t)tid, check_tid)) continue; q->tid = tid; -- Gitee From 478ee963f1e3edcfa908979a0d14ed4e05b6e592 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 11 Apr 2020 16:48:47 +0100 Subject: [PATCH 0058/1062] async dns: test app: dont use exp as ambiguous --- minimal-examples/api-tests/api-test-async-dns/main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/minimal-examples/api-tests/api-test-async-dns/main.c b/minimal-examples/api-tests/api-test-async-dns/main.c index 518daa18..83b8931c 100644 --- a/minimal-examples/api-tests/api-test-async-dns/main.c +++ b/minimal-examples/api-tests/api-test-async-dns/main.c @@ -12,7 +12,7 @@ #include #include -static int interrupted, dtest, ok, fail, exp = 26; +static int interrupted, dtest, ok, fail, _exp = 26; struct lws_context *context; /* @@ -290,7 +290,7 @@ main(int argc, const char **argv) } #if !defined(LWS_WITH_IPV6) - exp -= 2; + _exp -= 2; #endif /* kick off the async dns tests */ @@ -305,11 +305,11 @@ main(int argc, const char **argv) lws_context_destroy(context); - if (fail || ok != exp) - lwsl_user("Completed: PASS: %d / %d, FAIL: %d\n", ok, exp, + if (fail || ok != _exp) + lwsl_user("Completed: PASS: %d / %d, FAIL: %d\n", ok, _exp, fail); else - lwsl_user("Completed: ALL PASS: %d / %d\n", ok, exp); + lwsl_user("Completed: ALL PASS: %d / %d\n", ok, _exp); - return !(ok == exp && !fail); + return !(ok == _exp && !fail); } -- Gitee From acc3e9ba13601017f13007ba7849bf8abeb434cb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 11 Apr 2020 16:54:58 +0100 Subject: [PATCH 0059/1062] lws_struct: sqlite3: avoid chown for windows --- lib/misc/lws-struct-sqlite.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/misc/lws-struct-sqlite.c b/lib/misc/lws-struct-sqlite.c index 327537c1..fbcb5ea9 100644 --- a/lib/misc/lws-struct-sqlite.c +++ b/lib/misc/lws-struct-sqlite.c @@ -445,7 +445,9 @@ int lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, sqlite3 **pdb) { +#if !defined(WIN32) int uid = 0, gid = 0; +#endif if (sqlite3_open_v2(sqlite3_path, pdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, @@ -456,6 +458,7 @@ lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, return 1; } +#if !defined(WIN32) lws_get_effective_uid_gid(context, &uid, &gid); if (uid) chown(sqlite3_path, uid, gid); @@ -463,7 +466,9 @@ lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, lwsl_notice("%s: created %s owned by %u:%u mode 0600\n", __func__, sqlite3_path, (unsigned int)uid, (unsigned int)gid); - +#else + lwsl_notice("%s: created %s\n", __func__, sqlite3_path); +#endif sqlite3_extended_result_codes(*pdb, 1); return 0; -- Gitee From e3d780dac638123a01ede5089936aaf5dd320577 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 12 Apr 2020 08:39:15 +0100 Subject: [PATCH 0060/1062] gencrypto: windows: warnings Coming out of increasing number of build variants on windows via Sai --- lib/jose/jwe/enc/aescbc.c | 6 +- lib/jose/jwe/enc/aeskw.c | 2 +- lib/jose/jwe/jwe-ecdh-es-aeskw.c | 6 +- lib/jose/jwe/jwe-rsa-aescbc.c | 3 +- lib/jose/jwe/jwe.c | 16 ++--- lib/jose/jwk/jwk.c | 10 ++-- lib/jose/jws/jose.c | 8 +-- lib/jose/jws/jws.c | 29 ++++----- lib/tls/openssl/openssl-x509.c | 2 +- .../api-tests/api-test-jose/jwe.c | 59 ++++++++++--------- .../api-tests/api-test-jose/jws.c | 18 +++--- .../crypto/minimal-crypto-jwe/main.c | 8 ++- .../crypto/minimal-crypto-jwk/main.c | 20 +++++-- .../crypto/minimal-crypto-jws/main.c | 6 +- .../crypto/minimal-crypto-x509/main.c | 6 +- 15 files changed, 109 insertions(+), 90 deletions(-) diff --git a/lib/jose/jwe/enc/aescbc.c b/lib/jose/jwe/enc/aescbc.c index 9a72ab12..d15475d5 100755 --- a/lib/jose/jwe/enc/aescbc.c +++ b/lib/jose/jwe/enc/aescbc.c @@ -29,7 +29,7 @@ int lws_jwe_encrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *cek, uint8_t *aad, int aad_len) { - int n, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type); + int n, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); uint8_t digest[LWS_GENHASH_LARGEST]; struct lws_gencrypto_keyelem el; struct lws_genhmac_ctx hmacctx; @@ -100,7 +100,7 @@ lws_jwe_encrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *cek, NULL, NULL, LWS_AES_CBC_BLOCKLEN); paddedlen = lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN, jwe->jws.map.len[LJWE_CTXT]); - jwe->jws.map.len[LJWE_CTXT] = paddedlen; + jwe->jws.map.len[LJWE_CTXT] = (uint32_t)paddedlen; lws_genaes_destroy(&aesctx, (uint8_t *)jwe->jws.map.buf[LJWE_CTXT] + paddedlen - LWS_AES_CBC_BLOCKLEN, LWS_AES_CBC_BLOCKLEN); if (n) { @@ -162,7 +162,7 @@ int lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *enc_cek, uint8_t *aad, int aad_len) { - int n, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type); + int n, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); uint8_t digest[LWS_GENHASH_LARGEST]; struct lws_gencrypto_keyelem el; struct lws_genhmac_ctx hmacctx; diff --git a/lib/jose/jwe/enc/aeskw.c b/lib/jose/jwe/enc/aeskw.c index 43bbbeb6..78cf4f95 100644 --- a/lib/jose/jwe/enc/aeskw.c +++ b/lib/jose/jwe/enc/aeskw.c @@ -41,7 +41,7 @@ lws_jwe_encrypt_aeskw_cbc_hs(struct lws_jwe *jwe, char *temp, int *temp_len) /* we are wrapping a key, so size for the worst case after wrap */ uint8_t enc_cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES + LWS_JWE_RFC3394_OVERHEAD_BYTES]; - int n, m, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type), + int n, m, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type), ot = *temp_len; if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_OCT) { diff --git a/lib/jose/jwe/jwe-ecdh-es-aeskw.c b/lib/jose/jwe/jwe-ecdh-es-aeskw.c index 421be2eb..fc073b01 100644 --- a/lib/jose/jwe/jwe-ecdh-es-aeskw.c +++ b/lib/jose/jwe/jwe-ecdh-es-aeskw.c @@ -203,7 +203,7 @@ lws_jwe_encrypt_ecdh(struct lws_jwe *jwe, char *temp, int *temp_len, derived[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES]; int m, n, ret = -1, ot = *temp_len, ss_len = sizeof(shared_secret), // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type), - enc_hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type), + enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type), ekbytes = 32; //jwe->jose.alg->keybits_fixed / 8; struct lws_genec_ctx ecctx; struct lws_jwk *ephem = &jwe->jose.recipient[jwe->recip].jwk_ephemeral; @@ -378,7 +378,7 @@ int lws_jwe_encrypt_ecdh_cbc_hs(struct lws_jwe *jwe, char *temp, int *temp_len) { int ss_len, // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type), - enc_hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type); + enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); uint8_t cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES]; int ekbytes = jwe->jose.alg->keybits_fixed / 8; int n, ot = *temp_len, ret = -1; @@ -455,7 +455,7 @@ lws_jwe_auth_and_decrypt_ecdh(struct lws_jwe *jwe) uint8_t shared_secret[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES], derived[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES]; int ekbytes = jwe->jose.enc_alg->keybits_fixed / 8, - enc_hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type); + enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); struct lws_genec_ctx ecctx; int n, ret = -1, ss_len = sizeof(shared_secret); diff --git a/lib/jose/jwe/jwe-rsa-aescbc.c b/lib/jose/jwe/jwe-rsa-aescbc.c index 4683772c..c2ff06ff 100644 --- a/lib/jose/jwe/jwe-rsa-aescbc.c +++ b/lib/jose/jwe/jwe-rsa-aescbc.c @@ -46,7 +46,8 @@ int lws_jwe_encrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe, char *temp, int *temp_len) { - int n, hlen = lws_genhmac_size(jwe->jose.enc_alg->hmac_type), ot = *temp_len; + int n, hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type), + ot = *temp_len; char ekey[LWS_GENHASH_LARGEST]; struct lws_genrsa_ctx rsactx; diff --git a/lib/jose/jwe/jwe.c b/lib/jose/jwe/jwe.c index f4f8214b..feb682f2 100755 --- a/lib/jose/jwe/jwe.c +++ b/lib/jose/jwe/jwe.c @@ -209,7 +209,7 @@ int lws_jwa_concat_kdf(struct lws_jwe *jwe, int direct, uint8_t *out, const uint8_t *shared_secret, int sslen) { - int hlen = lws_genhash_size(LWS_GENHASH_TYPE_SHA256), aidlen; + int hlen = (int)lws_genhash_size(LWS_GENHASH_TYPE_SHA256), aidlen; struct lws_genhash_ctx hash_ctx; uint32_t ctr = 1, t; const char *aid; @@ -236,7 +236,7 @@ lws_jwa_concat_kdf(struct lws_jwe *jwe, int direct, uint8_t *out, */ aid = direct ? jwe->jose.enc_alg->alg : jwe->jose.alg->alg; - aidlen = strlen(aid); + aidlen = (int)strlen(aid); /* * PartyUInfo (PartyVInfo is the same deal) @@ -284,7 +284,7 @@ lws_jwa_concat_kdf(struct lws_jwe *jwe, int direct, uint8_t *out, /* Z */ lws_genhash_update(&hash_ctx, shared_secret, sslen) || /* other info */ - lws_genhash_update(&hash_ctx, be32(strlen(aid), &t), 4) || + lws_genhash_update(&hash_ctx, be32((uint32_t)strlen(aid), &t), 4) || lws_genhash_update(&hash_ctx, aid, aidlen) || lws_genhash_update(&hash_ctx, be32(jwe->jose.e[LJJHI_APU].len, &t), 4) || @@ -541,7 +541,7 @@ lws_jwe_render_compact(struct lws_jwe *jwe, char *out, size_t out_len) *out++ = '\0'; out_len -= n; - return orig - out_len; + return (int)(orig - out_len); } int @@ -578,9 +578,9 @@ lws_jwe_create_packet(struct lws_jwe *jwe, const char *payload, size_t len, if (!jwe->jose.alg || !jwe->jose.alg->alg) goto bail; - p += lws_snprintf(p, end - p, "{\"alg\":\"%s\",\"jwk\":", + p += lws_snprintf(p, lws_ptr_diff(end, p), "{\"alg\":\"%s\",\"jwk\":", jwe->jose.alg->alg); - m = end - p; + m = lws_ptr_diff(end, p); n = lws_jwk_export(&jwe->jwk, 0, p, &m); if (n < 0) { lwsl_notice("failed to export jwk\n"); @@ -647,7 +647,7 @@ lws_jwe_create_packet(struct lws_jwe *jwe, const char *payload, size_t len, free(buf); - return p1 - out; + return lws_ptr_diff(p1, out); bail: lws_jws_destroy(&jws); @@ -782,7 +782,7 @@ lws_jwe_render_flattened(struct lws_jwe *jwe, char *out, size_t out_len) p1 += lws_snprintf(p1, end1 - p1, "\n}\n"); - return p1 - out; + return lws_ptr_diff(p1, out); bail: lws_jws_destroy(&jwe->jws); diff --git a/lib/jose/jwk/jwk.c b/lib/jose/jwk/jwk.c index a7d4f106..fdd1717b 100644 --- a/lib/jose/jwk/jwk.c +++ b/lib/jose/jwk/jwk.c @@ -595,7 +595,7 @@ lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk, case LWS_GENCRYPTO_KTY_OCT: sn = lws_gencrypto_bits_to_bytes(bits); jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf = lws_malloc(sn, "oct"); - jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = sn; + jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = (uint32_t)sn; if (lws_get_random(context, jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, sn) != sn) { lwsl_err("%s: problem getting random\n", __func__); @@ -646,7 +646,7 @@ lws_jwk_import(struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user, lws_jwk_init_jps(&jctx, &jps, jwk, cb, user); - m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)in, len); + m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)in, (int)len); lejp_destruct(&jctx); if (m < 0) { @@ -789,7 +789,7 @@ lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len) lws_strnncpy(p, (const char *)jwk->e[l->idx].buf, jwk->e[l->idx].len, end - p); - m = strlen(p); + m = (int)strlen(p); } else m = lws_jws_base64_enc( (const char *)jwk->e[l->idx].buf, @@ -808,9 +808,9 @@ lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len) p += lws_snprintf(p, end - p, (flags & LWSJWKF_EXPORT_NOCRLF) ? "}" : "}\n"); - *len -= p - start; + *len -= lws_ptr_diff(p, start); - return p - start; + return lws_ptr_diff(p, start); } int diff --git a/lib/jose/jws/jose.c b/lib/jose/jws/jose.c index d7aa261f..ff608138 100644 --- a/lib/jose/jws/jose.c +++ b/lib/jose/jws/jose.c @@ -509,7 +509,7 @@ lws_jose_render(struct lws_jose *jose, struct lws_jwk *aux_jwk, sub = 1; m = lws_b64_encode_string_url((const char *) jose->e[n].buf, jose->e[n].len, - out, end - out); + out, lws_ptr_diff(end, out)); if (m < 0) return -1; out += m; @@ -528,7 +528,7 @@ lws_jose_render(struct lws_jose *jose, struct lws_jwk *aux_jwk, sub = 1; m = lws_b64_encode_string((const char *) jose->e[n].buf, jose->e[n].len, - out, end - out); + out, lws_ptr_diff(end, out)); if (m < 0) return -1; out += m; @@ -546,7 +546,7 @@ lws_jose_render(struct lws_jose *jose, struct lws_jwk *aux_jwk, out += lws_snprintf(out, end - out, "%s\"%s\":", sub ? ",\n" : "", jws_jose[n]); sub = 1; - vl = end - out; + vl = lws_ptr_diff(end, out); m = lws_jwk_export(jwk, 0, out, &vl); if (m < 0) { lwsl_notice("%s: failed to export key\n", @@ -598,7 +598,7 @@ lws_jose_render(struct lws_jose *jose, struct lws_jwk *aux_jwk, if (out > end - 2) return -1; - return out_len - (end - out) - 1; + return lws_ptr_diff(out_len, (end - out)) - 1; bail: return -1; diff --git a/lib/jose/jws/jws.c b/lib/jose/jws/jws.c index de0a5723..6cf9dccf 100644 --- a/lib/jose/jws/jws.c +++ b/lib/jose/jws/jws.c @@ -200,10 +200,10 @@ lws_jws_dup_element(struct lws_jws_map *map, int idx, char *temp, int *temp_len, memcpy(temp, in, in_len); - map->len[idx] = in_len; + map->len[idx] = (uint32_t)in_len; map->buf[idx] = temp; - *temp_len -= actual_alloc; + *temp_len -= (int)actual_alloc; return 0; } @@ -241,7 +241,7 @@ lws_jws_randomize_element(struct lws_context *context, struct lws_jws_map *map, if ((size_t)*temp_len < actual_alloc) return -1; - map->len[idx] = random_len; + map->len[idx] = (uint32_t)random_len; map->buf[idx] = temp; if (lws_get_random(context, temp, random_len) != random_len) { @@ -249,7 +249,7 @@ lws_jws_randomize_element(struct lws_context *context, struct lws_jws_map *map, return -1; } - *temp_len -= actual_alloc; + *temp_len -= (int)actual_alloc; return 0; } @@ -264,9 +264,9 @@ lws_jws_alloc_element(struct lws_jws_map *map, int idx, char *temp, if ((size_t)*temp_len < actual_alloc) return -1; - map->len[idx] = len; + map->len[idx] = (uint32_t)len; map->buf[idx] = temp; - *temp_len -= actual_alloc; + *temp_len -= (int)actual_alloc; return 0; } @@ -276,7 +276,7 @@ lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max) { int n; - n = lws_b64_encode_string_url(in, in_len, out, out_max - 1); + n = lws_b64_encode_string_url(in, (int)in_len, out, (int)out_max - 1); if (n < 0) { lwsl_notice("%s: in len %d too large for %d out buf\n", __func__, (int)in_len, (int)out_max); @@ -391,7 +391,7 @@ int lws_jws_encode_section(const char *in, size_t in_len, int first, char **p, char *end) { - int n, len = (end - *p) - 1; + int n, len = lws_ptr_diff(end, (*p)) - 1; char *p_entry = *p; if (len < 3) @@ -406,7 +406,7 @@ lws_jws_encode_section(const char *in, size_t in_len, int first, char **p, *p += n; - return (*p) - p_entry; + return lws_ptr_diff((*p), p_entry); } int @@ -542,7 +542,7 @@ lws_jws_sig_confirm(struct lws_jws_map *map_b64, struct lws_jws_map *map, /* SHA256/384/512 HMAC */ - h_len = lws_genhmac_size(jose.alg->hmac_type); + h_len = (int)lws_genhmac_size(jose.alg->hmac_type); /* 6) compute HMAC over payload */ @@ -629,7 +629,7 @@ lws_jws_sig_confirm(struct lws_jws_map *map_b64, struct lws_jws_map *map, return -1; } - h_len = lws_genhash_size(jose.alg->hash_type); + h_len = (int)lws_genhash_size(jose.alg->hash_type); if (lws_genecdsa_create(&ecdsactx, context, NULL)) { lwsl_notice("%s: lws_genrsa_public_decrypt_create\n", @@ -696,10 +696,10 @@ lws_jws_sig_confirm_compact_b64(const char *in, size_t len, struct lws_jws_map map_b64; int n; - if (lws_jws_b64_compact_map(in, len, &map_b64) < 0) + if (lws_jws_b64_compact_map(in, (int)len, &map_b64) < 0) return -1; - n = lws_jws_compact_decode(in, len, map, &map_b64, temp, temp_len); + n = lws_jws_compact_decode(in, (int)len, map, &map_b64, temp, temp_len); if (n > 3 || n < 0) return -1; @@ -727,7 +727,8 @@ lws_jws_sig_confirm_json(const char *in, size_t len, struct lws_context *context, char *temp, int *temp_len) { - if (lws_jws_json_parse(jws, (const uint8_t *)in, len, temp, temp_len)) { + if (lws_jws_json_parse(jws, (const uint8_t *)in, + (int)len, temp, temp_len)) { lwsl_err("%s: lws_jws_json_parse failed\n", __func__); return -1; diff --git a/lib/tls/openssl/openssl-x509.c b/lib/tls/openssl/openssl-x509.c index bd6e0162..bf85120a 100644 --- a/lib/tls/openssl/openssl-x509.c +++ b/lib/tls/openssl/openssl-x509.c @@ -474,7 +474,7 @@ static int lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u) { const char *pp = (const char *)u; - int n = strlen(pp); + int n = (int)strlen(pp); if (n > size - 1) return -1; diff --git a/minimal-examples/api-tests/api-test-jose/jwe.c b/minimal-examples/api-tests/api-test-jose/jwe.c index 4ff5f5a1..44f33f67 100644 --- a/minimal-examples/api-tests/api-test-jose/jwe.c +++ b/minimal-examples/api-tests/api-test-jose/jwe.c @@ -82,7 +82,7 @@ test_jwe_a1(struct lws_context *context) } /* converts a compact serialization to jws b64 + decoded maps */ - if (lws_jws_compact_decode(ex_a1_compact, strlen(ex_a1_compact), + if (lws_jws_compact_decode(ex_a1_compact, (int)strlen(ex_a1_compact), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -100,7 +100,7 @@ test_jwe_a1(struct lws_context *context) /* allowing for trailing padding, confirm the plaintext */ if (jwe.jws.map.len[LJWE_CTXT] < strlen(ex_a1_ptext) || lws_timingsafe_bcmp(jwe.jws.map.buf[LJWE_CTXT], ex_a1_ptext, - strlen(ex_a1_ptext))) { + (uint32_t)strlen(ex_a1_ptext))) { lwsl_err("%s: plaintext AES decrypt wrong\n", __func__); lwsl_hexdump_notice(ex_a1_ptext, strlen(ex_a1_ptext)); lwsl_hexdump_notice(jwe.jws.map.buf[LJWE_CTXT], @@ -185,7 +185,7 @@ test_jwe_a1(struct lws_context *context) temp_len = sizeof(temp); /* converts a compact serialization to jws b64 + decoded maps */ - if (lws_jws_compact_decode(compact, strlen(compact), &jwe.jws.map, + if (lws_jws_compact_decode(compact, (int)strlen(compact), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); goto bail; @@ -299,7 +299,7 @@ test_jwe_a2(struct lws_context *context) /* converts a compact serialization to jws b64 + decoded maps */ if (lws_jws_compact_decode((const char *)ex_a2_compact, - strlen((char *)ex_a2_compact), + (int)strlen((char *)ex_a2_compact), &jwe.jws.map, &jwe.jws.map_b64, (char *)temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -527,7 +527,7 @@ test_jwe_ra_ptext_1024(struct lws_context *context, char *jwk_txt, int jwk_len) } jwe.jws.map.buf[LJWE_JOSE] = rsa256a128_jose; - jwe.jws.map.len[LJWE_JOSE] = strlen(rsa256a128_jose); + jwe.jws.map.len[LJWE_JOSE] = (uint32_t)strlen(rsa256a128_jose); n = lws_jwe_parse_jose(&jwe.jose, jwe.jws.map.buf[LJWE_JOSE], jwe.jws.map.len[LJWE_JOSE], @@ -657,7 +657,7 @@ test_jwe_r256a192_ptext(struct lws_context *context, char *jwk_txt, int jwk_len) } jwe.jws.map.buf[LJWE_JOSE] = rsa256a192_jose; - jwe.jws.map.len[LJWE_JOSE] = strlen(rsa256a192_jose); + jwe.jws.map.len[LJWE_JOSE] = (uint32_t)strlen(rsa256a192_jose); n = lws_jwe_parse_jose(&jwe.jose, jwe.jws.map.buf[LJWE_JOSE], jwe.jws.map.len[LJWE_JOSE], @@ -789,9 +789,10 @@ test_jwe_r256a256_ptext(struct lws_context *context, char *jwk_txt, int jwk_len) } jwe.jws.map.buf[LJWE_JOSE] = rsa256a256_jose; - jwe.jws.map.len[LJWE_JOSE] = strlen(rsa256a256_jose); + jwe.jws.map.len[LJWE_JOSE] = (int)strlen(rsa256a256_jose); - n = lws_jwe_parse_jose(&jwe.jose, rsa256a256_jose, strlen(rsa256a256_jose), + n = lws_jwe_parse_jose(&jwe.jose, rsa256a256_jose, + (int)strlen(rsa256a256_jose), lws_concat_temp(temp, temp_len), &temp_len); if (n < 0) { lwsl_err("%s: JOSE parse failed\n", __func__); @@ -1058,7 +1059,7 @@ test_jwe_r256a128_jwe_openssl(struct lws_context *context) /* converts a compact serialization to jws b64 + decoded maps */ if (lws_jws_compact_decode((const char *)jwe_compact_rsa_cbc_openssl, - strlen((char *)jwe_compact_rsa_cbc_openssl), + (int)strlen((char *)jwe_compact_rsa_cbc_openssl), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -1149,7 +1150,7 @@ test_jwe_r256a128_jwe_mbedtls(struct lws_context *context) /* converts a compact serialization to jws b64 + decoded maps */ if (lws_jws_compact_decode((const char *)jwe_compact_rsa_cbc_mbedtls, - strlen((char *)jwe_compact_rsa_cbc_mbedtls), + (int)strlen((char *)jwe_compact_rsa_cbc_mbedtls), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -1240,7 +1241,7 @@ test_jwe_a3(struct lws_context *context) /* converts a compact serialization to jws b64 + decoded maps */ if (lws_jws_compact_decode((const char *)ex_a3_compact, - strlen((char *)ex_a3_compact), + (int)strlen((char *)ex_a3_compact), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -1649,7 +1650,7 @@ test_jwa_c(struct lws_context *context) * See test_jwe_a3 above for a more normal usage pattern. */ - if (lws_jwe_parse_jose(&jwe.jose, ex_jwa_c_jose, strlen(ex_jwa_c_jose), + if (lws_jwe_parse_jose(&jwe.jose, ex_jwa_c_jose, (int)strlen(ex_jwa_c_jose), temp, &temp_len) < 0) { lwsl_err("%s: JOSE parse failed\n", __func__); @@ -1797,7 +1798,7 @@ test_ecdhes_t1(struct lws_context *context, const char *jose_hdr, jose_hdr, strlen(jose_hdr), 0)) goto bail; - if (lws_jwe_parse_jose(&jwe.jose, jose_hdr, strlen(jose_hdr), + if (lws_jwe_parse_jose(&jwe.jose, jose_hdr, (int)strlen(jose_hdr), temp, &temp_len) < 0) { lwsl_err("%s: JOSE parse failed\n", __func__); @@ -1873,7 +1874,7 @@ test_ecdhes_t1(struct lws_context *context, const char *jose_hdr, } /* converts a compact serialization to jws b64 + decoded maps */ - if (lws_jws_compact_decode(compact, strlen(compact), &jwe.jws.map, + if (lws_jws_compact_decode(compact, (int)strlen(compact), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); goto bail; @@ -1975,7 +1976,7 @@ test_akw_decrypt(struct lws_context *context, const char *test_name, } /* converts a compact serialization to jws b64 + decoded maps */ - if (lws_jws_compact_decode(ciphertext, strlen(ciphertext), + if (lws_jws_compact_decode(ciphertext, (int)strlen(ciphertext), &jwe.jws.map, &jwe.jws.map_b64, temp, &temp_len) != 5) { lwsl_err("%s: lws_jws_compact_decode failed\n", __func__); @@ -1992,7 +1993,7 @@ test_akw_decrypt(struct lws_context *context, const char *test_name, /* allowing for trailing padding, confirm the plaintext */ if (jwe.jws.map.len[LJWE_CTXT] < strlen(akw_ptext) || lws_timingsafe_bcmp(jwe.jws.map.buf[LJWE_CTXT], akw_ptext, - strlen(akw_ptext))) { + (int)strlen(akw_ptext))) { lwsl_err("%s: plaintext AES decrypt wrong\n", __func__); lwsl_hexdump_notice(akw_ptext, strlen(akw_ptext)); lwsl_hexdump_notice(jwe.jws.map.buf[LJWE_CTXT], @@ -2141,7 +2142,7 @@ test_jwe_json_complete(struct lws_context *context) lws_jwe_init(&jwe, context); - if (lws_jwe_parse_jose(&jwe.jose, complete, strlen(complete), + if (lws_jwe_parse_jose(&jwe.jose, complete, (int)strlen(complete), temp, &temp_len) < 0) { lwsl_err("%s: JOSE parse failed\n", __func__); @@ -2199,29 +2200,29 @@ test_jwe(struct lws_context *context) n |= test_jwe_a2(context); n |= test_jwe_ra_ptext_1024(context, (char *)lws_jwe_ex_a2_jwk_json, - strlen((char *)lws_jwe_ex_a2_jwk_json)); + (int)strlen((char *)lws_jwe_ex_a2_jwk_json)); n |= test_jwe_r256a192_ptext(context, (char *)lws_jwe_ex_a2_jwk_json, - strlen((char *)lws_jwe_ex_a2_jwk_json)); + (int)strlen((char *)lws_jwe_ex_a2_jwk_json)); n |= test_jwe_r256a256_ptext(context, (char *)lws_jwe_ex_a2_jwk_json, - strlen((char *)lws_jwe_ex_a2_jwk_json)); + (int)strlen((char *)lws_jwe_ex_a2_jwk_json)); n |= test_jwe_ra_ptext_1024(context, (char *)rsa_key_2048, - strlen((char *)rsa_key_2048)); + (int)strlen((char *)rsa_key_2048)); n |= test_jwe_r256a192_ptext(context, (char *)rsa_key_2048, - strlen((char *)rsa_key_2048)); + (int)strlen((char *)rsa_key_2048)); n |= test_jwe_r256a256_ptext(context, (char *)rsa_key_2048, - strlen((char *)rsa_key_2048)); + (int)strlen((char *)rsa_key_2048)); n |= test_jwe_ra_ptext_1024(context, (char *)rsa_key_4096, - strlen((char *)rsa_key_4096)); + (int)strlen((char *)rsa_key_4096)); n |= test_jwe_r256a192_ptext(context, (char *)rsa_key_4096, - strlen((char *)rsa_key_4096)); + (int)strlen((char *)rsa_key_4096)); n |= test_jwe_r256a256_ptext(context, (char *)rsa_key_4096, - strlen((char *)rsa_key_4096)); + (int)strlen((char *)rsa_key_4096)); n |= test_jwe_ra_ptext_1024(context, (char *)rsa_key_4096_no_optional, - strlen((char *)rsa_key_4096_no_optional)); + (int)strlen((char *)rsa_key_4096_no_optional)); n |= test_jwe_r256a192_ptext(context, (char *)rsa_key_4096_no_optional, - strlen((char *)rsa_key_4096_no_optional)); + (int)strlen((char *)rsa_key_4096_no_optional)); n |= test_jwe_r256a256_ptext(context, (char *)rsa_key_4096_no_optional, - strlen((char *)rsa_key_4096_no_optional)); + (int)strlen((char *)rsa_key_4096_no_optional)); /* AESKW decrypt all variations */ diff --git a/minimal-examples/api-tests/api-test-jose/jws.c b/minimal-examples/api-tests/api-test-jose/jws.c index 8fc6ad5e..55ffcc97 100644 --- a/minimal-examples/api-tests/api-test-jose/jws.c +++ b/minimal-examples/api-tests/api-test-jose/jws.c @@ -46,7 +46,7 @@ test_jws_none(struct lws_context *context) /* A.5 Unsecured JSON "none" RFC7515 worked example */ /* decode the b64.b64[.b64] compact serialization blocks */ - n = lws_jws_compact_decode(none_cser, strlen(none_cser), &map, NULL, + n = lws_jws_compact_decode(none_cser, (int)strlen(none_cser), &map, NULL, temp, &temp_len); if (n != 2) { lwsl_err("%s: concat_map failed\n", __func__); @@ -131,8 +131,8 @@ test_jws_HS256(struct lws_context *context) /* parse the JOSE header */ - if (lws_jws_parse_jose(&jose, test1, strlen(test1), temp, &temp_len) < 0 || - !jose.alg) { + if (lws_jws_parse_jose(&jose, test1, (int)strlen(test1), temp, + &temp_len) < 0 || !jose.alg) { lwsl_err("%s: JOSE parse failed\n", __func__); goto bail; } @@ -314,7 +314,7 @@ test_jws_RS256(struct lws_context *context) goto bail; } - if (lws_jws_b64_compact_map(rfc7515_rsa_a1, strlen(rfc7515_rsa_a1), + if (lws_jws_b64_compact_map(rfc7515_rsa_a1, (int)strlen(rfc7515_rsa_a1), &jws.map_b64) != 3) { lwsl_notice("%s: lws_jws_b64_compact_map failed\n", __func__); goto bail; @@ -323,7 +323,7 @@ test_jws_RS256(struct lws_context *context) /* 2.3: generate our own signature for a copy of the test packet */ in = lws_concat_temp(temp, temp_len); - l = strlen(rfc7515_rsa_a1); + l = (int)strlen(rfc7515_rsa_a1); if (temp_len < l + 1) goto bail; memcpy(in, rfc7515_rsa_a1, l + 1); @@ -421,7 +421,7 @@ test_jws_ES256(struct lws_context *context) lws_jose_init(&jose); /* decode the b64.b64[.b64] compact serialization blocks */ - if (lws_jws_compact_decode(es256_cser, strlen(es256_cser), + if (lws_jws_compact_decode(es256_cser, (int)strlen(es256_cser), &jws.map, &jws.map_b64, temp, &temp_len) != 3) { lwsl_err("%s: concat_map failed\n", __func__); @@ -481,7 +481,7 @@ test_jws_ES256(struct lws_context *context) /* A.3 "ES256" RFC7515 worked example - sign */ - l = strlen(es256_cser); + l = (int)strlen(es256_cser); if (temp_len < l + 1) goto bail1; p = lws_concat_temp(temp, temp_len); @@ -582,7 +582,7 @@ test_jws_ES512(struct lws_context *context) lws_jose_init(&jose); /* decode the b64.b64[.b64] compact serialization blocks */ - if (lws_jws_compact_decode(es512_cser, strlen(es512_cser), + if (lws_jws_compact_decode(es512_cser, (int)strlen(es512_cser), &jws.map, &jws.map_b64, temp, &temp_len) != 3) { lwsl_err("%s: concat_map failed\n", __func__); @@ -642,7 +642,7 @@ test_jws_ES512(struct lws_context *context) /* A.3 "es512" RFC7515 worked example - sign */ - l = strlen(es512_cser); + l = (int)strlen(es512_cser); if (temp_len < l) goto bail1; p = lws_concat_temp(temp, temp_len); diff --git a/minimal-examples/crypto/minimal-crypto-jwe/main.c b/minimal-examples/crypto/minimal-crypto-jwe/main.c index 94856b8b..811b1f90 100644 --- a/minimal-examples/crypto/minimal-crypto-jwe/main.c +++ b/minimal-examples/crypto/minimal-crypto-jwe/main.c @@ -156,7 +156,7 @@ int main(int argc, const char **argv) /* account for padding as well */ - temp_len -= lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN, n); + temp_len -= (int)lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN, n); /* grab the key */ @@ -219,7 +219,11 @@ int main(int argc, const char **argv) if (lws_cmdline_option(argc, argv, "-c")) format_c(compact); else - if (write(1, compact, strlen(compact)) < 0) { + if (write(1, compact, +#if defined(WIN32) + (unsigned int) +#endif + strlen(compact)) < 0) { lwsl_err("Write stdout failed\n"); goto bail1; } diff --git a/minimal-examples/crypto/minimal-crypto-jwk/main.c b/minimal-examples/crypto/minimal-crypto-jwk/main.c index 5298c812..97dd7c2a 100644 --- a/minimal-examples/crypto/minimal-crypto-jwk/main.c +++ b/minimal-examples/crypto/minimal-crypto-jwk/main.c @@ -123,16 +123,16 @@ int main(int argc, const char **argv) } if ((p = lws_cmdline_option(argc, argv, "--kid"))) - lws_jwk_strdup_meta(&jwk, JWK_META_KID, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_KID, p, (int)strlen(p)); if ((p = lws_cmdline_option(argc, argv, "--use"))) - lws_jwk_strdup_meta(&jwk, JWK_META_USE, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_USE, p, (int)strlen(p)); if ((p = lws_cmdline_option(argc, argv, "--alg"))) - lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p)); if ((p = lws_cmdline_option(argc, argv, "--key-ops"))) - lws_jwk_strdup_meta(&jwk, JWK_META_KEY_OPS, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_KEY_OPS, p, (int)strlen(p)); if ((p = lws_cmdline_option(argc, argv, "--public")) && kty != LWS_GENCRYPTO_KTY_OCT) { @@ -156,7 +156,11 @@ int main(int argc, const char **argv) if (lws_cmdline_option(argc, argv, "-c")) format_c(fd, key); else { - if (write(fd, key, strlen(key)) < 0) { + if (write(fd, key, +#if defined(WIN32) + (unsigned int) +#endif + strlen(key)) < 0) { lwsl_err("Write public failed\n"); return 1; } @@ -177,7 +181,11 @@ int main(int argc, const char **argv) if (format_c(1, key) < 0) return 1; } else - if (write(1, key, strlen(key)) < 0) { + if (write(1, key, +#if defined(WIN32) + (unsigned int) +#endif + strlen(key)) < 0) { lwsl_err("Write stdout failed\n"); return 1; } diff --git a/minimal-examples/crypto/minimal-crypto-jws/main.c b/minimal-examples/crypto/minimal-crypto-jws/main.c index 5879fa9c..f48b0b05 100644 --- a/minimal-examples/crypto/minimal-crypto-jws/main.c +++ b/minimal-examples/crypto/minimal-crypto-jws/main.c @@ -152,7 +152,11 @@ int main(int argc, const char **argv) /* dump the compact JWS representation on stdout */ - if (write(1, compact, strlen(compact)) < 0) { + if (write(1, compact, +#if defined(WIN32) + (unsigned int) +#endif + strlen(compact)) < 0) { lwsl_err("Write stdout failed\n"); goto bail1; } diff --git a/minimal-examples/crypto/minimal-crypto-x509/main.c b/minimal-examples/crypto/minimal-crypto-x509/main.c index 74aade74..d04f6c47 100644 --- a/minimal-examples/crypto/minimal-crypto-x509/main.c +++ b/minimal-examples/crypto/minimal-crypto-x509/main.c @@ -126,7 +126,7 @@ int main(int argc, const char **argv) } if ((p = lws_cmdline_option(argc, argv, "--alg"))) - lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p)); lwsl_info("JWK version of trusted cert:\n"); lws_jwk_dump(&jwk); @@ -143,7 +143,7 @@ int main(int argc, const char **argv) lwsl_info("JWK version of cert:\n"); if ((p = lws_cmdline_option(argc, argv, "--alg"))) - lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p)); lws_jwk_dump(&jwk); /* only print public if he doesn't provide private */ @@ -172,7 +172,7 @@ int main(int argc, const char **argv) } if ((p = lws_cmdline_option(argc, argv, "--alg"))) - lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p)); + lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p)); lwsl_info("JWK version of cert + privkey:\n"); lws_jwk_dump(&jwk); -- Gitee From 2d5a7d1430c7508e26f719b65b295aef64ec8a86 Mon Sep 17 00:00:00 2001 From: Octavia93 <63444430+Octavia93@users.noreply.github.com> Date: Mon, 13 Apr 2020 18:10:59 +0300 Subject: [PATCH 0061/1062] alloc.c: add license header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Is this file also licensed under MIT license, I don’t see a license header like the other files in this repo? --- lib/core/alloc.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/core/alloc.c b/lib/core/alloc.c index 1e6a8a70..71940686 100644 --- a/lib/core/alloc.c +++ b/lib/core/alloc.c @@ -1,3 +1,27 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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 "private-lib-core.h" #if defined(LWS_HAVE_MALLOC_USABLE_SIZE) -- Gitee From eb5a41eeb55002e23b8360206b82cab617369352 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 13 Apr 2020 19:28:33 +0100 Subject: [PATCH 0062/1062] eventfd: restrict test to linux Seems otherwise it gets confused on iOS --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7592ac8b..a20737d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -904,7 +904,10 @@ CHECK_FUNCTION_EXISTS(atoll LWS_HAVE_ATOLL) CHECK_FUNCTION_EXISTS(_atoi64 LWS_HAVE__ATOI64) CHECK_FUNCTION_EXISTS(_stat32i64 LWS_HAVE__STAT32I64) CHECK_FUNCTION_EXISTS(clock_gettime LWS_HAVE_CLOCK_GETTIME) -CHECK_FUNCTION_EXISTS(eventfd LWS_HAVE_EVENTFD) + +IF (CMAKE_SYSTEM_NAME STREQUAL Linux) + CHECK_FUNCTION_EXISTS(eventfd LWS_HAVE_EVENTFD) +endif() if (NOT LWS_HAVE_GETIFADDRS) if (LWS_WITHOUT_BUILTIN_GETIFADDRS) -- Gitee From 63c8a237763045207f726e487bab7006d347b151 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 7 Apr 2020 06:35:00 +0100 Subject: [PATCH 0063/1062] lws_spawn: windows Move the unix spawn.c from lib/misc through to lib/plat/unix, and add an implementation for windows in lib/plat/windows --- .gitignore | 1 + .sai.json | 28 +- CMakeLists.txt | 7 +- include/libwebsockets/lws-misc.h | 5 +- lib/core-net/private-lib-core-net.h | 9 +- lib/core/libwebsockets.c | 11 +- lib/core/logs.c | 3 +- lib/misc/lejp.c | 4 +- lib/misc/threadpool/threadpool.c | 46 +- lib/plat/unix/private-lib-plat-unix.h | 1 + lib/{misc/spawn.c => plat/unix/unix-spawn.c} | 0 lib/plat/windows/private-lib-plat-windows.h | 1 + lib/plat/windows/windows-service.c | 2 +- lib/plat/windows/windows-spawn.c | 545 ++++++++++++++++++ .../minimal-raw-adopt-udp.c | 6 +- .../minimal-secure-streams-avs/avs.c | 8 +- 16 files changed, 645 insertions(+), 32 deletions(-) rename lib/{misc/spawn.c => plat/unix/unix-spawn.c} (100%) create mode 100644 lib/plat/windows/windows-spawn.c diff --git a/.gitignore b/.gitignore index 0e6e2daf..80c28361 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,4 @@ doc /bb/ /openssl3/ /bb-linkit/ +/bq/ diff --git a/.sai.json b/.sai.json index 1f651a94..10fca2a7 100644 --- a/.sai.json +++ b/.sai.json @@ -15,20 +15,30 @@ "build": "mkdir build destdir; cd build; cmake .. -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/openssl@1.1/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} && make -j" }, "linkit-cross": { - "build": "mkdir build;cd build;cmake .. ${cmake};make -j", + "build": "mkdir build;cd build;cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/tmp -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake -DLWS_PLAT_FREERTOS=1 -DLWS_WITH_ZLIB=0 -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_HTTP_STREAM_COMPRESSION=0 -DLWS_WITH_MBEDTLS=1 -DLWS_WITH_FILE_OPS=0 ${cmake};make -j", + "default": false + }, + "windows-10": { + "build": "mkdir build && cd build && cmake .. -DLWS_EXT_PTHREAD_INCLUDE_DIR=\"C:\\Program Files (x86)\\pthreads\\include\" -DLWS_EXT_PTHREAD_LIBRARIES=\"C:\\Program Files (x86)\\pthreads\\lib\\x64\\libpthreadGC2.a\" ${cmake} && cmake --build . --config DEBUG", "default": false } }, "configurations": { "default": { + "cmake": "", + "deps": "openssl", + "platforms": "windows-10, linkit-cross" + }, + "default-examples": { "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", - "deps": "openssl" + "deps": "openssl", + "platforms": "windows-10" }, - "linkit": { - "cmake": "-DCMAKE_INSTALL_PREFIX:PATH=/tmp -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake -DLWS_PLAT_FREERTOS=1 -DLWS_WITH_ZLIB=0 -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_HTTP_STREAM_COMPRESSION=0 -DLWS_WITH_MBEDTLS=1 -DLWS_WITH_FILE_OPS=0", - "deps": "linkit-sdk", - "platforms": "linkit-cross" + "lws_system": { + "cmake": "-DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=RELEASE -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", + "deps": "libz,openssl", + "platforms": "windows-10" }, "lwsws": { "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", @@ -70,7 +80,8 @@ "deps": "libglib" }, "ipv6": { - "cmake": "-DLWS_IPV6=ON" + "cmake": "-DLWS_IPV6=ON", + "platforms": "windows-10" }, "nossl": { "cmake": "-DLWS_WITH_SSL=OFF" @@ -96,7 +107,8 @@ "deps": "openssl" }, "threadpool": { - "cmake": "-DLWS_WITH_THREADPOOL=1 -DLWS_WITH_MINIMAL_EXAMPLES=1" + "cmake": "-DLWS_WITH_THREADPOOL=1 -DLWS_WITH_MINIMAL_EXAMPLES=1", + "platforms": "windows-10" } } } diff --git a/CMakeLists.txt b/CMakeLists.txt index a20737d6..6f510e1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1109,7 +1109,12 @@ set(SOURCES ) if (LWS_WITH_SPAWN) - list(APPEND SOURCES lib/misc/spawn.c) + if (UNIX) + list(APPEND SOURCES lib/plat/unix/unix-spawn.c) + endif() + if (WIN32) + list(APPEND SOURCES lib/plat/windows/windows-spawn.c) + endif() endif() if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index 493218c1..67c56524 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -724,7 +724,10 @@ lws_vbi_decode(const void *buf, uint64_t *value, size_t len); struct lws_spawn_piped; #if defined(WIN32) -typedef struct _lws_siginfo_t *siginfo_t; +struct _lws_siginfo_t { + int retcode; +}; +typedef struct _lws_siginfo_t siginfo_t; #endif typedef void (*lsp_cb_t)(void *opaque, lws_usec_t *accounting, siginfo_t *si, diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index b6540083..ebc1807b 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -799,6 +799,7 @@ struct lws { unsigned int oom4:1; unsigned int validity_hup:1; unsigned int skip_fallback:1; + unsigned int file_desc:1; unsigned int could_have_pending:1; /* detect back-to-back writes */ unsigned int outer_will_close:1; @@ -883,8 +884,9 @@ struct lws_spawn_piped { struct lws_dll2 dll; lws_sorted_usec_list_t sul; + struct lws_context *context; struct lws *stdwsi[3]; - int pipe_fds[3][2]; + lws_filefd_type pipe_fds[3][2]; int count_log_lines; lws_usec_t created; /* set by lws_spawn_piped() */ @@ -892,9 +894,14 @@ struct lws_spawn_piped { lws_usec_t accounting[4]; +#if defined(WIN32) + HANDLE child_pid; + lws_sorted_usec_list_t sul_poll; +#else pid_t child_pid; siginfo_t si; +#endif uint8_t pipes_alive:2; uint8_t we_killed_him_timeout:1; diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index 5745f0fb..8453ac03 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -413,7 +413,14 @@ lws_json_purify(char *escaped, const char *string, int len, int *in_used) continue; } - if (*p == '\"' || *p == '\\' || *p < 0x20) { + if (*p == '\\') { + p++; + *q++ = '\\'; + *q++ = '\\'; + continue; + } + + if (*p == '\"' || *p < 0x20) { *q++ = '\\'; *q++ = 'u'; *q++ = '0'; @@ -469,7 +476,9 @@ lws_filename_purify_inplace(char *filename) } if (*filename == ':' || +#if !defined(WIN32) *filename == '\\' || +#endif *filename == '$' || *filename == '%') *filename = '_'; diff --git a/lib/core/logs.c b/lib/core/logs.c index 268b2e36..3fde1192 100644 --- a/lib/core/logs.c +++ b/lib/core/logs.c @@ -162,7 +162,8 @@ lwsl_emit_stderr_notimestamp(int level, const char *line) #if !(defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK)) void _lws_logv(int filter, const char *format, va_list vl) { -#if LWS_MAX_SMP == 1 +#if LWS_MAX_SMP == 1 && !defined(LWS_WITH_THREADPOOL) + /* this is incompatible with multithreaded logging */ static char buf[256]; #else char buf[1024]; diff --git a/lib/misc/lejp.c b/lib/misc/lejp.c index 83a3e1fc..240f116a 100644 --- a/lib/misc/lejp.c +++ b/lib/misc/lejp.c @@ -346,10 +346,10 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) ctx->uni |= c - '0'; else if (c >= 'a' && c <= 'f') - ctx->uni = c - 'a' + 10; + ctx->uni |= c - 'a' + 10; else if (c >= 'A' && c <= 'F') - ctx->uni = c - 'A' + 10; + ctx->uni |= c - 'A' + 10; else { ret = LEJP_REJECT_ILLEGAL_HEX; goto reject; diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index 61048ba9..646c5f2f 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -171,7 +171,8 @@ __lws_threadpool_task_dump(struct lws_threadpool_task *task, char *buf, int len) void lws_threadpool_dump(struct lws_threadpool *tp) { -#if defined(_DEBUG) +#if 0 + //defined(_DEBUG) struct lws_threadpool_task **c; char buf[160]; int n, count; @@ -290,8 +291,14 @@ __lws_threadpool_reap(struct lws_threadpool_task *task) c = &(*c)->task_queue_next; } - if (!t) + if (!t) { lwsl_err("%s: task %p not in done queue\n", __func__, task); + /* + * This shouldn't occur, but in this case not really + * safe to assume there's a task to destroy + */ + return; + } } else lwsl_err("%s: task->tp NULL already\n", __func__); @@ -473,6 +480,8 @@ done: return 0; } +static int dummy; + static void * lws_threadpool_worker(void *d) { @@ -495,8 +504,8 @@ lws_threadpool_worker(void *d) pthread_cond_wait(&tp->wake_idle, &tp->lock); if (tp->destroying) { - pthread_mutex_unlock(&tp->lock); /* ------ tp unlock */ - continue; + lwsl_notice("%s: bailing\n", __func__); + goto doneski; } c = &tp->task_queue_head; @@ -651,13 +660,17 @@ lws_threadpool_worker(void *d) } } +doneski: pool->task = NULL; pthread_mutex_unlock(&tp->lock); /* --------------- tp unlock */ } - /* threadpool is being destroyed */ + lwsl_notice("%s: Exiting\n", __func__); - pthread_exit(NULL); + /* threadpool is being destroyed */ +#if !defined(WIN32) + pthread_exit(&dummy); +#endif return NULL; } @@ -760,8 +773,8 @@ lws_threadpool_destroy(struct lws_threadpool *tp) /* remove us from the context list of threadpools */ lws_context_lock(tp->context, __func__); - ptp = &tp->context->tp_list_head; + while (*ptp) { if (*ptp == tp) { *ptp = tp->tp_list; @@ -772,27 +785,32 @@ lws_threadpool_destroy(struct lws_threadpool *tp) lws_context_unlock(tp->context); + /* + * Wake up the threadpool guys and tell them to exit + */ pthread_mutex_lock(&tp->lock); /* ======================== tpool lock */ - tp->destroying = 1; pthread_cond_broadcast(&tp->wake_idle); pthread_mutex_unlock(&tp->lock); /* -------------------- tpool unlock */ lws_threadpool_dump(tp); + lwsl_info("%s: waiting for threads to rejoin\n", __func__); +#if defined(WIN32) + Sleep(1000); +#endif + for (n = 0; n < tp->threads_in_pool; n++) { task = tp->pool_list[n].task; - /* he could be sitting waiting for SYNC */ - - if (task != NULL) - pthread_cond_broadcast(&task->wake_idle); - pthread_join(tp->pool_list[n].thread, &retval); pthread_mutex_destroy(&tp->pool_list[n].lock); } lwsl_info("%s: all threadpools exited\n", __func__); +#if defined(WIN32) + Sleep(1000); +#endif task = tp->task_done_head; while (task) { @@ -1074,6 +1092,8 @@ void lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop) { lwsl_debug("%s\n", __func__); + if (!task) + return; if (stop) state_transition(task, LWS_TP_STATUS_STOPPING); diff --git a/lib/plat/unix/private-lib-plat-unix.h b/lib/plat/unix/private-lib-plat-unix.h index e3262f05..d64f8988 100644 --- a/lib/plat/unix/private-lib-plat-unix.h +++ b/lib/plat/unix/private-lib-plat-unix.h @@ -166,6 +166,7 @@ delete_from_fd(const struct lws_context *context, int fd); #endif #define compatible_close(x) close(x) +#define compatible_file_close(fd) close(fd) #define lws_plat_socket_offset() (0) /* diff --git a/lib/misc/spawn.c b/lib/plat/unix/unix-spawn.c similarity index 100% rename from lib/misc/spawn.c rename to lib/plat/unix/unix-spawn.c diff --git a/lib/plat/windows/private-lib-plat-windows.h b/lib/plat/windows/private-lib-plat-windows.h index b8053bc2..558aedf5 100644 --- a/lib/plat/windows/private-lib-plat-windows.h +++ b/lib/plat/windows/private-lib-plat-windows.h @@ -51,6 +51,7 @@ #define SHUT_WR SD_SEND #define compatible_close(fd) closesocket(fd) + #define compatible_file_close(fd) CloseHandle(fd) #define lws_set_blocking_send(wsi) wsi->sock_send_blocking = 1 #include diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index 7c7fc8e3..5a6fc1b8 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -131,7 +131,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) _lws_plat_service_forced_tsi(context, tsi); /* - * service pending callbakcs and get maximum wait time + * service pending callbacks and get maximum wait time */ { lws_usec_t us; diff --git a/lib/plat/windows/windows-spawn.c b/lib/plat/windows/windows-spawn.c new file mode 100644 index 00000000..2bd0d103 --- /dev/null +++ b/lib/plat/windows/windows-spawn.c @@ -0,0 +1,545 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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 "private-lib-core.h" + +#include +#include +#include + +void +lws_spawn_timeout(struct lws_sorted_usec_list *sul) +{ + struct lws_spawn_piped *lsp = lws_container_of(sul, + struct lws_spawn_piped, sul); + + lwsl_warn("%s: spawn exceeded timeout, killing\n", __func__); + + lws_spawn_piped_kill_child_process(lsp); +} + +static struct lws * +lws_create_basic_wsi(struct lws_context *context, int tsi, + const struct lws_role_ops *ops) +{ + struct lws *new_wsi; + + if (!context->vhost_list) + return NULL; + + if ((unsigned int)context->pt[tsi].fds_count == + context->fd_limit_per_thread - 1) { + lwsl_err("no space for new conn\n"); + return NULL; + } + + new_wsi = lws_zalloc(sizeof(*new_wsi), "new wsi"); + if (new_wsi == NULL) { + lwsl_err("Out of memory for new connection\n"); + return NULL; + } + + new_wsi->tsi = tsi; + new_wsi->context = context; + new_wsi->pending_timeout = NO_PENDING_TIMEOUT; + new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; + + /* initialize the instance struct */ + + lws_role_transition(new_wsi, 0, LRS_ESTABLISHED, ops); + + new_wsi->hdr_parsing_completed = 0; + new_wsi->position_in_fds_table = LWS_NO_FDS_POS; + + /* + * these can only be set once the protocol is known + * we set an unestablished connection's protocol pointer + * to the start of the defauly vhost supported list, so it can look + * for matching ones during the handshake + */ + + new_wsi->user_space = NULL; + new_wsi->desc.sockfd = LWS_SOCK_INVALID; + context->count_wsi_allocated++; + + return new_wsi; +} + +void +lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) +{ + struct lws_spawn_piped *lsp = *_lsp; + struct lws *wsi; + int n; + + if (!lsp) + return; + + for (n = 0; n < 3; n++) { + if (lsp->pipe_fds[n][!!(n == 0)]) { + CloseHandle(lsp->pipe_fds[n][n == 0]); + lsp->pipe_fds[n][n == 0] = NULL; + } + + for (n = 0; n < 3; n++) { + if (lsp->stdwsi[n]) { + lwsl_notice("%s: closing stdwsi %d\n", __func__, n); + wsi = lsp->stdwsi[n]; + lsp->stdwsi[n]->desc.filefd = NULL; + lsp->stdwsi[n] = NULL; + lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); + } + } + } + + lws_dll2_remove(&lsp->dll); + + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, + NULL, LWS_SET_TIMER_USEC_CANCEL); + + lws_sul_schedule(lsp->context, 0, &lsp->sul_poll, NULL, + LWS_SET_TIMER_USEC_CANCEL); + + lwsl_warn("%s: deleting lsp\n", __func__); + + lws_free_set_NULL((*_lsp)); +} + +int +lws_spawn_reap(struct lws_spawn_piped *lsp) +{ + + void *opaque = lsp->info.opaque; + lsp_cb_t cb = lsp->info.reap_cb; + struct _lws_siginfo_t lsi; + lws_usec_t acct[4]; + DWORD ex; + + if (!lsp->child_pid) + return 0; + + if (!GetExitCodeProcess(lsp->child_pid, &ex)) { + lwsl_notice("%s: GetExitCodeProcess failed\n", __func__); + return 0; + } + + /* nonzero = success */ + + if (ex == STILL_ACTIVE) { + lwsl_notice("%s: still active\n", __func__); + return 0; + } + + /* mark the earliest time we knew he had gone */ + if (!lsp->reaped) { + lsp->reaped = lws_now_usecs(); + + /* + * Switch the timeout to restrict the amount of grace time + * to drain stdwsi + */ + + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul, lws_spawn_timeout, + 5 * LWS_US_PER_SEC); + } + + /* + * Stage finalizing our reaction to the process going down until the + * stdwsi flushed whatever is in flight and all noticed they were + * closed. For that reason, each stdwsi close must call lws_spawn_reap + * to check if that was the last one and we can proceed with the reap. + */ + + if (!lsp->ungraceful && lsp->pipes_alive) { + lwsl_notice("%s: stdwsi alive, not reaping\n", __func__); + return 0; + } + + /* we reached the reap point, no need for timeout wait */ + + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, NULL, + LWS_SET_TIMER_USEC_CANCEL); + + /* + * All the stdwsi went down, nothing more is coming... it's over + * Collect the final information and then reap the dead process + */ + + lsi.retcode = 0x10000 | (int)ex; + lwsl_notice("%s: process exit 0x%x\n", __func__, lsi.retcode); + lsp->child_pid = NULL; + + /* destroy the lsp itself first (it's freed and plsp set NULL */ + + if (lsp->info.plsp) + lws_spawn_piped_destroy(lsp->info.plsp); + + /* then do the parent callback informing it's destroyed */ + + memset(acct, 0, sizeof(acct)); + if (cb) + cb(opaque, acct, &lsi, 0); + + lwsl_notice("%s: completed reap\n", __func__); + + return 1; /* was reaped */ +} + +int +lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp) +{ + if (!lsp->child_pid) + return 1; + + lsp->ungraceful = 1; /* don't wait for flushing, just kill it */ + + if (lws_spawn_reap(lsp)) + /* that may have invalidated lsp */ + return 0; + + lwsl_warn("%s: calling TerminateProcess on child pid\n", __func__); + TerminateProcess(lsp->child_pid, 252); + lws_spawn_reap(lsp); + + /* that may have invalidated lsp */ + + return 0; +} + +static void +windows_pipe_poll_hack(lws_sorted_usec_list_t *sul) +{ + struct lws_spawn_piped *lsp = lws_container_of(sul, + struct lws_spawn_piped, sul_poll); + struct lws *wsi, *wsi1; + DWORD br; + char c; + + /* + * Do it first, we know lsp exists and if it's destroyed inbetweentimes, + * it will already have cancelled this + */ + + lws_sul_schedule(lsp->context, 0, &lsp->sul_poll, + windows_pipe_poll_hack, 50 * LWS_US_PER_MS); + + wsi = lsp->stdwsi[LWS_STDOUT]; + wsi1 = lsp->stdwsi[LWS_STDERR]; + if (wsi && lsp->pipe_fds[LWS_STDOUT][0] != NULL) { + if (!PeekNamedPipe(lsp->pipe_fds[LWS_STDOUT][0], &c, 1, &br, + NULL, NULL)) { + + lwsl_notice("%s: stdout pipe errored\n", __func__); + CloseHandle(lsp->stdwsi[LWS_STDOUT]->desc.filefd); + lsp->pipe_fds[LWS_STDOUT][0] = NULL; + lsp->stdwsi[LWS_STDOUT]->desc.filefd = NULL; + lsp->stdwsi[LWS_STDOUT] = NULL; + lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); + + if (lsp->stdwsi[LWS_STDIN]) { + lwsl_notice("%s: closing stdin from stdout close\n", + __func__); + CloseHandle(lsp->stdwsi[LWS_STDIN]->desc.filefd); + wsi = lsp->stdwsi[LWS_STDIN]; + lsp->stdwsi[LWS_STDIN]->desc.filefd = NULL; + lsp->stdwsi[LWS_STDIN] = NULL; + lsp->pipe_fds[LWS_STDIN][1] = NULL; + lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); + } + + /* + * lsp may be destroyed by here... if we wanted to + * handle a still-extant stderr we'll get it next time + */ + + return; + } else + if (br) + wsi->protocol->callback(wsi, + LWS_CALLBACK_RAW_RX_FILE, + NULL, NULL, 0); + } + + /* + * lsp may have been destroyed above + */ + + if (wsi1 && lsp->pipe_fds[LWS_STDERR][0]) { + if (!PeekNamedPipe(lsp->pipe_fds[LWS_STDERR][0], &c, 1, &br, + NULL, NULL)) { + + lwsl_notice("%s: stderr pipe errored\n", __func__); + CloseHandle(wsi1->desc.filefd); + /* + * Assume is stderr still extant on entry, lsp can't + * have been destroyed by stdout/stdin processing + */ + lsp->stdwsi[LWS_STDERR]->desc.filefd = NULL; + lsp->stdwsi[LWS_STDERR] = NULL; + lsp->pipe_fds[LWS_STDERR][0] = NULL; + lws_set_timeout(wsi1, 1, LWS_TO_KILL_SYNC); + /* + * lsp may have been destroyed above + */ + } else + if (br) + wsi1->protocol->callback(wsi1, + LWS_CALLBACK_RAW_RX_FILE, + NULL, NULL, 0); + } +} + + + +/* + * Deals with spawning a subprocess and executing it securely with stdin/out/err + * diverted into pipes + */ + +struct lws_spawn_piped * +lws_spawn_piped(const struct lws_spawn_piped_info *i) +{ + const struct lws_protocols *pcol = i->vh->context->vhost_list->protocols; + struct lws_context *context = i->vh->context; + struct lws_spawn_piped *lsp; + PROCESS_INFORMATION pi; + SECURITY_ATTRIBUTES sa; + char cli[300], *p; + STARTUPINFO si; + int n; + + if (i->protocol_name) + pcol = lws_vhost_name_to_protocol(i->vh, i->protocol_name); + if (!pcol) { + lwsl_err("%s: unknown protocol %s\n", __func__, + i->protocol_name ? i->protocol_name : "default"); + + return NULL; + } + + lsp = lws_zalloc(sizeof(*lsp), __func__); + if (!lsp) { + lwsl_err("%s: OOM\n", __func__); + return NULL; + } + + /* wholesale take a copy of info */ + lsp->info = *i; + lsp->context = context; + + /* + * Prepare the stdin / out / err pipes + */ + + for (n = 0; n < 3; n++) { + lsp->pipe_fds[n][0] = NULL; + lsp->pipe_fds[n][1] = NULL; + } + + /* create pipes for [stdin|stdout] and [stderr] */ + + memset(&sa, 0, sizeof(sa)); + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; /* inherit the pipes */ + sa.lpSecurityDescriptor = NULL; + + for (n = 0; n < 3; n++) { + DWORD waitmode = PIPE_NOWAIT; + + if (!CreatePipe(&lsp->pipe_fds[n][0], &lsp->pipe_fds[n][1], + &sa, 0)) { + lwsl_err("%s: CreatePipe() failed\n", __func__); + goto bail1; + } + + SetNamedPipeHandleState(lsp->pipe_fds[1][0], &waitmode, NULL, NULL); + SetNamedPipeHandleState(lsp->pipe_fds[2][0], &waitmode, NULL, NULL); + + /* don't inherit the pipe side that belongs to the parent */ + + if (!SetHandleInformation(&lsp->pipe_fds[n][!n], + HANDLE_FLAG_INHERIT, 0)) { + lwsl_err("%s: SetHandleInformation() failed\n", __func__); + //goto bail1; + } + } + + /* create wsis for each stdin/out/err fd */ + + for (n = 0; n < 3; n++) { + lsp->stdwsi[n] = lws_create_basic_wsi(i->vh->context, i->tsi, + i->ops ? i->ops : &role_ops_raw_file); + if (!lsp->stdwsi[n]) { + lwsl_err("%s: unable to create lsp stdwsi\n", __func__); + goto bail2; + } + lsp->stdwsi[n]->lsp_channel = n; + lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]); + lsp->stdwsi[n]->protocol = pcol; + lsp->stdwsi[n]->opaque_user_data = i->opaque; + + lsp->stdwsi[n]->desc.filefd = lsp->pipe_fds[n][!n]; + lsp->stdwsi[n]->file_desc = 1; + + lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n", + __func__, lsp->stdwsi[n], n, + lsp->pipe_fds[n][!!(n == 0)], + lsp->pipe_fds[n][!(n == 0)]); + +#if 0 + + /* read side is 0, stdin we want the write side, others read */ + + lsp->stdwsi[n]->desc.filefd = lsp->pipe_fds[n][!!(n == 0)]; + if (fcntl(lsp->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK) < 0) { + lwsl_err("%s: setting NONBLOCK failed\n", __func__); + goto bail2; + } +#endif + } + + for (n = 0; n < 3; n++) + if (i->opt_parent) { + lsp->stdwsi[n]->parent = i->opt_parent; + lsp->stdwsi[n]->sibling_list = i->opt_parent->child_list; + i->opt_parent->child_list = lsp->stdwsi[n]; + } + + lwsl_notice("%s: pipe handles in %p, out %p, err %p\n", __func__, + lsp->stdwsi[LWS_STDIN]->desc.sockfd, + lsp->stdwsi[LWS_STDOUT]->desc.sockfd, + lsp->stdwsi[LWS_STDERR]->desc.sockfd); + + /* + * Windows nonblocking pipe handling is a mess that is unable + * to interoperate with WSA-based wait as far as I can tell. + * + * Let's set up a sul to poll the pipes and synthesize the + * protocol callbacks if anything coming. + */ + lws_sul_schedule(context, 0, &lsp->sul_poll, windows_pipe_poll_hack, + 50 * LWS_US_PER_MS); + + + /* + * Windows wants a single string commandline + */ + p = cli; + n = 0; + while (i->exec_array[n]) { + lws_strncpy(p, i->exec_array[n], + sizeof(cli) - lws_ptr_diff(p, cli)); + if (sizeof(cli) - lws_ptr_diff(p, cli) < 4) + break; + p += strlen(p); + *p++ = ' '; + *p = '\0'; + n++; + } + + puts(cli); + + memset(&pi, 0, sizeof(pi)); + memset(&si, 0, sizeof(si)); + + si.cb = sizeof(STARTUPINFO); + si.hStdInput = lsp->pipe_fds[LWS_STDIN][0]; + si.hStdOutput = lsp->pipe_fds[LWS_STDOUT][1]; + si.hStdError = lsp->pipe_fds[LWS_STDERR][1]; + si.dwFlags = STARTF_USESTDHANDLES | CREATE_NO_WINDOW; + si.wShowWindow = TRUE; + + if (!CreateProcess(NULL, cli, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { + lwsl_err("%s: CreateProcess failed 0x%x\n", __func__, + (unsigned long)GetLastError()); + goto bail3; + } + + lsp->child_pid = pi.hProcess; + + lwsl_notice("%s: lsp %p spawned PID %d\n", __func__, lsp, lsp->child_pid); + + lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout, + i->timeout_us ? i->timeout_us : 300 * LWS_US_PER_SEC); + + /* + * close: stdin:r, stdout:w, stderr:w + */ + for (n = 0; n < 3; n++) + CloseHandle(lsp->pipe_fds[n][n != 0]); + + lsp->pipes_alive = 3; + lsp->created = lws_now_usecs(); + + if (i->owner) + lws_dll2_add_head(&lsp->dll, i->owner); + + if (i->timeout_us) + lws_sul_schedule(context, i->tsi, &lsp->sul, + lws_spawn_timeout, i->timeout_us); + + return lsp; + +bail3: + + lws_sul_schedule(context, 0, &lsp->sul_poll, NULL, + LWS_SET_TIMER_USEC_CANCEL); + + while (--n >= 0) + __remove_wsi_socket_from_fds(lsp->stdwsi[n]); +bail2: + for (n = 0; n < 3; n++) + if (lsp->stdwsi[n]) + __lws_free_wsi(lsp->stdwsi[n]); + +bail1: + for (n = 0; n < 3; n++) { + if (lsp->pipe_fds[n][0] >= 0) + CloseHandle(lsp->pipe_fds[n][0]); + if (lsp->pipe_fds[n][1] >= 0) + CloseHandle(lsp->pipe_fds[n][1]); + } + + lws_free(lsp); + + lwsl_err("%s: failed\n", __func__); + + return NULL; +} + +void +lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp) +{ + assert(lsp); + lsp->pipes_alive--; + lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive); + lws_spawn_reap(lsp); +} + +int +lws_spawn_get_stdfd(struct lws *wsi) +{ + return wsi->lsp_channel; +} diff --git a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c index 8af3804c..6e23a3c5 100644 --- a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c +++ b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c @@ -104,7 +104,11 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, #if defined(WIN32) (const char *) #endif - sendbuf, sendlen, 0, &udp.sa, (socklen_t)udp.salen); + sendbuf, +#if defined(WIN32) + (int) +#endif + sendlen, 0, &udp.sa, (socklen_t)udp.salen); if (n < (ssize_t)len) lwsl_notice("%s: send returned %d\n", __func__, (int)n); break; diff --git a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c index d7f268f7..ea8f97e2 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c @@ -104,7 +104,7 @@ use_buffer_50ms(lws_sorted_usec_list_t *sul) if (n < (sizeof(m->buf) * 2) / 3 && e < (int)(sizeof(m->buf) - 1 - n)) { lwsl_info("%s: requesting additional %d\n", __func__, (int)(sizeof(m->buf) - 1 - e - n)); - lws_ss_add_peer_tx_credit(m->ss, (sizeof(m->buf) - 1 - e - n)); + lws_ss_add_peer_tx_credit(m->ss, (int32_t)(sizeof(m->buf) - 1 - e - n)); } lws_sul_schedule(context, 0, &m->sul, use_buffer_50ms, @@ -389,7 +389,11 @@ avs_example_start(struct lws_context *context) goto bail; } - if (read(fd, wav, wav_len) != (int)wav_len) { + if (read(fd, wav, +#if defined(WIN32) + (unsigned int) +#endif + wav_len) != (int)wav_len) { lwsl_err("%s: failed to read wav\n", __func__); goto bail; -- Gitee From eca75ee14de29de3f2e144946db2a55a0aea7096 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 15 Apr 2020 19:16:29 +0100 Subject: [PATCH 0064/1062] http: pipelining: fixes from xenial sai --- lib/core-net/vhost.c | 4 ++++ lib/roles/http/client/client-handshake.c | 17 +++++++++++++---- lib/roles/http/client/client-http.c | 3 ++- .../minimal-http-client-multi.c | 6 +++--- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index 3bdd7abf..a80ef0a2 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -1424,6 +1424,10 @@ lws_get_vhost_by_name(struct lws_context *context, const char *name) * * This was originally in the client code but since the list is held on the * vhost (to ensure the same client tls ctx is involved) it's cleaner in vhost.c + * + * ACTIVE_CONNS_QUEUED: We're queued on an active connection, set *nwsi to that + * ACTIVE_CONNS_MUXED: We are joining an active mux conn *nwsi as a child + * ACTIVE_CONNS_SOLO: There's no existing conn to join either way */ int diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 780c97bc..97f3a6b2 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -192,7 +192,8 @@ send_hs: } else { lwsl_info("%s: wsi %p: %s %s client created own conn (raw %d) vh %sm st 0x%x\n", __func__, wsi, wsi->role_ops->name, - wsi->protocol->name, rawish, wsi->vhost->name, lwsi_state(wsi)); + wsi->protocol->name, rawish, wsi->vhost->name, + lwsi_state(wsi)); /* we are making our own connection */ @@ -231,9 +232,10 @@ send_hs: } #endif - if (!rawish) - lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE); - else { + if (!rawish) { + if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2) + lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE); + } else { /* for a method = "RAW" connection, this makes us * established */ @@ -848,6 +850,13 @@ lws_client_connect_2_dnsreq(struct lws *wsi) return wsi; case ACTIVE_CONNS_QUEUED: + if (lwsi_state(wsi) == LRS_UNCONNECTED) { + if (lwsi_role_h2(w)) + lwsi_set_state(wsi, LRS_H2_WAITING_TO_SEND_HEADERS); + else + lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); + } + return lws_client_connect_4_established(wsi, w, 0); } diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index f34cbbc5..fd317c2d 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -471,7 +471,8 @@ client_http_body_sent: return lws_client_interpret_server_handshake(wsi); bail3: - lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n"); + lwsl_info("%s: closing conn at LWS_CONNMODE...SERVER_REPLY, wsi %p, state 0x%x\n", + __func__, wsi, lwsi_state(wsi)); if (cce) lwsl_info("reason: %s\n", cce); lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); diff --git a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c index 16cb1d0b..caca20b2 100644 --- a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c +++ b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c @@ -44,7 +44,7 @@ static int completed, failed, numbered, stagger_idx, posting, count = COUNT; static lws_sorted_usec_list_t sul_stagger; static struct lws_client_connect_info i; static struct lws *client_wsi[COUNT]; -static char urlpath[64]; +static char urlpath[64], intr; static struct lws_context *context; /* we only need this for tracking POST emit state */ @@ -198,7 +198,7 @@ finished: lwsl_user("Done: all OK\n"); else lwsl_err("Done: failed: %d\n", failed); - //interrupted = 1; + intr = 1; /* * This is how we can exit the event loop even when it's an * event library backing it... it will start and stage the @@ -459,7 +459,7 @@ int main(int argc, const char **argv) 100 * LWS_US_PER_MS); start = us(); - while (!lws_service(context, 0)) + while (!intr && !lws_service(context, 0)) ; lwsl_user("Duration: %lldms\n", (us() - start) / 1000); -- Gitee From a8eebc47a533db0e7a0d71d2c748c730147378df Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 15 Apr 2020 20:57:00 +0100 Subject: [PATCH 0065/1062] smp: helgrind and sai lock fixes --- lib/core-net/pollfd.c | 2 +- lib/core-net/private-lib-core-net.h | 2 +- lib/core-net/vhost.c | 4 ++-- lib/core-net/wsi.c | 8 +++++--- lib/core/context.c | 11 +++++------ lib/roles/http/client/client-http.c | 2 +- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/core-net/pollfd.c b/lib/core-net/pollfd.c index a8d8759d..5a45ad72 100644 --- a/lib/core-net/pollfd.c +++ b/lib/core-net/pollfd.c @@ -372,7 +372,7 @@ __remove_wsi_socket_from_fds(struct lws *wsi) return -1; #endif - lws_same_vh_protocol_remove(wsi); + __lws_same_vh_protocol_remove(wsi); /* the guy who is to be deleted's slot index in pt->fds */ m = wsi->position_in_fds_table; diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index ebc1807b..19c4d9a4 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -1388,7 +1388,7 @@ lws_async_dns_deinit(lws_async_dns_t *dns); int lws_protocol_init_vhost(struct lws_vhost *vh, int *any); int -_lws_generic_transaction_completed_active_conn(struct lws **wsi); +_lws_generic_transaction_completed_active_conn(struct lws **wsi, char take_vh_lock); #define ACTIVE_CONNS_SOLO 0 #define ACTIVE_CONNS_MUXED 1 diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index a80ef0a2..ff73d019 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -1506,7 +1506,7 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin) if (lwsi_state(w) == LRS_IDLING) { // lwsi_set_state(w, LRS_ESTABLISHED); - _lws_generic_transaction_completed_active_conn(&w); + _lws_generic_transaction_completed_active_conn(&w, 0); } //lwsi_set_state(w, LRS_H1C_ISSUE_HANDSHAKE2); @@ -1560,7 +1560,7 @@ lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin) if (lwsi_state(w) == LRS_IDLING) { // lwsi_set_state(w, LRS_ESTABLISHED); - _lws_generic_transaction_completed_active_conn(&w); + _lws_generic_transaction_completed_active_conn(&w, 0); } /* diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index d0b49af3..0dfbdb99 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -761,7 +761,7 @@ lws_get_context(const struct lws *wsi) #if defined(LWS_WITH_CLIENT) int -_lws_generic_transaction_completed_active_conn(struct lws **_wsi) +_lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_lock) { struct lws *wnew, *wsi = *_wsi; @@ -808,7 +808,8 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi) * closing ourself */ - lws_vhost_lock(wsi->vhost); + if (take_vh_lock) + lws_vhost_lock(wsi->vhost); wnew = lws_container_of(wsi->dll2_cli_txn_queue_owner.head, struct lws, dll2_cli_txn_queue); @@ -891,7 +892,8 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi) } lws_end_foreach_dll_safe(d, d1); - lws_vhost_unlock(wsi->vhost); + if (take_vh_lock) + lws_vhost_unlock(wsi->vhost); /* * The original leader who passed on all his powers already can die... diff --git a/lib/core/context.c b/lib/core/context.c index 8c357d7e..4c2a48e7 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -1075,6 +1075,10 @@ lws_context_destroy3(struct lws_context *context) lws_system_blob_destroy( lws_system_get_blob(context, n, 0)); +#if LWS_MAX_SMP > 1 + lws_mutex_refcount_destroy(&context->mr); +#endif + lws_free(context); lwsl_info("%s: ctx %p freed\n", __func__, context); @@ -1197,14 +1201,11 @@ lws_context_destroy2(struct lws_context *context) lws_check_deferred_free(context, 0, 1); #endif + lws_context_unlock(context); /* } context ------ */ -#if LWS_MAX_SMP > 1 - lws_mutex_refcount_destroy(&context->mr); -#endif #if defined(LWS_WITH_NETWORK) if (context->event_loop_ops->destroy_context2) if (context->event_loop_ops->destroy_context2(context)) { - lws_context_unlock(context); /* } context ----------- */ context->finalize_destroy_after_internal_loops_stopped = 1; return; } @@ -1216,12 +1217,10 @@ lws_context_destroy2(struct lws_context *context) for (n = 0; n < context->count_threads; n++) if (context->pt[n].inside_service) { lwsl_debug("%p: bailing as inside service\n", __func__); - lws_context_unlock(context); /* } context --- */ return; } } #endif - lws_context_unlock(context); /* } context ------------------- */ lws_context_destroy3(context); } diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index fd317c2d..03af4f84 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -510,7 +510,7 @@ lws_http_transaction_completed_client(struct lws *wsi) * For h1, wsi may pass some assets on to a queued child and be * destroyed during this. */ - n = _lws_generic_transaction_completed_active_conn(&wsi); + n = _lws_generic_transaction_completed_active_conn(&wsi, 1); if (wsi->http.ah) { if (wsi->client_mux_substream) -- Gitee From d339505f5120a296bfef34de14bd216b4c2257f1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Apr 2020 06:53:10 +0100 Subject: [PATCH 0066/1062] h2: cmake: build with NO_SERVER --- CMakeLists.txt | 12 +----------- lib/roles/h2/http2.c | 2 +- lib/roles/h2/ops-h2.c | 6 ++++++ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f510e1c..5e2dfbf6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -383,12 +383,6 @@ if(GIT_EXECUTABLE) message("Git commit hash: ${LWS_BUILD_HASH}") endif() -# translate old functionality enables to set up ROLE enables so nothing changes -if (LWS_WITH_HTTP2 AND LWS_WITHOUT_SERVER) - set(LWS_WITH_HTTP2 0) - message("HTTP2 disabled due to LWS_WITHOUT_SERVER") -endif() - if (LWS_WITH_HTTP2) set(LWS_ROLE_H2 1) endif() @@ -791,10 +785,6 @@ if (LWS_UNIX_SOCK) set(LWS_WITH_UNIX_SOCK 1) endif() -if (LWS_WITH_HTTP2) - set(LWS_WITH_HTTP2 1) -endif() - if ("${LWS_MAX_SMP}" STREQUAL "") set(LWS_MAX_SMP 1) endif() @@ -1514,7 +1504,7 @@ if (NOT LWS_WITHOUT_BUILTIN_SHA1) lib/misc/sha-1.c) endif() -if (LWS_WITH_HTTP2 AND NOT LWS_WITHOUT_SERVER) +if (LWS_WITH_HTTP2) list(APPEND SOURCES lib/roles/h2/http2.c lib/roles/h2/hpack.c diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 931b453e..a7c02ca0 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -2466,7 +2466,7 @@ fail_length: } #endif -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) && defined(LWS_WITH_SERVER) int lws_h2_ws_handshake(struct lws *wsi) { diff --git a/lib/roles/h2/ops-h2.c b/lib/roles/h2/ops-h2.c index 65b8f509..f7744fde 100644 --- a/lib/roles/h2/ops-h2.c +++ b/lib/roles/h2/ops-h2.c @@ -488,6 +488,7 @@ rops_write_role_protocol_h2(struct lws *wsi, unsigned char *buf, size_t len, return (int)olen; } +#if defined(LWS_WITH_SERVER) static int rops_check_upgrades_h2(struct lws *wsi) { @@ -526,6 +527,7 @@ rops_check_upgrades_h2(struct lws *wsi) return LWS_UPG_RET_CONTINUE; #endif } +#endif static int rops_init_vhost_h2(struct lws_vhost *vh, @@ -1225,7 +1227,11 @@ rops_issue_keepalive_h2(struct lws *wsi, int isvalid) const struct lws_role_ops role_ops_h2 = { /* role name */ "h2", /* alpn id */ "h2", +#if defined(LWS_WITH_SERVER) /* check_upgrades */ rops_check_upgrades_h2, +#else + NULL, +#endif /* pt_init_destroy */ rops_pt_init_destroy_h2, /* init_vhost */ rops_init_vhost_h2, /* destroy_vhost */ NULL, -- Gitee From 886a588963f61045114c3e23512425e0ca20a1bd Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Apr 2020 10:56:03 +0100 Subject: [PATCH 0067/1062] lws_dir: XFS does not report directories via dirent If it says it's unknown, we always need to fall back on to the stat method. --- lib/misc/dir.c | 95 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 27 deletions(-) diff --git a/lib/misc/dir.c b/lib/misc/dir.c index d2011e28..aa8915d5 100644 --- a/lib/misc/dir.c +++ b/lib/misc/dir.c @@ -34,6 +34,8 @@ #include #include +#define COMBO_SIZEOF 256 + #if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0 int @@ -94,12 +96,62 @@ static int filter(const struct dirent *ent) return 1; } + +#if !defined(WIN32) +static char csep = '/'; +#else +static char csep = '\\'; +#endif + +static void +lws_dir_via_stat(char *combo, size_t l, const char *path, struct lws_dir_entry *lde) +{ + struct stat s; + + lws_strncpy(combo + l, path, COMBO_SIZEOF - l); + + lde->type = LDOT_UNKNOWN; + + if (!stat(combo, &s)) { + switch (s.st_mode & S_IFMT) { + case S_IFBLK: + lde->type = LDOT_BLOCK; + break; + case S_IFCHR: + lde->type = LDOT_CHAR; + break; + case S_IFDIR: + lde->type = LDOT_DIR; + break; + case S_IFIFO: + lde->type = LDOT_FIFO; + break; +#if !defined(WIN32) + case S_IFLNK: + lde->type = LDOT_LINK; + break; +#endif + case S_IFREG: + lde->type = LDOT_FILE; + break; + default: + break; + } + } +} + int lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) { struct lws_dir_entry lde; struct dirent **namelist; int n, i, ret = 1; + char combo[COMBO_SIZEOF]; + size_t l; + + l = lws_snprintf(combo, COMBO_SIZEOF - 2, "%s", dirpath); + combo[l++] = csep; + combo[l] = '\0'; n = scandir((char *)dirpath, &namelist, filter, alphasort); if (n < 0) { @@ -118,46 +170,34 @@ lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) */ #if defined(__sun) - struct stat s; - stat(namelist[i]->d_name, &s); - switch (s.st_mode) { - case S_IFBLK: - lde.type = LDOT_BLOCK; - break; - case S_IFCHR: - lde.type = LDOT_CHAR; - break; - case S_IFDIR: - lde.type = LDOT_DIR; - break; - case S_IFIFO: - lde.type = LDOT_FIFO; - break; - case S_IFLNK: - lde.type = LDOT_LINK; - break; - case S_IFREG: - lde.type = LDOT_FILE; - break; - default: - lde.type = LDOT_UNKNOWN; - break; - } + lws_dir_via_stat(combo, l, namelist[i]->d_name, &lde); #else + /* + * XFS on Linux doesn't fill in d_type at all, always zero. + */ + switch (namelist[i]->d_type) { +#if DT_BLK != DT_UNKNOWN case DT_BLK: lde.type = LDOT_BLOCK; break; +#endif +#if DT_CHR != DT_UNKNOWN case DT_CHR: lde.type = LDOT_CHAR; break; +#endif +#if DT_DIR != DT_UNKNOWN case DT_DIR: lde.type = LDOT_DIR; break; +#endif +#if DT_FIFO != DT_UNKNOWN case DT_FIFO: lde.type = LDOT_FIFO; break; -#if !defined(WIN32) +#endif +#if DT_LNK != DT_UNKNOWN case DT_LNK: lde.type = LDOT_LINK; break; @@ -165,13 +205,14 @@ lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) case DT_REG: lde.type = LDOT_FILE; break; -#if !defined(WIN32) +#if DT_SOCK != DT_UNKNOWN case DT_SOCK: lde.type = LDOTT_SOCKET; break; #endif default: lde.type = LDOT_UNKNOWN; + lws_dir_via_stat(combo, l, namelist[i]->d_name, &lde); break; } #endif -- Gitee From d5cb0c6aa3cf36c50024282e1da3d0c6fb533661 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Apr 2020 11:17:37 +0100 Subject: [PATCH 0068/1062] async-dns: cope with larger resolv.conf Eg, systemd-resolved produces a huge comment at the start of its default resolv.conf. Buffer it into the pt_serv_buf to cope. --- lib/plat/unix/unix-resolv.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/plat/unix/unix-resolv.c b/lib/plat/unix/unix-resolv.c index 9765c2d4..f5877634 100644 --- a/lib/plat/unix/unix-resolv.c +++ b/lib/plat/unix/unix-resolv.c @@ -28,10 +28,12 @@ lws_async_dns_server_check_t lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) { lws_async_dns_server_check_t s = LADNS_CONF_SERVER_CHANGED; - char resolv[512], ads[48]; lws_sockaddr46 sa46t; lws_tokenize_t ts; int fd, n, ns = 0; + char ads[48], *r; + + r = (char *)context->pt[0].serv_buf; /* grab the first chunk of /etc/resolv.conf */ @@ -39,17 +41,17 @@ lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) if (fd < 0) return LADNS_CONF_SERVER_UNKNOWN; - n = read(fd, resolv, sizeof(resolv) - 1); + n = read(fd, r, context->pt_serv_buf_size - 1); close(fd); if (n < 0) return LADNS_CONF_SERVER_UNKNOWN; - resolv[n] = '\0'; - lws_tokenize_init(&ts, resolv, LWS_TOKENIZE_F_DOT_NONTERM | - LWS_TOKENIZE_F_NO_FLOATS | - LWS_TOKENIZE_F_NO_INTEGERS | - LWS_TOKENIZE_F_MINUS_NONTERM | - LWS_TOKENIZE_F_HASH_COMMENT); + r[n] = '\0'; + lws_tokenize_init(&ts, r, LWS_TOKENIZE_F_DOT_NONTERM | + LWS_TOKENIZE_F_NO_FLOATS | + LWS_TOKENIZE_F_NO_INTEGERS | + LWS_TOKENIZE_F_MINUS_NONTERM | + LWS_TOKENIZE_F_HASH_COMMENT); do { ts.e = lws_tokenize(&ts); if (ts.e != LWS_TOKZE_TOKEN) { -- Gitee From 6e4eac2b806bc40fc67487110d29c9b3ed3d284b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Apr 2020 12:46:49 +0100 Subject: [PATCH 0069/1062] http: client multipart: caulate remaining length correctly The current position is understood to be in *p, but for the remaining length calculation we are wrongly comparing to p... --- lib/roles/http/client/client-http.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 03af4f84..d4127939 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -1022,7 +1022,7 @@ lws_client_http_multipart(struct lws *wsi, const char *name, assert(wsi->http.multipart); if (!name) { - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "\xd\xa--%s--\xd\xa", wsi->http.multipart_boundary); @@ -1030,22 +1030,22 @@ lws_client_http_multipart(struct lws *wsi, const char *name, } if (wsi->client_subsequent_mime_part) - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "\xd\xa"); + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "\xd\xa"); wsi->client_subsequent_mime_part = 1; - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "--%s\xd\xa" + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "--%s\xd\xa" "Content-Disposition: form-data; " "name=\"%s\"", wsi->http.multipart_boundary, name); if (filename) - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "; filename=\"%s\"", filename); if (content_type) - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "\xd\xa" + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "\xd\xa" "Content-Type: %s", content_type); - *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, p), "\xd\xa\xd\xa"); + *p += lws_snprintf((char *)(*p), lws_ptr_diff(end, *p), "\xd\xa\xd\xa"); return *p == end; } -- Gitee From e4c59e3a91e41f516db49ded8e58993d66026cae Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Apr 2020 14:16:29 +0100 Subject: [PATCH 0070/1062] osx: mbedtls: SYSCALL and errno 35 is WANT_READ --- lib/tls/mbedtls/mbedtls-server.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/tls/mbedtls/mbedtls-server.c b/lib/tls/mbedtls/mbedtls-server.c index 2b698304..d7a93559 100644 --- a/lib/tls/mbedtls/mbedtls-server.c +++ b/lib/tls/mbedtls/mbedtls-server.c @@ -332,6 +332,11 @@ lws_tls_server_accept(struct lws *wsi) if (m == SSL_ERROR_SYSCALL && errno == 11) return LWS_SSL_CAPABLE_MORE_SERVICE_READ; +#if defined(__APPLE__) + if (m == SSL_ERROR_SYSCALL && errno == 35) + return LWS_SSL_CAPABLE_MORE_SERVICE_READ; +#endif + #if defined(WIN32) if (m == SSL_ERROR_SYSCALL && errno == 0) return LWS_SSL_CAPABLE_MORE_SERVICE_READ; -- Gitee From e3c6d9d6c1d5d07d7934e463ec71fecb4b9a4835 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Apr 2020 14:17:15 +0100 Subject: [PATCH 0071/1062] context creation: remove chance to create vhost twice --- lib/core/context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index 4c2a48e7..f7a8c907 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -862,9 +862,9 @@ lws_create_context(const struct lws_context_creation_info *info) lwsl_err("%s: policy set failed\n", __func__); goto bail; } - } else + } //else #endif - lws_create_vhost(context, info); + // lws_create_vhost(context, info); #endif lws_context_init_extensions(info, context); -- Gitee From a8ad5068e488437a86c99cacc112141d58a67995 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Apr 2020 18:49:59 +0100 Subject: [PATCH 0072/1062] windows: fix service for udp and pending tls delays UDP: call to recv() in there for unknown reasons was trashing udp delays: pending tls (where data is buffered and no pending POLLIN) was not reflected in forcing the wait to 0 properly. --- lib/plat/windows/windows-service.c | 138 +++++++++++++++-------------- 1 file changed, 72 insertions(+), 66 deletions(-) diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index 5a6fc1b8..f265877b 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -32,9 +32,9 @@ int _lws_plat_service_forced_tsi(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; - int m, n; + int m, n, r; - lws_service_flag_pending(context, tsi); + r = lws_service_flag_pending(context, tsi); /* any socket with events to service? */ for (n = 0; n < (int)pt->fds_count; n++) { @@ -51,7 +51,7 @@ _lws_plat_service_forced_tsi(struct lws_context *context, int tsi) lws_service_do_ripe_rxflow(pt); - return 0; + return r; } @@ -124,12 +124,6 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) i--; } - /* - * is there anybody with pending stuff that needs service forcing? - */ - if (!lws_service_adjust_timeout(context, 1, tsi)) - _lws_plat_service_forced_tsi(context, tsi); - /* * service pending callbacks and get maximum wait time */ @@ -145,6 +139,15 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) lws_pt_unlock(pt); } + if (_lws_plat_service_forced_tsi(context, tsi)) + timeout_us = 0; + + /* + * is there anybody with pending stuff that needs service forcing? + */ + if (!lws_service_adjust_timeout(context, 1, tsi)) + timeout_us = 0; + for (n = 0; n < (int)pt->fds_count; n++) WSAEventSelect(pt->fds[n].fd, pt->events, FD_READ | (!!(pt->fds[n].events & LWS_POLLOUT) * FD_WRITE) | @@ -155,70 +158,73 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) ev = WSAWaitForMultipleEvents(1, &pt->events, FALSE, (DWORD)(timeout_us / LWS_US_PER_MS), FALSE); - if (ev == WSA_WAIT_EVENT_0) { - EnterCriticalSection(&pt->interrupt_lock); - interrupt_requested = pt->interrupt_requested; - pt->interrupt_requested = 0; - LeaveCriticalSection(&pt->interrupt_lock); - if (interrupt_requested) { - lws_broadcast(pt, LWS_CALLBACK_EVENT_WAIT_CANCELLED, - NULL, 0); - return 0; - } + if (ev != WSA_WAIT_EVENT_0) + return 0; + + EnterCriticalSection(&pt->interrupt_lock); + interrupt_requested = pt->interrupt_requested; + pt->interrupt_requested = 0; + LeaveCriticalSection(&pt->interrupt_lock); + if (interrupt_requested) { + lws_broadcast(pt, LWS_CALLBACK_EVENT_WAIT_CANCELLED, + NULL, 0); + return 0; + } #if defined(LWS_WITH_TLS) - if (pt->context->tls_ops && - pt->context->tls_ops->fake_POLLIN_for_buffered) - pt->context->tls_ops->fake_POLLIN_for_buffered(pt); + if (pt->context->tls_ops && + pt->context->tls_ops->fake_POLLIN_for_buffered) + pt->context->tls_ops->fake_POLLIN_for_buffered(pt); #endif - for (eIdx = 0; eIdx < pt->fds_count; ++eIdx) { - unsigned int err; - - if (WSAEnumNetworkEvents(pt->fds[eIdx].fd, pt->events, - &networkevents) == SOCKET_ERROR) { - lwsl_err("WSAEnumNetworkEvents() failed " - "with error %d\n", LWS_ERRNO); - return -1; - } - - if (!networkevents.lNetworkEvents) - networkevents.lNetworkEvents = LWS_POLLOUT; - - pfd = &pt->fds[eIdx]; - pfd->revents = (short)networkevents.lNetworkEvents; - - err = networkevents.iErrorCode[FD_CONNECT_BIT]; - - if ((networkevents.lNetworkEvents & FD_CONNECT) && - err && err != LWS_EALREADY && - err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK && - err != WSAEINVAL) { - lwsl_debug("Unable to connect errno=%d\n", err); - pfd->revents |= LWS_POLLHUP; - } - - if (pfd->revents & LWS_POLLOUT) { - wsi = wsi_from_fd(context, pfd->fd); - if (wsi) - wsi->sock_send_blocking = 0; - } - /* if something closed, retry this slot */ - if (pfd->revents & LWS_POLLHUP) - --eIdx; - - if (pfd->revents) { - recv(pfd->fd, NULL, 0, 0); - lws_service_fd_tsi(context, pfd, tsi); - } + for (eIdx = 0; eIdx < pt->fds_count; ++eIdx) { + unsigned int err; + + if (WSAEnumNetworkEvents(pt->fds[eIdx].fd, pt->events, + &networkevents) == SOCKET_ERROR) { + lwsl_err("WSAEnumNetworkEvents() failed " + "with error %d\n", LWS_ERRNO); + return -1; } - return 0; - } + if (!networkevents.lNetworkEvents) + networkevents.lNetworkEvents = LWS_POLLOUT; + + pfd = &pt->fds[eIdx]; + pfd->revents = (short)networkevents.lNetworkEvents; - // if (ev == WSA_WAIT_TIMEOUT) { } - // if (ev == WSA_WAIT_FAILED) - // return 0; + err = networkevents.iErrorCode[FD_CONNECT_BIT]; + + if ((networkevents.lNetworkEvents & FD_CONNECT) && + err && err != LWS_EALREADY && + err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK && + err != WSAEINVAL) { + lwsl_debug("Unable to connect errno=%d\n", err); + pfd->revents |= LWS_POLLHUP; + } + + if (pfd->revents & LWS_POLLOUT) { + wsi = wsi_from_fd(context, pfd->fd); + if (wsi) + wsi->sock_send_blocking = 0; + } + /* if something closed, retry this slot */ + if (pfd->revents & LWS_POLLHUP) + --eIdx; + + if (pfd->revents) { + /* + * On windows is somehow necessary to "acknowledge" the + * POLLIN event, otherwise we never receive another one + * on the TCP connection. But it breaks UDP, so only + * do it on non-UDP. + */ + if (!wsi_from_fd(context, pfd->fd)->udp) + recv(pfd->fd, NULL, 0, 0); + + lws_service_fd_tsi(context, pfd, tsi); + } + } return 0; } -- Gitee From 8299bd4191a67994451476f45e4ccdac06553274 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Apr 2020 18:49:15 +0100 Subject: [PATCH 0073/1062] windows: async dns find DNS server using modern api --- lib/plat/windows/windows-resolv.c | 51 +++++++++---------------------- 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/lib/plat/windows/windows-resolv.c b/lib/plat/windows/windows-resolv.c index 541cc0ae..146db2c4 100644 --- a/lib/plat/windows/windows-resolv.c +++ b/lib/plat/windows/windows-resolv.c @@ -1,16 +1,4 @@ /* - * Adapted from tadns 1.1, from http://adns.sourceforge.net/ - * Original license --> - * - * Copyright (c) 2004-2005 Sergey Lyubka - * - * "THE BEER-WARE LICENSE" (Revision 42): - * Sergey Lyubka wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. - * - * Integrated into lws, largely rewritten and relicensed (as allowed above) - * * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010 - 2019 Andy Green @@ -35,39 +23,28 @@ */ #include "private-lib-core.h" +#include lws_async_dns_server_check_t lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) { - char subkey[512], value[128], *key = - "SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"; - HKEY hKey, hSub; - LONG err; - int i, n; + unsigned long ul; + FIXED_INFO fi; + int n; - if ((err = RegOpenKey(HKEY_LOCAL_MACHINE, key, &hKey)) != ERROR_SUCCESS) { - lwsl_err("%s: cannot open reg key %s: %d\n", __func__, key, err); + ul = sizeof(fi); + if (GetNetworkParams(&fi, &ul) != NO_ERROR) { + lwsl_err("%s: can't get dns servers\n", __func__); - return 1; + return LADNS_CONF_SERVER_UNKNOWN; } - for (i = 0; RegEnumKey(hKey, i, subkey, sizeof(subkey)) == ERROR_SUCCESS; i++) { - DWORD type, len = sizeof(value); - - if (RegOpenKey(hKey, subkey, &hSub) == ERROR_SUCCESS && - (RegQueryValueEx(hSub, "NameServer", 0, - &type, value, &len) == ERROR_SUCCESS || - RegQueryValueEx(hSub, "DhcpNameServer", 0, - &type, value, &len) == ERROR_SUCCESS)) { - n = lws_sa46_parse_numeric_address(value, sa46); - RegCloseKey(hSub); - RegCloseKey(hKey); - return n == 0 ? LADNS_CONF_SERVER_CHANGED : - LADNS_CONF_SERVER_UNKNOWN; - } - } - RegCloseKey(hKey); + lwsl_info("%s: trying %s\n", __func__, + fi.DnsServerList.IpAddress.String); + n = lws_sa46_parse_numeric_address( + fi.DnsServerList.IpAddress.String, sa46); - return LADNS_CONF_SERVER_UNKNOWN; + return n == 0 ? LADNS_CONF_SERVER_CHANGED : + LADNS_CONF_SERVER_UNKNOWN; } -- Gitee From ef294c979f74d77e13d57b757698497708017197 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 17 Apr 2020 05:25:32 +0100 Subject: [PATCH 0074/1062] ntpclient: make retries less sparse --- lib/system/ntpclient/ntpclient.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/system/ntpclient/ntpclient.c b/lib/system/ntpclient/ntpclient.c index 2316fddd..4474051a 100644 --- a/lib/system/ntpclient/ntpclient.c +++ b/lib/system/ntpclient/ntpclient.c @@ -50,7 +50,8 @@ struct vhd_ntpc { * and the transaction forever. */ -static const uint32_t botable[] = { 1000, 1250, 1500, 2000, 3000 }; +static const uint32_t botable[] = + { 300, 500, 650, 800, 800, 900, 1000, 1100, 1500 }; static const lws_retry_bo_t bo = { botable, LWS_ARRAY_SIZE(botable), LWS_RETRY_CONCEAL_ALWAYS, 0, 0, 20 }; -- Gitee From dacae3a951d20c0c46397d62fbd967a7243423da Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 17 Apr 2020 07:05:13 +0100 Subject: [PATCH 0075/1062] osx: do not connect udp Unlike linux or windows, blanket rejects sendto() afterwards with EISCONN --- lib/core-net/adopt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 216b3702..616449dd 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -539,7 +539,7 @@ lws_create_adopt_udp2(struct lws *wsi, const char *ads, } if (!wsi->do_bind && !wsi->pf_packet) { - +#if !defined(__APPLE__) if (connect(sock.sockfd, wsi->dns_results_next->ai_addr, (socklen_t)wsi->dns_results_next->ai_addrlen) == -1) { lwsl_err("%s: conn fd %d fam %d %s:%u failed " @@ -552,7 +552,7 @@ lws_create_adopt_udp2(struct lws *wsi, const char *ads, compatible_close(sock.sockfd); goto resume; } - +#endif memcpy(&wsi->udp->sa, wsi->dns_results_next->ai_addr, wsi->dns_results_next->ai_addrlen); wsi->udp->salen = (socklen_t)wsi->dns_results_next->ai_addrlen; -- Gitee From 7399f82959e2fa20629e6982088b59786d800c1a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 19 Apr 2020 06:15:02 +0100 Subject: [PATCH 0076/1062] spawn: CLOEXEC the wsi fds earlier --- lib/plat/unix/unix-spawn.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/plat/unix/unix-spawn.c b/lib/plat/unix/unix-spawn.c index fdc61cd2..cbfc11d3 100644 --- a/lib/plat/unix/unix-spawn.c +++ b/lib/plat/unix/unix-spawn.c @@ -329,13 +329,14 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) lsp->stdwsi[n]->opaque_user_data = i->opaque; lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n", __func__, - lsp->stdwsi[n], n, lsp->pipe_fds[n][!!(n == 0)], - lsp->pipe_fds[n][!(n == 0)]); + lsp->stdwsi[n], n, lsp->pipe_fds[n][n == 0], + lsp->pipe_fds[n][n != 0]); /* read side is 0, stdin we want the write side, others read */ - lsp->stdwsi[n]->desc.sockfd = lsp->pipe_fds[n][!!(n == 0)]; - if (fcntl(lsp->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK) < 0) { + lws_plat_apply_FD_CLOEXEC(lsp->pipe_fds[n][n == 0]); + lsp->stdwsi[n]->desc.sockfd = lsp->pipe_fds[n][n == 0]; + if (fcntl(lsp->pipe_fds[n][n == 0], F_SETFL, O_NONBLOCK) < 0) { lwsl_err("%s: setting NONBLOCK failed\n", __func__); goto bail2; } @@ -389,27 +390,27 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) if (lsp->child_pid) { - /* we are the parent process */ - - lwsl_info("%s: lsp %p spawned PID %d\n", __func__, lsp, - lsp->child_pid); - - lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout, - i->timeout_us ? i->timeout_us : - 300 * LWS_US_PER_SEC); - /* + * We are the parent process + * * close: stdin:r, stdout:w, stderr:w * hide from other forks: stdin:w, stdout:r, stderr:r */ for (n = 0; n < 3; n++) { - lws_plat_apply_FD_CLOEXEC(lsp->pipe_fds[n][!!(n == 0)]); - close(lsp->pipe_fds[n][!(n == 0)]); + /* these guys don't have any wsi footprint */ + close(lsp->pipe_fds[n][n != 0]); } lsp->pipes_alive = 3; lsp->created = lws_now_usecs(); + lwsl_info("%s: lsp %p spawned PID %d\n", __func__, lsp, + lsp->child_pid); + + lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout, + i->timeout_us ? i->timeout_us : + 300 * LWS_US_PER_SEC); + if (i->owner) lws_dll2_add_head(&lsp->dll, i->owner); @@ -444,7 +445,7 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) lwsl_notice("%s: Failed to cd to %s\n", __func__, wd); for (m = 0; m < 3; m++) { - if (dup2(lsp->pipe_fds[m][!(m == 0)], m) < 0) { + if (dup2(lsp->pipe_fds[m][m != 0], m) < 0) { lwsl_err("%s: stdin dup2 failed\n", __func__); goto bail3; } @@ -457,8 +458,7 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) * identity during this pre-exec() time */ #if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) - close(lsp->pipe_fds[m][!(m == 0)]); - close(lsp->pipe_fds[m][!!(m == 0)]); + close(lsp->pipe_fds[m][m != 0]); #endif } -- Gitee From a57e62d502e5880d41d4241a1aa780e10f9c756d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 19 Apr 2020 08:43:01 +0100 Subject: [PATCH 0077/1062] ctest: fixes-and-changes --- include/libwebsockets/lws-threadpool.h | 3 ++ lib/core-net/adopt.c | 2 +- lib/core-net/close.c | 3 ++ lib/core-net/connect.c | 2 +- lib/core/context.c | 3 +- lib/core/private-lib-core.h | 2 +- lib/misc/threadpool/threadpool.c | 11 ++++-- lib/roles/h1/ops-h1.c | 3 +- lib/roles/http/client/client-handshake.c | 15 ++++---- lib/roles/listen/ops-listen.c | 2 +- lib/roles/raw-skt/ops-raw-skt.c | 3 +- lib/system/async-dns/async-dns.c | 4 +-- lib/tls/private-network.h | 3 +- lib/tls/tls-server.c | 44 +++++++++++++++++++----- 14 files changed, 74 insertions(+), 26 deletions(-) diff --git a/include/libwebsockets/lws-threadpool.h b/include/libwebsockets/lws-threadpool.h index a12c92d3..144c2557 100644 --- a/include/libwebsockets/lws-threadpool.h +++ b/include/libwebsockets/lws-threadpool.h @@ -219,6 +219,9 @@ lws_threadpool_task_status_wsi(struct lws *wsi, LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status lws_threadpool_task_status(struct lws_threadpool_task *task, void **user); +LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status +lws_threadpool_task_status_noreap(struct lws_threadpool_task *task); + /** * lws_threadpool_task_sync() - Indicate to a stalled task it may continue * diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 616449dd..d9f87a7f 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -260,7 +260,7 @@ lws_adopt_descriptor_vhost2(struct lws *new_wsi, lws_adoption_type type, } #if defined(LWS_WITH_SERVER) else - if (lws_server_socket_service_ssl(new_wsi, fd.sockfd)) { + if (lws_server_socket_service_ssl(new_wsi, fd.sockfd, 0)) { #if defined(LWS_WITH_ACCESS_LOG) lwsl_notice("%s: fail ssl negotiation: %s\n", __func__, new_wsi->simple_ip); diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 062f410c..f579733e 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -454,6 +454,9 @@ just_kill_connection: !wsi->already_did_cce && wsi->protocol) { static const char _reason[] = "closed before established"; + lwsl_notice("%s: closing in unestablished state 0x%x\n", + __func__, lwsi_state(wsi)); + lws_inform_client_conn_fail(wsi, (void *)_reason, sizeof(_reason)); } diff --git a/lib/core-net/connect.c b/lib/core-net/connect.c index a63bab30..96806f14 100644 --- a/lib/core-net/connect.c +++ b/lib/core-net/connect.c @@ -173,7 +173,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) if (p) lws_bind_protocol(wsi, p, __func__); else - lwsl_err("%s: unknown protocol %s\n", __func__, local); + lwsl_info("%s: unknown protocol %s\n", __func__, local); lwsl_info("%s: wsi %p: %s %s entry\n", __func__, wsi, wsi->role_ops->name, diff --git a/lib/core/context.c b/lib/core/context.c index f7a8c907..a264e18f 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -306,7 +306,8 @@ lws_create_context(const struct lws_context_creation_info *info) context->ss_proxy_bind = info->ss_proxy_bind; context->ss_proxy_port = info->ss_proxy_port; context->ss_proxy_address = info->ss_proxy_address; - lwsl_notice("%s: using ss proxy bind '%s', port %d, ads '%s'\n", + if (context->ss_proxy_bind && context->ss_proxy_address) + lwsl_notice("%s: using ss proxy bind '%s', port %d, ads '%s'\n", __func__, context->ss_proxy_bind, context->ss_proxy_port, context->ss_proxy_address); #endif diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 49ea3f6b..6335a89d 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -589,7 +589,7 @@ LWS_EXTERN void lwsl_emit_stderr(int level, const char *line); #define lws_ssl_capable_read lws_ssl_capable_read_no_ssl #define lws_ssl_capable_write lws_ssl_capable_write_no_ssl #define lws_ssl_pending lws_ssl_pending_no_ssl - #define lws_server_socket_service_ssl(_b, _c) (0) + #define lws_server_socket_service_ssl(_b, _c, _d) (0) #define lws_ssl_close(_a) (0) #define lws_ssl_context_destroy(_a) #define lws_ssl_SSL_CTX_destroy(_a) diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index 646c5f2f..b1e56fd4 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -757,9 +757,8 @@ lws_threadpool_finish(struct lws_threadpool *tp) c = &task->task_queue_next; } - pthread_mutex_unlock(&tp->lock); /* -------------------- tpool unlock */ - pthread_cond_broadcast(&tp->wake_idle); + pthread_mutex_unlock(&tp->lock); /* -------------------- tpool unlock */ } void @@ -1067,6 +1066,12 @@ lws_threadpool_task_status(struct lws_threadpool_task *task, void **user) return status; } +enum lws_threadpool_task_status +lws_threadpool_task_status_noreap(struct lws_threadpool_task *task) +{ + return task->status; +} + enum lws_threadpool_task_status lws_threadpool_task_status_wsi(struct lws *wsi, struct lws_threadpool_task **_task, void **user) @@ -1098,7 +1103,9 @@ lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop) if (stop) state_transition(task, LWS_TP_STATUS_STOPPING); + pthread_mutex_lock(&task->tp->lock); pthread_cond_signal(&task->wake_idle); + pthread_mutex_unlock(&task->tp->lock); } int diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index 8e100808..2b273c83 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -643,7 +643,8 @@ rops_handle_POLLIN_h1(struct lws_context_per_thread *pt, struct lws *wsi, return n; if (lwsi_state(wsi) != LRS_SSL_INIT) if (lws_server_socket_service_ssl(wsi, - LWS_SOCK_INVALID)) + LWS_SOCK_INVALID, + !!(pollfd->revents & LWS_POLLIN))) return LWS_HPI_RET_PLEASE_CLOSE_ME; return LWS_HPI_RET_HANDLED; diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 97f3a6b2..6a540f84 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -204,8 +204,6 @@ send_hs: if (lwsi_state(wsi) == LRS_WAITING_CONNECT && (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { - - /* we can retry this... just cook the SSL BIO the first time */ switch (lws_client_create_tls(wsi, &cce, 1)) { @@ -217,13 +215,18 @@ send_hs: goto failed; } + /* + * We succeeded to negotiate a new client tls tunnel. + * If it's h2 alpn, we have arranged to send to h2 + * prefix and set our state to + * LRS_H2_WAITING_TO_SEND_HEADERS already. + */ - - lwsl_notice("%s: wsi %p: st 0x%x\n", + lwsl_notice("%s: wsi %p: tls established st 0x%x\n", __func__, wsi, lwsi_state(wsi)); - if (lwsi_state(wsi) == LRS_WAITING_CONNECT) - lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); + if (lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS) + lwsi_set_state(wsi, LRS_WAITING_SSL); lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, wsi->context->timeout_secs); diff --git a/lib/roles/listen/ops-listen.c b/lib/roles/listen/ops-listen.c index c49159f1..3cb2e998 100644 --- a/lib/roles/listen/ops-listen.c +++ b/lib/roles/listen/ops-listen.c @@ -153,7 +153,7 @@ rops_handle_POLLIN_listen(struct lws_context_per_thread *pt, struct lws *wsi, return LWS_HPI_RET_WSI_ALREADY_DIED; } /* - if (lws_server_socket_service_ssl(cwsi, accept_fd)) { + if (lws_server_socket_service_ssl(cwsi, accept_fd, 1)) { lws_close_free_wsi(cwsi, LWS_CLOSE_STATUS_NOSTATUS, "listen svc fail"); return LWS_HPI_RET_WSI_ALREADY_DIED; diff --git a/lib/roles/raw-skt/ops-raw-skt.c b/lib/roles/raw-skt/ops-raw-skt.c index 9cdfe2f9..423063dd 100644 --- a/lib/roles/raw-skt/ops-raw-skt.c +++ b/lib/roles/raw-skt/ops-raw-skt.c @@ -60,7 +60,8 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, if (lwsi_state(wsi) != LRS_SSL_INIT) if (lws_server_socket_service_ssl(wsi, - LWS_SOCK_INVALID)) + LWS_SOCK_INVALID, + !!(pollfd->revents & pollfd->events & LWS_POLLIN))) return LWS_HPI_RET_PLEASE_CLOSE_ME; return LWS_HPI_RET_HANDLED; diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index c1332d14..88deb4be 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -214,8 +214,8 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) n = lws_ptr_diff(p, pkt + LWS_PRE); m = lws_write(wsi, pkt + LWS_PRE, n, 0); if (m != n) { - lwsl_notice("%s: dns write failed %d %d\n", __func__, - m, n); + lwsl_notice("%s: dns write failed %d %d errno %d\n", __func__, + m, n, errno); goto qfail; } diff --git a/lib/tls/private-network.h b/lib/tls/private-network.h index cf328763..88474fc1 100644 --- a/lib/tls/private-network.h +++ b/lib/tls/private-network.h @@ -87,7 +87,8 @@ lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len); LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_ssl_pending(struct lws *wsi); LWS_EXTERN int LWS_WARN_UNUSED_RESULT -lws_server_socket_service_ssl(struct lws *new_wsi, lws_sockfd_type accept_fd); +lws_server_socket_service_ssl(struct lws *new_wsi, lws_sockfd_type accept_fd, + char is_pollin); LWS_EXTERN int lws_ssl_close(struct lws *wsi); LWS_EXTERN void diff --git a/lib/tls/tls-server.c b/lib/tls/tls-server.c index 43c930f0..8b1ae6f1 100644 --- a/lib/tls/tls-server.c +++ b/lib/tls/tls-server.c @@ -123,7 +123,7 @@ lws_context_init_server_ssl(const struct lws_context_creation_info *info, #endif int -lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) +lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd, char from_pollin) { struct lws_context *context = wsi->context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; @@ -141,10 +141,13 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) if (accept_fd == LWS_SOCK_INVALID) assert(0); - if (lws_tls_restrict_borrow(context)) + if (lws_tls_restrict_borrow(context)) { + lwsl_err("%s: failed on ssl restriction\n", __func__); return 1; + } if (lws_tls_server_new_nonblocking(wsi, accept_fd)) { + lwsl_err("%s: failed on lws_tls_server_new_nonblocking\n", __func__); if (accept_fd != LWS_SOCK_INVALID) compatible_close(accept_fd); lws_tls_restrict_return(context); @@ -183,6 +186,10 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) } if (wsi->vhost->tls.allow_non_ssl_on_ssl_port && !wsi->skip_fallback) { + /* + * We came here by POLLIN, so there is supposed to be + * something to read... + */ n = recv(wsi->desc.sockfd, (char *)pt->serv_buf, context->pt_serv_buf_size, MSG_PEEK); @@ -263,13 +270,32 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) } if (!n) { /* - * connection is gone, fail out + * POLLIN but nothing to read is supposed to + * mean the connection is gone, we should + * fail out... + * */ - lwsl_debug("PEEKed 0\n"); + lwsl_warn("%s: PEEKed 0 (from_pollin %d)\n", + __func__, from_pollin); + if (!from_pollin) + /* + * If this wasn't actually info from a + * pollin let it go around again until + * either data came or we still get told + * zero length peek AND POLLIN + */ + goto punt; + + /* + * treat as remote closed + */ + goto fail; } if (n < 0 && (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK)) { + +punt: /* * well, we get no way to know ssl or not * so go around again waiting for something @@ -277,7 +303,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) * connection. */ if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { - lwsl_info("%s: change_pollfd failed\n", + lwsl_err("%s: change_pollfd failed\n", __func__); return -1; } @@ -303,8 +329,8 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) break; case LWS_SSL_CAPABLE_ERROR: lws_stats_bump(pt, LWSSTATS_C_SSL_CONNECTIONS_FAILED, 1); - lwsl_info("SSL_accept failed socket %u: %d\n", - wsi->desc.sockfd, n); + lwsl_warn("%s: SSL_accept failed socket %u: %d\n", + __func__, wsi->desc.sockfd, n); wsi->socket_is_permanently_unusable = 1; goto fail; @@ -349,8 +375,10 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) context->timeout_secs); lwsi_set_state(wsi, LRS_ESTABLISHED); - if (lws_tls_server_conn_alpn(wsi)) + if (lws_tls_server_conn_alpn(wsi)) { + lwsl_warn("%s: fail on alpn\n", __func__); goto fail; + } lwsl_debug("accepted new SSL conn\n"); break; -- Gitee From 40803b3e0dd89d24d82fe8a2c7bb367ea7411cd1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 20 Apr 2020 06:35:08 +0100 Subject: [PATCH 0078/1062] lws_struct: sqlite open option for create or not --- include/libwebsockets/lws-struct.h | 2 +- lib/misc/lws-struct-sqlite.c | 11 ++++++----- .../api-tests/api-test-lws_struct_sqlite/main.c | 2 +- plugins/generic-sessions/protocol_generic_sessions.c | 2 +- plugins/generic-sessions/protocol_lws_messageboard.c | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/libwebsockets/lws-struct.h b/include/libwebsockets/lws-struct.h index 3091feae..fe396b26 100644 --- a/include/libwebsockets/lws-struct.h +++ b/include/libwebsockets/lws-struct.h @@ -258,7 +258,7 @@ lws_struct_sq3_create_table(sqlite3 *pdb, const lws_struct_map_t *schema); LWS_VISIBLE LWS_EXTERN int lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, - sqlite3 **pdb); + char create_if_missing, sqlite3 **pdb); LWS_VISIBLE LWS_EXTERN int lws_struct_sq3_close(sqlite3 **pdb); diff --git a/lib/misc/lws-struct-sqlite.c b/lib/misc/lws-struct-sqlite.c index fbcb5ea9..23a040a1 100644 --- a/lib/misc/lws-struct-sqlite.c +++ b/lib/misc/lws-struct-sqlite.c @@ -207,7 +207,7 @@ lws_struct_sq3_deserialize(sqlite3 *pdb, const char *filter, const char *order, _limit < 0 ? "desc " : "", limit); if (sqlite3_exec(pdb, s, lws_struct_sq3_deser_cb, &a, NULL) != SQLITE_OK) { - lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb)); + lwsl_err("%s: %s: fail %s\n", __func__, sqlite3_errmsg(pdb), s); lwsac_free(&a.ac); return -1; } @@ -443,14 +443,15 @@ lws_struct_sq3_create_table(sqlite3 *pdb, const lws_struct_map_t *schema) int lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, - sqlite3 **pdb) + char create_if_missing, sqlite3 **pdb) { #if !defined(WIN32) int uid = 0, gid = 0; #endif if (sqlite3_open_v2(sqlite3_path, pdb, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, + SQLITE_OPEN_READWRITE | + (create_if_missing ? SQLITE_OPEN_CREATE : 0), NULL) != SQLITE_OK) { lwsl_err("%s: Unable to open db %s: %s\n", __func__, sqlite3_path, sqlite3_errmsg(*pdb)); @@ -464,10 +465,10 @@ lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, chown(sqlite3_path, uid, gid); chmod(sqlite3_path, 0600); - lwsl_notice("%s: created %s owned by %u:%u mode 0600\n", __func__, + lwsl_debug("%s: created %s owned by %u:%u mode 0600\n", __func__, sqlite3_path, (unsigned int)uid, (unsigned int)gid); #else - lwsl_notice("%s: created %s\n", __func__, sqlite3_path); + lwsl_debug("%s: created %s\n", __func__, sqlite3_path); #endif sqlite3_extended_result_codes(*pdb, 1); diff --git a/minimal-examples/api-tests/api-test-lws_struct_sqlite/main.c b/minimal-examples/api-tests/api-test-lws_struct_sqlite/main.c index b332d6e2..ec1ae80c 100644 --- a/minimal-examples/api-tests/api-test-lws_struct_sqlite/main.c +++ b/minimal-examples/api-tests/api-test-lws_struct_sqlite/main.c @@ -97,7 +97,7 @@ int main(int argc, const char **argv) unlink("_lws_apitest.sq3"); - if (lws_struct_sq3_open(context, "_lws_apitest.sq3", &db)) { + if (lws_struct_sq3_open(context, "_lws_apitest.sq3", 1, &db)) { lwsl_err("%s: failed to open table\n", __func__); goto bail; } diff --git a/plugins/generic-sessions/protocol_generic_sessions.c b/plugins/generic-sessions/protocol_generic_sessions.c index 5d0bb651..7622187d 100644 --- a/plugins/generic-sessions/protocol_generic_sessions.c +++ b/plugins/generic-sessions/protocol_generic_sessions.c @@ -228,7 +228,7 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason, } if (lws_struct_sq3_open(lws_get_context(wsi), - vhd->session_db, &vhd->pdb)) { + vhd->session_db, 1, &vhd->pdb)) { lwsl_err("Unable to open session db %s: %s\n", vhd->session_db, sqlite3_errmsg(vhd->pdb)); diff --git a/plugins/generic-sessions/protocol_lws_messageboard.c b/plugins/generic-sessions/protocol_lws_messageboard.c index fce51631..94c01ab8 100644 --- a/plugins/generic-sessions/protocol_lws_messageboard.c +++ b/plugins/generic-sessions/protocol_lws_messageboard.c @@ -193,7 +193,7 @@ callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason, } if (lws_struct_sq3_open(lws_get_context(wsi), - vhd->message_db, &vhd->pdb)) { + vhd->message_db, 1, &vhd->pdb)) { lwsl_err("Unable to open message db %s: %s\n", vhd->message_db, sqlite3_errmsg(vhd->pdb)); -- Gitee From 90aa78f0a82e2fbe853889cfba1aef6720659e9a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 20 Apr 2020 18:02:41 +0100 Subject: [PATCH 0079/1062] docs: add notes on cmake --- READMEs/README.cmake.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 READMEs/README.cmake.md diff --git a/READMEs/README.cmake.md b/READMEs/README.cmake.md new file mode 100644 index 00000000..127282a5 --- /dev/null +++ b/READMEs/README.cmake.md @@ -0,0 +1,41 @@ +# Tips about CMake + +## Don't be afraid to nuke your build dir + +CMake likes to cache options and other things in the build dir... if you stop +asserting the state of something like `-DMY_OPTION=1`, then the last way it was +set it cached. On order to keep track of what you have set and not set, it's +very advisable to explicitly keep all your options and set them all on one cmake +line. + +Then, when you meet a situation you changed something but somehow cmake is +sticking with what it knew before, you can fearlessly delete your build dir +and create a new one with your explicit config. + +On Linux, it's usually enough to delete `CMakeCache.txt` to trigger it to config +from the start again, but on, eg, windows, it isn't, for whatever reason it +literally needs the build dir removing. + +## CMake presence tests that fail + +Lws makes use of various CMake features to figure out what apis your libraries +offer, eg, OpenSSL has many different apis based on version, lws knows how to +work around most of the changes, but to do it it must find out what apis are +available first on your build environment. + +CMake basically builds little throwaway test programs using each api in turn, and +if it builds, it understands that the api was available and sets a preprocessor +symbol that's available in the main build accordingly. Then we can do `#if xxx` +to figure out if we can use `xxx` or need to do a workaround at build-time. + +This works very well, but unfortunately if the program didn't build, there are +many possible ways for the build to break even if the api being tested is +really available... for example, some library in your toolchain isn't being +linked for the throwaway test program. + +When this happens, cmake indicates that apis that must be available are not available... +CMake keeps a log of what happened with the failed test programs in +`./build/CMakeFiles/CMakeError.log`. This is appeneded to, so the best way is blow +away the build dir and reconfig a new one from scratch, and go look in there to +find out what the compiler or linker was complaining about. + -- Gitee From c42442652310a84eb4f48a3808bd056e4a559cf9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 21 Apr 2020 03:48:00 +0100 Subject: [PATCH 0080/1062] test-server: bump generated selsigned cert to 2048 bits On Ubuntu 20.04 Focal, openssl is configured by default to reject the old 1024-bit keys --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e2dfbf6..500aa260 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2318,9 +2318,9 @@ if (GENCERTS) if (WIN32) if (MINGW) - message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -subj \"/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost\" -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") + message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -subj \"/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost\" -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") execute_process( - COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -subj "/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost" -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" + COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -subj "/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost" -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" RESULT_VARIABLE OPENSSL_RETURN_CODE) else() file(WRITE "${PROJECT_BINARY_DIR}/openssl_input.txt" @@ -2335,11 +2335,11 @@ if (GENCERTS) # The "type" command is a bit picky with paths. file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/openssl_input.txt" OPENSSL_INPUT_WIN_PATH) message("OPENSSL_INPUT_WIN_PATH = ${OPENSSL_INPUT_WIN_PATH}") - message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") + message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") execute_process( COMMAND cmd /c type "${OPENSSL_INPUT_WIN_PATH}" - COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" + COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" RESULT_VARIABLE OPENSSL_RETURN_CODE OUTPUT_QUIET ERROR_QUIET) @@ -2356,7 +2356,7 @@ if (GENCERTS) execute_process( COMMAND printf "GB\\nErewhon\\nAll around\\nlibwebsockets-test\\n\\nlocalhost\\nnone@invalid.org\\n" COMMAND "${OPENSSL_EXECUTABLE}" - req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" + req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" RESULT_VARIABLE OPENSSL_RETURN_CODE # OUTPUT_QUIET ERROR_QUIET ) -- Gitee From aa0e94ca5d15618b88df272ff4b24124ba3a6d30 Mon Sep 17 00:00:00 2001 From: Valentin B Date: Tue, 21 Apr 2020 01:33:33 +0200 Subject: [PATCH 0081/1062] CMake: Silence CMP0048 warnings When libwebsockets is included as a subdirectory in other projects that rely on a minimum CMake version of 3.x, a CMP0048 policy warning will be raised due to the project not specifying a version in the project call. This patch silences the warning by explicitly setting the policy within libwebsockets to NEW if it has already been forwarded as such, without any further impact on the behavior of CMake. --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 500aa260..ed20162b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,9 @@ cmake_minimum_required(VERSION 2.8.9) +if(POLICY CMP0048) + cmake_policy(SET CMP0048 NEW) +endif() + # General Advice # # For selecting between DEBUG / RELEASE, use -DCMAKE_BUILD_TYPE=DEBUG or =RELEASE -- Gitee From beb49292d4fa52dac73561a1ebc4ee9971e74e94 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 21 Apr 2020 19:49:58 +0100 Subject: [PATCH 0082/1062] client: fix bad state after early tls connection If we are slow and we can complete the tls connection quickly, if we want to send a hs we must use H1C...HANDSHAKE2 now we have the tls negotiation done. --- lib/roles/http/client/client-handshake.c | 25 ++++++++++++++++-------- lib/roles/http/client/client-http.c | 13 ++++++------ lib/roles/http/private-lib-roles-http.h | 6 ++++++ 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 6a540f84..0f5d83b3 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -203,13 +203,19 @@ send_hs: if (lwsi_state(wsi) == LRS_WAITING_CONNECT && (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { + int result; - /* we can retry this... just cook the SSL BIO the first time */ + /* + * We can retry this... just cook the SSL BIO + * the first time + */ - switch (lws_client_create_tls(wsi, &cce, 1)) { - case 0: + result = lws_client_create_tls(wsi, &cce, 1); + lwsl_debug("%s: create_tls said %d\n", __func__, result); + switch (result) { + case CCTLS_RETURN_DONE: break; - case 1: + case CCTLS_RETURN_RETRY: return wsi; default: goto failed; @@ -226,12 +232,11 @@ send_hs: __func__, wsi, lwsi_state(wsi)); if (lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS) - lwsi_set_state(wsi, LRS_WAITING_SSL); + lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, wsi->context->timeout_secs); - //if () - return wsi; + goto provoke_service; } #endif @@ -310,7 +315,9 @@ send_hs: * and won't until many retries from main loop. To stop that * becoming endless, cover with a timeout. */ - +#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS) +provoke_service: +#endif lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, wsi->context->timeout_secs); @@ -732,6 +739,7 @@ conn_good: wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE, wsi->user_space, NULL, 0); + lwsl_debug("%s: going into connect_4\n", __func__); return lws_client_connect_4_established(wsi, NULL, plen); oom4: @@ -853,6 +861,7 @@ lws_client_connect_2_dnsreq(struct lws *wsi) return wsi; case ACTIVE_CONNS_QUEUED: + lwsl_debug("%s: ACTIVE_CONNS_QUEUED st 0x%x: \n", __func__, lwsi_state(wsi)); if (lwsi_state(wsi) == LRS_UNCONNECTED) { if (lwsi_role_h2(w)) lwsi_set_state(wsi, LRS_H2_WAITING_TO_SEND_HEADERS); diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index d4127939..2fae4117 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -37,13 +37,13 @@ lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) if (!wsi->tls.ssl) { if (lws_ssl_client_bio_create(wsi) < 0) { *pcce = "bio_create failed"; - return -1; + return CCTLS_RETURN_ERROR; } if (!wsi->transaction_from_pipeline_queue && lws_tls_restrict_borrow(wsi->context)) { *pcce = "tls restriction limit"; - return -1; + return CCTLS_RETURN_ERROR; } } @@ -51,11 +51,12 @@ lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) return 0; n = lws_ssl_client_connect1(wsi); + lwsl_debug("%s: lws_ssl_client_connect1: %d\n", __func__, n); if (!n) - return 1; /* caller should return 0 */ + return CCTLS_RETURN_RETRY; /* caller should return 0 */ if (n < 0) { *pcce = "lws_ssl_client_connect1 failed"; - return -1; + return CCTLS_RETURN_ERROR; } } else wsi->tls.ssl = NULL; @@ -76,12 +77,12 @@ lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) /* send the H2 preface to legitimize the connection */ if (lws_h2_issue_preface(wsi)) { *pcce = "error sending h2 preface"; - return -1; + return CCTLS_RETURN_ERROR; } } #endif - return 0; /* OK */ + return CCTLS_RETURN_DONE; /* OK */ } #endif diff --git a/lib/roles/http/private-lib-roles-http.h b/lib/roles/http/private-lib-roles-http.h index 2bf43fe0..0d9812da 100644 --- a/lib/roles/http/private-lib-roles-http.h +++ b/lib/roles/http/private-lib-roles-http.h @@ -327,5 +327,11 @@ lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul); uint8_t * lws_http_multipart_headers(struct lws *wsi, uint8_t *p); +enum { + CCTLS_RETURN_ERROR = -1, + CCTLS_RETURN_DONE = 0, + CCTLS_RETURN_RETRY = 1, +}; + int lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1); -- Gitee From d9f793ae12e24c5205f86ea3359c31d07dcd5374 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 22 Apr 2020 06:32:15 +0100 Subject: [PATCH 0083/1062] logs: allow giving log bitfields from cmake to force build or exclusion By default this doesn't change any existing logging behaviour at all. But it allows you to define cmake options to force or force-disable the build of individual log levels using new cmake option bitfields LWS_LOGGING_BITFIELD_SET and LWS_LOGGING_BITFIELD_CLEAR. Eg, -DLWS_LOGGING_BITFIELD_SET="(LLL_INFO)" can force INFO log level built even in release mode. -DLWS_LOGGING_BITFIELD_CLEAR="(LLL_NOTICE)" will likewise remove NOTICE logging from the build regardless of DEBUG or RELEASE mode. --- CMakeLists.txt | 4 +- cmake/lws_config.h.in | 2 + include/libwebsockets/lws-logs.h | 153 ++++++++++++++++++++++--------- lib/core-net/pollfd.c | 2 +- lib/core-net/state.c | 16 ++-- lib/core-net/wsi.c | 4 +- lib/core/context.c | 2 + lib/core/lws_dll2.c | 2 + lib/misc/lwsac/lwsac.c | 2 +- lib/tls/openssl/openssl-client.c | 6 +- 10 files changed, 137 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed20162b..0e8867bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,7 +140,9 @@ else() option(LWS_WITH_DIR "Directory scanning api support" ON) option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" ON) endif() -option(LWS_WITH_NO_LOGS "Disable all logging from being compiled in" OFF) +option(LWS_WITH_NO_LOGS "Disable all logging other than _err and _user from being compiled in" OFF) +set(LWS_LOGGING_BITFIELD_SET 0 CACHE STRING "Bitfield describing which log levels to force included into the build") +set(LWS_LOGGING_BITFIELD_CLEAR 0 CACHE STRING "Bitfield describing which log levels to force removed from the build") option(LWS_LOGS_TIMESTAMP "Timestamp at start of logs" ON) option(LWS_AVOID_SIGPIPE_IGN "Android 7+ reportedly needs this" OFF) option(LWS_WITH_STATS "Keep statistics of lws internal operations" OFF) diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index de5e2f67..e2b8cb07 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -84,6 +84,8 @@ #cmakedefine LWS_HAVE_X509_get_key_usage #cmakedefine LWS_HAVE_X509_VERIFY_PARAM_set1_host #cmakedefine LWS_LIBRARY_VERSION "${LWS_LIBRARY_VERSION}" +#define LWS_LOGGING_BITFIELD_CLEAR ${LWS_LOGGING_BITFIELD_CLEAR} +#define LWS_LOGGING_BITFIELD_SET ${LWS_LOGGING_BITFIELD_SET} #cmakedefine LWS_MINGW_SUPPORT #cmakedefine LWS_NO_CLIENT #cmakedefine LWS_NO_DAEMONIZE diff --git a/include/libwebsockets/lws-logs.h b/include/libwebsockets/lws-logs.h index dc29b349..c08384e6 100644 --- a/include/libwebsockets/lws-logs.h +++ b/include/libwebsockets/lws-logs.h @@ -34,22 +34,20 @@ */ ///@{ -enum lws_log_levels { - LLL_ERR = 1 << 0, - LLL_WARN = 1 << 1, - LLL_NOTICE = 1 << 2, - LLL_INFO = 1 << 3, - LLL_DEBUG = 1 << 4, - LLL_PARSER = 1 << 5, - LLL_HEADER = 1 << 6, - LLL_EXT = 1 << 7, - LLL_CLIENT = 1 << 8, - LLL_LATENCY = 1 << 9, - LLL_USER = 1 << 10, - LLL_THREAD = 1 << 11, - - LLL_COUNT = 12 /* set to count of valid flags */ -}; +#define LLL_ERR (1 << 0) +#define LLL_WARN (1 << 1) +#define LLL_NOTICE (1 << 2) +#define LLL_INFO (1 << 3) +#define LLL_DEBUG (1 << 4) +#define LLL_PARSER (1 << 5) +#define LLL_HEADER (1 << 6) +#define LLL_EXT (1 << 7) +#define LLL_CLIENT (1 << 8) +#define LLL_LATENCY (1 << 9) +#define LLL_USER (1 << 10) +#define LLL_THREAD (1 << 11) + +#define LLL_COUNT (12) /* set to count of valid flags */ /** * lwsl_timestamp: generate logging timestamp string @@ -70,51 +68,124 @@ LWS_VISIBLE LWS_EXTERN void _lws_log(int filter, const char *format, ...) LWS_FO LWS_VISIBLE LWS_EXTERN void _lws_logv(int filter, const char *format, va_list vl); #endif -/* these guys are unconditionally included */ +/* + * Figure out which logs to build in or not + */ -#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__) -#define lwsl_user(...) _lws_log(LLL_USER, __VA_ARGS__) +#if defined(_DEBUG) + /* + * In DEBUG build, select all logs unless NO_LOGS + */ + #if defined(LWS_WITH_NO_LOGS) + #define _LWS_LINIT (LLL_ERR | LLL_USER) + #else + #define _LWS_LINIT ((1 << LLL_COUNT) - 1) + #endif +#else /* not _DEBUG */ + #define _LWS_LINIT (LLL_ERR | LLL_USER | LLL_WARN | LLL_NOTICE) +#endif /* _DEBUG */ -#if !defined(LWS_WITH_NO_LOGS) -/* notice and warn are usually included by being compiled in */ -#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__) -#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__) +/* + * Create either empty overrides or the ones forced at build-time. + * These overrides have the final say... any bits set in + * LWS_LOGGING_BITFIELD_SET force the build of those logs, any bits + * set in LWS_LOGGING_BITFIELD_CLEAR disable the build of those logs. + * + * If not defined lws decides based on CMAKE_BUILD_TYPE=DEBUG or not + */ + +#if defined(LWS_LOGGING_BITFIELD_SET) + #define _LWS_LBS (LWS_LOGGING_BITFIELD_SET) +#else + #define _LWS_LBS 0 #endif + +#if defined(LWS_LOGGING_BITFIELD_CLEAR) + #define _LWS_LBC (LWS_LOGGING_BITFIELD_CLEAR) +#else + #define _LWS_LBC 0 +#endif + /* - * weaker logging can be deselected by telling CMake to build in RELEASE mode - * that gets rid of the overhead of checking while keeping _warn and _err - * active + * Compute the final active logging bitfield for build */ +#define _LWS_ENABLED_LOGS (((_LWS_LINIT) | (_LWS_LBS)) & ~(_LWS_LBC)) -#if defined(_DEBUG) -#if defined(LWS_WITH_NO_LOGS) -/* notice, warn and log are always compiled in */ -#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__) -#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__) +/* + * Individually enable or disable log levels for build + * depending on what was computed + */ + +#if (_LWS_ENABLED_LOGS & LLL_ERR) +#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__) +#else +#define lwsl_err(...) do {} while(0) #endif -#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__) -#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__) -#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__) -#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__) -#define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__) -#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__) -#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__) -#define lwsl_thread(...) _lws_log(LLL_THREAD, __VA_ARGS__) -#else /* no debug */ -#if defined(LWS_WITH_NO_LOGS) +#if (_LWS_ENABLED_LOGS & LLL_WARN) +#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__) +#else #define lwsl_warn(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) +#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__) +#else #define lwsl_notice(...) do {} while(0) #endif + +#if (_LWS_ENABLED_LOGS & LLL_INFO) +#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__) +#else #define lwsl_info(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) +#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__) +#else #define lwsl_debug(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_PARSER) +#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__) +#else #define lwsl_parser(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_HEADER) +#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__) +#else #define lwsl_header(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_EXT) +#define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__) +#else #define lwsl_ext(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_CLIENT) +#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__) +#else #define lwsl_client(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_LATENCY) +#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__) +#else #define lwsl_latency(...) do {} while(0) +#endif + +#if (_LWS_ENABLED_LOGS & LLL_THREAD) +#define lwsl_thread(...) _lws_log(LLL_THREAD, __VA_ARGS__) +#else #define lwsl_thread(...) do {} while(0) +#endif +#if (_LWS_ENABLED_LOGS & LLL_USER) +#define lwsl_user(...) _lws_log(LLL_USER, __VA_ARGS__) +#else +#define lwsl_user(...) do {} while(0) #endif diff --git a/lib/core-net/pollfd.c b/lib/core-net/pollfd.c index 5a45ad72..aa4c4924 100644 --- a/lib/core-net/pollfd.c +++ b/lib/core-net/pollfd.c @@ -242,7 +242,7 @@ lws_accept_modulation(struct lws_context *context, } #endif -#if defined(_DEBUG) +#if _LWS_ENABLED_LOGS & LLL_WARN void __dump_fds(struct lws_context_per_thread *pt, const char *s) { diff --git a/lib/core-net/state.c b/lib/core-net/state.c index 56424647..8fe830bf 100644 --- a/lib/core-net/state.c +++ b/lib/core-net/state.c @@ -46,7 +46,7 @@ lws_state_reg_notifier_list(lws_state_manager_t *mgr, lws_state_reg_notifier(mgr, *notify_link_array++); } -#if defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & (LLL_INFO | LLL_DEBUG)) static const char * _systnm(lws_state_manager_t *mgr, int state, char *temp8) { @@ -62,7 +62,7 @@ _systnm(lws_state_manager_t *mgr, int state, char *temp8) static int _report(lws_state_manager_t *mgr, int a, int b) { -#if defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & LLL_INFO) char temp8[8]; #endif @@ -72,12 +72,14 @@ _report(lws_state_manager_t *mgr, int a, int b) if (l->notify_cb(mgr, l, a, b)) { /* a dependency took responsibility for retry */ -#if defined(_DEBUG) + +#if (_LWS_ENABLED_LOGS & LLL_INFO) lwsl_info("%s: %s: %s: rejected '%s' -> '%s'\n", __func__, mgr->name, l->name, _systnm(mgr, a, temp8), _systnm(mgr, b, temp8)); #endif + return 1; } @@ -89,14 +91,14 @@ _report(lws_state_manager_t *mgr, int a, int b) static int _lws_state_transition(lws_state_manager_t *mgr, int target) { -#if defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) char temp8[8]; #endif if (_report(mgr, mgr->state, target)) return 1; -#if defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) lwsl_debug("%s: %s: changed %d '%s' -> %d '%s'\n", __func__, mgr->name, mgr->state, _systnm(mgr, mgr->state, temp8), target, _systnm(mgr, target, temp8)); @@ -114,7 +116,7 @@ int lws_state_transition_steps(lws_state_manager_t *mgr, int target) { int n = 0; -#if defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & LLL_INFO) int i = mgr->state; char temp8[8]; #endif @@ -125,7 +127,7 @@ lws_state_transition_steps(lws_state_manager_t *mgr, int target) while (!n && mgr->state != target) n = _lws_state_transition(mgr, mgr->state + 1); -#if defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & LLL_INFO) lwsl_info("%s: %s -> %s\n", __func__, _systnm(mgr, i, temp8), _systnm(mgr, mgr->state, temp8)); #endif diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index 0dfbdb99..ff003228 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -445,13 +445,13 @@ void lws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state, const struct lws_role_ops *ops) { -#if defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) const char *name = "(unset)"; #endif wsi->wsistate = role | state; if (ops) wsi->role_ops = ops; -#if defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & LLL_DEBUG) if (wsi->role_ops) name = wsi->role_ops->name; lwsl_debug("%s: %p: wsistate 0x%lx, ops %s\n", __func__, wsi, diff --git a/lib/core/context.c b/lib/core/context.c index a264e18f..03fdc826 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -957,7 +957,9 @@ lws_system_cpd_start(struct lws_context *cx) #endif } +#if (_LWS_ENABLED_LOGS & LLL_NOTICE) static const char *cname[] = { "?", "OK", "Captive", "No internet" }; +#endif void lws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result) diff --git a/lib/core/lws_dll2.c b/lib/core/lws_dll2.c index 2b3218fc..7556695d 100644 --- a/lib/core/lws_dll2.c +++ b/lib/core/lws_dll2.c @@ -214,6 +214,7 @@ lws_dll2_add_sorted(lws_dll2_t *d, lws_dll2_owner_t *own, void lws_dll2_describe(lws_dll2_owner_t *owner, const char *desc) { +#if _LWS_ENABLED_LOGS & LLL_INFO int n = 1; lwsl_info("%s: %s: owner %p: count %d, head %p, tail %p\n", @@ -224,6 +225,7 @@ lws_dll2_describe(lws_dll2_owner_t *owner, const char *desc) lwsl_info("%s: %d: %p: owner %p, prev %p, next %p\n", __func__, n++, p, p->owner, p->prev, p->next); } lws_end_foreach_dll_safe(p, tp); +#endif } #endif diff --git a/lib/misc/lwsac/lwsac.c b/lib/misc/lwsac/lwsac.c index 596b0821..cde97ef3 100644 --- a/lib/misc/lwsac/lwsac.c +++ b/lib/misc/lwsac/lwsac.c @@ -277,7 +277,7 @@ lwsac_free(struct lwsac **head) void lwsac_info(struct lwsac *head) { -#if defined(_DEBUG) +#if _LWS_ENABLED_LOGS & LLL_DEBUG struct lwsac_head *lachead; if (!head) { diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 9a258b10..2a4e7363 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -383,14 +383,14 @@ lws_tls_client_connect(struct lws *wsi) unsigned int len; #endif int m, n; -#if defined(WIN32) || defined(_DEBUG) +#if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO) int en; #endif errno = 0; ERR_clear_error(); n = SSL_connect(wsi->tls.ssl); -#if defined(WIN32) || defined(_DEBUG) +#if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO) en = errno; #endif m = lws_ssl_get_error(wsi, n); @@ -400,7 +400,7 @@ lws_tls_client_connect(struct lws *wsi) && en #endif ) { -#if defined(WIN32) || defined(_DEBUG) +#if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO) lwsl_info("%s: n %d, m %d, errno %d\n", __func__, n, m, en); #endif return LWS_SSL_CAPABLE_ERROR; -- Gitee From 974b65a2f0e490eff5cc1b246dbfbc9c17bd25cd Mon Sep 17 00:00:00 2001 From: huangkaicheng Date: Thu, 23 Apr 2020 06:17:22 +0100 Subject: [PATCH 0084/1062] iOS: detect and avoid net/route.h LWS builds OK on iOS SDK as unix type plat, except it doesn't have net/route.h. Detect we're building on iOS at CMake and export a preprocessor define we can use to snip out the missing include. --- CMakeLists.txt | 4 ++++ cmake/lws_config.h.in | 1 + lib/plat/unix/unix-sockets.c | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e8867bc..a76c5776 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,6 +179,10 @@ option(LWS_WITH_FANALYZER "Enable gcc -fanalyzer if compiler supports" OFF) # End of user settings # +if(IOS) + set(LWS_DETECTED_PLAT_IOS 1) +endif() + # Workaround for ESP-IDF # Detect ESP_PLATFORM environment flag, if exist, set LWS_WITH_ESP32. # Otherwise the user may not be able to run configuration ESP-IDF in the first time. diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index e2b8cb07..5d2ac129 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -24,6 +24,7 @@ #cmakedefine LWS_BUILD_HASH "${LWS_BUILD_HASH}" #cmakedefine LWS_BUILTIN_GETIFADDRS #cmakedefine LWS_CLIENT_HTTP_PROXYING +#cmakedefine LWS_DETECTED_PLAT_IOS #cmakedefine LWS_FALLBACK_GETHOSTBYNAME #cmakedefine LWS_HAS_INTPTR_T #cmakedefine LWS_HAS_GETOPT_LONG diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index abdb07f9..fa590f08 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -28,7 +28,11 @@ #include "private-lib-core.h" #include + +#if !defined(LWS_DETECTED_PLAT_IOS) #include +#endif + #include #include -- Gitee From e72fe1bc4dfb3ce747376e1f139bb454f7deb718 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 23 Apr 2020 08:26:18 +0100 Subject: [PATCH 0085/1062] unix: try to work around externally closed fds --- lib/plat/unix/unix-fds.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/plat/unix/unix-fds.c b/lib/plat/unix/unix-fds.c index 3fee0abb..a00a57b0 100644 --- a/lib/plat/unix/unix-fds.c +++ b/lib/plat/unix/unix-fds.c @@ -69,7 +69,6 @@ insert_wsi(const struct lws_context *context, struct lws *wsi) p = context->lws_lookup; done = &p[context->max_fds]; -#if defined(_DEBUG) /* confirm it doesn't already exist */ @@ -79,18 +78,28 @@ insert_wsi(const struct lws_context *context, struct lws *wsi) assert(p == done); p = context->lws_lookup; - /* confirm fd doesn't already exist */ + /* confirm fd isn't already in use by a wsi */ while (p != done && (!*p || (*p)->desc.sockfd != wsi->desc.sockfd)) p++; if (p != done) { - lwsl_err("%s: wsi %p already says it has fd %d\n", + lwsl_warn("%s: wsi %p already lists fd %d, transferring\n", __func__, *p, wsi->desc.sockfd); - assert(0); + /* + * So something closed that fd outside of the wsi activities... + * later the closed fd has been reused for something else. + * + * Work around it by invalidating the old guy's fd, mark him + * as unable to do any transfers and close him. + */ + + (*p)->desc.sockfd = LWS_SOCK_INVALID; + (*p)->position_in_fds_table = -1; + (*p)->socket_is_permanently_unusable = 1; + lws_set_timeout(*p, 1, LWS_TO_KILL_ASYNC); } p = context->lws_lookup; -#endif /* find an empty slot */ -- Gitee From 99e778ac08681ade91c2749466843eb945c215ef Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 23 Apr 2020 15:12:17 +0100 Subject: [PATCH 0086/1062] http: add cmake option for header reduction defeat Lws now strips out http headers releated to h2, ws and unusual headers based on cmake config settings for those features... it saves some heap for the ah and reduces the table size in .rodata. It's possible code might have some external dependency on the original header indexes, but, eg, you don't enable h2 so those indexes are optimized with the h2 ones taken out. This introduces a cmake option "LWS_HTTP_HEADERS_ALL", default-OFF, that defeats the header table optimization for compatibility with older versions in the case the client software can't be adapted to use the lws-exported matching header enums. You probably don't need this. --- CMakeLists.txt | 1 + cmake/lws_config.h.in | 1 + include/libwebsockets/lws-http.h | 36 +++++++++++++++---------------- lib/roles/h2/hpack.c | 16 +++++++------- lib/roles/http/lextable-strings.h | 34 ++++++++++++++--------------- lib/roles/http/lextable.h | 32 +++++++++++++-------------- lib/roles/http/minilex.c | 22 ++++++++++++++----- 7 files changed, 78 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a76c5776..ab7bde0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,6 +172,7 @@ option(LWS_WITH_UDP "Platform supports UDP" ON) option(LWS_WITH_SPAWN "Spawn subprocesses with piped stdin/out/stderr" OFF) option(LWS_WITH_FSMOUNT "Overlayfs and fallback mounting apis" OFF) option(LWS_WITH_FANALYZER "Enable gcc -fanalyzer if compiler supports" OFF) +option(LWS_HTTP_HEADERS_ALL "Override header reduction optimization and include all like older lws versions" OFF) # # to use miniz, enable both LWS_WITH_ZLIB and LWS_WITH_MINIZ diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 5d2ac129..2b50635a 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -132,6 +132,7 @@ #cmakedefine LWS_WITH_HTTP2 #cmakedefine LWS_WITH_HTTP_BASIC_AUTH #cmakedefine LWS_WITH_HTTP_BROTLI +#cmakedefine LWS_HTTP_HEADERS_ALL #cmakedefine LWS_WITH_HTTP_PROXY #cmakedefine LWS_WITH_HTTP_STREAM_COMPRESSION #cmakedefine LWS_WITH_HTTP_UNCOMMON_HEADERS diff --git a/include/libwebsockets/lws-http.h b/include/libwebsockets/lws-http.h index d0daeda9..d5851101 100644 --- a/include/libwebsockets/lws-http.h +++ b/include/libwebsockets/lws-http.h @@ -215,18 +215,18 @@ struct lws_tokens { enum lws_token_indexes { WSI_TOKEN_GET_URI, /* 0 */ WSI_TOKEN_POST_URI, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_OPTIONS_URI, #endif WSI_TOKEN_HOST, WSI_TOKEN_CONNECTION, WSI_TOKEN_UPGRADE, /* 5 */ WSI_TOKEN_ORIGIN, -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_DRAFT, #endif WSI_TOKEN_CHALLENGE, -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_EXTENSIONS, WSI_TOKEN_KEY1, /* 10 */ WSI_TOKEN_KEY2, @@ -235,11 +235,11 @@ enum lws_token_indexes { WSI_TOKEN_NONCE, #endif WSI_TOKEN_HTTP, -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP2_SETTINGS, /* 16 */ #endif WSI_TOKEN_HTTP_ACCEPT, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_AC_REQUEST_HEADERS, #endif WSI_TOKEN_HTTP_IF_MODIFIED_SINCE, @@ -254,15 +254,15 @@ enum lws_token_indexes { WSI_TOKEN_HTTP_CONTENT_TYPE, WSI_TOKEN_HTTP_DATE, WSI_TOKEN_HTTP_RANGE, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_REFERER, #endif -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_KEY, WSI_TOKEN_VERSION, WSI_TOKEN_SWORIGIN, #endif -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_COLON_AUTHORITY, WSI_TOKEN_HTTP_COLON_METHOD, WSI_TOKEN_HTTP_COLON_PATH, @@ -270,11 +270,11 @@ enum lws_token_indexes { WSI_TOKEN_HTTP_COLON_STATUS, #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_ACCEPT_CHARSET, #endif WSI_TOKEN_HTTP_ACCEPT_RANGES, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN, #endif WSI_TOKEN_HTTP_AGE, @@ -294,7 +294,7 @@ enum lws_token_indexes { WSI_TOKEN_HTTP_LAST_MODIFIED, WSI_TOKEN_HTTP_LINK, WSI_TOKEN_HTTP_LOCATION, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_MAX_FORWARDS, WSI_TOKEN_HTTP_PROXY_AUTHENTICATE, WSI_TOKEN_HTTP_PROXY_AUTHORIZATION, @@ -303,24 +303,24 @@ enum lws_token_indexes { WSI_TOKEN_HTTP_RETRY_AFTER, WSI_TOKEN_HTTP_SERVER, WSI_TOKEN_HTTP_SET_COOKIE, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY, #endif WSI_TOKEN_HTTP_TRANSFER_ENCODING, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_HTTP_USER_AGENT, WSI_TOKEN_HTTP_VARY, WSI_TOKEN_HTTP_VIA, WSI_TOKEN_HTTP_WWW_AUTHENTICATE, #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_PATCH_URI, WSI_TOKEN_PUT_URI, WSI_TOKEN_DELETE_URI, #endif WSI_TOKEN_HTTP_URI_ARGS, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_PROXY, WSI_TOKEN_HTTP_X_REAL_IP, #endif @@ -328,11 +328,11 @@ enum lws_token_indexes { WSI_TOKEN_X_FORWARDED_FOR, WSI_TOKEN_CONNECT, WSI_TOKEN_HEAD_URI, -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_TE, WSI_TOKEN_REPLAY_NONCE, /* ACME */ #endif -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_COLON_PROTOCOL, #endif WSI_TOKEN_X_AUTH_TOKEN, @@ -356,7 +356,7 @@ enum lws_token_indexes { /* parser state additions, no storage associated */ WSI_TOKEN_NAME_PART, -#if defined(LWS_WITH_CUSTOM_HEADERS) +#if defined(LWS_WITH_CUSTOM_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) WSI_TOKEN_UNKNOWN_VALUE_PART, #endif WSI_TOKEN_SKIPPING, diff --git a/lib/roles/h2/hpack.c b/lib/roles/h2/hpack.c index 2b9df394..153e8d28 100644 --- a/lib/roles/h2/hpack.c +++ b/lib/roles/h2/hpack.c @@ -754,42 +754,42 @@ lws_hpack_use_idx_hdr(struct lws *wsi, int idx, int known_token) return 0; } -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if defined(LWS_HTTP_HEADERS_ALL) || (defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2)) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00, }; diff --git a/lib/roles/http/lextable-strings.h b/lib/roles/http/lextable-strings.h index e0558ce3..fd3bbaea 100644 --- a/lib/roles/http/lextable-strings.h +++ b/lib/roles/http/lextable-strings.h @@ -3,19 +3,19 @@ static const char * const set[] = { "get ", "post ", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) "options ", #endif "host:", "connection:", "upgrade:", "origin:", -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) "sec-websocket-draft:", #endif "\x0d\x0a", -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) "sec-websocket-extensions:", "sec-websocket-key1:", "sec-websocket-key2:", @@ -25,12 +25,12 @@ static const char * const set[] = { "sec-websocket-nonce:", #endif "http/1.1 ", -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "http2-settings:", #endif "accept:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) "access-control-request-headers:", #endif "if-modified-since:", @@ -45,26 +45,26 @@ static const char * const set[] = { "content-type:", "date:", "range:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "referer:", #endif -#if defined(LWS_ROLE_WS) +#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) "sec-websocket-key:", "sec-websocket-version:", "sec-websocket-origin:", #endif -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) ":authority", ":method", ":path", ":scheme", ":status", #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "accept-charset:", #endif "accept-ranges:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "access-control-allow-origin:", #endif "age:", @@ -84,7 +84,7 @@ static const char * const set[] = { "last-modified:", "link:", "location:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "max-forwards:", "proxy-authenticate:", "proxy-authorization:", @@ -93,17 +93,17 @@ static const char * const set[] = { "retry-after:", "server:", "set-cookie:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "strict-transport-security:", #endif "transfer-encoding:", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "user-agent:", "vary:", "via:", "www-authenticate:", #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) "patch", "put", "delete", @@ -111,7 +111,7 @@ static const char * const set[] = { "uri-args", /* fake header used for uri-only storage */ -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) "proxy ", "x-real-ip:", #endif @@ -120,11 +120,11 @@ static const char * const set[] = { "x-forwarded-for:", "connect ", "head ", -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) "te:", /* http/2 wants it to reject it */ "replay-nonce:", /* ACME */ #endif -#if defined(LWS_ROLE_H2) +#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) ":protocol", /* defined in mcmanus-httpbis-h2-ws-02 */ #endif diff --git a/lib/roles/http/lextable.h b/lib/roles/http/lextable.h index bf927373..7e4a3fc3 100644 --- a/lib/roles/http/lextable.h +++ b/lib/roles/http/lextable.h @@ -1,4 +1,4 @@ -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 3: host: */ @@ -522,7 +522,7 @@ /* total size 662 bytes */ #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 2: options */ @@ -1290,7 +1290,7 @@ /* total size 968 bytes */ #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 3: host: */ @@ -2134,7 +2134,7 @@ /* total size 1088 bytes */ #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 2: options */ @@ -2998,7 +2998,7 @@ /* total size 1088 bytes */ #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 3: host: */ @@ -3912,7 +3912,7 @@ /* total size 1177 bytes */ #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 2: options */ @@ -4833,7 +4833,7 @@ /* total size 1177 bytes */ #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) /* 0: 0: get */ /* 1: 1: post */ /* 2: 3: host: */ @@ -5757,7 +5757,7 @@ /* total size 1177 bytes */ #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if defined(LWS_HTTP_HEADERS_ALL) || (defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2)) /* 0: 0: get */ /* 1: 1: post */ /* 2: 2: options */ @@ -6690,42 +6690,42 @@ /* -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && !defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x80,0x0f,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && !defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x3e,0x00,0x00,0x00,0x80,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if !defined(LWS_HTTP_HEADERS_ALL) && !defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2) +#if defined(LWS_HTTP_HEADERS_ALL) || (defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && defined(LWS_ROLE_WS) && defined(LWS_ROLE_H2)) static uint8_t lws_header_implies_psuedoheader_map[] = { 0x07,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x0e,0x04,0x00,0x00,0x00,0x00,0x00, }; diff --git a/lib/roles/http/minilex.c b/lib/roles/http/minilex.c index 2f9d6a8d..083d66ce 100644 --- a/lib/roles/http/minilex.c +++ b/lib/roles/http/minilex.c @@ -249,10 +249,16 @@ int issue(int version) memset(rset, 0, sizeof(rset)); - printf("#if %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " - "%cdefined(LWS_ROLE_WS) && " - "%cdefined(LWS_ROLE_H2)\n", version & 1 ? ' ' : '!', - version & 2 ? ' ' : '!', version & 4 ? ' ' : '!'); + if (version == 7) + printf("#if defined(LWS_HTTP_HEADERS_ALL) || (%cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " + "%cdefined(LWS_ROLE_WS) && " + "%cdefined(LWS_ROLE_H2))\n", version & 1 ? ' ' : '!', + version & 2 ? ' ' : '!', version & 4 ? ' ' : '!'); + else + printf("#if !defined(LWS_HTTP_HEADERS_ALL) && %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " + "%cdefined(LWS_ROLE_WS) && " + "%cdefined(LWS_ROLE_H2)\n", version & 1 ? ' ' : '!', + version & 2 ? ' ' : '!', version & 4 ? ' ' : '!'); /* * let's create version's view of the set of strings @@ -467,7 +473,13 @@ int main(void) for (n = 0; n < 8; n++) { - printf("#if %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " + if (n == 7) + printf("#if defined(LWS_HTTP_HEADERS_ALL) || (%cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " + "%cdefined(LWS_ROLE_WS) && " + "%cdefined(LWS_ROLE_H2))\n", n & 1 ? ' ' : '!', + n & 2 ? ' ' : '!', n & 4 ? ' ' : '!'); + else + printf("#if !defined(LWS_HTTP_HEADERS_ALL) && %cdefined(LWS_WITH_HTTP_UNCOMMON_HEADERS) && " "%cdefined(LWS_ROLE_WS) && " "%cdefined(LWS_ROLE_H2)\n", n & 1 ? ' ' : '!', n & 2 ? ' ' : '!', n & 4 ? ' ' : '!'); -- Gitee From ee40b52c620a8e3f6c118d84385c9bcb36235e22 Mon Sep 17 00:00:00 2001 From: Adam Duskett Date: Thu, 23 Apr 2020 11:53:06 -0700 Subject: [PATCH 0087/1062] dhcpclient: Fix unused-variable error in release dhcp_entry_names is only used when _DEBUG is defined, so wrap the array in Signed-off-by: Adam Duskett --- lib/system/dhcpclient/dhcpclient.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/system/dhcpclient/dhcpclient.c b/lib/system/dhcpclient/dhcpclient.c index fccd58e5..cf58b5b4 100644 --- a/lib/system/dhcpclient/dhcpclient.c +++ b/lib/system/dhcpclient/dhcpclient.c @@ -168,6 +168,7 @@ static const uint8_t rawdisc[] = { * +---------------------------------------------------------------+ */ +#if defined(_DEBUG) static const char *dhcp_entry_names[] = { "proposed ip", "dhcp server", @@ -183,6 +184,7 @@ static const char *dhcp_entry_names[] = { "rebinding secs", "renewal secs", }; +#endif static void lws_dhcpc_retry_conn(struct lws_sorted_usec_list *sul) -- Gitee From c95706a17f635de5cd8a9ff947c046765fe80cb0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 23 Apr 2020 22:28:25 +0100 Subject: [PATCH 0088/1062] ntpclient: add plat-specific init with env var LWS_NTP_SERVER able to set it on unix and windows Trying to use a remote pool is very variable with CI, the builder can force a local ntpd this way cleanly. When enabled all the test apps use ntpclient, so this lets us tell them all to go to the local ntpd in one hit. --- lib/core/private-lib-core.h | 3 +++ lib/plat/freertos/freertos-resolv.c | 17 +++++++++++++++++ lib/plat/optee/lws-plat-optee.c | 17 +++++++++++++++++ lib/plat/unix/unix-resolv.c | 21 +++++++++++++++++++++ lib/plat/windows/windows-resolv.c | 16 ++++++++++++++++ lib/system/ntpclient/ntpclient.c | 3 +++ 6 files changed, 77 insertions(+) diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 6335a89d..316c2912 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -710,6 +710,9 @@ int lws_plat_user_colon_group_to_ids(const char *u_colon_g, uid_t *puid, gid_t *pgid); #endif +int +lws_plat_ntpclient_config(struct lws_context *context); + int lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len); diff --git a/lib/plat/freertos/freertos-resolv.c b/lib/plat/freertos/freertos-resolv.c index 2c760182..cccd8340 100644 --- a/lib/plat/freertos/freertos-resolv.c +++ b/lib/plat/freertos/freertos-resolv.c @@ -40,3 +40,20 @@ lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) return s; } + +int +lws_plat_ntpclient_config(struct lws_context *context) +{ +#if 0 + char *ntpsrv = getenv("LWS_NTP_SERVER"); + + if (ntpsrv && strlen(ntpsrv) < 64) { + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0), + (const uint8_t *)ntpsrv, + strlen(ntpsrv)); + return 1; + } +#endif + return 0; +} diff --git a/lib/plat/optee/lws-plat-optee.c b/lib/plat/optee/lws-plat-optee.c index 80c62447..08c60c3c 100644 --- a/lib/plat/optee/lws-plat-optee.c +++ b/lib/plat/optee/lws-plat-optee.c @@ -235,3 +235,20 @@ lws_plat_recommended_rsa_bits(void) { return 4096; } + +int +lws_plat_ntpclient_config(struct lws_context *context) +{ +#if 0 + char *ntpsrv = getenv("LWS_NTP_SERVER"); + + if (ntpsrv && strlen(ntpsrv) < 64) { + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0), + (const uint8_t *)ntpsrv, + strlen(ntpsrv)); + return 1; + } +#endif + return 0; +} diff --git a/lib/plat/unix/unix-resolv.c b/lib/plat/unix/unix-resolv.c index f5877634..00a47351 100644 --- a/lib/plat/unix/unix-resolv.c +++ b/lib/plat/unix/unix-resolv.c @@ -88,3 +88,24 @@ lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) return LADNS_CONF_SERVER_UNKNOWN; } + +/* + * Platform-specific ntpclient server configuration + */ + +int +lws_plat_ntpclient_config(struct lws_context *context) +{ +#if defined(LWS_HAVE_GETENV) + char *ntpsrv = getenv("LWS_NTP_SERVER"); + + if (ntpsrv && strlen(ntpsrv) < 64) { + lws_system_blob_direct_set(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0), + (const uint8_t *)ntpsrv, + strlen(ntpsrv)); + return 1; + } +#endif + return 0; +} diff --git a/lib/plat/windows/windows-resolv.c b/lib/plat/windows/windows-resolv.c index 146db2c4..3fbdb8e9 100644 --- a/lib/plat/windows/windows-resolv.c +++ b/lib/plat/windows/windows-resolv.c @@ -48,3 +48,19 @@ lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) LADNS_CONF_SERVER_UNKNOWN; } +int +lws_plat_ntpclient_config(struct lws_context *context) +{ +#if defined(LWS_HAVE_GETENV) + char *ntpsrv = getenv("LWS_NTP_SERVER"); + + if (ntpsrv && strlen(ntpsrv) < 64) { + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0), + (const uint8_t *)ntpsrv, + strlen(ntpsrv)); + return 1; + } +#endif + return 0; +} diff --git a/lib/system/ntpclient/ntpclient.c b/lib/system/ntpclient/ntpclient.c index 4474051a..8499cd5e 100644 --- a/lib/system/ntpclient/ntpclient.c +++ b/lib/system/ntpclient/ntpclient.c @@ -159,10 +159,13 @@ callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_state_reg_notifier(&wsi->context->mgr_system, &v->notify_link); v->ntp_server_ads = "pool.ntp.org"; + lws_plat_ntpclient_config(v->context); lws_system_blob_get_single_ptr(lws_system_get_blob( v->context, LWS_SYSBLOB_TYPE_NTP_SERVER, 0), (const uint8_t **)&v->ntp_server_ads); + lwsl_info("%s: using ntp server %s\n", __func__, v->ntp_server_ads); + lws_ntpc_retry_conn(&v->sul_conn); break; -- Gitee From 2d5662a4f9f0d6cf579b770b178f46ecf24e940f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 24 Apr 2020 07:56:32 +0100 Subject: [PATCH 0089/1062] CMake: no pthreads in LWS_PLAT_FREERTOS --- CMakeLists.txt | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab7bde0c..b638b182 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1027,21 +1027,21 @@ CHECK_C_SOURCE_COMPILES("#include return 0; }" LWS_HAS_INTPTR_T) -if (LWS_HAVE_PTHREAD_H) - if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-pthread -Wno-error=unused-command-line-argument") - else() - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-pthread") - endif() + if (LWS_HAVE_PTHREAD_H AND NOT LWS_PLAT_FREERTOS) + if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-pthread -Wno-error=unused-command-line-argument") + else() + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-pthread") + endif() - CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE - #include - int main(void) { - pthread_t th = 0; - pthread_setname_np(th, NULL); - return 0; - }" LWS_HAS_PTHREAD_SETNAME_NP) -endif() + CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE + #include + int main(void) { + pthread_t th = 0; + pthread_setname_np(th, NULL); + return 0; + }" LWS_HAS_PTHREAD_SETNAME_NP) + endif() CHECK_C_SOURCE_COMPILES("#include #include -- Gitee From 9660245108b58cbe2135adaf979e708d69cde9b1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 24 Apr 2020 12:47:12 +0100 Subject: [PATCH 0090/1062] linkit-force-mbedtls-options --- contrib/cross-linkit.cmake | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/contrib/cross-linkit.cmake b/contrib/cross-linkit.cmake index 596cd0af..5d417aca 100644 --- a/contrib/cross-linkit.cmake +++ b/contrib/cross-linkit.cmake @@ -1,10 +1,10 @@ # # CMake Toolchain file for crosscompiling on Mediatek Linkit 7967 # -# This can be used like this (with Linkit sdk unpacked to /projects/linkit/sdk) +# This can be used like this (with Linkit sdk unpacked to /opt/linkit) # # cd build/ -# cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/projects/linkit/cross-root \ +# cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/opt/linkit/cross-root \ # -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake \ # -DLWS_PLAT_FREERTOS=1 \ # -DLWS_WITH_ZLIB=0 \ @@ -37,6 +37,22 @@ set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/arm-none-eabi-g++") set(CMAKE_C_COMPILER_WORKS 1) set(CMAKE_CXX_COMPILER_WORKS 1) +# +# similarly we're building a .a like this, we can't actually build +# complete test programs to probe api availability... so force some +# key ones + +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols 1) +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols 1) +set(LWS_HAVE_mbedtls_ssl_get_alpn_protocol 1) +set(LWS_HAVE_mbedtls_ssl_conf_sni 1) +set(LWS_HAVE_mbedtls_ssl_set_hs_ca_chain 1) +set(LWS_HAVE_mbedtls_ssl_set_hs_own_cert 1) +set(LWS_HAVE_mbedtls_ssl_set_hs_authmode 1) +set(LWS_HAVE_mbedtls_net_init 1) +set(LWS_HAVE_mbedtls_md_setup 1) # not on xenial 2.2 +set(LWS_HAVE_mbedtls_rsa_complete 1) # not on xenial 2.2 +set(LWS_HAVE_mbedtls_internal_aes_encrypt 1) # # Different build system distros set release optimization level to different # things according to their local policy, eg, Fedora is -O2 and Ubuntu is -O3 @@ -53,7 +69,7 @@ if (CMAKE_BUILD_TYPE MATCHES RELEASE OR CMAKE_BUILD_TYPE MATCHES Release OR CMAK set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") endif() -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostartfiles -I${CROSS_BASE}/middleware/third_party/lwip/src/include/lwip -I${CROSS_BASE}/middleware/third_party/lwip/src/include -I${CROSS_BASE}/project/mt7687_hdk/apps/httpd/inc/ -I${CROSS_BASE}/kernel/service/inc/ -I${CROSS_BASE}/driver/chip/inc -I${CROSS_BASE}/driver/chip/mt7687/inc/ -I${CROSS_BASE}/driver/CMSIS/Device/MTK/mt7687/Include/ -I${CROSS_BASE}/driver/CMSIS/Include -I${CROSS_BASE}/middleware/third_party/lwip/ports/include/ -I${CROSS_BASE}/middleware/third_party/lwip/src/include/posix/ -I${CROSS_BASE}/kernel/rtos/FreeRTOS/Source/include/ -I${CROSS_BASE}/middleware/third_party/mbedtls/include/ -I${CROSS_BASE}/kernel/rtos/FreeRTOS/Source/portable/GCC/ARM_CM4F/ -I${CROSS_BASE}/middleware/third_party/sntp/inc/ -DLWS_AMAZON_RTOS=1" CACHE STRING "" FORCE) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lnosys -nostartfiles -I${CROSS_BASE}/middleware/third_party/lwip/src/include/lwip -I${CROSS_BASE}/middleware/third_party/lwip/src/include -I${CROSS_BASE}/project/mt7687_hdk/apps/httpd/inc/ -I${CROSS_BASE}/kernel/service/inc/ -I${CROSS_BASE}/driver/chip/inc -I${CROSS_BASE}/driver/chip/mt7687/inc/ -I${CROSS_BASE}/driver/CMSIS/Device/MTK/mt7687/Include/ -I${CROSS_BASE}/driver/CMSIS/Include -I${CROSS_BASE}/middleware/third_party/lwip/ports/include/ -I${CROSS_BASE}/middleware/third_party/lwip/src/include/posix/ -I${CROSS_BASE}/kernel/rtos/FreeRTOS/Source/include/ -I${CROSS_BASE}/middleware/third_party/mbedtls/include/ -I${CROSS_BASE}/kernel/rtos/FreeRTOS/Source/portable/GCC/ARM_CM4F/ -I${CROSS_BASE}/middleware/third_party/sntp/inc/ -DLWS_AMAZON_RTOS=1" CACHE STRING "" FORCE) # Where to look for the target environment. (More paths can be added here) set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") -- Gitee From f2d5d4274bcc3d501f3be1e5a1bdcc8a61bd57a4 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 26 Apr 2020 06:14:41 +0100 Subject: [PATCH 0091/1062] client: change default connect timeout to 30s --- lib/core/private-lib-core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 316c2912..4ac7ef84 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -83,7 +83,7 @@ #define SPEC_LATEST_SUPPORTED 13 #endif #ifndef AWAITING_TIMEOUT -#define AWAITING_TIMEOUT 20 +#define AWAITING_TIMEOUT 30 #endif #ifndef CIPHERS_LIST_STRING #define CIPHERS_LIST_STRING "DEFAULT" -- Gitee From 79ef48e33c92d8f28390a952e700007ff9121e5e Mon Sep 17 00:00:00 2001 From: huangkaicheng Date: Mon, 27 Apr 2020 13:58:40 +0100 Subject: [PATCH 0092/1062] cmake: remove unicode quote from lws_config_private template Apparently some toolchains / platforms / locales don't handle UTF-8 well --- cmake/lws_config_private.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/lws_config_private.h.in b/cmake/lws_config_private.h.in index 55bd4fb7..b0615b50 100644 --- a/cmake/lws_config_private.h.in +++ b/cmake/lws_config_private.h.in @@ -19,7 +19,7 @@ /* Define to 1 if you have the `fork' function. */ #cmakedefine LWS_HAVE_FORK -/* Define to 1 if you have the `getenv’ function. */ +/* Define to 1 if you have the `getenv' function. */ #cmakedefine LWS_HAVE_GETENV /* Define to 1 if you have the header file. */ -- Gitee From abf3875d783d25295e001e2fc8f7e71c27468700 Mon Sep 17 00:00:00 2001 From: Sakthi Kannan Ramabadran Date: Mon, 27 Apr 2020 19:42:55 +0100 Subject: [PATCH 0093/1062] mqtt: some toolchains object to typedef Use struct type instead of typedef to avoid it. --- lib/roles/mqtt/private-lib-roles-mqtt.h | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/roles/mqtt/private-lib-roles-mqtt.h b/lib/roles/mqtt/private-lib-roles-mqtt.h index 5eb937a6..a458ef3b 100644 --- a/lib/roles/mqtt/private-lib-roles-mqtt.h +++ b/lib/roles/mqtt/private-lib-roles-mqtt.h @@ -25,8 +25,6 @@ #ifndef _PRIVATE_LIB_ROLES_MQTT #define _PRIVATE_LIB_ROLES_MQTT 1 -#include - extern struct lws_role_ops role_ops_mqtt; #define lwsi_role_mqtt(wsi) (wsi->role_ops == &role_ops_mqtt) @@ -115,7 +113,7 @@ lws_mqtt_vbi_r(lws_mqtt_vbi *vbi, const uint8_t **in, size_t *len); lws_mqtt_stateful_primitive_return_t lws_mqtt_mb_parse(lws_mqtt_vbi *vbi, const uint8_t **in, size_t *len); -typedef struct lws_mqtt_str_st { +struct lws_mqtt_str_st { uint8_t *buf; uint16_t len; @@ -124,14 +122,14 @@ typedef struct lws_mqtt_str_st { uint16_t pos; char len_valid; char needs_freeing; -} lws_mqtt_str_t; +}; static inline int -lws_mqtt_str_first(lws_mqtt_str_t *s) { return !s->buf && !s->pos; } +lws_mqtt_str_first(struct lws_mqtt_str_st *s) { return !s->buf && !s->pos; } lws_mqtt_stateful_primitive_return_t -lws_mqtt_str_parse(lws_mqtt_str_t *bd, const uint8_t **in, size_t *len); +lws_mqtt_str_parse(struct lws_mqtt_str_st *bd, const uint8_t **in, size_t *len); typedef enum { LMQCPP_IDLE, @@ -251,7 +249,7 @@ typedef enum { } lwsgs_mqtt_states_t; typedef struct lws_mqtt_parser_st { - /* lws_mqtt_str_t s_content_type; */ + /* struct lws_mqtt_str_st s_content_type; */ lws_mqtt_packet_parse_state_t state; lws_mqtt_vbi vbit; @@ -308,12 +306,12 @@ typedef struct lws_mqtts { typedef struct lws_mqttc { lws_mqtt_parser_t par; lwsgs_mqtt_states_t estate; - lws_mqtt_str_t *id; - lws_mqtt_str_t *username; - lws_mqtt_str_t *password; + struct lws_mqtt_str_st *id; + struct lws_mqtt_str_st *username; + struct lws_mqtt_str_st *password; struct { - lws_mqtt_str_t *topic; - lws_mqtt_str_t *message; + struct lws_mqtt_str_st *topic; + struct lws_mqtt_str_st *message; lws_mqtt_qos_levels_t qos; uint8_t retain; } will; -- Gitee From a9275d8dea258b7069592cd1ff83ccbdacf6ea2e Mon Sep 17 00:00:00 2001 From: Steve Kyoungwon Kim Date: Wed, 29 Apr 2020 12:18:41 -0700 Subject: [PATCH 0094/1062] BoringSSL: provide X509_VERYFY_PARAM_Set1_host length X509_VERYFY_PARAM_Set1_host of openSSL allows the third argument, which is the length of the hostname string, to be 0. Then, it assumes hostname is a null-terminated C string. BoringSSL enforces the actual length to be specified, and the hostname string should end with a null char. Just provide the length, making both OpenSSL and BoringSSL happy. --- lib/tls/openssl/openssl-client.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 2a4e7363..e4d33d89 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -21,6 +21,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ +#include #include "private-lib-core.h" #include "private-lib-tls-openssl.h" @@ -194,9 +195,10 @@ lws_ssl_client_bio_create(struct lws *wsi) X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); #endif - // Handle the case where the hostname is an IP address. + /* Handle the case where the hostname is an IP address */ if (!X509_VERIFY_PARAM_set1_ip_asc(param, hostname)) - X509_VERIFY_PARAM_set1_host(param, hostname, 0); + X509_VERIFY_PARAM_set1_host(param, hostname, + strnlen(hostname, sizeof(hostname))); } #else if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { -- Gitee From fa7c86951c2cf87949172f1ec5ad2ac499a6017e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 3 May 2020 13:04:15 +0100 Subject: [PATCH 0095/1062] lws_struct: blob Add support for blob type in sqlite3... it's unusual in that it is created into the table schema as a column of blob type, but is not serialized or deserialized into or from JSON or sqlite. Because the size of blobs is open-ended, accessing them in one hit may not be possible, eg, exceed the size of available heap. As binary, they would have to be base64-encoded in JSON representation and that bloating may be excessive, with, eg, a 500MB blob. So while they can be defined using lws_struct schema, and coexist inside a column of a table managed by lws_struct, they must be read and written separately. --- include/libwebsockets/lws-struct.h | 18 ++++++ lib/misc/lws-struct-lejp.c | 5 ++ lib/misc/lws-struct-sqlite.c | 98 ++++++++++++++++++++++++------ 3 files changed, 101 insertions(+), 20 deletions(-) diff --git a/include/libwebsockets/lws-struct.h b/include/libwebsockets/lws-struct.h index fe396b26..90e6b27e 100644 --- a/include/libwebsockets/lws-struct.h +++ b/include/libwebsockets/lws-struct.h @@ -35,6 +35,7 @@ typedef enum { LSMT_LIST, LSMT_CHILD_PTR, LSMT_SCHEMA, + LSMT_BLOB_PTR, } lws_struct_map_type_eum; @@ -189,6 +190,23 @@ typedef struct lws_struct_args { LSMT_SCHEMA \ } +/* + * This is just used to create the table schema, it is not part of serialization + * and deserialization. Blobs should be accessed separately. + */ + +#define LSM_BLOB_PTR(type, blobptr_name, qname) \ + { \ + qname, /* JSON item, or sqlite3 column name */ \ + NULL, \ + NULL, \ + offsetof(type, blobptr_name), /* member that points to blob */ \ + sizeof (((type *)0)->blobptr_name), /* size of blob pointer */ \ + 0, /* member holding blob len */ \ + 0, /* size of blob length member */ \ + LSMT_BLOB_PTR \ + } + typedef struct lws_struct_serialize_st { const struct lws_dll2 *dllpos; const lws_struct_map_t *map; diff --git a/lib/misc/lws-struct-lejp.c b/lib/misc/lws-struct-lejp.c index 627a891f..c9a29cc7 100644 --- a/lib/misc/lws-struct-lejp.c +++ b/lib/misc/lws-struct-lejp.c @@ -496,6 +496,9 @@ lws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, goto up; break; + case LSMT_BLOB_PTR: + goto up; + default: break; } @@ -653,6 +656,8 @@ lws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, j->subsequent = 1; j->idt = 1; break; + default: + break; } switch (map->type) { diff --git a/lib/misc/lws-struct-sqlite.c b/lib/misc/lws-struct-sqlite.c index 23a040a1..6a532323 100644 --- a/lib/misc/lws-struct-sqlite.c +++ b/lib/misc/lws-struct-sqlite.c @@ -181,9 +181,10 @@ lws_struct_sq3_deserialize(sqlite3 *pdb, const char *filter, const char *order, const lws_struct_map_t *schema, lws_dll2_owner_t *o, struct lwsac **ac, int start, int _limit) { - char s[250], where[250]; - lws_struct_args_t a; int limit = _limit < 0 ? -_limit : _limit; + char s[768], results[512], where[250]; + lws_struct_args_t a; + int n, m; if (!order) order = "_lws_idx"; @@ -197,15 +198,27 @@ lws_struct_sq3_deserialize(sqlite3 *pdb, const char *filter, const char *order, lws_dll2_owner_clear(o); + /* + * Explicitly list the columns instead of use *, so we can skip blobs + */ + + m = 0; + for (n = 0; n < (int)schema->child_map_size; n++) + m += lws_snprintf(&results[m], sizeof(results) - n - 1, + "%s%c", schema->child_map[n].colname, + n + 1 == (int)schema->child_map_size ? ' ' : ','); + where[0] = '\0'; lws_snprintf(where, sizeof(where), " where _lws_idx >= %llu %s", (unsigned long long)start, filter ? filter : ""); - lws_snprintf(s, sizeof(s) - 1, "select * " - "from %s %s order by %s %slimit %d;", + lws_snprintf(s, sizeof(s) - 1, "select %s " + "from %s %s order by %s %slimit %d;", results, schema->colname, where, order, _limit < 0 ? "desc " : "", limit); + + if (sqlite3_exec(pdb, s, lws_struct_sq3_deser_cb, &a, NULL) != SQLITE_OK) { lwsl_err("%s: %s: fail %s\n", __func__, sqlite3_errmsg(pdb), s); lwsac_free(&a.ac); @@ -227,7 +240,7 @@ _lws_struct_sq3_ser_one(sqlite3 *pdb, const lws_struct_map_t *schema, uint32_t idx, void *st) { const lws_struct_map_t *map = schema->child_map; - int n, m, pk = 0, nentries = schema->child_map_size; + int n, m, pk = 0, nentries = schema->child_map_size, nef = 0, did; size_t sql_est = 46 + strlen(schema->colname) + 1; /* "insert into (_lws_idx, ) values (00000001,);" ... * plus the table name */ @@ -235,6 +248,26 @@ _lws_struct_sq3_ser_one(sqlite3 *pdb, const lws_struct_map_t *schema, const char *p; char *sql; + /* + * Figure out effective number of columns, exluding BLOB. + * + * The first UNSIGNED is a hidden index. Blobs are not handled by + * lws_struct except to create the column in the schema. + */ + + pk = 0; + nef = 0; + for (n = 0; n < nentries; n++) { + if (!pk && map[n].type == LSMT_UNSIGNED) { + pk = 1; + continue; + } + if (map[n].type == LSMT_BLOB_PTR) + continue; + + nef++; + } + /* * Figure out an estimate for the length of the populated sqlite * command, and then malloc it up @@ -276,6 +309,11 @@ _lws_struct_sq3_ser_one(sqlite3 *pdb, const lws_struct_map_t *schema, sql_est += (p ? lws_sql_purify_len(p) : 0) + 2; break; + case LSMT_BLOB_PTR: + /* we don't deal with blobs actually */ + sql_est -= strlen(map[n].colname) + 2; + break; + default: lwsl_err("%s: unsupported type\n", __func__); assert(0); @@ -295,19 +333,26 @@ _lws_struct_sq3_ser_one(sqlite3 *pdb, const lws_struct_map_t *schema, * not be specified */ + pk = 0; + did = 0; for (n = 0; n < nentries; n++) { if (!pk && map[n].type == LSMT_UNSIGNED) { pk = 1; continue; } + if (map[n].type == LSMT_BLOB_PTR) + continue; + + did++; m += lws_snprintf(sql + m, sql_est - m, - n == nentries - 1 ? "%s" : "%s, ", + did == nef ? "%s" : "%s, ", map[n].colname); } m += lws_snprintf(sql + m, sql_est - m, ") values(%u, ", idx); pk = 0; + did = 0; for (n = 0; n < nentries; n++) { uint64_t uu64; size_t q; @@ -351,13 +396,18 @@ _lws_struct_sq3_ser_one(sqlite3 *pdb, const lws_struct_map_t *schema, } sql[m++] = '\''; break; + + case LSMT_BLOB_PTR: + continue; + default: lwsl_err("%s: unsupported type\n", __func__); assert(0); break; } - if (n != nentries - 1) { + did++; + if (did != nef) { if (sql_est - m < 6) return -1; sql[m++] = ','; @@ -368,11 +418,13 @@ _lws_struct_sq3_ser_one(sqlite3 *pdb, const lws_struct_map_t *schema, lws_snprintf(sql + m, sql_est - m, ");"); n = sqlite3_exec(pdb, sql, NULL, NULL, NULL); - free(sql); if (n != SQLITE_OK) { + lwsl_err("%s\n", sql); + free(sql); lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb)); return -1; } + free(sql); return 0; } @@ -406,7 +458,7 @@ lws_struct_sq3_create_table(sqlite3 *pdb, const lws_struct_map_t *schema) schema->colname); while (map_size--) { - if (map->type > LSMT_STRING_PTR) { + if (map->type > LSMT_STRING_PTR && map->type != LSMT_BLOB_PTR) { map++; continue; } @@ -415,17 +467,23 @@ lws_struct_sq3_create_table(sqlite3 *pdb, const lws_struct_map_t *schema) *p++ = ' '; } subsequent = 1; - if (map->type < LSMT_STRING_CHAR_ARRAY) { - use = ""; - if (map->colname[0] != '_') /* _lws_idx is not primary key */ - use = pri; - p += lws_snprintf(p, end - p, "%s integer%s", - map->colname, use); - if (map->colname[0] != '_') - pri = ""; - } else - p += lws_snprintf(p, end - p, "%s varchar", - map->colname); + if (map->type == LSMT_BLOB_PTR) { + + p += lws_snprintf(p, end - p, "%s blob", map->colname); + + } else { + if (map->type < LSMT_STRING_CHAR_ARRAY) { + use = ""; + if (map->colname[0] != '_') /* _lws_idx is not primary key */ + use = pri; + p += lws_snprintf(p, end - p, "%s integer%s", + map->colname, use); + if (map->colname[0] != '_') + pri = ""; + } else + p += lws_snprintf(p, end - p, "%s varchar", + map->colname); + } map++; } -- Gitee From 71e4b4118ec10cb7fe9049da133d84395eec4210 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 30 Apr 2020 20:26:19 +0100 Subject: [PATCH 0096/1062] strexp: reset out offset each time A second strexp mustn't inherit the offset of the first, completed one --- lib/core/libwebsockets.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index 8453ac03..e9283285 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -947,6 +947,7 @@ lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len, if (*in == '{') { exp->state = LWS_EXPS_NAME_OR_CLOSE; exp->name_pos = 0; + exp->exp_ofs = 0; break; } /* treat as a literal */ -- Gitee From cb0ea63ef181c41737723969fe1519859d79793a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 1 May 2020 05:45:18 +0100 Subject: [PATCH 0097/1062] Refresh of ctest-migrate-and-deprecate --- .sai.json | 78 ++++++++++----------- CMakeLists.txt | 184 ++++++++++++++++++++++++------------------------- 2 files changed, 129 insertions(+), 133 deletions(-) diff --git a/.sai.json b/.sai.json index 10fca2a7..41c7a9e5 100644 --- a/.sai.json +++ b/.sai.json @@ -1,25 +1,32 @@ { "schema": "sai-1", + # We're doing separate install into destdir so that the test server + # has somewhere to go to find its /usr/share content like certs + "platforms": { - "linux-ubuntu-xenial-amd64": { - "build": "mkdir build destdir;cd build;cmake .. ${cmake};make -j;make -j DESTDIR=../destdir install" - }, "linux-ubuntu-bionic-amd64": { - "build": "mkdir build destdir;cd build;cmake .. ${cmake};make -j;make -j DESTDIR=../destdir install" + "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" + }, + "linux-ubuntu-focal-amd64": { + "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, "linux-fedora-32-x86_64": { - "build": "mkdir build destdir;cd build;cmake .. ${cmake};make -j;make -j DESTDIR=../destdir install" + "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" + }, + "linux-debian-buster-arm32": { + "build": "mkdir build;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j3 && make -j DESTDIR=../destdir install && ctest -j3 --output-on-failure ${cpack}", + "default": false }, "OSX-catalina": { - "build": "mkdir build destdir; cd build; cmake .. -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/openssl@1.1/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} && make -j" + "build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";cmake .. -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/openssl@1.1/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, "linkit-cross": { - "build": "mkdir build;cd build;cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/tmp -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake -DLWS_PLAT_FREERTOS=1 -DLWS_WITH_ZLIB=0 -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_HTTP_STREAM_COMPRESSION=0 -DLWS_WITH_MBEDTLS=1 -DLWS_WITH_FILE_OPS=0 ${cmake};make -j", + "build": "mkdir build;cd build;export CCACHE_DISABLE=1;cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/tmp -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake -DLWS_PLAT_FREERTOS=1 -DLWS_WITH_ZLIB=0 -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_HTTP_STREAM_COMPRESSION=0 -DLWS_WITH_MBEDTLS=1 -DLWS_WITH_FILE_OPS=0 ${cmake};make -j", "default": false }, "windows-10": { - "build": "mkdir build && cd build && cmake .. -DLWS_EXT_PTHREAD_INCLUDE_DIR=\"C:\\Program Files (x86)\\pthreads\\include\" -DLWS_EXT_PTHREAD_LIBRARIES=\"C:\\Program Files (x86)\\pthreads\\lib\\x64\\libpthreadGC2.a\" ${cmake} && cmake --build . --config DEBUG", + "build": "mkdir build && cd build && set SAI_CPACK=\"-G ZIP\" && cmake .. -DLWS_EXT_PTHREAD_INCLUDE_DIR=\"C:\\Program Files (x86)\\pthreads\\include\" -DLWS_EXT_PTHREAD_LIBRARIES=\"C:\\Program Files (x86)\\pthreads\\lib\\x64\\libpthreadGC2.a\" ${cmake} && cmake --build . --config DEBUG && set CTEST_OUTPUT_ON_FAILURE=1 && ctest . -C DEBUG -j4 --output-on-failure", "default": false } }, @@ -27,57 +34,51 @@ "configurations": { "default": { "cmake": "", - "deps": "openssl", - "platforms": "windows-10, linkit-cross" + "platforms": "windows-10, linkit-cross, linux-debian-buster-arm32" }, "default-examples": { "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", - "deps": "openssl", - "platforms": "windows-10" + "platforms": "windows-10, linux-debian-buster-arm32" }, "lws_system": { "cmake": "-DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=RELEASE -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", - "deps": "libz,openssl", "platforms": "windows-10" }, + "distro_recommended": { + "cmake": "-DLWS_WITH_DISTRO_RECOMMENDED=1", + "platforms": "not linkit-cross, not windows-10, linux-debian-buster-arm32", + "cpack": "&& cpack $SAI_CPACK", + "artifacts": "build/*.rpm, build/*.deb" + }, "lwsws": { - "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", - "deps": "libz,openssl" + "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1" }, "lwsws2": { - "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_LWS_DSH=1", - "deps": "libz,openssl" + "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_LWS_DSH=1" }, "mbedtls": { - "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG", - "deps": "mbedtls" + "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG" }, "noserver": { - "cmake": "-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1", - "deps": "openssl" + "cmake": "-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" }, "noclient": { - "cmake": "-DLWS_WITHOUT_CLIENT=ON -DLWS_WITH_MINIMAL_EXAMPLES=1", - "deps": "openssl" + "cmake": "-DLWS_WITHOUT_CLIENT=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" }, "ext": { - "cmake": "-DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_MINIMAL_EXAMPLES=1", - "deps": "libz,openssl" + "cmake": "-DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_MINIMAL_EXAMPLES=1" }, "nonetwork": { "cmake": "-DLWS_WITH_NETWORK=0" }, "libev": { - "cmake": "-DLWS_WITH_LIBEV=ON", - "deps": "libev" + "cmake": "-DLWS_WITH_LIBEV=ON" }, "libevent": { - "cmake": "-DLWS_WITH_LIBEVENT=ON", - "deps": "libevent" + "cmake": "-DLWS_WITH_LIBEVENT=ON" }, "libglib": { - "cmake": "-DLWS_WITH_GLIB=ON", - "deps": "libglib" + "cmake": "-DLWS_WITH_GLIB=ON" }, "ipv6": { "cmake": "-DLWS_IPV6=ON", @@ -87,24 +88,19 @@ "cmake": "-DLWS_WITH_SSL=OFF" }, "daemon": { - "cmake": "-DLWS_WITHOUT_DAEMONIZE=OFF", - "deps": "openssl" + "cmake": "-DLWS_WITHOUT_DAEMONIZE=OFF" }, "cgi": { - "cmake": "-DLWS_WITH_CGI=ON", - "deps": "openssl" + "cmake": "-DLWS_WITH_CGI=ON" }, "nologs": { - "cmake": "-DLWS_WITH_NO_LOGS=ON", - "deps": "openssl" + "cmake": "-DLWS_WITH_NO_LOGS=ON" }, "smp": { - "cmake": "-DLWS_MAX_SMP=32 -DLWS_WITH_MINIMAL_EXAMPLES=1", - "deps": "openssl" + "cmake": "-DLWS_MAX_SMP=32 -DLWS_WITH_MINIMAL_EXAMPLES=1" }, "nows": { - "cmake": "-DLWS_ROLE_WS=0", - "deps": "openssl" + "cmake": "-DLWS_ROLE_WS=0" }, "threadpool": { "cmake": "-DLWS_WITH_THREADPOOL=1 -DLWS_WITH_MINIMAL_EXAMPLES=1", diff --git a/CMakeLists.txt b/CMakeLists.txt index b638b182..72bbe67f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ set(LWS_WITH_POLL 1) # it's at this point any toolchain file is brought in project(libwebsockets C) +include(CTest) # # Select features recommended for PC distro packaging @@ -72,6 +73,18 @@ option(LWS_WITH_SECURE_STREAMS_PROXY_API "Secure Streams support to work across option(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM "Auth support for api.amazon.com" OFF) option(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY "Secure Streams Policy is hardcoded only" OFF) +# +# CTest options +# +# +# If you build with LWS_WITH_MINIMAL_EXAMPLES, you can use CTest / make test to run +# examples that can give a pass/fail response. By default it runs tests both against +# a local server peer and warmcat.com, if your CI wants to do the tests but does not +# have internet routing, then you can still run a subset of tests with CTest / make +# test that only does local tests by disabling this option. +# +option(LWS_CTEST_INTERNET_AVAILABLE "CTest will performs tests that need the Internet" ON) + # # TLS library options... all except mbedTLS are basically OpenSSL variants. # @@ -261,6 +274,9 @@ if(LWS_WITH_DISTRO_RECOMMENDED) set(LWS_WITH_SPAWN 1) set(LWS_WITH_FSMOUNT 1) set(LWS_ROLE_MQTT 1) + set(LWS_WITH_SECURE_STREAMS 1) + set(LWS_WITH_SECURE_STREAMS_PROXY_API 1) + set(LWS_WITH_DIR 1) endif() if (LWS_WITH_SECURE_STREAMS_PROXY_API) @@ -303,8 +319,11 @@ if (LWS_WITH_STRUCT_SQLITE3) set(LWS_WITH_SQLITE3 1) endif() -# do you care about this? Then send me a patch where it disables it on travis -# but allows it on APPLE +if (LWS_WITH_HTTP_BASIC_AUTH) + # WWW_AUTHENTICATE used by basic auth is an "uncommon header" + set(LWS_WITH_HTTP_UNCOMMON_HEADERS 1) +endif() + if (APPLE) set(LWS_ROLE_DBUS 0) endif() @@ -324,13 +343,47 @@ if (LWS_PLAT_FREERTOS) set(LWS_WITH_FTS 0) endif() + +# Try to find the current Git hash. +find_package(Git) +if(GIT_EXECUTABLE) + execute_process( + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMAND "${GIT_EXECUTABLE}" describe --tags --always + OUTPUT_VARIABLE GIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(LWS_BUILD_HASH ${GIT_HASH}) + + # append the build user and hostname + if(NOT LWS_REPRODUCIBLE) + execute_process( + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMAND "whoami" + OUTPUT_VARIABLE GIT_USER + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + execute_process( + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMAND "hostname" + OUTPUT_VARIABLE GIT_HOST + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + string(REGEX REPLACE "([^\\])[\\]([^\\])" "\\1\\\\\\\\\\2" GIT_USER ${GIT_USER}) + set(LWS_BUILD_HASH ${GIT_USER}@${GIT_HOST}-${GIT_HASH}) + endif() + + message("Git commit hash: ${LWS_BUILD_HASH}") +endif() + set(PACKAGE "libwebsockets") +set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_PACKAGE_NAME "${PACKAGE}") set(CPACK_PACKAGE_VERSION_MAJOR "4") set(CPACK_PACKAGE_VERSION_MINOR "0") -set(CPACK_PACKAGE_VERSION_PATCH "99") +set(CPACK_PACKAGE_VERSION_PATCH "99-${LWS_BUILD_HASH}") set(CPACK_PACKAGE_RELEASE 1) -set(CPACK_GENERATOR "RPM") + set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") set(CPACK_PACKAGE_VENDOR "andy@warmcat.com") set(CPACK_PACKAGE_CONTACT "andy@warmcat.com") @@ -347,6 +400,18 @@ set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") set(VERSION "${CPACK_PACKAGE_VERSION}") +set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) +set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") +set(CPACK_RPM_DEBUGINFO_PACKAGE ON) +# below makes some kind of chimera rpm with binaries and sources +set(CPACK_RPM_PACKAGE_SOURCES OFF) +set(CPACK_RPM_INSTALL_WITH_EXEC ON) + +set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT") +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) +set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON) +set(CPACK_DEBIAN_PACKAGE_SOURCE ON) + set(LWS_LIBRARY_VERSION ${CPACK_PACKAGE_VERSION}) set(LWS_LIBRARY_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) set(LWS_LIBRARY_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR}) @@ -362,38 +427,6 @@ if(WIN32) set(RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/win32port/version.rc) endif() -# Try to find the current Git hash. -find_package(Git) -if(GIT_EXECUTABLE) - execute_process( - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMAND "${GIT_EXECUTABLE}" describe --tags --always - OUTPUT_VARIABLE GIT_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - set(LWS_BUILD_HASH ${GIT_HASH}) - - # append the build user and hostname - if(NOT LWS_REPRODUCIBLE) - execute_process( - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMAND "whoami" - OUTPUT_VARIABLE GIT_USER - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - execute_process( - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMAND "hostname" - OUTPUT_VARIABLE GIT_HOST - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - string(REGEX REPLACE "([^\\])[\\]([^\\])" "\\1\\\\\\\\\\2" GIT_USER ${GIT_USER}) - set(LWS_BUILD_HASH ${GIT_USER}@${GIT_HOST}-${GIT_HASH}) - endif() - - message("Git commit hash: ${LWS_BUILD_HASH}") -endif() - if (LWS_WITH_HTTP2) set(LWS_ROLE_H2 1) endif() @@ -954,30 +987,14 @@ if (LWS_ROLE_DBUS) set(LWS_DBUS_LIB "dbus-1") endif() - CHECK_LIBRARY_EXISTS(${LWS_DBUS_LIB} dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_DBUS1 dbus-1 QUIET) + list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) + list(APPEND LWS_DBUS_LIB ${PC_DBUS1_LIBRARIES}) endif() - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1}) CHECK_C_SOURCE_COMPILES("#include int main(void) { @@ -1778,10 +1795,11 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) set(CMAKE_C_FLAGS "-fanalyzer ${CMAKE_C_FLAGS}" ) endif() + # always warn all and Werror, and generate debug info if (UNIX AND NOT LWS_PLAT_FREERTOS) - set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wstrict-aliasing -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" ) + set(CMAKE_C_FLAGS "-g -Wall -Wsign-compare -Wstrict-aliasing -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" ) else() - set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wuninitialized -Werror ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) + set(CMAKE_C_FLAGS "-g -Wall -Wsign-compare -Wuninitialized -Werror ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) endif() endif () @@ -1839,23 +1857,18 @@ if (LWS_WITH_STATIC) PROPERTIES OUTPUT_NAME websockets_static) endif() + if (NOT LWS_WITH_SHARED) add_custom_command( - TARGET websockets + TARGET websockets POST_BUILD + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h - ) - - add_custom_command( - TARGET websockets + ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets/ - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets - ) - - add_custom_command( - TARGET websockets + ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h - ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h + ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h ) + endif() endif() @@ -1886,25 +1899,18 @@ if (LWS_WITH_SHARED) set_property(TARGET websockets_shared PROPERTY MACOSX_RPATH YES) endif() - add_custom_command( - TARGET websockets_shared - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h - ) - - add_custom_command( - TARGET websockets - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets - ) add_custom_command( - TARGET websockets_shared + TARGET websockets_shared POST_BUILD + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h + ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets/ + ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h - ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h + ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h ) - endif() # Set the so version of the lib. @@ -2157,9 +2163,7 @@ endif() if (LWS_ROLE_DBUS) message("dbus include dir 1: ${LWS_DBUS_INCLUDE1}") - message("dbus include dir 2: ${LWS_DBUS_INCLUDE2}") include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") list(APPEND LIB_LIST ${LWS_DBUS_LIB}) endif() @@ -3059,10 +3063,6 @@ set(CPACK_SOURCE_IGNORE_FILES $(CPACK_SOURCE_IGNORE_FILES) "/.git/" "/build/" "\ # Most people are more used to "make dist" compared to "make package_source" add_custom_target(dist COMMAND "${CMAKE_MAKE_PROGRAM}" package_source) -include(UseRPMTools) -if (RPMTools_FOUND) - RPMTools_ADD_RPM_TARGETS(libwebsockets scripts/libwebsockets.spec) -endif() message("---------------------------------------------------------------------") message(" Settings: (For more help do cmake -LH )") -- Gitee From cced12822bb6ba55296accab55b10b1a00cb2253 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 1 May 2020 12:56:20 +0100 Subject: [PATCH 0098/1062] lws_dir: add rm -rf and glob filter callbacks Bring over two general-purpose callbacks for lws_dir from Sai --- include/libwebsockets/lws-misc.h | 47 +++++++++++ lib/misc/dir.c | 140 +++++++++++++++++++++---------- 2 files changed, 143 insertions(+), 44 deletions(-) diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index 67c56524..05514533 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -577,6 +577,53 @@ lws_dir_callback_function(const char *dirpath, void *user, */ LWS_VISIBLE LWS_EXTERN int lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb); + +/** + * lws_dir_rm_rf_cb() - callback for lws_dir that performs recursive rm -rf + * + * \param dirpath: directory we are at in lws_dir + * \param user: ignored + * \param lde: lws_dir info on the file or directory we are at + * + * This is a readymade rm -rf callback for use with lws_dir. It recursively + * removes everything below the starting dir and then the starting dir itself. + * Works on linux, OSX and Windows at least. + */ +LWS_VISIBLE LWS_EXTERN int +lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde); + +/* + * We pass every file in the base dir through a filter, and call back on the + * ones that match. Directories are ignored. + * + * The original path filter string may look like, eg, "sai-*.deb" or "*.txt" + */ + +typedef int (*lws_dir_glob_cb_t)(void *data, const char *path); + +typedef struct lws_dir_glob { + const char *filter; + lws_dir_glob_cb_t cb; + void *user; +} lws_dir_glob_t; + +/** + * lws_dir_glob_cb() - callback for lws_dir that performs filename globbing + * + * \param dirpath: directory we are at in lws_dir + * \param user: pointer to your prepared lws_dir_glob_cb_t + * \param lde: lws_dir info on the file or directory we are at + * + * \p user is prepared with an `lws_dir_glob_t` containing a callback for paths + * that pass the filtering, a user pointer to pass to that callback, and a + * glob string like "*.txt". It may not contain directories, the lws_dir musr + * be started at the correct dir. + * + * Only the base path passed to lws_dir is scanned, it does not look in subdirs. + */ +LWS_VISIBLE LWS_EXTERN int +lws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde); + #endif /** diff --git a/lib/misc/dir.c b/lib/misc/dir.c index aa8915d5..971afa41 100644 --- a/lib/misc/dir.c +++ b/lib/misc/dir.c @@ -34,51 +34,23 @@ #include #include -#define COMBO_SIZEOF 256 - -#if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0 - -int -lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) -{ - struct lws_dir_entry lde; - uv_dirent_t dent; - uv_fs_t req; - int ret = 1, ir; - uv_loop_t loop; - - ir = uv_loop_init(&loop); - if (ir) { - lwsl_err("%s: loop init failed %d\n", __func__, ir); - return 1; - } - - ir = uv_fs_scandir(&loop, &req, dirpath, 0, NULL); - if (ir < 0) { - lwsl_err("Scandir on %s failed, errno %d\n", dirpath, LWS_ERRNO); - ret = 2; - goto bail; - } - - while (uv_fs_scandir_next(&req, &dent) != UV_EOF) { - lde.name = dent.name; - lde.type = (int)dent.type; - if (cb(dirpath, user, &lde)) - goto bail1; - } - - ret = 0; - -bail1: - uv_fs_req_cleanup(&req); -bail: - while (uv_loop_close(&loop)) - ; - - return ret; -} +#include +#if defined(WIN32) +#include +#define read _read +#define open _open +#define close _close +#define write _write +#define mkdir(x,y) _mkdir(x) +#define rmdir _rmdir +#define unlink _unlink +#define HAVE_STRUCT_TIMESPEC +#if defined(pid_t) +#undef pid_t +#endif +#endif /* win32 */ -#else +#define COMBO_SIZEOF 256 #if !defined(LWS_PLAT_FREERTOS) @@ -232,5 +204,85 @@ bail: return ret; } + +/* + * Check filename against one globby filter + * + * We can support things like "*.rpm" + */ + +static int +lws_dir_glob_check(const char *nm, const char *filt) +{ + while (*nm) { + if (*filt == '*') { + if (!strcmp(nm, filt + 1)) + return 1; + } else { + if (*nm != *filt) + return 0; + filt++; + } + nm++; + } + + return 0; +} + +/* + * We get passed a single filter string, like "*.txt" or "mydir/\*.rpm" or so. + */ + +int +lws_dir_glob_cb(const char *dirpath, void *user, struct lws_dir_entry *lde) +{ + lws_dir_glob_t *filter = (lws_dir_glob_t*)user; + char path[384]; + + if (!strcmp(lde->name, ".") || !strcmp(lde->name, "..")) + return 0; + + if (lde->type == LDOT_DIR) + return 0; + + if (lws_dir_glob_check(lde->name, filter->filter)) { + lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep, + lde->name); + filter->cb(filter->user, path); + } + + return 0; +} + +int +lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde) +{ + char path[384]; + + if (!strcmp(lde->name, ".") || !strcmp(lde->name, "..")) + return 0; + + lws_snprintf(path, sizeof(path), "%s%c%s", dirpath, csep, lde->name); + + if (lde->type == LDOT_DIR) { + lws_dir(path, NULL, lws_dir_rm_rf_cb); + if (rmdir(path)) + lwsl_warn("%s: rmdir %s failed %d\n", __func__, path, errno); + } else { + if (unlink(path)) { +#if defined(WIN32) + SetFileAttributesA(path, FILE_ATTRIBUTE_NORMAL); + if (unlink(path)) +#else + if (rmdir(path)) #endif + lwsl_warn("%s: unlink %s failed %d (type %d)\n", + __func__, path, errno, lde->type); + } + } + + return 0; +} + + #endif -- Gitee From 2d3e62b112a3c850ab0e850c9f7df16943e3056d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 4 May 2020 08:26:48 +0100 Subject: [PATCH 0099/1062] h2: client sid: must be allocated at header send There is no way to allocate a client wsi mux sid before the headers are send, because we don't know the order in which new wsi headers will be sent and so seen by the peer. The peer inisists that sid indexes only increase... we cannot allocat sids monotonically at the client and then send them disordered... --- lib/roles/h2/http2.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index a7c02ca0..34008b37 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -316,10 +316,13 @@ lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi) #endif wsi->h2.initialized = 1; +#if 0 + /* only assign sid at header send time when we know it */ if (!wsi->mux.my_sid) { wsi->mux.my_sid = nwsi->h2.h2n->highest_sid; nwsi->h2.h2n->highest_sid += 2; } +#endif lwsl_info("%s: binding wsi %p to sid %d (next %d)\n", __func__, wsi, (int)wsi->mux.my_sid, (int)nwsi->h2.h2n->highest_sid); @@ -2329,14 +2332,17 @@ lws_h2_client_handshake(struct lws *wsi) lwsl_debug("%s\n", __func__); - nwsi->h2.h2n->highest_sid_opened = sid; - if (!wsi->mux.my_sid) - wsi->mux.my_sid = sid; - else { - lwsl_debug("%s: %p already sid %d\n", - __func__, wsi, (int)wsi->mux.my_sid); - //assert(0); - } + /* + * We MUST allocate our sid here at the point we're about to send the + * stream open. It's because we don't know the order in which multiple + * open streams will send their headers... in h2, sending the headers + * is the point the stream is opened. The peer requires that we only + * open streams in ascending sid order + */ + + wsi->mux.my_sid = nwsi->h2.h2n->highest_sid_opened = sid; + lwsl_info("%s: wsi %p: assigning SID %d at header send\n", __func__, wsi, sid); + lwsl_info("%s: CLIENT_WAITING_TO_SEND_HEADERS: pollout (sid %d)\n", __func__, wsi->mux.my_sid); -- Gitee From 3d995cf7c5c471a010d9cc7c90f20f028f940f6e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 4 May 2020 07:24:58 +0100 Subject: [PATCH 0100/1062] fds: add sanity checks --- .gitignore | 1 + include/libwebsockets/lws-misc.h | 3 +- lib/core-net/close.c | 18 +++- lib/core-net/pollfd.c | 3 +- lib/core-net/private-lib-core-net.h | 18 +++- lib/core-net/wsi.c | 5 + lib/misc/threadpool/threadpool.c | 8 ++ lib/plat/unix/unix-fds.c | 121 ++++++++++++++++++----- lib/plat/unix/unix-spawn.c | 38 +++++-- lib/plat/windows/windows-spawn.c | 22 ++++- lib/roles/http/client/client-handshake.c | 35 ++++--- 11 files changed, 214 insertions(+), 58 deletions(-) diff --git a/.gitignore b/.gitignore index 80c28361..bdbdb429 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,4 @@ doc /openssl3/ /bb-linkit/ /bq/ +/cros/ diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index 05514533..47e7ba0e 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -862,6 +862,7 @@ lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp); * lws_spawn_stdwsi_closed() - inform the spawn one of its stdxxx pipes closed * * \p lsp: the spawn object + * \p wsi: the wsi that is closing * * When you notice one of the spawn stdxxx pipes closed, inform the spawn * instance using this api. When it sees all three have closed, it will @@ -871,7 +872,7 @@ lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp); * has closed. */ LWS_VISIBLE LWS_EXTERN void -lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp); +lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi); /** * lws_spawn_get_stdfd() - return std channel index for stdwsi diff --git a/lib/core-net/close.c b/lib/core-net/close.c index f579733e..93969b35 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -456,6 +456,7 @@ just_kill_connection: lwsl_notice("%s: closing in unestablished state 0x%x\n", __func__, lwsi_state(wsi)); + wsi->socket_is_permanently_unusable = 1; lws_inform_client_conn_fail(wsi, (void *)_reason, sizeof(_reason)); @@ -548,10 +549,7 @@ just_kill_connection: // lwsl_notice("%s: wsi %p, fd %d\n", __func__, wsi, wsi->desc.sockfd); /* checking return redundant since we anyway close */ - if (wsi->desc.sockfd != LWS_SOCK_INVALID) - __remove_wsi_socket_from_fds(wsi); - else - __lws_same_vh_protocol_remove(wsi); + __remove_wsi_socket_from_fds(wsi); lwsi_set_state(wsi, LRS_DEAD_SOCKET); lws_buflist_destroy_all_segments(&wsi->buflist); @@ -634,6 +632,16 @@ __lws_close_free_wsi_final(struct lws *wsi) if (n) lwsl_debug("closing: close ret %d\n", LWS_ERRNO); + __remove_wsi_socket_from_fds(wsi); + if (lws_socket_is_valid(wsi->desc.sockfd)) + delete_from_fd(wsi->context, wsi->desc.sockfd); + +#if !defined(LWS_PLAT_FREERTOS) && !defined(WIN32) && !defined(LWS_PLAT_OPTEE) + delete_from_fdwsi(wsi->context, wsi); +#endif + + sanity_assert_no_sockfd_traces(wsi->context, wsi->desc.sockfd); + wsi->desc.sockfd = LWS_SOCK_INVALID; } @@ -649,6 +657,8 @@ __lws_close_free_wsi_final(struct lws *wsi) } #endif + __lws_wsi_remove_from_sul(wsi); + sanity_assert_no_wsi_traces(wsi->context, wsi); __lws_free_wsi(wsi); } diff --git a/lib/core-net/pollfd.c b/lib/core-net/pollfd.c index aa4c4924..ff873685 100644 --- a/lib/core-net/pollfd.c +++ b/lib/core-net/pollfd.c @@ -378,8 +378,7 @@ __remove_wsi_socket_from_fds(struct lws *wsi) m = wsi->position_in_fds_table; /* these are the only valid possibilities for position_in_fds_table */ - assert(m == LWS_NO_FDS_POS || (m >= 0 && - (unsigned int)m < pt->fds_count)); + assert(m == LWS_NO_FDS_POS || (m >= 0 && (unsigned int)m < pt->fds_count)); if (context->event_loop_ops->io) context->event_loop_ops->io(wsi, diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 19c4d9a4..54f6abdd 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -796,7 +796,6 @@ struct lws { unsigned int h1_ws_proxied:1; unsigned int proxied_ws_parent:1; unsigned int do_bind:1; - unsigned int oom4:1; unsigned int validity_hup:1; unsigned int skip_fallback:1; unsigned int file_desc:1; @@ -883,6 +882,7 @@ struct lws_spawn_piped { struct lws_dll2 dll; lws_sorted_usec_list_t sul; + lws_sorted_usec_list_t sul_reap; struct lws_context *context; struct lws *stdwsi[3]; @@ -1395,6 +1395,22 @@ _lws_generic_transaction_completed_active_conn(struct lws **wsi, char take_vh_lo #define ACTIVE_CONNS_QUEUED 2 #define ACTIVE_CONNS_FAILED 3 +#if defined(_DEBUG) && !defined(LWS_PLAT_FREERTOS) && !defined(WIN32) && !defined(LWS_PLAT_OPTEE) + +int +sanity_assert_no_wsi_traces(const struct lws_context *context, struct lws *wsi); +int +sanity_assert_no_sockfd_traces(const struct lws_context *context, + lws_sockfd_type sfd); +#else +static inline int sanity_assert_no_wsi_traces(const struct lws_context *context, struct lws *wsi) { (void)context; (void)wsi; return 0; } +static inline int sanity_assert_no_sockfd_traces(const struct lws_context *context, lws_sockfd_type sfd) { (void)context; (void)sfd; return 0; } +#endif + + +void +delete_from_fdwsi(const struct lws_context *context, struct lws *wsi); + int lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin); diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index ff003228..8f1c83bc 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -831,8 +831,13 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_l if (__remove_wsi_socket_from_fds(wsi)) return -1; + + sanity_assert_no_wsi_traces(wsi->context, wsi); + sanity_assert_no_sockfd_traces(wsi->context, wsi->desc.sockfd); wsi->desc.sockfd = LWS_SOCK_INVALID; + __lws_wsi_remove_from_sul(wsi); + /* * ... we're doing some magic here in terms of handing off the socket * that has been active to a wsi that has not yet itself been active... diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index b1e56fd4..916c9a3f 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -319,6 +319,9 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) struct lws_threadpool_task **c, *task = NULL; struct lws_threadpool *tp; struct lws *wsi; + char some = 0; + + lwsl_notice("%s\n", __func__); lws_context_lock(context, __func__); @@ -340,6 +343,7 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) !task->wanted_writeable_cb) continue; + some = 1; task->wanted_writeable_cb = 0; lws_memory_barrier(); @@ -363,6 +367,7 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) if (wsi && wsi->tsi == tsi && task->wanted_writeable_cb) { + some = 1; task->wanted_writeable_cb = 0; lws_memory_barrier(); @@ -381,6 +386,9 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) tp = tp->tp_list; } + if (!some) + lwsl_notice("%s: unable to find task wanting sync\n", __func__); + lws_context_unlock(context); return 0; diff --git a/lib/plat/unix/unix-fds.c b/lib/plat/unix/unix-fds.c index a00a57b0..eaa255a1 100644 --- a/lib/plat/unix/unix-fds.c +++ b/lib/plat/unix/unix-fds.c @@ -49,11 +49,77 @@ wsi_from_fd(const struct lws_context *context, int fd) return NULL; } +#if defined(_DEBUG) +int +sanity_assert_no_wsi_traces(const struct lws_context *context, struct lws *wsi) +{ + struct lws **p, **done; + + if (!context->max_fds_unrelated_to_ulimit) + /* can't tell */ + return 0; + + /* slow fds handling */ + + p = context->lws_lookup; + done = &p[context->max_fds]; + + /* confirm the wsi doesn't already exist */ + + while (p != done && *p != wsi) + p++; + + if (p == done) + return 0; + + assert(0); /* this wsi is still mentioned inside lws */ + + return 1; +} + +int +sanity_assert_no_sockfd_traces(const struct lws_context *context, + lws_sockfd_type sfd) +{ + struct lws **p, **done; + + if (sfd == LWS_SOCK_INVALID) + return 0; + + if (!context->max_fds_unrelated_to_ulimit && + context->lws_lookup[sfd - lws_plat_socket_offset()]) { + assert(0); /* the fd is still in use */ + return 1; + } + + /* slow fds handling */ + + p = context->lws_lookup; + done = &p[context->max_fds]; + + /* confirm the sfd not already in use */ + + while (p != done && (!*p || (*p)->desc.sockfd != sfd)) + p++; + + if (p == done) + return 0; + + assert(0); /* this fd is still in the tables */ + + return 1; +} +#endif + + int insert_wsi(const struct lws_context *context, struct lws *wsi) { struct lws **p, **done; + if (sanity_assert_no_wsi_traces(context, wsi)) + return 0; + if (!context->max_fds_unrelated_to_ulimit) { assert(context->lws_lookup[wsi->desc.sockfd - lws_plat_socket_offset()] == 0); @@ -69,36 +135,11 @@ insert_wsi(const struct lws_context *context, struct lws *wsi) p = context->lws_lookup; done = &p[context->max_fds]; - - /* confirm it doesn't already exist */ - - while (p != done && *p != wsi) - p++; - - assert(p == done); - p = context->lws_lookup; - /* confirm fd isn't already in use by a wsi */ - while (p != done && (!*p || (*p)->desc.sockfd != wsi->desc.sockfd)) - p++; + if (sanity_assert_no_sockfd_traces(context, wsi->desc.sockfd)) + return 0; - if (p != done) { - lwsl_warn("%s: wsi %p already lists fd %d, transferring\n", - __func__, *p, wsi->desc.sockfd); - /* - * So something closed that fd outside of the wsi activities... - * later the closed fd has been reused for something else. - * - * Work around it by invalidating the old guy's fd, mark him - * as unable to do any transfers and close him. - */ - - (*p)->desc.sockfd = LWS_SOCK_INVALID; - (*p)->position_in_fds_table = -1; - (*p)->socket_is_permanently_unusable = 1; - lws_set_timeout(*p, 1, LWS_TO_KILL_ASYNC); - } p = context->lws_lookup; /* find an empty slot */ @@ -116,6 +157,8 @@ insert_wsi(const struct lws_context *context, struct lws *wsi) return 0; } + + void delete_from_fd(const struct lws_context *context, int fd) { @@ -156,6 +199,30 @@ delete_from_fd(const struct lws_context *context, int fd) #endif } +void +delete_from_fdwsi(const struct lws_context *context, struct lws *wsi) +{ + + struct lws **p, **done; + + if (!context->max_fds_unrelated_to_ulimit) + return; + + + /* slow fds handling */ + + p = context->lws_lookup; + done = &p[context->max_fds]; + + /* find the match */ + + while (p != done && (!*p || (*p) != wsi)) + p++; + + if (p != done) + *p = NULL; +} + void lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi) { diff --git a/lib/plat/unix/unix-spawn.c b/lib/plat/unix/unix-spawn.c index cbfc11d3..f5cf7700 100644 --- a/lib/plat/unix/unix-spawn.c +++ b/lib/plat/unix/unix-spawn.c @@ -40,6 +40,16 @@ lws_spawn_timeout(struct lws_sorted_usec_list *sul) lws_spawn_piped_kill_child_process(lsp); } +void +lws_spawn_sul_reap(struct lws_sorted_usec_list *sul) +{ + struct lws_spawn_piped *lsp = lws_container_of(sul, + struct lws_spawn_piped, sul_reap); + + lwsl_warn("%s: reaping spawn after last stdpipe closed\n", __func__); + lws_spawn_reap(lsp); +} + static struct lws * lws_create_basic_wsi(struct lws_context *context, int tsi, const struct lws_role_ops *ops) @@ -96,7 +106,13 @@ lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) if (!lsp) return; + lws_dll2_remove(&lsp->dll); + + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, + NULL, LWS_SET_TIMER_USEC_CANCEL); + for (n = 0; n < 3; n++) { +#if 0 if (lsp->pipe_fds[n][!!(n == 0)] == 0) lwsl_err("ZERO FD IN CGI CLOSE"); @@ -104,13 +120,13 @@ lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) close(lsp->pipe_fds[n][!!(n == 0)]); lsp->pipe_fds[n][!!(n == 0)] = LWS_SOCK_INVALID; } +#endif + if (lsp->stdwsi[n]) { + lws_set_timeout(lsp->stdwsi[n], 1, LWS_TO_KILL_ASYNC); + lsp->stdwsi[n] = NULL; + } } - lws_dll2_remove(&lsp->dll); - - lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, - NULL, LWS_SET_TIMER_USEC_CANCEL); - lws_free_set_NULL((*_lsp)); } @@ -510,12 +526,20 @@ bail1: } void -lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp) +lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi) { + int n; + assert(lsp); lsp->pipes_alive--; lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive); - lws_spawn_reap(lsp); + if (!lsp->pipes_alive) + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul_reap, lws_spawn_sul_reap, 1); + + for (n = 0; n < 3; n++) + if (lsp->stdwsi[n] == wsi) + lsp->stdwsi[n] = NULL; } int diff --git a/lib/plat/windows/windows-spawn.c b/lib/plat/windows/windows-spawn.c index 2bd0d103..1269e145 100644 --- a/lib/plat/windows/windows-spawn.c +++ b/lib/plat/windows/windows-spawn.c @@ -39,6 +39,16 @@ lws_spawn_timeout(struct lws_sorted_usec_list *sul) lws_spawn_piped_kill_child_process(lsp); } +void +lws_spawn_sul_reap(struct lws_sorted_usec_list *sul) +{ + struct lws_spawn_piped *lsp = lws_container_of(sul, + struct lws_spawn_piped, sul_reap); + + lwsl_warn("%s: reaping spawn after last stdpipe closed\n", __func__); + lws_spawn_reap(lsp); +} + static struct lws * lws_create_basic_wsi(struct lws_context *context, int tsi, const struct lws_role_ops *ops) @@ -530,12 +540,20 @@ bail1: } void -lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp) +lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi) { + int n; + assert(lsp); lsp->pipes_alive--; lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive); - lws_spawn_reap(lsp); + if (!lsp->pipes_alive) + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul_reap, lws_spawn_sul_reap, 1); + + for (n = 0; n < 3; n++) + if (lsp->stdwsi[n] == wsi) + lsp->stdwsi[n] = NULL; } int diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 0f5d83b3..c90abea5 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -378,15 +378,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, if (!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) return wsi; -#if 0 - if (!ads && !result) { - cce = "dns resolution failed"; - if (!wsi->oom4) - goto oom4; - else - goto failed; - } -#endif + #if !defined(WIN32) /* * We can check using getsockopt if our connect actually completed. @@ -626,17 +618,20 @@ ads_known: if (__insert_wsi_socket_into_fds(wsi->context, wsi)) goto try_next_result_closesock; - if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) - goto try_next_result_fds; - /* + * The fd + wsi combination is entered into the wsi tables + * at this point, with a pollfd + * * Past here, we can't simply free the structs as error * handling as oom4 does. * * We can run the whole close flow, or unpick the fds inclusion * and anything else we have done. */ - wsi->oom4 = 1; + + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) + goto try_next_result_fds; + if (!wsi->protocol) wsi->protocol = &wsi->vhost->protocols[0]; @@ -743,11 +738,17 @@ conn_good: return lws_client_connect_4_established(wsi, NULL, plen); oom4: + /* + * We get here if we're trying to clean up a connection attempt that + * didn't make it as far as getting inserted into the wsi / fd tables + */ + if (lwsi_role_client(wsi) && wsi->protocol /* && lwsi_state_est(wsi) */) lws_inform_client_conn_fail(wsi,(void *)cce, strlen(cce)); /* take care that we might be inserted in fds already */ if (wsi->position_in_fds_table != LWS_NO_FDS_POS) + /* do the full wsi close flow */ goto failed1; /* @@ -759,20 +760,26 @@ oom4: */ { struct lws_vhost *vhost = wsi->vhost; + lws_sockfd_type sfd = wsi->desc.sockfd; lws_vhost_lock(vhost); __lws_free_wsi(wsi); lws_vhost_unlock(vhost); + + sanity_assert_no_wsi_traces(vhost->context, wsi); + sanity_assert_no_sockfd_traces(vhost->context, sfd); } return NULL; try_next_result_fds: - wsi->oom4 = 0; __remove_wsi_socket_from_fds(wsi); try_next_result_closesock: + /* + * We are killing the socket but leaving + */ compatible_close(wsi->desc.sockfd); wsi->desc.sockfd = LWS_SOCK_INVALID; -- Gitee From 2cc0a7f6f612fb3ece4c4d2311840578a5f59bf7 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 4 May 2020 14:34:45 +0100 Subject: [PATCH 0101/1062] ss: handle rx and tx return values properly You can disconnect the stream by returning -1 from tx(). You can give up your chance to send anything by returning 1 from tx(). Returning 0 sends `*len` amount of the provided buffer. Returning <0 from rx() also disconnects the stream. --- lib/secure-streams/README.md | 11 +++++++++++ lib/secure-streams/protocols/ss-h1.c | 12 +++++++++--- lib/secure-streams/protocols/ss-mqtt.c | 16 +++++++++++----- lib/secure-streams/protocols/ss-raw.c | 12 +++++++++--- lib/secure-streams/protocols/ss-ws.c | 14 ++++++++++---- 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index 6098008e..730d6f8f 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -13,6 +13,17 @@ creation, but able to be updated from a remote copy. ![overview](../doc-assets/ss-explain.png) +## Convention for rx and tx callback return + +Function|Return|Meaning +---|---|--- +tx|0|Send the amount of `buf` stored in `*len` +tx|>0|Do not send anything +tx|<0|Finished with stream +rx|>=0|accepted +rx|<0|Finished with stream + + # JSON Policy Database Example JSON policy... formatting is shown for clarity but whitespace can be diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 2daf8747..4376f41c 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -162,7 +162,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], *end = &buf[sizeof(buf) - 1]; - int f = 0, m, status; + int f = 0, m, status, txr; size_t buflen; switch (reason) { @@ -410,7 +410,8 @@ malformed: // lwsl_notice("%s: HTTP_READ: client side sent len %d fl 0x%x\n", // __func__, (int)len, (int)f); - h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f); + if (h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f) < 0) + return -1; return 0; /* don't passthru */ @@ -467,7 +468,12 @@ malformed: #endif - if (h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f)) { + txr = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f); + if (txr < 0) { + lwsl_debug("%s: tx handler asked to close\n", __func__); + return -1; + } + if (txr > 0) { /* don't want to send anything */ lwsl_debug("%s: dont want to write\n", __func__); return 0; diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 99a36b61..1c6d506b 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -31,8 +31,8 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); lws_mqtt_publish_param_t mqpp, *pmqpp; uint8_t buf[LWS_PRE + 1400]; + int f = 0, txr; size_t buflen; - int f = 0; switch (reason) { @@ -93,8 +93,9 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->subseq = 1; - h->info.rx(ss_to_userobj(h), (const uint8_t *)pmqpp->payload, - len, f); + if (h->info.rx(ss_to_userobj(h), (const uint8_t *)pmqpp->payload, + len, f) < 0) + return -1; return 0; /* don't passthru */ @@ -143,8 +144,13 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, buflen = sizeof(buf) - LWS_PRE; - if (h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, - &buflen, &f)) + txr = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, + &buflen, &f); + if (txr < 0) { + lwsl_debug("%s: tx handler asked to close\n", __func__); + return -1; + } + if (txr > 0) /* don't want to send anything */ return 0; diff --git a/lib/secure-streams/protocols/ss-raw.c b/lib/secure-streams/protocols/ss-raw.c index 05dc8248..bad9c257 100644 --- a/lib/secure-streams/protocols/ss-raw.c +++ b/lib/secure-streams/protocols/ss-raw.c @@ -33,7 +33,7 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], *end = &buf[sizeof(buf) - 1]; - int f = 0; + int f = 0, txr; size_t buflen; switch (reason) { @@ -78,7 +78,8 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!h) return 0; - h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, 0); + if (h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, 0) < 0) + return -1; return 0; /* don't passthru */ @@ -88,7 +89,12 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, return 0; buflen = lws_ptr_diff(end, p); - if (h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f)) { + txr = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f); + if (txr < 0) { + lwsl_debug("%s: tx handler asked to close\n", __func__); + return -1; + } + if (txr > 0) { /* don't want to send anything */ lwsl_debug("%s: dont want to write\n", __func__); return 0; diff --git a/lib/secure-streams/protocols/ss-ws.c b/lib/secure-streams/protocols/ss-ws.c index 91d36a58..086975cb 100644 --- a/lib/secure-streams/protocols/ss-ws.c +++ b/lib/secure-streams/protocols/ss-ws.c @@ -30,8 +30,8 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1400]; + int f = 0, f1, txr; size_t buflen; - int f = 0, f1; switch (reason) { @@ -83,7 +83,8 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->subseq = 1; - h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f); + if (h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f) < 0) + return -1; return 0; /* don't passthru */ @@ -98,8 +99,13 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, } buflen = sizeof(buf) - LWS_PRE; - if (h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, - &buflen, &f)) + txr = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, + &buflen, &f); + if (txr < 0) { + lwsl_debug("%s: tx handler asked to close\n", __func__); + return -1; + } + if (txr > 0) /* don't want to send anything */ return 0; -- Gitee From 54e63cf75d482412729476dfa1d8cc738025310c Mon Sep 17 00:00:00 2001 From: Jed Lu Date: Fri, 1 May 2020 14:27:19 -0700 Subject: [PATCH 0102/1062] ss auth: dont attempt auth if necessary blob unavailable --- lib/core/context.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/core/context.c b/lib/core/context.c index 03fdc826..ab6470c9 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -130,12 +130,17 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, #if defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) /* * Skip this if we are running something without the policy for it + * + * If root token is empty, skip too. */ if (target == LWS_SYSTATE_AUTH1 && context->pss_policies && !lws_system_blob_get_size(lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, - 0))) { + 0)) && + lws_system_blob_get_size(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_AUTH, + 1))) { lwsl_info("%s: AUTH1 state triggering api.amazon.com auth\n", __func__); /* * Start trying to acquire it if it's not already in progress -- Gitee From 401d6951da55e61a35b3af449d8692a371b2d43a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 5 May 2020 12:17:27 +0100 Subject: [PATCH 0103/1062] h2: client: do not apply host header if h2 negotiated by alpn If client negotiated over alpn, it will have done SNI. Some peers like youtube.com reject with 400 if you sent a host: as well. --- lib/roles/h2/http2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 34008b37..3377fb1a 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -1414,6 +1414,7 @@ lws_h2_parse_end_of_frame(struct lws *wsi) /* pass on the initial headers to SID 1 */ h2n->swsi->http.ah = wsi->http.ah; h2n->swsi->client_mux_substream = 1; + h2n->swsi->client_h2_alpn = 1; #if defined(LWS_WITH_CLIENT) h2n->swsi->flags = wsi->flags; #endif @@ -2382,7 +2383,8 @@ lws_h2_client_handshake(struct lws *wsi) &p, end)) goto fail_length; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HOST, + if (!wsi->client_h2_alpn && + lws_add_http_header_by_token(wsi, WSI_TOKEN_HOST, (unsigned char *)lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST), lws_hdr_total_length(wsi, _WSI_TOKEN_CLIENT_HOST), -- Gitee From f1f27562a01f54369660fd05b4c85ba6f838f446 Mon Sep 17 00:00:00 2001 From: Jed Lu Date: Tue, 5 May 2020 16:57:11 +0100 Subject: [PATCH 0104/1062] ss: auth: lwa reacquire --- .../system/auth-api.amazon.com/auth.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/secure-streams/system/auth-api.amazon.com/auth.c b/lib/secure-streams/system/auth-api.amazon.com/auth.c index 7e3d6d4e..4772d3ba 100644 --- a/lib/secure-streams/system/auth-api.amazon.com/auth.c +++ b/lib/secure-streams/system/auth-api.amazon.com/auth.c @@ -67,9 +67,7 @@ lws_ss_sys_auth_api_amazon_com_renew(lws_sorted_usec_list_t *sul) struct lws_context *context = lws_container_of(sul, struct lws_context, sul_api_amazon_com); - /* if nothing is there to intercept anything, go all the way */ - lws_state_transition_steps(&context->mgr_system, - LWS_SYSTATE_OPERATIONAL); + lws_ss_sys_auth_api_amazon_com(context); } static signed char @@ -201,6 +199,8 @@ ss_api_amazon_auth_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: + lws_ss_set_metadata(m->ss, "ctype", "application/json", 16); + /* fallthru */ case LWSSSCS_CONNECTING: s = lws_system_blob_get_size( lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, @@ -226,18 +226,16 @@ ss_api_amazon_auth_state(void *userobj, void *sh, lws_ss_constate_t state, lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, AUTH_IDX_LWA)); - if (s) + if (s && context->mgr_system.state != LWS_SYSTATE_OPERATIONAL) lws_sul_schedule(context, 0, &context->sul_api_amazon_com_kick, lws_ss_sys_auth_api_amazon_com_kick, 1); + lws_ss_destroy(&m->ss); + context->hss_auth = NULL; + break; case LWSSSCS_DESTROYING: - lws_sul_schedule(context, 0, &context->sul_api_amazon_com, - NULL, LWS_SET_TIMER_USEC_CANCEL); - lws_system_blob_destroy( - lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, - AUTH_IDX_LWA)); break; default: -- Gitee From 641831b3c52882b7280ba4e3c639fb3f30e5e48a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 6 May 2020 07:41:16 +0100 Subject: [PATCH 0105/1062] context: if linux and fd_limit_per_thread set try to configure by setrlimit --- include/libwebsockets/lws-context-vhost.h | 5 +++++ lib/core/context.c | 19 +++++++++++++++++++ lib/plat/unix/unix-init.c | 4 ++-- lib/roles/http/server/lejp-conf.c | 6 ++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index c0c61a0b..ffb0c8f5 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -737,6 +737,11 @@ struct lws_context_creation_info { * ss_proxy_bind and the given port */ #endif + int rlimit_nofile; + /**< 0 = inherit the initial ulimit for files / sockets from the startup + * environment. Nonzero = try to set the limit for this process. + */ + /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility * diff --git a/lib/core/context.c b/lib/core/context.c index ab6470c9..89c2f3a5 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -30,6 +30,11 @@ static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH; +#if defined(__linux__) +/* for setrlimit */ +#include +#endif + #if defined(LWS_WITH_NETWORK) /* in ms */ static uint32_t default_backoff_table[] = { 1000, 3000, 9000, 17000 }; @@ -411,6 +416,20 @@ lws_create_context(const struct lws_context_creation_info *info) context->options = info->options; +#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) && !defined(WIN32) + /* + * If asked, try to set the rlimit / ulimit for process sockets / files. + * We read the effective limit in a moment, so we will find out the + * real limit according to system constraints then. + */ + if (info->rlimit_nofile) { + struct rlimit rl; + + rl.rlim_cur = rl.rlim_max = info->rlimit_nofile; + setrlimit(RLIMIT_NOFILE, &rl); + } +#endif + #ifndef LWS_NO_DAEMONIZE if (pid_daemon) { context->started_with_parent = pid_daemon; diff --git a/lib/plat/unix/unix-init.c b/lib/plat/unix/unix-init.c index 72c59959..6abe4c7b 100644 --- a/lib/plat/unix/unix-init.c +++ b/lib/plat/unix/unix-init.c @@ -126,8 +126,8 @@ lws_plat_init(struct lws_context *context, #endif context->fd_random = fd; if (context->fd_random < 0) { - lwsl_err("Unable to open random device %s %d\n", - SYSTEM_RANDOM_FILEPATH, context->fd_random); + lwsl_err("Unable to open random device %s %d, errno %d\n", + SYSTEM_RANDOM_FILEPATH, context->fd_random, errno); return 1; } diff --git a/lib/roles/http/server/lejp-conf.c b/lib/roles/http/server/lejp-conf.c index 7f1a1e06..e8b951d8 100644 --- a/lib/roles/http/server/lejp-conf.c +++ b/lib/roles/http/server/lejp-conf.c @@ -47,6 +47,7 @@ static const char * const paths_global[] = { "global.default-alpn", "global.ip-limit-ah", "global.ip-limit-wsi", + "global.rlimit-nofile", }; enum lejp_global_paths { @@ -65,6 +66,7 @@ enum lejp_global_paths { LWJPGP_DEFAULT_ALPN, LWJPGP_IP_LIMIT_AH, LWJPGP_IP_LIMIT_WSI, + LWJPGP_FD_LIMIT_PT, }; static const char * const paths_vhosts[] = { @@ -346,6 +348,10 @@ lejp_globals_cb(struct lejp_ctx *ctx, char reason) a->info->ip_limit_wsi = atoi(ctx->buf); return 0; + case LWJPGP_FD_LIMIT_PT: + a->info->rlimit_nofile = atoi(ctx->buf); + return 0; + default: return 0; } -- Gitee From 43b83c333bfff199e77797f3c2e8710d3fbb93a5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 6 May 2020 07:53:41 +0100 Subject: [PATCH 0106/1062] client: allow setting keep warm time Until now if the generic transaction completes and the connection is idle, there's a fixed 5s grace period to keep the connection up in case something else wants it. This allows setting it in the client creation info struct .keep_warm_secs. If left at 0, then it maintains the backward-compatible 5s wait. --- include/libwebsockets/lws-client.h | 6 ++++++ lib/core-net/connect.c | 5 ++++- lib/core-net/private-lib-core-net.h | 3 +++ lib/core-net/wsi.c | 5 +++-- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index 25fd062c..85b8488d 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -163,6 +163,12 @@ struct lws_client_connect_info { void *mqtt_cp; #endif + uint16_t keep_warm_secs; + /**< 0 means 5s. If the client connection to the endpoint becomes idle, + * defer closing it for this many seconds in case another outgoing + * connection to the same endpoint turns up. + */ + /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility * diff --git a/lib/core-net/connect.c b/lib/core-net/connect.c index 96806f14..3601c536 100644 --- a/lib/core-net/connect.c +++ b/lib/core-net/connect.c @@ -58,7 +58,10 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) if (wsi == NULL) goto bail; - + if (i->keep_warm_secs) + wsi->keep_warm_secs = i->keep_warm_secs; + else + wsi->keep_warm_secs = 5; wsi->context = i->context; wsi->desc.sockfd = LWS_SOCK_INVALID; diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 54f6abdd..811e4ef8 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -830,6 +830,9 @@ struct lws { uint16_t ocport, c_port; uint16_t retry; +#if defined(LWS_WITH_CLIENT) + uint16_t keep_warm_secs; +#endif /* chars */ diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index 8f1c83bc..67ccd7df 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -798,7 +798,8 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_l lwsl_info("%s: nothing pipelined waiting\n", __func__); lwsi_set_state(wsi, LRS_IDLING); - lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5); + lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, + wsi->keep_warm_secs); return 0; /* no new transaction right now */ } @@ -873,7 +874,7 @@ _lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_l wnew->cli_hostname_copy = wsi->cli_hostname_copy; wsi->cli_hostname_copy = NULL; - + wnew->keep_warm_secs = wsi->keep_warm_secs; /* * selected queued guy now replaces the original leader on the -- Gitee From c3a8387afdc4d962ede1bad90d4d458774174579 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 6 May 2020 15:20:22 +0100 Subject: [PATCH 0107/1062] ss: support no tls in policy If there's no trust store in use, create a default vhost so everything can continue normally --- lib/secure-streams/policy-common.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index 24fe833b..fc8883a3 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -189,6 +189,16 @@ lws_ss_policy_set(struct lws_context *context, const char *name) if (!pol->trust_store) { pol = pol->next; + if (!pol && !context->vhost_list) { + /* corner case... there's no trust store used */ + i.options = context->options; + i.vhost_name = "_ss_default"; + i.port = CONTEXT_PORT_NO_LISTEN; + v = lws_create_vhost(context, &i); + if (!v) + lwsl_err("%s: failed to create vhost %s\n", + __func__, i.vhost_name); + } continue; } v = lws_get_vhost_by_name(context, pol->trust_store->name); -- Gitee From bebd3f71a68eac70613c508adccdba971f8d240e Mon Sep 17 00:00:00 2001 From: Kyle Greenwell Date: Thu, 7 May 2020 15:21:48 -0700 Subject: [PATCH 0108/1062] h2: add prior knowledge support --- include/libwebsockets/lws-client.h | 1 + include/libwebsockets/lws-context-vhost.h | 5 +++++ lib/roles/h1/ops-h1.c | 15 ++++++++++++--- lib/roles/h2/http2.c | 5 +++++ lib/roles/http/client/client-http.c | 17 +++++++++++++---- .../minimal-http-client/minimal-http-client.c | 3 +++ .../minimal-http-server/minimal-http-server.c | 3 +++ 7 files changed, 42 insertions(+), 7 deletions(-) diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index 85b8488d..e957b3a3 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -58,6 +58,7 @@ enum lws_client_connect_ssl_connection_flags { * HTTP/2: always possible... uses parallel streams */ LCCSCF_MUXABLE_STREAM = (1 << 17), + LCCSCF_H2_PRIOR_KNOWLEDGE = (1 << 18) }; /** struct lws_client_connect_info - parameters to connect with when using diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index ffb0c8f5..268b3d5a 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -221,6 +221,11 @@ #define LWS_SERVER_OPTION_GLIB (1ll << 33) /**< (CTX) Use glib event loop */ +#define LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE (1ll << 34) + /**< (VH) Tell the vhost to treat plain text http connections as + * H2 with prior knowledge (no upgrade request involved) + */ + /****** add new things just above ---^ ******/ diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index 2b273c83..254e003a 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -907,11 +907,20 @@ rops_adoption_bind_h1(struct lws *wsi, int type, const char *vh_prot_name) return 1; } - lws_role_transition(wsi, LWSIFR_SERVER, (type & LWS_ADOPT_ALLOW_SSL) ? - LRS_SSL_INIT : LRS_HEADERS, &role_ops_h1); + /* If Non-TLS and HTTP2 prior knowledge is enabled, skip to clear text HTTP2 */ + +#if defined(LWS_WITH_HTTP2) + if ((!(type & LWS_ADOPT_ALLOW_SSL)) && (wsi->vhost->options & LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE)) { + lwsl_info("http/2 prior knowledge\n"); + lws_role_call_alpn_negotiated(wsi, "h2"); + } + else +#endif + lws_role_transition(wsi, LWSIFR_SERVER, (type & LWS_ADOPT_ALLOW_SSL) ? + LRS_SSL_INIT : LRS_HEADERS, &role_ops_h1); /* - * We have to bind to h1 as a default even when we're actually going to + * Otherwise, we have to bind to h1 as a default even when we're actually going to * replace it as an h2 bind later. So don't take this seriously if the * default is disabled (ws upgrade caees properly about it) */ diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 3377fb1a..82f01225 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -765,6 +765,11 @@ int lws_h2_do_pps_send(struct lws *wsi) #endif if (lws_is_ssl(lws_get_network_wsi(wsi))) break; + + if (wsi->vhost->options & + LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE) + break; + /* * we need to treat the headers from the upgrade as the * first job. So these need to get shifted to sid 1. diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 2fae4117..8e1b6a3a 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -232,8 +232,13 @@ start_ws_handshake: cce = ebuf; goto bail3; } - } else + } else { wsi->tls.ssl = NULL; + if(wsi->flags & LCCSCF_H2_PRIOR_KNOWLEDGE) { + lwsl_info("h2 prior knowledge\n"); + lws_role_call_alpn_negotiated(wsi, "h2"); + } + } #endif #if defined(LWS_WITH_DETAILED_LATENCY) if (context->detailed_latency_cb) { @@ -248,14 +253,18 @@ start_ws_handshake: #if defined (LWS_WITH_HTTP2) if (wsi->client_h2_alpn) { /* - * We connected to the server and set up tls, and - * negotiated "h2". + * We connected to the server and set up tls and + * negotiated "h2" or connected as clear text + * with http/2 prior knowledge. * * So this is it, we are an h2 master client connection * now, not an h1 client connection. */ + #if defined(LWS_WITH_TLS) - lws_tls_server_conn_alpn(wsi); + if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { + lws_tls_server_conn_alpn(wsi); + } #endif /* send the H2 preface to legitimize the connection */ diff --git a/minimal-examples/http-client/minimal-http-client/minimal-http-client.c b/minimal-examples/http-client/minimal-http-client/minimal-http-client.c index fffe8882..f75d3042 100644 --- a/minimal-examples/http-client/minimal-http-client/minimal-http-client.c +++ b/minimal-examples/http-client/minimal-http-client/minimal-http-client.c @@ -204,6 +204,9 @@ system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, if (lws_cmdline_option(a->argc, a->argv, "--h1")) i.alpn = "http/1.1"; + if (lws_cmdline_option(a->argc, a->argv, "--h2-prior-knowledge")) + i.ssl_connection |= LCCSCF_H2_PRIOR_KNOWLEDGE; + if ((p = lws_cmdline_option(a->argc, a->argv, "-p"))) i.port = atoi(p); diff --git a/minimal-examples/http-server/minimal-http-server/minimal-http-server.c b/minimal-examples/http-server/minimal-http-server/minimal-http-server.c index 1cd26227..7bd74e2b 100644 --- a/minimal-examples/http-server/minimal-http-server/minimal-http-server.c +++ b/minimal-examples/http-server/minimal-http-server/minimal-http-server.c @@ -72,6 +72,9 @@ int main(int argc, const char **argv) info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; + if (lws_cmdline_option(argc, argv, "--h2-prior-knowledge")) + info.options |= LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE; + context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); -- Gitee From af26f0c76547cc652ec287be8537a0eac3578d54 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 10 May 2020 21:48:04 +0100 Subject: [PATCH 0109/1062] lejp: correct return temp type to int lejp_parse() return type is an int... but in the function, the temp for it is a char. This leads to badness that is currently worked around by casting the return through a signed char type. But that leads to more badness since if there's >127 bytes of buffer left after the end of the JSON object, we misreport it. Bite the bullet and fix the temp type, and fix up all the guys who were working around it at the caller return casting to use the resulting straight int. If you are using this api, remove any casting you may have cut- and-pasted like this n = (int)(signed char)lejp_parse(...); ... to just be like this... n = lejp_parse(...); --- lib/jose/jwe/jwe.c | 2 +- lib/jose/jwk/jwk.c | 2 +- lib/jose/jws/jose.c | 2 +- lib/jose/jws/jws.c | 2 +- lib/misc/lejp.c | 181 ++++++++---------- lib/roles/http/server/lejp-conf.c | 2 +- lib/secure-streams/policy-json.c | 2 +- .../system/auth-api.amazon.com/auth.c | 2 +- .../api-tests/api-test-lws_struct-json/main.c | 19 +- .../acme-client/protocol_lws_acme_client.c | 3 +- 10 files changed, 111 insertions(+), 106 deletions(-) diff --git a/lib/jose/jwe/jwe.c b/lib/jose/jwe/jwe.c index feb682f2..61e7c6ad 100755 --- a/lib/jose/jwe/jwe.c +++ b/lib/jose/jwe/jwe.c @@ -148,7 +148,7 @@ lws_jwe_json_parse(struct lws_jwe *jwe, const uint8_t *buf, int len, lejp_construct(&jctx, lws_jwe_json_cb, &args, jwe_json, LWS_ARRAY_SIZE(jwe_json)); - m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)buf, len); + m = lejp_parse(&jctx, (uint8_t *)buf, len); lejp_destruct(&jctx); if (m < 0) { lwsl_notice("%s: parse returned %d\n", __func__, m); diff --git a/lib/jose/jwk/jwk.c b/lib/jose/jwk/jwk.c index fdd1717b..1ad91867 100644 --- a/lib/jose/jwk/jwk.c +++ b/lib/jose/jwk/jwk.c @@ -646,7 +646,7 @@ lws_jwk_import(struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user, lws_jwk_init_jps(&jctx, &jps, jwk, cb, user); - m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)in, (int)len); + m = lejp_parse(&jctx, (uint8_t *)in, (int)len); lejp_destruct(&jctx); if (m < 0) { diff --git a/lib/jose/jws/jose.c b/lib/jose/jws/jose.c index ff608138..4d68a82b 100644 --- a/lib/jose/jws/jose.c +++ b/lib/jose/jws/jose.c @@ -430,7 +430,7 @@ lws_jose_parse(struct lws_jose *jose, const uint8_t *buf, int n, lejp_construct(&jctx, lws_jws_jose_cb, &args, jws_jose, LWS_ARRAY_SIZE(jws_jose)); - m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)buf, n); + m = lejp_parse(&jctx, (uint8_t *)buf, n); lejp_destruct(&jctx); if (m < 0) { lwsl_notice("%s: parse returned %d\n", __func__, m); diff --git a/lib/jose/jws/jws.c b/lib/jose/jws/jws.c index 6cf9dccf..b582a5b0 100644 --- a/lib/jose/jws/jws.c +++ b/lib/jose/jws/jws.c @@ -150,7 +150,7 @@ lws_jws_json_parse(struct lws_jws *jws, const uint8_t *buf, int len, lejp_construct(&jctx, lws_jws_json_cb, &args, jws_json, LWS_ARRAY_SIZE(jws_json)); - m = (int)(signed char)lejp_parse(&jctx, (uint8_t *)buf, len); + m = lejp_parse(&jctx, (uint8_t *)buf, len); lejp_destruct(&jctx); if (m < 0) { lwsl_notice("%s: parse returned %d\n", __func__, m); diff --git a/lib/misc/lejp.c b/lib/misc/lejp.c index 240f116a..668bb434 100644 --- a/lib/misc/lejp.c +++ b/lib/misc/lejp.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -229,13 +229,15 @@ lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len) * unused. */ +static const char esc_char[] = "\"\\/bfnrt"; +static const char esc_tran[] = "\"\\/\b\f\n\r\t"; +static const char tokens[] = "rue alse ull "; + int lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) { - unsigned char c, n, s, ret = LEJP_REJECT_UNKNOWN; - static const char esc_char[] = "\"\\/bfnrt"; - static const char esc_tran[] = "\"\\/\b\f\n\r\t"; - static const char tokens[] = "rue alse ull "; + unsigned char c, n, s; + int ret = LEJP_REJECT_UNKNOWN; if (!ctx->sp && !ctx->pst[ctx->pst_sp].ppos) ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_START); @@ -267,10 +269,9 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) ret = LEJP_REJECT_IDLE_NO_BRACE; goto reject; } - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_OBJECT_START)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_OBJECT_START)) + goto reject_callback; ctx->st[ctx->sp].s = LEJP_MEMBERS; break; case LEJP_MEMBERS: @@ -300,10 +301,8 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) if (ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) { ctx->buf[ctx->npos] = '\0'; if (ctx->pst[ctx->pst_sp].callback(ctx, - LEJPCB_VAL_STR_END) < 0) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + LEJPCB_VAL_STR_END) < 0) + goto reject_callback; } /* pop */ ctx->sp--; @@ -409,10 +408,8 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; lejp_check_path_match(ctx); - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_PAIR_NAME)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_PAIR_NAME)) + goto reject_callback; break; case LEJP_MP_VALUE: @@ -430,10 +427,9 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) c = LEJP_MP_STRING; ctx->npos = 0; ctx->buf[0] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_STR_START)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_STR_START)) + goto reject_callback; goto add_stack_level; case '{': @@ -441,10 +437,9 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END; c = LEJP_MEMBERS; lejp_check_path_match(ctx); - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_OBJECT_START)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_OBJECT_START)) + goto reject_callback; ctx->path_match = 0; goto add_stack_level; @@ -455,10 +450,8 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) ctx->path[ctx->pst[ctx->pst_sp].ppos++] = '['; ctx->path[ctx->pst[ctx->pst_sp].ppos++] = ']'; ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_START)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_START)) + goto reject_callback; ctx->i[ctx->ipos++] = 0; if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) { ret = LEJP_REJECT_MP_DELIM_ISTACK; @@ -479,7 +472,8 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) } /* drop the path [n] bit */ if (ctx->sp) { - ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p; + ctx->pst[ctx->pst_sp].ppos = + ctx->st[ctx->sp - 1].p; ctx->ipos = ctx->st[ctx->sp - 1].i; } ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; @@ -559,15 +553,13 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) ctx->buf[ctx->npos] = '\0'; if (ctx->f & LEJP_SEEN_POINT) { - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NUM_FLOAT)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_NUM_FLOAT)) + goto reject_callback; } else { - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NUM_INT)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_NUM_INT)) + goto reject_callback; } /* then this is the post-number character, loop */ @@ -595,25 +587,22 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) case 3: ctx->buf[0] = '1'; ctx->buf[1] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_TRUE)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_TRUE)) + goto reject_callback; break; case 8: ctx->buf[0] = '0'; ctx->buf[1] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_FALSE)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_FALSE)) + goto reject_callback; break; case 12: ctx->buf[0] = '\0'; - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NULL)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_NULL)) + goto reject_callback; break; } ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END; @@ -636,7 +625,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p; ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; if (ctx->path_match && - ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) + ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) /* * we shrank the path to be * smaller than the matching point @@ -664,12 +653,13 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) } /* drop the path [n] bit */ if (ctx->sp) { - ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p; + ctx->pst[ctx->pst_sp].ppos = + ctx->st[ctx->sp - 1].p; ctx->ipos = ctx->st[ctx->sp - 1].i; } ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; if (ctx->path_match && - ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) + ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) /* * we shrank the path to be * smaller than the matching point @@ -679,49 +669,44 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) /* do LEJP_MP_ARRAY_END processing */ goto redo_character; } - if (c == '}') { - if (!ctx->sp) { - lejp_check_path_match(ctx); - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_OBJECT_END)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_COMPLETE)) - goto reject; - else - /* done, return unused amount */ - return len; - } + if (c != '}') { + ret = LEJP_REJECT_MP_C_OR_E_NEITHER; + goto reject; + } + if (!ctx->sp) { + lejp_check_path_match(ctx); + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_OBJECT_END)) + goto reject_callback; + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_COMPLETE)) + goto reject_callback; - /* pop */ + /* done, return unused amount */ + return len; + } - ctx->sp--; - if (ctx->sp) { - ctx->pst[ctx->pst_sp].ppos = - ctx->st[ctx->sp].p; - ctx->ipos = ctx->st[ctx->sp].i; - } - ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; - if (ctx->path_match && - ctx->pst[ctx->pst_sp].ppos <= - ctx->path_match_len) - /* - * we shrank the path to be - * smaller than the matching point - */ - ctx->path_match = 0; + /* pop */ - lejp_check_path_match(ctx); - if (ctx->pst[ctx->pst_sp].callback(ctx, - LEJPCB_OBJECT_END)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } - break; + ctx->sp--; + if (ctx->sp) { + ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp].p; + ctx->ipos = ctx->st[ctx->sp].i; } + ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; + if (ctx->path_match && + ctx->pst[ctx->pst_sp].ppos <= ctx->path_match_len) + /* + * we shrank the path to be + * smaller than the matching point + */ + ctx->path_match = 0; - ret = LEJP_REJECT_MP_C_OR_E_NEITHER; - goto reject; + lejp_check_path_match(ctx); + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_OBJECT_END)) + goto reject_callback; + break; case LEJP_MP_ARRAY_END: array_end: @@ -732,7 +717,8 @@ array_end: ctx->i[ctx->ipos - 1]++; ctx->st[ctx->sp].s = LEJP_MP_VALUE; if (ctx->sp) - ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp - 1].p; + ctx->pst[ctx->pst_sp].ppos = + ctx->st[ctx->sp - 1].p; ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; break; } @@ -753,10 +739,9 @@ emit_string_char: /* assemble the string value into chunks */ ctx->buf[ctx->npos++] = c; if (ctx->npos == sizeof(ctx->buf) - 1) { - if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_STR_CHUNK)) { - ret = LEJP_REJECT_CALLBACK; - goto reject; - } + if (ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_VAL_STR_CHUNK)) + goto reject_callback; ctx->npos = 0; } continue; @@ -798,6 +783,10 @@ redo_character: return LEJP_CONTINUE; + +reject_callback: + ret = LEJP_REJECT_CALLBACK; + reject: ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_FAILED); return ret; diff --git a/lib/roles/http/server/lejp-conf.c b/lib/roles/http/server/lejp-conf.c index e8b951d8..15789e8b 100644 --- a/lib/roles/http/server/lejp-conf.c +++ b/lib/roles/http/server/lejp-conf.c @@ -930,7 +930,7 @@ lwsws_get_config(void *user, const char *f, const char * const *paths, if (!n) break; - m = (int)(signed char)lejp_parse(&ctx, buf, n); + m = lejp_parse(&ctx, buf, n); } while (m == LEJP_CONTINUE); close(fd); diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 51c05f1a..89170533 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -766,7 +766,7 @@ lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len) struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args; int m; - m = (int)(signed char)lejp_parse(&args->jctx, buf, (int)len); + m = lejp_parse(&args->jctx, buf, (int)len); if (m == LEJP_CONTINUE || m >= 0) return m; diff --git a/lib/secure-streams/system/auth-api.amazon.com/auth.c b/lib/secure-streams/system/auth-api.amazon.com/auth.c index 4772d3ba..d41b7bbd 100644 --- a/lib/secure-streams/system/auth-api.amazon.com/auth.c +++ b/lib/secure-streams/system/auth-api.amazon.com/auth.c @@ -124,7 +124,7 @@ ss_api_amazon_auth_rx(void *userobj, const uint8_t *buf, size_t len, int flags) lws_system_blob_heap_empty(ab); } - n = (int)(signed char)lejp_parse(&m->jctx, buf, (int)len); + n = lejp_parse(&m->jctx, buf, (int)len); if (n < 0) { lejp_destruct(&m->jctx); lws_system_blob_destroy( diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/main.c b/minimal-examples/api-tests/api-test-lws_struct-json/main.c index 7edfefb9..4083f320 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/main.c +++ b/minimal-examples/api-tests/api-test-lws_struct-json/main.c @@ -345,7 +345,7 @@ int main(int argc, const char **argv) a.ac_block_size = 512; lws_struct_json_init_parse(&ctx, NULL, &a); - n = (int)(signed char)lejp_parse(&ctx, (uint8_t *)json_tests[m], + n = lejp_parse(&ctx, (uint8_t *)json_tests[m], (int)strlen(json_tests[m])); if (n < 0) { lwsl_err("%s: notification JSON decode failed '%s'\n", @@ -482,6 +482,23 @@ done: lws_struct_json_serialize_destroy(&ser); + lwsl_notice("Test set 2\n"); + + memset(&a, 0, sizeof(a)); + a.map_st[0] = t2_map; + a.map_entries_st[0] = LWS_ARRAY_SIZE(t2_map); + a.ac_block_size = 128; + + lws_struct_json_init_parse(&ctx, NULL, &a); + m = lejp_parse(&ctx, (uint8_t *)t2, (int)strlen(t2)); + if (m < 0 || !a.dest) { + lwsl_notice("%s: notification JSON decode failed '%s'\n", + __func__, lejp_error_to_string(m)); + goto bail; + } + + lwsl_notice("Test set 2: %d: %s\n", m, + ((sai_cancel_t *)a.dest)->task_uuid); lwsl_user("Completed: PASS\n"); diff --git a/plugins/acme-client/protocol_lws_acme_client.c b/plugins/acme-client/protocol_lws_acme_client.c index c2b72954..73c9c672 100644 --- a/plugins/acme-client/protocol_lws_acme_client.c +++ b/plugins/acme-client/protocol_lws_acme_client.c @@ -1196,8 +1196,7 @@ pkt_add_hdrs: case ACME_STATE_DIRECTORY: ((char *)in)[len] = '\0'; puts(in); - m = (int)(signed char)lejp_parse(&ac->jctx, - (uint8_t *)in, len); + m = lejp_parse(&ac->jctx, (uint8_t *)in, len); if (m < 0 && m != LEJP_CONTINUE) { lwsl_notice("lejp parse failed %d\n", m); goto failed; -- Gitee From 9f1d019352e5d06db436674b985da4eff9738777 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 14 Apr 2020 19:04:13 +0100 Subject: [PATCH 0110/1062] CTest: migrate and deprecate existing selftest scripts Replace the bash selftest plumbing with CTest. To use the selftests, build with -DLWS_WITH_MINIMAL_EXAMPLES=1 and `CTEST_OUTPUT_ON_FAILURE=1 make test` or just `make test`. To disable tests that require internet access, also give -DLWS_CTEST_INTERNET_AVAILABLE=0 Remove travis and appveyor scripts on master. Remove travis and appveyor decals on README.md. --- .sai.json | 25 ++- .travis.yml | 54 ----- CMakeLists.txt | 3 +- README.md | 2 +- READMEs/README.build-windows.md | 190 ++++++++++++++---- READMEs/README.ctest.md | 66 ++++++ appveyor.yml | 77 ------- lib/core-net/close.c | 7 +- lib/core-net/dummy-callback.c | 4 +- lib/core-net/pollfd.c | 2 +- lib/core/libwebsockets.c | 12 +- lib/event-libs/libuv/libuv.c | 5 +- lib/misc/lws-struct-lejp.c | 6 +- lib/misc/lws-struct-sqlite.c | 5 +- lib/misc/threadpool/threadpool.c | 15 +- lib/plat/unix/unix-fds.c | 2 +- lib/plat/unix/unix-spawn.c | 60 ++++-- lib/plat/windows/windows-spawn.c | 3 + lib/roles/cgi/ops-cgi.c | 11 +- lib/roles/http/client/client-http.c | 9 +- lib/roles/ws/client-ws.c | 2 +- lib/tls/mbedtls/mbedtls-client.c | 4 +- lib/tls/mbedtls/mbedtls-server.c | 2 +- lib/tls/openssl/openssl-client.c | 18 +- lib/tls/openssl/openssl-ssl.c | 2 +- lib/tls/private-network.h | 4 +- lib/tls/tls-client.c | 8 +- .../api-test-async-dns/CMakeLists.txt | 5 + .../api-tests/api-test-async-dns/selftest.sh | 24 --- .../api-tests/api-test-fts/selftest.sh | 58 ------ .../api-test-gencrypto/CMakeLists.txt | 1 + .../api-tests/api-test-gencrypto/selftest.sh | 24 --- .../api-tests/api-test-jose/CMakeLists.txt | 4 + .../api-tests/api-test-jose/selftest.sh | 24 --- .../api-tests/api-test-lws_dsh/CMakeLists.txt | 1 + .../api-tests/api-test-lws_dsh/selftest.sh | 24 --- .../api-test-lws_struct-json/CMakeLists.txt | 1 + .../api-tests/api-test-lws_struct-json/main.c | 29 +++ .../api-test-lws_struct-json/selftest.sh | 24 --- .../api-test-lws_struct_sqlite/CMakeLists.txt | 3 +- .../api-test-lws_struct_sqlite/selftest.sh | 24 --- .../api-test-lws_tokenize/CMakeLists.txt | 3 +- .../api-test-lws_tokenize/selftest.sh | 24 --- .../api-tests/api-test-lwsac/CMakeLists.txt | 3 +- .../api-tests/api-test-lwsac/selftest.sh | 24 --- .../minimal-dbus-client/CMakeLists.txt | 47 +---- .../CMakeLists.txt | 47 +---- .../minimal-dbus-server/CMakeLists.txt | 47 +---- .../minimal-dbus-ws-proxy/CMakeLists.txt | 45 +---- .../CMakeLists.txt | 9 + .../minimal-http-client-h2-rxflow/selftest.sh | 33 --- .../CMakeLists.txt | 11 + .../minimal-http-client-hugeurl.c | 18 +- .../minimal-http-client-hugeurl/selftest.sh | 47 ----- .../minimal-http-client-multi/CMakeLists.txt | 148 ++++++++++++++ .../minimal-http-client-multi.c | 20 +- .../minimal-http-client-multi/selftest.sh | 66 ------ .../minimal-http-client-post/CMakeLists.txt | 66 ++++++ .../minimal-http-client-post.c | 6 + .../minimal-http-client-post/selftest.sh | 39 ---- .../minimal-http-client/CMakeLists.txt | 13 +- .../minimal-http-client/selftest.sh | 33 --- .../minimal-http-server-form-post.c | 3 + .../minimal-http-server-tls.c | 19 +- minimal-examples/selftests-library.sh | 110 ---------- minimal-examples/selftests.sh | 61 ------ .../minimal-ws-client-rx/CMakeLists.txt | 10 +- .../minimal-ws-client-rx/selftest.sh | 25 --- .../minimal-ws-client-spam/CMakeLists.txt | 47 +++++ .../minimal-ws-client-spam.c | 3 + .../minimal-ws-client-spam/selftest.sh | 26 --- plugins/protocol_lws_mirror.c | 17 +- scripts/ctest-background-kill.sh | 54 +++++ scripts/ctest-background.sh | 16 ++ scripts/libwebsockets.spec | 180 ----------------- test-apps/test-server.c | 22 +- win32port/version.rc.in | 5 +- 77 files changed, 875 insertions(+), 1316 deletions(-) delete mode 100644 .travis.yml create mode 100644 READMEs/README.ctest.md delete mode 100644 appveyor.yml delete mode 100755 minimal-examples/api-tests/api-test-async-dns/selftest.sh delete mode 100755 minimal-examples/api-tests/api-test-fts/selftest.sh delete mode 100755 minimal-examples/api-tests/api-test-gencrypto/selftest.sh delete mode 100755 minimal-examples/api-tests/api-test-jose/selftest.sh delete mode 100755 minimal-examples/api-tests/api-test-lws_dsh/selftest.sh delete mode 100755 minimal-examples/api-tests/api-test-lws_struct-json/selftest.sh delete mode 100755 minimal-examples/api-tests/api-test-lws_struct_sqlite/selftest.sh delete mode 100755 minimal-examples/api-tests/api-test-lws_tokenize/selftest.sh delete mode 100755 minimal-examples/api-tests/api-test-lwsac/selftest.sh delete mode 100755 minimal-examples/http-client/minimal-http-client-h2-rxflow/selftest.sh delete mode 100755 minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh delete mode 100755 minimal-examples/http-client/minimal-http-client-multi/selftest.sh delete mode 100755 minimal-examples/http-client/minimal-http-client-post/selftest.sh delete mode 100755 minimal-examples/http-client/minimal-http-client/selftest.sh delete mode 100755 minimal-examples/selftests-library.sh delete mode 100755 minimal-examples/selftests.sh delete mode 100644 minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh delete mode 100755 minimal-examples/ws-client/minimal-ws-client-spam/selftest.sh create mode 100755 scripts/ctest-background-kill.sh create mode 100755 scripts/ctest-background.sh delete mode 100644 scripts/libwebsockets.spec diff --git a/.sai.json b/.sai.json index 41c7a9e5..294ffa30 100644 --- a/.sai.json +++ b/.sai.json @@ -14,6 +14,9 @@ "linux-fedora-32-x86_64": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, + "linux-centos-8-x8664": { + "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" + }, "linux-debian-buster-arm32": { "build": "mkdir build;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j3 && make -j DESTDIR=../destdir install && ctest -j3 --output-on-failure ${cpack}", "default": false @@ -44,20 +47,34 @@ "cmake": "-DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=RELEASE -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", "platforms": "windows-10" }, + "secure-streams": { + "cmake": "-DLWS_WITH_SECURE_STREAMS=1", + "platforms": "windows-10" + }, + "secure-streams-proxy": { + "cmake": "-DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1", + "platforms": "not windows-10" + }, "distro_recommended": { "cmake": "-DLWS_WITH_DISTRO_RECOMMENDED=1", "platforms": "not linkit-cross, not windows-10, linux-debian-buster-arm32", "cpack": "&& cpack $SAI_CPACK", - "artifacts": "build/*.rpm, build/*.deb" + "artifacts": "build/*.rpm, build/*.deb, build/*.zip" }, "lwsws": { - "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1" + "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", + # no distro -devel package for libuv + "platforms": "not linux-centos-8-x8664" }, "lwsws2": { - "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_LWS_DSH=1" + "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_LWS_DSH=1", + # no distro -devel package for libuv + "platforms": "not linux-centos-8-x8664" }, "mbedtls": { - "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG" + "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG", + # no distro -devel package for mbedtls + "platforms": "not linux-centos-8-x8664" }, "noserver": { "cmake": "-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b0b9f59b..00000000 --- a/.travis.yml +++ /dev/null @@ -1,54 +0,0 @@ -env: - # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created - # via the "travis encrypt" command using the project repo's public key - global: - - secure: "KhAdQ9ja+LBObWNQTYO7Df5J4DyOih6S+eerDMu8UPSO+CoWV2pWoQzbOfocjyOscGOwC+2PrrHDNZyGfqkCLDXg1BxynXPCFerHC1yc2IajvKpGXmAAygNIvp4KACDfGv/dkXrViqIzr/CdcNaU4vIMHSVb5xkeLi0W1dPnQOI=" - matrix: - # 2019-09-30: travis build no longer has dbus - # LWS_METHOD=lwsws CMAKE_ARGS="-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_ROLE_DBUS=1 -DLWS_DBUS_INCLUDE2=/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1" - # LWS_METHOD=lwsws2 CMAKE_ARGS="-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_ROLE_DBUS=1 -DLWS_DBUS_INCLUDE2=/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ -DLWS_WITH_LWS_DSH=1" - - LWS_METHOD=lwsws CMAKE_ARGS="-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1" - - LWS_METHOD=lwsws2 CMAKE_ARGS="-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_LWS_DSH=1" - - LWS_METHOD=default CMAKE_ARGS="-DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=mbedtls CMAKE_ARGS="-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG" - - LWS_METHOD=ss CMAKE_ARGS="-DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=ss+mbedtls CMAKE_ARGS="-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=noserver CMAKE_ARGS="-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=noclient CMAKE_ARGS="-DLWS_WITHOUT_CLIENT=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=noext CMAKE_ARGS="-DLWS_WITHOUT_EXTENSIONS=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=nonetwork CMAKE_ARGS="-DLWS_WITH_NETWORK=0" - - LWS_METHOD=libev CMAKE_ARGS="-DLWS_WITH_LIBEV=ON" - - LWS_METHOD=ipv6 CMAKE_ARGS="-DLWS_IPV6=ON" - - LWS_METHOD=nossl CMAKE_ARGS="-DLWS_WITH_SSL=OFF" - - LWS_METHOD=nodaemon CMAKE_ARGS="-DLWS_WITHOUT_DAEMONIZE=ON" - - LWS_METHOD=cgi CMAKE_ARGS="-DLWS_WITH_CGI=ON" - - LWS_METHOD=nologs CMAKE_ARGS="-DLWS_WITH_NO_LOGS=ON" - - LWS_METHOD=smp CMAKE_ARGS="-DLWS_MAX_SMP=32 -DLWS_WITH_MINIMAL_EXAMPLES=1" - - LWS_METHOD=nows CMAKE_ARGS="-DLWS_ROLE_WS=0" - - LWS_METHOD=mqtt CMAKE_ARGS="-DLWS_ROLE_MQTT=1" - - LWS_METHOD=threadpool CMAKE_ARGS="-DLWS_WITH_THREADPOOL=1 -DLWS_WITH_MINIMAL_EXAMPLES=1" - -os: - - linux - - osx -language: generic -install: - - ./scripts/travis_install.sh -# - ./travis-tool.sh github_package jimhester/covr - -#after_success: -# - Rscript -e 'covr::coveralls()' - -script: - - ./scripts/travis_control.sh -sudo: required -dist: trusty -addons: - coverity_scan: - project: - name: "warmcat/libwebsockets" - notification_email: andy@warmcat.com - build_command_prepend: "mkdir build && cd build && cmake .." - build_command: "cmake --build ." - branch_pattern: coverity_scan - diff --git a/CMakeLists.txt b/CMakeLists.txt index 72bbe67f..5d5abe38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,7 +272,8 @@ if(LWS_WITH_DISTRO_RECOMMENDED) set(LWS_WITH_STRUCT_JSON 1) set(LWS_WITH_STRUCT_SQLITE3 1) set(LWS_WITH_SPAWN 1) - set(LWS_WITH_FSMOUNT 1) +# libmount is problematic on Centos 8 / RHEL 8 +# set(LWS_WITH_FSMOUNT 1) set(LWS_ROLE_MQTT 1) set(LWS_WITH_SECURE_STREAMS 1) set(LWS_WITH_SECURE_STREAMS_PROXY_API 1) diff --git a/README.md b/README.md index ce2e1398..8e1e7c47 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Travis Build Status](https://travis-ci.org/warmcat/libwebsockets.svg)](https://travis-ci.org/warmcat/libwebsockets) [![Appveyor Build status](https://ci.appveyor.com/api/projects/status/qfasji8mnfnd2r8t?svg=true)](https://ci.appveyor.com/project/lws-team/libwebsockets) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3576/badge.svg)](https://scan.coverity.com/projects/3576) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2266/badge)](https://bestpractices.coreinfrastructure.org/projects/2266) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/144fb195a83046e484a75c8b4c6cfc99)](https://www.codacy.com/app/lws-team/libwebsockets?utm_source=github.com&utm_medium=referral&utm_content=warmcat/libwebsockets&utm_campaign=Badge_Grade) [![Total alerts](https://img.shields.io/lgtm/alerts/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/alerts/) [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/context:cpp) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/context:javascript) +[![CI status](https://libwebsockets.org/sai/status/libwebsockets)](https://libwebsockets.org/git/libwebsockets) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3576/badge.svg)](https://scan.coverity.com/projects/3576) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2266/badge)](https://bestpractices.coreinfrastructure.org/projects/2266) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/144fb195a83046e484a75c8b4c6cfc99)](https://www.codacy.com/app/lws-team/libwebsockets?utm_source=github.com&utm_medium=referral&utm_content=warmcat/libwebsockets&utm_campaign=Badge_Grade) [![Total alerts](https://img.shields.io/lgtm/alerts/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/alerts/) [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/context:cpp) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/warmcat/libwebsockets.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/warmcat/libwebsockets/context:javascript) # Libwebsockets diff --git a/READMEs/README.build-windows.md b/READMEs/README.build-windows.md index 7b853694..e9d7a23b 100644 --- a/READMEs/README.build-windows.md +++ b/READMEs/README.build-windows.md @@ -1,28 +1,47 @@ # Some notes for the windows jungle -This was how I compiled libwebsockets in windows March 2020. +This was how I compiled libwebsockets starting from a blank windows install +in March - April 2020. Doing this on a linux distro is way simpler and quicker +than all this! -## OpenSSL +## Notes on vm installation -### Installing prebuilt libs +### Disk size -I used the 1.1.1d (the latest) libs from here, as recommended on the OpenSSL site +For building you'll need 40GB+ available for the guest storage. -[overbyte.eu](https:..wiki.overbyte.eu/wiki/index.php/ICS_Download#Download_OpenSSL_Binaries_.28required_for_SSL-enabled_components.29) +### Required: Windows product key -I had to use procmon64 (windows' strace) to establish that these libraries are -looking for a cert bundle at "C:\Program Files\Common Files\SSL\cert.pem"... it's not -included in the zip file from the above, so... +Assuming like me the first thing you do with a new laptop is install Linux over +the windows it came with, you can recover your 'windows tax' windows product key +from your device typically using `sudo strings /sys/firmware/acpi/tables/MSDM`, +and use that for your VM install. -### Installing a cert bundle +### Required: Spice guest -You can get a trusted cert bundle from here +To have shared clipboard, and for windows video driver to match your vm window +resolution, you must install spice guest tools inside the windows VM. It also +installs some virtio pieces you will want. -[drwetter/testssl cert bundle](https://raw.githubusercontent.com/drwetter/testssl.sh/3.1dev/etc/Microsoft.pem) +https://www.spice-space.org/download/windows/spice-guest-tools/spice-guest-tools-latest.exe -Save it into `C:\Program Files\Common Files\SSL\cert.pem` where openssl will be able to see it. +### Blood-pressure reduction: Firefox + +https://www.mozilla.org/en-US/exp/firefox/ + +When it's up, add-ons: ublock origin, privacy badger, noscript, disable search +bar prediction -### Installing cmake +### Blood-pressure reduction: Clink + +This is a hack on cmd.exe that lets it understand Ctrl-R and fixup unix-style +slashes automagically. + +https://github.com/mridgers/clink/releases/download/0.4.9/clink_0.4.9_setup.exe + +If you're usually using *nix, you definitely need this to keep your sanity. + +### Required: cmake CMake have a windows installer thing downloadable from here @@ -30,51 +49,113 @@ CMake have a windows installer thing downloadable from here after that you can use `cmake` from the terminal OK. -### Installing git +### Required: git Visit the canonical git site to download their windows installer thing [git](https://git-scm.com/download/win) -after that `git` from the terminal is working. +**Select the install option for "extra unix commands"** so you can get `ls -l`, +`cp`, `mv` and suchlike working in cmd.exe... that's awesome, thanks git! + +Afterwards you can just use `git` as normal from cmd.exe as well. -### Install the free "community" visual studio +### Required: Install the "free" "community" visual studio You can do this through "windows store" by searching for "visual studio" -I installed as little as possible, we just want the C "C++" tools. +I installed as little as possible, we just want the C "C++" tools... 7GB :-) It still wouldn't link without the "mt" helper tool from the huge windows SDK, so you have to install GB of that as well. -### Building +They don't mention it during the install, but after 30 days this "free" +"community" edition demands you open a microsoft account or it stops working. +In the install they give you the option to add a microsoft account and the +alternative is, "not now, maybe later". Compare and contrast to gcc or git or +the other FOSS projects. -Somehow windows cmake seems slightly broken, some of the plugins and -examples are conditional on `if (NOT WIN32)`, but it configures them -anyway. For this reason (it seems "only", it worked when I commented the -cmake entries for the related plugins) `-DLWS_WITH_MINIMAL_EXAMPLES=1` +### Required: OpenSSL -Instead I followed how appveyor builds the stuff in CI... clone libwebsockets then +Ugh... I tried using prebuilts but it's unreliable and needs an unfeasible +amount of trust. So I recommend bite the bullet and build your own... that's +trivial on Linux but of course windows makes everything nasty. + +At least hopefully all the "research" is done and listed out here. + +#### OpenSSL build Prerequisite: install perl binary + +Move the git version of perl out of the way, it won't work for OpenSSL build ``` -> git clone https://libwebsockets.org/repo/libwebsockets -> cd libwebsockets -> mkdir build -> cd build -> cmake .. -> cmake --build . --config DEBUG +mv /usr/bin/perl /usr/bin/perl-git ``` -Installing requires admin privs, I opened a second cmd window as admin and did it -there. +For windows, OpenSSL "recommends" ActiveState perl but it doesn't work for me, +complaining about stuff needed from cpan and then dying when it was installed. +"Strawberry Perl" is installed in `C:\Strawberry` and worked out the box. + +http://strawberryperl.com/download/5.30.2.1/strawberry-perl-5.30.2.1-64bit.msi + +The installer sets up `%PATH%` if you open a new cmd window. + +#### OpenSSL build Prerequisite: NASM + +Go here and click on the latest stable, download the win32 .exe + +https://nasm.us/ + +Just install via the defaults. Then add it to the PATH temporarily... ``` -> cmake --install . --config DEBUG +$ set PATH=%PATH%;C:\Program Files (x86)\NASM +``` + +#### OpenSSL build setup: source VC env vars + +These fix up the PATH and include dirs etc necessary for VC build in the cmd +window. + +``` +$ call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 +``` + +### OpenSSL build: + +Grab openssl from git... assuming the prerequisites above went well it will +just sit there building for 30 minutes or whatever. + +``` +$ git clone https://github.com/openssl/openssl +$ cd openssl +$ perl Configure VC-WIN64A +$ nmake ``` -After that you can run the test apps OK. +Afterwards, open an Administrator mode cmd.exe, redo the msvc path and then +install the build. -## pthreads +``` +$ cd openssl +$ call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 +$ nmake install +``` + +Oh another grindingly slow windows build action. Finally it's in there in +`C:\Program Files\OpenSSL`. + +libraries are looking for a cert bundle at "C:\Program Files\Common Files\SSL\cert.pem"... +it's not documented or included in the zip file from the above, so... + +#### Installing a cert bundle + +You can get a trusted cert bundle from here + +[drwetter/testssl cert bundle](https://raw.githubusercontent.com/drwetter/testssl.sh/3.1dev/etc/Microsoft.pem) + +Save it into `C:\Program Files\Common Files\SSL\cert.pem` where openssl will be able to see it. + +## Required: pthreads It's amazing but after all these years windows doesn't offer pthreads compatibility itself. Just like the many other missing POSIX bits like fork(). @@ -89,6 +170,45 @@ Then I created a dir "C:\Program Files (x86)\pthreads", and copied the `dll`, The cmake incantation to build against pthreads set up like that is ``` - $ cmake .. -DLWS_EXT_PTHREAD_INCLUDE_DIR="C:\Program Files (x86)\pthreads\include" -DLWS_EXT_PTHREAD_LIBRARIES="C:\Program Files (x86)\pthreads\lib\x64\libpthreadGC2.a" -DLWS_WITH_MINIMAL_EXAMPLES=1 + $ cmake .. -DLWS_HAVE_PTHREAD_H=1 -DLWS_EXT_PTHREAD_INCLUDE_DIR="C:\Program Files (x86)\pthreads\include" -DLWS_EXT_PTHREAD_LIBRARIES="C:\Program Files (x86)\pthreads\lib\x64\libpthreadGC2.a" -DLWS_WITH_MINIMAL_EXAMPLES=1 ``` +## Building libwebsockets + +We'll clone libwebsockets then use cmake to build via vs tools + +``` +> git clone https://libwebsockets.org/repo/libwebsockets +> cd libwebsockets +> mkdir build +> cd build +> cmake .. +> cmake --build . --config DEBUG +``` + +Installing requires admin privs, I opened a second cmd window as admin and did it +there. + +``` +> cmake --install . --config DEBUG +``` + +### Hack the libs into view + +The libs we built against aren't visible in the system, I don't know what +Real Windows Programmers are supposed to do about that, but I used an Admin cmd +prompt to copy them into C:\windows\system32 + +``` +$ cp "C:\Program Files (x86)\pthreads\dll\x64\pthreadGC2.dll" "C:\Program Files\OpenSSL\bin\libcrypto-3.dll" "C:\Program Files\OpenSSL\bin\libssl-3.dll" C:\Windows\system32 +``` + +After that you can run the test apps OK, eg + +``` +$ libwebsockets-test-server.exe -s +``` + +## Note about using paths with spaces in with cmake + + diff --git a/READMEs/README.ctest.md b/READMEs/README.ctest.md new file mode 100644 index 00000000..142f33f6 --- /dev/null +++ b/READMEs/README.ctest.md @@ -0,0 +1,66 @@ +## Using CTest with lws + +### Prerequisites + +You need a recent cmake to have the CTest tests work properly, if you're on an +older distro you need to update your cmake. Luckily Kitware provide a repo for +common distros. These instructions work for bionic and xenial. + +First remove the old distro cmake and install the pieces needed to get the new repo keys + +``` +# apt purge --auto-remove cmake +# apt install gnupg wget apt-transport-https ca-certificates +# wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add - +# apt edit-sources +``` + +Add the line `deb https://apt.kitware.com/ubuntu/ bionic main` at the end +replacing `bionic` with `xenial` as needed, and save (:wq). Then + +``` +# apt update +# apt install cmake +``` + +## Generating the tests + +The main tests just need `-DLWS_WITH_MINIMAL_EXAMPLES=1`. You can optionally set +`-DLWS_CTEST_INTERNET_AVAILABLE=0` to indicate you can't run the tests that need +internet connectivity. + +## Running the tests + +CMake puts the test action into a build-host type specific form, for unix type +platforms you just run `make test` or `CTEST_OUTPUT_ON_FAILURE=1 make test` to +see what happened to any broken tests. + +On windows, it looks like `ctest . -C DEBUG` or RELEASE if that was the build +type. + +## Considerations for creating tests + +### Timeout + +The default test timeout is 1500s, for that reason it's good practice to set +a more suitable `TIMEOUT` property on every test. + +### Working Directory + +Server-side test apps usually need to be run from their `./minimal-examples/...` +directory so they can access their assets like index.html etc. + +However when building with `-DLWS_WITH_MBEDTLS=1` then even client-side apps +need to be run from their directory, since they need to get the trusted CA for +warmcat.com or libwebsockets.org additionally. + +For that reason it's good practice to set the `WORKING_DIRECTORY` property to +the home dir of the example app in all cases. + +### SIGTERM from CTest... + +After a lot of headscratching I realized some tests were failing simply because +CTest was firing SIGTERMs at them for whatever reason. I added a commandline +option `--ignore-sigterm` in `lws_cmdline_option_handle_builtin()` to allow the +test to defeat this, and then it continues and completes fine. + diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 809ff62b..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,77 +0,0 @@ -environment: - matrix: - - LWS_METHOD: jose - CMAKE_ARGS: -DLWS_WITH_JOSE=1 - - - LWS_METHOD: x64 - CMAKE_ARGS: -DCMAKE_GENERATOR_PLATFORM=x64 -DLWS_WITH_HTTP2=1 -DLWS_WITH_PLUGINS=1 -DLIBUV_INCLUDE_DIRS=C:\assets\libuv64\include -DLIBUV_LIBRARIES=C:\assets\libuv64\libuv.lib - - - LWS_METHOD: lwsws - CMAKE_ARGS: -DLWS_WITH_LWSWS=1 -DSQLITE3_INCLUDE_DIRS=C:\assets\sqlite3 -DSQLITE3_LIBRARIES=C:\assets\sqlite3\sqlite3.lib -DLIBUV_INCLUDE_DIRS=C:\assets\libuv\include -DLIBUV_LIBRARIES=C:\assets\libuv\libuv.lib - - - LWS_METHOD: default - - - LWS_METHOD: noserver - CMAKE_ARGS: -DLWS_WITHOUT_SERVER=ON - - - LWS_METHOD: noclient - CMAKE_ARGS: -DLWS_WITHOUT_CLIENT=ON - - - LWS_METHOD: noext - CMAKE_ARGS: -DLWS_WITHOUT_EXTENSIONS=ON - - - LWS_METHOD: nossl - CMAKE_ARGS: -DLWS_WITH_SSL=OFF - -install: - - appveyor DownloadFile https://libwebsockets.org:444/win-libuv.zip - - mkdir c:\assets - - mkdir c:\assets\libuv - - 7z x -oc:\assets\libuv win-libuv.zip - - appveyor DownloadFile https://libwebsockets.org:444/win-libuv64.zip - - mkdir c:\assets\libuv64 - - 7z x -oc:\assets\libuv64 win-libuv64.zip - - appveyor DownloadFile https://libwebsockets.org:444/nsis-3.0rc1-setup.exe - - cmd /c start /wait nsis-3.0rc1-setup.exe /S /D=C:\nsis - - appveyor DownloadFile https://libwebsockets.org:444/sqlite-dll-win32-x86-3130000.zip - - mkdir c:\assets\sqlite3 - - 7z x -oc:\assets\sqlite3 sqlite-dll-win32-x86-3130000.zip - - SET PATH=C:\Program Files\NSIS\;C:\Program Files (x86)\NSIS\;c:\nsis;%PATH% - -build_script: - - md build - - cd build - - cmake -DCMAKE_BUILD_TYPE=Release %CMAKE_ARGS% .. - - cmake --build . --config Release - -after_build: - - cd %APPVEYOR_BUILD_FOLDER% - - mkdir staging - - mkdir staging\include - - cp -r %APPVEYOR_BUILD_FOLDER%\build\bin %APPVEYOR_BUILD_FOLDER%\build\lib staging - - if EXIST staging\bin\share mv staging\bin\share staging - - if NOT EXIST staging\share\libwebsockets-test-server mkdir staging\share\libwebsockets-test-server - - IF EXIST %APPVEYOR_BUILD_FOLDER%\build\libwebsockets-test-server.pem cp %APPVEYOR_BUILD_FOLDER%\build\libwebsockets-test-server.pem staging\share\libwebsockets-test-server - - IF EXIST %APPVEYOR_BUILD_FOLDER%\build\libwebsockets-test-server.key.pem cp %APPVEYOR_BUILD_FOLDER%\build\libwebsockets-test-server.key.pem staging\share\libwebsockets-test-server - - IF EXIST %APPVEYOR_BUILD_FOLDER%\build\lws_config.h cp %APPVEYOR_BUILD_FOLDER%\build\lws_config.h staging\include - - cp %APPVEYOR_BUILD_FOLDER%\include\libwebsockets.h staging\include - - cp -r %APPVEYOR_BUILD_FOLDER%\include\libwebsockets staging\include - - 7z a build\lws-%LWS_METHOD%-%APPVEYOR_BUILD_ID%.zip %APPVEYOR_BUILD_FOLDER%\staging\* - -artifacts: - - path: build\lws-%LWS_METHOD%-%APPVEYOR_BUILD_ID%.zip - -#deploy: -#- provider: BinTray -# username: lws-team -# api_key: -# secure: nDpZ7P/wrk98DwJPMC6KpCC23QrVP8f3RxvKzBaqOmb9LiVrg1IyO1cc5vcgShZC -# subject: lws-team -# repo: libwebsockets -# package: windows -# publish: true -# override: true -# explode: false - -matrix: - fast_finish: true diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 93969b35..ad6e9990 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -144,6 +144,7 @@ __lws_free_wsi(struct lws *wsi) return; __lws_reset_wsi(wsi); + __lws_wsi_remove_from_sul(wsi); if (wsi->context->event_loop_ops->destroy_wsi) wsi->context->event_loop_ops->destroy_wsi(wsi); @@ -271,7 +272,7 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, wsi2 = wsi->child_list; while (wsi2) { wsi1 = wsi2->sibling_list; - wsi2->parent = NULL; +// wsi2->parent = NULL; /* stop it doing shutdown processing */ wsi2->socket_is_permanently_unusable = 1; __lws_close_free_wsi(wsi2, reason, @@ -306,7 +307,7 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, lws_cgi_remove_and_kill(wsi->parent); /* end the binding between us and master */ - if (wsi->parent->http.cgi) + if (wsi->parent->http.cgi && wsi->parent->http.cgi->lsp) wsi->parent->http.cgi->lsp->stdwsi[(int)wsi->lsp_channel] = NULL; } @@ -454,7 +455,7 @@ just_kill_connection: !wsi->already_did_cce && wsi->protocol) { static const char _reason[] = "closed before established"; - lwsl_notice("%s: closing in unestablished state 0x%x\n", + lwsl_debug("%s: closing in unestablished state 0x%x\n", __func__, lwsi_state(wsi)); wsi->socket_is_permanently_unusable = 1; diff --git a/lib/core-net/dummy-callback.c b/lib/core-net/dummy-callback.c index 2089ffcb..bfbb6c35 100644 --- a/lib/core-net/dummy-callback.c +++ b/lib/core-net/dummy-callback.c @@ -125,7 +125,7 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: case LWS_CALLBACK_CLIENT_CLOSED: - lwsl_user("%s: client closed: parent %p\n", __func__, wsi->parent); + lwsl_info("%s: client closed: parent %p\n", __func__, wsi->parent); if (wsi->parent) lws_set_timeout(wsi->parent, 1, LWS_TO_KILL_ASYNC); break; @@ -193,7 +193,7 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason, return 1; case LWS_CALLBACK_CLOSED: - lwsl_user("%s: closed\n", __func__); + lwsl_info("%s: closed\n", __func__); return -1; case LWS_CALLBACK_RECEIVE: diff --git a/lib/core-net/pollfd.c b/lib/core-net/pollfd.c index ff873685..f27c404c 100644 --- a/lib/core-net/pollfd.c +++ b/lib/core-net/pollfd.c @@ -417,7 +417,7 @@ __remove_wsi_socket_from_fds(struct lws *wsi) lwsl_err("no wsi for fd %d pos %d, " "pt->fds_count=%d\n", (int)pt->fds[m].fd, m, pt->fds_count); - assert(0); + // assert(0); } else end_wsi->position_in_fds_table = m; } diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index e9283285..128bbbd5 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -27,6 +27,7 @@ #ifdef LWS_HAVE_SYS_TYPES_H #include #endif +#include void lws_ser_wu16be(uint8_t *b, uint16_t u) @@ -1086,9 +1087,15 @@ lws_cmdline_option(int argc, const char **argv, const char *val) static const char * const builtins[] = { "-d", "--udp-tx-loss", - "--udp-rx-loss" + "--udp-rx-loss", + "--ignore-sigterm" }; +static void +lws_sigterm_catch(int sig) +{ +} + void lws_cmdline_option_handle_builtin(int argc, const char **argv, struct lws_context_creation_info *info) @@ -1113,6 +1120,9 @@ lws_cmdline_option_handle_builtin(int argc, const char **argv, case 2: info->udp_loss_sim_rx_pc = m; break; + case 3: + signal(SIGTERM, lws_sigterm_catch); + break; } } diff --git a/lib/event-libs/libuv/libuv.c b/lib/event-libs/libuv/libuv.c index 378a5dc6..2b0883e6 100644 --- a/lib/event-libs/libuv/libuv.c +++ b/lib/event-libs/libuv/libuv.c @@ -545,7 +545,8 @@ elops_destroy_context2_uv(struct lws_context *context) static int elops_wsi_logical_close_uv(struct lws *wsi) { - if (!lws_socket_is_valid(wsi->desc.sockfd)) + if (!lws_socket_is_valid(wsi->desc.sockfd) && + wsi->role_ops != &role_ops_raw_file) return 0; if (wsi->listener || wsi->event_pipe) { @@ -656,7 +657,7 @@ elops_io_uv(struct lws *wsi, int flags) } if (!w->uv.pwatcher || wsi->told_event_loop_closed) { - lwsl_err("%s: no watcher\n", __func__); + lwsl_info("%s: no watcher\n", __func__); return; } diff --git a/lib/misc/lws-struct-lejp.c b/lib/misc/lws-struct-lejp.c index c9a29cc7..0d9009d4 100644 --- a/lib/misc/lws-struct-lejp.c +++ b/lib/misc/lws-struct-lejp.c @@ -138,7 +138,7 @@ lws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason) if (map->type == LSMT_SCHEMA) { while (n--) { - if (strcmp(map->colname, ctx->buf)) { + if (strncmp(map->colname, ctx->buf, ctx->npos)) { map++; continue; } @@ -157,7 +157,9 @@ lws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason) return 0; } - lwsl_notice("%s: unknown schema\n", __func__); + lwsl_notice("%s: unknown schema %.*s, tried %d\n", __func__, + ctx->npos, ctx->buf, + (int)args->map_entries_st[ctx->pst_sp]); goto cleanup; } diff --git a/lib/misc/lws-struct-sqlite.c b/lib/misc/lws-struct-sqlite.c index 6a532323..ef550c12 100644 --- a/lib/misc/lws-struct-sqlite.c +++ b/lib/misc/lws-struct-sqlite.c @@ -511,7 +511,7 @@ lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, SQLITE_OPEN_READWRITE | (create_if_missing ? SQLITE_OPEN_CREATE : 0), NULL) != SQLITE_OK) { - lwsl_err("%s: Unable to open db %s: %s\n", + lwsl_info("%s: Unable to open db %s: %s\n", __func__, sqlite3_path, sqlite3_errmsg(*pdb)); return 1; @@ -520,7 +520,8 @@ lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, #if !defined(WIN32) lws_get_effective_uid_gid(context, &uid, &gid); if (uid) - chown(sqlite3_path, uid, gid); + if (chown(sqlite3_path, uid, gid)) + lwsl_err("%s: failed to chown %s\n", __func__, sqlite3_path); chmod(sqlite3_path, 0600); lwsl_debug("%s: created %s owned by %u:%u mode 0600\n", __func__, diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index 916c9a3f..0e1a98c6 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -319,9 +319,6 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) struct lws_threadpool_task **c, *task = NULL; struct lws_threadpool *tp; struct lws *wsi; - char some = 0; - - lwsl_notice("%s\n", __func__); lws_context_lock(context, __func__); @@ -340,10 +337,10 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) wsi = task_to_wsi(task); if (!wsi || wsi->tsi != tsi || - !task->wanted_writeable_cb) + (!task->wanted_writeable_cb && + task->status != LWS_TP_STATUS_SYNCING)) continue; - some = 1; task->wanted_writeable_cb = 0; lws_memory_barrier(); @@ -365,9 +362,9 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) wsi = task_to_wsi(task); if (wsi && wsi->tsi == tsi && - task->wanted_writeable_cb) { + (task->wanted_writeable_cb || + task->status == LWS_TP_STATUS_SYNCING)) { - some = 1; task->wanted_writeable_cb = 0; lws_memory_barrier(); @@ -386,9 +383,6 @@ lws_threadpool_tsi_context(struct lws_context *context, int tsi) tp = tp->tp_list; } - if (!some) - lwsl_notice("%s: unable to find task wanting sync\n", __func__); - lws_context_unlock(context); return 0; @@ -829,6 +823,7 @@ lws_threadpool_destroy(struct lws_threadpool *tp) pthread_mutex_destroy(&tp->lock); + memset(tp, 0xdd, sizeof(*tp)); lws_free(tp); } diff --git a/lib/plat/unix/unix-fds.c b/lib/plat/unix/unix-fds.c index eaa255a1..a236b9ba 100644 --- a/lib/plat/unix/unix-fds.c +++ b/lib/plat/unix/unix-fds.c @@ -182,7 +182,7 @@ delete_from_fd(const struct lws_context *context, int fd) p++; if (p == done) - lwsl_err("%s: fd %d not found\n", __func__, fd); + lwsl_debug("%s: fd %d not found\n", __func__, fd); else *p = NULL; diff --git a/lib/plat/unix/unix-spawn.c b/lib/plat/unix/unix-spawn.c index f5cf7700..3f6ffbd8 100644 --- a/lib/plat/unix/unix-spawn.c +++ b/lib/plat/unix/unix-spawn.c @@ -110,6 +110,8 @@ lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, NULL, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul_reap, + NULL, LWS_SET_TIMER_USEC_CANCEL); for (n = 0; n < 3; n++) { #if 0 @@ -179,7 +181,8 @@ lws_spawn_reap(struct lws_spawn_piped *lsp) */ if (!lsp->ungraceful && lsp->pipes_alive) { - lwsl_debug("%s: stdwsi alive, not reaping\n", __func__); + lwsl_notice("%s: %d stdwsi alive, not reaping\n", __func__, + lsp->pipes_alive); return 0; } @@ -326,9 +329,16 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) /* create pipes for [stdin|stdout] and [stderr] */ - for (n = 0; n < 3; n++) + for (n = 0; n < 3; n++) { if (pipe(lsp->pipe_fds[n]) == -1) goto bail1; + lws_plat_apply_FD_CLOEXEC(lsp->pipe_fds[n][n == 0]); + } + + /* + * At this point, we have 6 pipe fds open on lws side and no wsis + * bound to them + */ /* create wsis for each stdin/out/err fd */ @@ -350,14 +360,26 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) /* read side is 0, stdin we want the write side, others read */ - lws_plat_apply_FD_CLOEXEC(lsp->pipe_fds[n][n == 0]); lsp->stdwsi[n]->desc.sockfd = lsp->pipe_fds[n][n == 0]; if (fcntl(lsp->pipe_fds[n][n == 0], F_SETFL, O_NONBLOCK) < 0) { lwsl_err("%s: setting NONBLOCK failed\n", __func__); goto bail2; } + + /* + * We have bound 3 x pipe fds to wsis, wr side of stdin and rd + * side of stdout / stderr... those are marked CLOEXEC so they + * won't go through the fork + * + * rd side of stdin and wr side of stdout / stderr are open but + * not bound to anything on lws side. + */ } + /* + * Stitch the wsi fd into the poll wait + */ + for (n = 0; n < 3; n++) { if (context->event_loop_ops->sock_accept) if (context->event_loop_ops->sock_accept(lsp->stdwsi[n])) @@ -384,7 +406,7 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) lsp->stdwsi[LWS_STDOUT]->desc.sockfd, lsp->stdwsi[LWS_STDERR]->desc.sockfd); - /* we are ready with the redirection pipes... run the thing */ + /* we are ready with the redirection pipes... do the (v)fork */ #if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) lsp->child_pid = fork(); #else @@ -407,15 +429,13 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) if (lsp->child_pid) { /* - * We are the parent process - * - * close: stdin:r, stdout:w, stderr:w - * hide from other forks: stdin:w, stdout:r, stderr:r + * We are the parent process. We can close our copy of the + * "other" side of the pipe fds, ie, rd for stdin and wr for + * stdout / stderr. */ - for (n = 0; n < 3; n++) { - /* these guys don't have any wsi footprint */ + for (n = 0; n < 3; n++) + /* these guys didn't have any wsi footprint */ close(lsp->pipe_fds[n][n != 0]); - } lsp->pipes_alive = 3; lsp->created = lws_now_usecs(); @@ -460,26 +480,26 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) if (chdir(wd)) lwsl_notice("%s: Failed to cd to %s\n", __func__, wd); + /* + * Bind the child's stdin / out / err to its side of our pipes + */ + for (m = 0; m < 3; m++) { if (dup2(lsp->pipe_fds[m][m != 0], m) < 0) { lwsl_err("%s: stdin dup2 failed\n", __func__); goto bail3; } /* - * If we used fork(), then we can close both sides of the - * original pipe now we bound it to fd 0, 1, 2. + * CLOEXEC on the lws-side of the pipe fds should have already + * dealt with closing those for the child perspective. * - * But if we used vfork(), until the exec() we have hijacked - * the original process temporarily and we are (ab)using its - * identity during this pre-exec() time + * Now it has done the dup, the child should close its original + * copies of its side of the pipes. */ -#if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) + close(lsp->pipe_fds[m][m != 0]); -#endif } - // lwsl_notice("%s: child cd %s, exec %s\n", __func__, wd, i->exec_array[0]); - #if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE) #if defined(__linux__) m = 0; diff --git a/lib/plat/windows/windows-spawn.c b/lib/plat/windows/windows-spawn.c index 1269e145..fcc11c6b 100644 --- a/lib/plat/windows/windows-spawn.c +++ b/lib/plat/windows/windows-spawn.c @@ -128,6 +128,9 @@ lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, NULL, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_schedule(lsp->context, 0, &lsp->sul_reap, NULL, + LWS_SET_TIMER_USEC_CANCEL); + lws_sul_schedule(lsp->context, 0, &lsp->sul_poll, NULL, LWS_SET_TIMER_USEC_CANCEL); diff --git a/lib/roles/cgi/ops-cgi.c b/lib/roles/cgi/ops-cgi.c index 6217335b..63863c38 100644 --- a/lib/roles/cgi/ops-cgi.c +++ b/lib/roles/cgi/ops-cgi.c @@ -113,6 +113,15 @@ rops_pt_init_destroy_cgi(struct lws_context *context, return 0; } +static int +rops_close_role_cgi(struct lws_context_per_thread *pt, struct lws *wsi) +{ + if (wsi->parent && wsi->parent->http.cgi && wsi->parent->http.cgi->lsp) + lws_spawn_stdwsi_closed(wsi->parent->http.cgi->lsp, wsi); + + return 0; +} + const struct lws_role_ops role_ops_cgi = { /* role name */ "cgi", @@ -131,7 +140,7 @@ const struct lws_role_ops role_ops_cgi = { /* encapsulation_parent */ NULL, /* alpn_negotiated */ NULL, /* close_via_role_protocol */ NULL, - /* close_role */ NULL, + /* close_role */ rops_close_role_cgi, /* close_kill_connection */ NULL, /* destroy_role */ rops_destroy_role_cgi, /* adoption_bind */ NULL, diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 8e1b6a3a..8cf66a2c 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -28,11 +28,11 @@ int lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) { - int n; /* we can retry this... just cook the SSL BIO the first time */ if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { + int n; if (!wsi->tls.ssl) { if (lws_ssl_client_bio_create(wsi) < 0) { @@ -50,12 +50,13 @@ lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) if (!do_c1) return 0; - n = lws_ssl_client_connect1(wsi); + n = lws_ssl_client_connect1(wsi, (char *)wsi->context->pt[(int)wsi->tsi].serv_buf, + wsi->context->pt_serv_buf_size); lwsl_debug("%s: lws_ssl_client_connect1: %d\n", __func__, n); if (!n) return CCTLS_RETURN_RETRY; /* caller should return 0 */ if (n < 0) { - *pcce = "lws_ssl_client_connect1 failed"; + *pcce = (const char *)wsi->context->pt[(int)wsi->tsi].serv_buf; return CCTLS_RETURN_ERROR; } } else @@ -485,6 +486,8 @@ bail3: __func__, wsi, lwsi_state(wsi)); if (cce) lwsl_info("reason: %s\n", cce); + else + cce = "unknown"; lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3"); diff --git a/lib/roles/ws/client-ws.c b/lib/roles/ws/client-ws.c index 802125ab..9a8c609a 100644 --- a/lib/roles/ws/client-ws.c +++ b/lib/roles/ws/client-ws.c @@ -131,7 +131,7 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) */ if (lws_ws_client_rx_sm(wsi, *(*buf)++)) { - lwsl_notice("%s: client_rx_sm exited, DROPPING %d\n", + lwsl_info("%s: client_rx_sm exited, DROPPING %d\n", __func__, (int)len); return -1; } diff --git a/lib/tls/mbedtls/mbedtls-client.c b/lib/tls/mbedtls/mbedtls-client.c index fa9aed75..0eac6b5f 100644 --- a/lib/tls/mbedtls/mbedtls-client.c +++ b/lib/tls/mbedtls/mbedtls-client.c @@ -167,7 +167,7 @@ int ERR_get_error(void) } enum lws_ssl_capable_status -lws_tls_client_connect(struct lws *wsi) +lws_tls_client_connect(struct lws *wsi, char *errbuf, int elen) { int m, n = SSL_connect(wsi->tls.ssl); const unsigned char *prot; @@ -191,6 +191,8 @@ lws_tls_client_connect(struct lws *wsi) if (!n) /* we don't know what he wants, but he says to retry */ return LWS_SSL_CAPABLE_MORE_SERVICE; + lws_snprintf(errbuf, elen, "mbedtls connect %d %d %d", n, m, errno); + return LWS_SSL_CAPABLE_ERROR; } diff --git a/lib/tls/mbedtls/mbedtls-server.c b/lib/tls/mbedtls/mbedtls-server.c index d7a93559..f0dcb6e2 100644 --- a/lib/tls/mbedtls/mbedtls-server.c +++ b/lib/tls/mbedtls/mbedtls-server.c @@ -325,7 +325,7 @@ lws_tls_server_accept(struct lws *wsi) } m = SSL_get_error(wsi->tls.ssl, n); - lwsl_debug("%s: %p: accept SSL_get_error %d errno %d\n", __func__, + lwsl_notice("%s: %p: accept SSL_get_error %d errno %d\n", __func__, wsi, m, errno); // mbedtls wrapper only diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index e4d33d89..1a6e5350 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -376,7 +376,7 @@ no_client_cert: } enum lws_ssl_capable_status -lws_tls_client_connect(struct lws *wsi) +lws_tls_client_connect(struct lws *wsi, char *errbuf, int elen) { #if defined(LWS_HAVE_SSL_set_alpn_protos) && \ defined(LWS_HAVE_SSL_get0_alpn_selected) @@ -384,17 +384,13 @@ lws_tls_client_connect(struct lws *wsi) char a[32]; unsigned int len; #endif - int m, n; -#if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO) - int en; -#endif + int m, n, en; errno = 0; ERR_clear_error(); n = SSL_connect(wsi->tls.ssl); -#if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO) en = errno; -#endif + m = lws_ssl_get_error(wsi, n); if (m == SSL_ERROR_SYSCALL @@ -405,11 +401,15 @@ lws_tls_client_connect(struct lws *wsi) #if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO) lwsl_info("%s: n %d, m %d, errno %d\n", __func__, n, m, en); #endif + lws_snprintf(errbuf, elen, "connect SYSCALL %d", en); return LWS_SSL_CAPABLE_ERROR; } - if (m == SSL_ERROR_SSL) + if (m == SSL_ERROR_SSL) { + n = lws_snprintf(errbuf, elen, "connect SSL err %d: ", m); + ERR_error_string_n(m, errbuf + n, elen - n); return LWS_SSL_CAPABLE_ERROR; + } if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) return LWS_SSL_CAPABLE_MORE_SERVICE_READ; @@ -437,6 +437,8 @@ lws_tls_client_connect(struct lws *wsi) if (!n) /* we don't know what he wants, but he says to retry */ return LWS_SSL_CAPABLE_MORE_SERVICE; + lws_snprintf(errbuf, elen, "connect unk %d", m); + return LWS_SSL_CAPABLE_ERROR; } diff --git a/lib/tls/openssl/openssl-ssl.c b/lib/tls/openssl/openssl-ssl.c index 1f2fd825..e1f8bd45 100644 --- a/lib/tls/openssl/openssl-ssl.c +++ b/lib/tls/openssl/openssl-ssl.c @@ -60,7 +60,7 @@ int lws_ssl_get_error(struct lws *wsi, int n) lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m, errno); - assert (errno != 9); + // assert (errno != 9); return m; } diff --git a/lib/tls/private-network.h b/lib/tls/private-network.h index 88474fc1..0cb92321 100644 --- a/lib/tls/private-network.h +++ b/lib/tls/private-network.h @@ -102,7 +102,7 @@ lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi); LWS_EXTERN int lws_ssl_client_bio_create(struct lws *wsi); LWS_EXTERN int -lws_ssl_client_connect1(struct lws *wsi); +lws_ssl_client_connect1(struct lws *wsi, char *errbuf, int len); LWS_EXTERN int lws_ssl_client_connect2(struct lws *wsi, char *errbuf, int len); LWS_EXTERN int @@ -158,7 +158,7 @@ LWS_EXTERN enum lws_ssl_capable_status __lws_tls_shutdown(struct lws *wsi); LWS_EXTERN enum lws_ssl_capable_status -lws_tls_client_connect(struct lws *wsi); +lws_tls_client_connect(struct lws *wsi, char *errbuf, int len); LWS_EXTERN int lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len); LWS_EXTERN int diff --git a/lib/tls/tls-client.c b/lib/tls/tls-client.c index b1b2da76..a3d45536 100644 --- a/lib/tls/tls-client.c +++ b/lib/tls/tls-client.c @@ -25,11 +25,11 @@ #include "private-lib-core.h" int -lws_ssl_client_connect1(struct lws *wsi) +lws_ssl_client_connect1(struct lws *wsi, char *errbuf, int len) { int n; - n = lws_tls_client_connect(wsi); + n = lws_tls_client_connect(wsi, errbuf, len); switch (n) { case LWS_SSL_CAPABLE_ERROR: return -1; @@ -53,12 +53,12 @@ lws_ssl_client_connect2(struct lws *wsi, char *errbuf, int len) int n; if (lwsi_state(wsi) == LRS_WAITING_SSL) { - n = lws_tls_client_connect(wsi); + n = lws_tls_client_connect(wsi, errbuf, len); lwsl_debug("%s: SSL_connect says %d\n", __func__, n); switch (n) { case LWS_SSL_CAPABLE_ERROR: - lws_snprintf(errbuf, len, "client connect failed"); + // lws_snprintf(errbuf, len, "client connect failed"); return -1; case LWS_SSL_CAPABLE_DONE: break; /* connected */ diff --git a/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt b/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt index 61a08276..461800d3 100644 --- a/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt @@ -69,6 +69,11 @@ require_lws_config(LWS_WITH_SYS_ASYNC_DNS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-async-dns COMMAND lws-api-test-async-dns) + set_tests_properties(api-test-async-dns + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/api-tests/api-test-async-dns + TIMEOUT 60) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/api-tests/api-test-async-dns/selftest.sh b/minimal-examples/api-tests/api-test-async-dns/selftest.sh deleted file mode 100755 index 16d1e2e8..00000000 --- a/minimal-examples/api-tests/api-test-async-dns/selftest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff --git a/minimal-examples/api-tests/api-test-fts/selftest.sh b/minimal-examples/api-tests/api-test-fts/selftest.sh deleted file mode 100755 index 03e7d49e..00000000 --- a/minimal-examples/api-tests/api-test-fts/selftest.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=4 - -FAILS=0 - -# -# let's make an index with just Dorian first -# -dotest $1 $2 apitest -c -i /tmp/lws-fts-dorian.index \ - "../minimal-examples/api-tests/api-test-fts/the-picture-of-dorian-gray.txt" - -# and let's hear about autocompletes for "b" - -dotest $1 $2 apitest -i /tmp/lws-fts-dorian.index b -cat $2/api-test-fts/apitest.log | cut -d' ' -f5- > /tmp/fts1 -diff -urN /tmp/fts1 "../minimal-examples/api-tests/api-test-fts/canned-1.txt" -if [ $? -ne 0 ] ; then - echo "Test 1 failed" - FAILS=$(( $FAILS + 1 )) -fi - -# -# let's make an index with Dorian + Les Mis in French (ie, UTF-8) as well -# -dotest $1 $2 apitest -c -i /tmp/lws-fts-both.index \ - "../minimal-examples/api-tests/api-test-fts/the-picture-of-dorian-gray.txt" \ - "../minimal-examples/api-tests/api-test-fts/les-mis-utf8.txt" - -# and let's hear about "help", which appears in both - -dotest $1 $2 apitest -i /tmp/lws-fts-both.index -f -l help -cat $2/api-test-fts/apitest.log | cut -d' ' -f5- > /tmp/fts2 -diff -urN /tmp/fts2 "../minimal-examples/api-tests/api-test-fts/canned-2.txt" -if [ $? -ne 0 ] ; then - echo "Test 1 failed" - FAILS=$(( $FAILS + 1 )) -fi - -exit $FAILS diff --git a/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt index cfeac879..0356ab82 100644 --- a/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt @@ -70,6 +70,7 @@ require_lws_config(LWS_WITH_JOSE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-gencrypto COMMAND lws-api-test-gencrypto) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/api-tests/api-test-gencrypto/selftest.sh b/minimal-examples/api-tests/api-test-gencrypto/selftest.sh deleted file mode 100755 index 16d1e2e8..00000000 --- a/minimal-examples/api-tests/api-test-gencrypto/selftest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff --git a/minimal-examples/api-tests/api-test-jose/CMakeLists.txt b/minimal-examples/api-tests/api-test-jose/CMakeLists.txt index 81c0cf89..33ae85b6 100644 --- a/minimal-examples/api-tests/api-test-jose/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-jose/CMakeLists.txt @@ -69,6 +69,10 @@ if (requirements) add_executable(${SAMP} ${SRCS}) + if (NOT (LWS_WITH_MBEDTLS AND NOT LWS_HAVE_mbedtls_internal_aes_encrypt)) + add_test(NAME api-test-jose COMMAND lws-api-test-jose) + endif() + if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) add_dependencies(${SAMP} websockets_shared) diff --git a/minimal-examples/api-tests/api-test-jose/selftest.sh b/minimal-examples/api-tests/api-test-jose/selftest.sh deleted file mode 100755 index 16d1e2e8..00000000 --- a/minimal-examples/api-tests/api-test-jose/selftest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff --git a/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt index 262b4f08..99aea9f7 100644 --- a/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt @@ -69,6 +69,7 @@ require_lws_config(LWS_WITH_LWS_DSH 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-lws_dsh COMMAND lws-api-test-lws_dsh) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/api-tests/api-test-lws_dsh/selftest.sh b/minimal-examples/api-tests/api-test-lws_dsh/selftest.sh deleted file mode 100755 index 16d1e2e8..00000000 --- a/minimal-examples/api-tests/api-test-lws_dsh/selftest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt index b931750f..50287100 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt @@ -68,6 +68,7 @@ require_lws_config(LWS_WITH_STRUCT_JSON 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-lws_struct-json COMMAND lws-api-test-lws_struct-json) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/main.c b/minimal-examples/api-tests/api-test-lws_struct-json/main.c index 4083f320..faa2650d 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/main.c +++ b/minimal-examples/api-tests/api-test-lws_struct-json/main.c @@ -296,6 +296,35 @@ static const lws_struct_map_t lsm_schema_map[] = { lsm_other, "com-warmcat-sai-other"), }; +typedef struct sai_cancel { + char task_uuid[65]; +} sai_cancel_t; + +const lws_struct_map_t lsm_task_cancel[] = { + LSM_CARRAY (sai_cancel_t, task_uuid, "uuid"), +}; + +static const lws_struct_map_t t2_map[] = { + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + "com.warmcat.sai.taskinfo"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + "com.warmcat.sai.eventinfo"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + /* shares struct */ "com.warmcat.sai.taskreset"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + /* shares struct */ "com.warmcat.sai.eventreset"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + /* shares struct */ "com.warmcat.sai.eventdelete"), + LSM_SCHEMA (sai_cancel_t, NULL, lsm_task_cancel, + "com.warmcat.sai.taskcan"), +}; + +static const char *t2 = + "{\"schema\":\"com.warmcat.sai.taskcan\"," + "\"uuid\": \"071ab46ab4296e5de674c628fec17c55088254679f7714ad991f8c4873dca\"}\x01\x02\xff\xff\xff\xff"; + + + static int show_target(struct lws_dll2 *d, void *user) { diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/selftest.sh b/minimal-examples/api-tests/api-test-lws_struct-json/selftest.sh deleted file mode 100755 index 16d1e2e8..00000000 --- a/minimal-examples/api-tests/api-test-lws_struct-json/selftest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff --git a/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt index f1496c2c..00ea42c1 100644 --- a/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt @@ -63,11 +63,12 @@ MACRO(require_lws_config reqconfig _val result) ENDMACRO() set(requirements 1) -require_lws_config(LWS_WITH_STRUCT_SQLITE 1 requirements) +require_lws_config(LWS_WITH_STRUCT_SQLITE3 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-lws_struct_sqlite COMMAND lws-api-test-lws_struct-sqlite) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared sqlite3) diff --git a/minimal-examples/api-tests/api-test-lws_struct_sqlite/selftest.sh b/minimal-examples/api-tests/api-test-lws_struct_sqlite/selftest.sh deleted file mode 100755 index 16d1e2e8..00000000 --- a/minimal-examples/api-tests/api-test-lws_struct_sqlite/selftest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff --git a/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt index 26b3f1f8..7eb968b2 100644 --- a/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt @@ -62,9 +62,8 @@ MACRO(require_lws_config reqconfig _val result) endif() ENDMACRO() - - add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-lws_tokenize COMMAND lws-api-test-lws_tokenize) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/api-tests/api-test-lws_tokenize/selftest.sh b/minimal-examples/api-tests/api-test-lws_tokenize/selftest.sh deleted file mode 100755 index 16d1e2e8..00000000 --- a/minimal-examples/api-tests/api-test-lws_tokenize/selftest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff --git a/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt b/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt index c5ad3174..7e147a73 100644 --- a/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt @@ -62,9 +62,8 @@ MACRO(require_lws_config reqconfig _val result) endif() ENDMACRO() - - add_executable(${SAMP} ${SRCS}) + add_test(NAME api-test-lwsac COMMAND lws-api-test-lwsac) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/api-tests/api-test-lwsac/selftest.sh b/minimal-examples/api-tests/api-test-lwsac/selftest.sh deleted file mode 100755 index 16d1e2e8..00000000 --- a/minimal-examples/api-tests/api-test-lwsac/selftest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 apiselftest -exit $FAILS diff --git a/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt b/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt index 9d3f4515..3e361b4e 100644 --- a/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt +++ b/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt @@ -6,42 +6,6 @@ include(CheckLibraryExists) set(SAMP lws-minimal-dbus-client) set(SRCS minimal-dbus-client.c) -if (NOT LWS_WITH_MINIMAL_EXAMPLES) - CHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() - endif() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) - - if (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2) - message(FATAL_ERROR "To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md") - endif() - -endif() - # If we are being built as part of lws, confirm current build config supports # reqconfig, else skip building ourselves. # @@ -107,10 +71,15 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) - + + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_DBUS1 dbus-1 QUIET) + list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) + list(APPEND LWS_DBUS_LIB "${PC_DBUS1_LIBRARIES};dl") + endif() + include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") - list(APPEND LIB_LIST dbus-1) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt index 0ec0cca9..dbc8195f 100644 --- a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt +++ b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt @@ -6,42 +6,6 @@ include(CheckLibraryExists) set(SAMP lws-minimal-dbus-ws-proxy-testclient) set(SRCS minimal-dbus-ws-proxy-testclient.c) -if (NOT LWS_WITH_MINIMAL_EXAMPLES) - CHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() - endif() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) - - if (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2) - message(FATAL_ERROR "To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md") - endif() - -endif() - # If we are being built as part of lws, confirm current build config supports # reqconfig, else skip building ourselves. # @@ -107,10 +71,15 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) - + + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_DBUS1 dbus-1 QUIET) + list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) + list(APPEND LWS_DBUS_LIB "${PC_DBUS1_LIBRARIES};dl") + endif() + include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") - list(APPEND LIB_LIST dbus-1) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt b/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt index 37e49f0a..105bb5cd 100644 --- a/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt +++ b/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt @@ -6,42 +6,6 @@ include(CheckLibraryExists) set(SAMP lws-minimal-dbus-server) set(SRCS main.c) -if (NOT LWS_WITH_MINIMAL_EXAMPLES) - CHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() - endif() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) - - if (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2) - message(FATAL_ERROR "To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md") - endif() - -endif() - # If we are being built as part of lws, confirm current build config supports # reqconfig, else skip building ourselves. # @@ -107,10 +71,15 @@ require_lws_config(LWS_WITH_SERVER 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) - + + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_DBUS1 dbus-1 QUIET) + list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) + list(APPEND LWS_DBUS_LIB "${PC_DBUS1_LIBRARIES};dl") + endif() + include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") - list(APPEND LIB_LIST dbus-1) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt index bd5148c2..9068a7b3 100644 --- a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt +++ b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt @@ -6,42 +6,6 @@ include(CheckLibraryExists) set(SAMP lws-minimal-dbus-ws-proxy) set(SRCS main.c) -if (NOT LWS_WITH_MINIMAL_EXAMPLES) - CHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions "" LWS_HAVE_LIBDBUS) - if (NOT LWS_HAVE_LIBDBUS) - message(FATAL_ERROR "Install dbus-devel, or libdbus-1-dev etc") - endif() - - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - if (NOT LWS_DBUS_INCLUDE1) - # look in fedora and debian / ubuntu place - if (EXISTS "/usr/include/dbus-1.0") - set(LWS_DBUS_INCLUDE1 "/usr/include/dbus-1.0") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are") - endif() - endif() - - if (NOT LWS_DBUS_INCLUDE2) - # look in fedora... debian / ubuntu has the ARCH in the path... - if (EXISTS "/usr/lib64/dbus-1.0/include") - set(LWS_DBUS_INCLUDE2 "/usr/lib64/dbus-1.0/include") - else() - message(FATAL_ERROR "Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system") - endif() - endif() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2}) - - if (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2) - message(FATAL_ERROR "To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md") - endif() - -endif() - # If we are being built as part of lws, confirm current build config supports # reqconfig, else skip building ourselves. # @@ -110,9 +74,14 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_DBUS1 dbus-1 QUIET) + list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) + list(APPEND LWS_DBUS_LIB "${PC_DBUS1_LIBRARIES};dl") + endif() + include_directories("${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE2}") - list(APPEND LIB_LIST dbus-1) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt index 4b31f9d3..fe195215 100644 --- a/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt @@ -70,6 +70,15 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME http-client-h2-rxflow-warmcat COMMAND lws-minimal-http-client-h2-rxflow --ignore-sigterm) + add_test(NAME http-client-h2-rxflow-warmcat-h1 COMMAND lws-minimal-http-client-h2-rxflow --ignore-sigterm --h1) + set_tests_properties(http-client-h2-rxflow-warmcat + http-client-h2-rxflow-warmcat-h1 + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-h2-rxflow + TIMEOUT 30) + endif() if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/http-client/minimal-http-client-h2-rxflow/selftest.sh b/minimal-examples/http-client/minimal-http-client-h2-rxflow/selftest.sh deleted file mode 100755 index c065b444..00000000 --- a/minimal-examples/http-client/minimal-http-client-h2-rxflow/selftest.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=4 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-h1 --h1 - -spawn "" $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost -l -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1 -l --h1 - -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null -exit $FAILS diff --git a/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt index b36eae40..d2f7415a 100644 --- a/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt @@ -70,6 +70,17 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME http-client-hugeurl-warmcat COMMAND lws-minimal-http-client-hugeurl --ignore-sigterm) + add_test(NAME http-client-hugeurl-warmcat-h1 COMMAND lws-minimal-http-client-hugeurl --ignore-sigterm --h1) + set_tests_properties(http-client-hugeurl-warmcat + http-client-hugeurl-warmcat-h1 + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-hugeurl + TIMEOUT 20) + + endif() + if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) add_dependencies(${SAMP} websockets_shared) diff --git a/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c b/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c index 6178396f..f0b90a28 100644 --- a/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c +++ b/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c @@ -149,23 +149,15 @@ int main(int argc, const char **argv) struct lws_context_creation_info info; struct lws_client_connect_info i; struct lws_context *context; - const char *p; - int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE - /* for LLL_ verbosity above NOTICE to be built into lws, - * lws must have been configured and built with - * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ - /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ - /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ - /* | LLL_DEBUG */; - - if ((p = lws_cmdline_option(argc, argv, "-d"))) - logs = atoi(p); + int n = 0; signal(SIGINT, sigint_handler); - lws_set_log_level(logs, NULL); - lwsl_user("LWS minimal http client hugeurl [-d ] [-l] [--h1]\n"); memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS minimal http client hugeurl [-d ] [-l] [--h1]\n"); + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ info.protocols = protocols; diff --git a/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh b/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh deleted file mode 100755 index 2da54b66..00000000 --- a/minimal-examples/http-client/minimal-http-client-hugeurl/selftest.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=6 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-h1 --h1 - -spawn "" $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost -l -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1 -l --h1 -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null - - -if [ -z "$TRAVIS_OS_NAME" ] ; then - SPID="" - spawn "" $5/http-server/minimal-http-server-eventlib $1/lws-minimal-http-server-eventlib --uv -s - dotest $1 $2 localhost-suv -l - spawn $SPID $5/http-server/minimal-http-server-eventlib $1/lws-minimal-http-server-eventlib --uv -s - dotest $1 $2 localhost-suv-h1 -l --h1 - - kill $SPID 2>/dev/null - wait $SPID 2>/dev/null -fi - -exit $FAILS - - diff --git a/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt index 2f9c3053..68466846 100644 --- a/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt @@ -70,6 +70,154 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + + # + # instantiate the server per sai builder instance, they are running in the same + # machine context in parallel so they can tread on each other otherwise + # + set(PORT_HCM_SRV "7670") + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "0") + set(PORT_HCM_SRV 7671) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "1") + set(PORT_HCM_SRV 7672) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "2") + set(PORT_HCM_SRV 7673) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "3") + set(PORT_HCM_SRV 7674) + endif() + + +# hack +if (NOT WIN32 AND LWS_WITH_SERVER) + + # + # Tests against built server running locally (needs daemonization...) + # + +if (WIN32) + add_test(NAME st_hcm_srv COMMAND cmd.exe /c start /b $ --port ${PORT_HCM_SRV}) + add_test(NAME ki_hcm_srv COMMAND taskkill /F /IM $ /T) + add_test(NAME st_hcmp_srv COMMAND cmd.exe /c start /b $ -s --port 1${PORT_HCM_SRV}) + add_test(NAME ki_hcmp_srv COMMAND taskkill /F /IM $ /T) +else() + add_test(NAME st_hcm_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + hcm_srv $ + --port ${PORT_HCM_SRV}) + add_test(NAME ki_hcm_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + hcm_srv $ + --port ${PORT_HCM_SRV}) + add_test(NAME st_hcmp_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + hcmp_srv $ -s + -r ${CMAKE_SOURCE_DIR}/destdir/usr/local/share/libwebsockets-test-server/ + --port 1${PORT_HCM_SRV}) + add_test(NAME ki_hcmp_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + hcmp_srv $ + --port 1${PORT_HCM_SRV}) +endif() + + set_tests_properties(st_hcm_srv PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-server/minimal-http-server-tls + FIXTURES_SETUP hcm_srv + TIMEOUT 800) + set_tests_properties(ki_hcm_srv PROPERTIES + FIXTURES_CLEANUP hcm_srv) + + set_tests_properties(st_hcmp_srv PROPERTIES + WORKING_DIRECTORY . + FIXTURES_SETUP hcmp_srv + TIMEOUT 800) + set_tests_properties(ki_hcmp_srv PROPERTIES + FIXTURES_CLEANUP hcmp_srv) + + # + # Tests against local server peer + # + + add_test(NAME http-client-multi COMMAND lws-minimal-http-client-multi + -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-h1 COMMAND lws-minimal-http-client-multi + --h1 -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-pipe COMMAND lws-minimal-http-client-multi + -p -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-h1-pipe COMMAND lws-minimal-http-client-multi + --h1 -p -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-stag COMMAND lws-minimal-http-client-multi + -s -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-stag-h1 COMMAND lws-minimal-http-client-multi + --h1 -s -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-stag-pipe COMMAND lws-minimal-http-client-multi + -p -s -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-stag-h1-pipe COMMAND lws-minimal-http-client-multi + --h1 -p -s -l --port ${PORT_HCM_SRV}) + + # confirm that the pipelined mode really is doing it in one connection + add_test(NAME http-client-multi-restrict-pipe COMMAND lws-minimal-http-client-multi -d1151 --limit 1 -p -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-restrict-h1-pipe COMMAND lws-minimal-http-client-multi -d1151 --limit 1 --h1 -p -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-restrict-stag-pipe COMMAND lws-minimal-http-client-multi -d1151 --limit 1 -p -s -l --port ${PORT_HCM_SRV}) + add_test(NAME http-client-multi-restrict-stag-h1-pipe COMMAND lws-minimal-http-client-multi -d1151 --limit 1 --h1 -p -s -l --port ${PORT_HCM_SRV}) + # confirm that we do fail with a one connection limit and no pipelining + add_test(NAME http-client-multi-restrict-nopipe-fail COMMAND lws-minimal-http-client-multi --limit 1 -l --port ${PORT_HCM_SRV}) + set_property(TEST http-client-multi-restrict-nopipe-fail PROPERTY WILL_FAIL TRUE) + add_test(NAME http-client-multi-restrict-h1-nopipe-fail COMMAND lws-minimal-http-client-multi --limit 1 --h1 -l --port ${PORT_HCM_SRV}) + set_property(TEST http-client-multi-restrict-h1-nopipe-fail PROPERTY WILL_FAIL TRUE) + + set_tests_properties(http-client-multi-restrict-pipe + http-client-multi-restrict-h1-pipe + http-client-multi-restrict-stag-pipe + http-client-multi-restrict-stag-h1-pipe + http-client-multi-restrict-nopipe-fail + http-client-multi-restrict-h1-nopipe-fail + http-client-multi + http-client-multi-h1 + http-client-multi-pipe + http-client-multi-h1-pipe + http-client-multi-stag + http-client-multi-stag-h1 + http-client-multi-stag-pipe + http-client-multi-stag-h1-pipe + PROPERTIES + FIXTURES_REQUIRED "hcm_srv" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-multi + TIMEOUT 20) + + # POSTs against local http-server-form-post + add_test(NAME http-client-multi-post COMMAND lws-minimal-http-client-multi + --post -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-h1 COMMAND lws-minimal-http-client-multi + --post --h1 -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-pipe COMMAND lws-minimal-http-client-multi + --post -p -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-h1-pipe COMMAND lws-minimal-http-client-multi + --post --h1 -p -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-stag COMMAND lws-minimal-http-client-multi + --post -s -l -d1151 --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-stag-h1 COMMAND lws-minimal-http-client-multi + --post --h1 -d1151 -s -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-stag-pipe COMMAND lws-minimal-http-client-multi + --post -p -s -l --port 1${PORT_HCM_SRV}) + add_test(NAME http-client-multi-post-stag-h1-pipe COMMAND lws-minimal-http-client-multi + --post --h1 -p -s -l --port 1${PORT_HCM_SRV}) + set_tests_properties(http-client-multi-post + http-client-multi-post-h1 + http-client-multi-post-pipe + http-client-multi-post-h1-pipe + http-client-multi-post-stag + http-client-multi-post-stag-h1 + http-client-multi-post-stag-pipe + http-client-multi-post-stag-h1-pipe + PROPERTIES + FIXTURES_REQUIRED "hcmp_srv" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-multi + TIMEOUT 20) + +endif(NOT WIN32 AND LWS_WITH_SERVER) if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c index caca20b2..99bb629b 100644 --- a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c +++ b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c @@ -132,7 +132,9 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, break; if (lws_http_is_redirected_to_get(wsi)) break; - lwsl_user("LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: %p, part %d\n", wsi, pss->body_part); + lwsl_info("LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: %p, idx %d," + " part %d\n", wsi, idx, pss->body_part); + n = LWS_WRITE_HTTP; /* @@ -318,18 +320,14 @@ int main(int argc, const char **argv) { struct lws_context_creation_info info; unsigned long long start; + int m, staggered = 0; const char *p; - int m, staggered = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE - /* for LLL_ verbosity above NOTICE to be built into lws, - * lws must have been configured and built with - * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ - /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ - /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ - /* | LLL_DEBUG */; memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ + lws_cmdline_option_handle_builtin(argc, argv, &info); + info.signal_cb = signal_cb; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; @@ -348,10 +346,7 @@ int main(int argc, const char **argv) signal(SIGINT, sigint_handler); staggered = !!lws_cmdline_option(argc, argv, "-s"); - if ((p = lws_cmdline_option(argc, argv, "-d"))) - logs = atoi(p); - lws_set_log_level(logs, NULL); lwsl_user("LWS minimal http client [-s (staggered)] [-p (pipeline)]\n"); lwsl_user(" [--h1 (http/1 only)] [-l (localhost)] [-d ]\n"); lwsl_user(" [-n (numbered)] [--post]\n"); @@ -424,6 +419,9 @@ int main(int argc, const char **argv) strcpy(urlpath, "/testserver/formtest"); } + if (lws_cmdline_option(argc, argv, "--no-tls")) + i.ssl_connection &= ~(LCCSCF_USE_SSL); + if (lws_cmdline_option(argc, argv, "-n")) numbered = 1; diff --git a/minimal-examples/http-client/minimal-http-client-multi/selftest.sh b/minimal-examples/http-client/minimal-http-client-multi/selftest.sh deleted file mode 100755 index 3140fda1..00000000 --- a/minimal-examples/http-client/minimal-http-client-multi/selftest.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=30 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-pipe -p -dotest $1 $2 warmcat-h1 --h1 -dotest $1 $2 warmcat-h1-pipe --h1 -p -dotest $1 $2 warmcat-stag -s -dotest $1 $2 warmcat-pipe-stag -p -s -dotest $1 $2 warmcat-h1-stag --h1 -s -dotest $1 $2 warmcat-h1-pipe-stag --h1 -p -s -dotest $1 $2 warmcat-post --post -dotest $1 $2 warmcat-post-pipe --post -p -dotest $1 $2 warmcat-post-pipe-stag --post -p -s -dotest $1 $2 warmcat-h1-post --post --h1 -dotest $1 $2 warmcat-h1-post-pipe --post --h1 -p -dotest $1 $2 warmcat-h1-post-pipe-stag --post --h1 -p -s -dotest $1 $2 warmcat-restrict-pipe --limit 1 -p -dotest $1 $2 warmcat-restrict-h1-pipe --limit 1 -p --h1 -dotest $1 $2 warmcat-restrict-pipe-stag --limit 1 -p -s -dotest $1 $2 warmcat-restrict-h1-pipe-stag --limit 1 -p --h1 -s -dofailtest $1 $2 fail-warmcat-restrict --limit 1 -dofailtest $1 $2 fail-warmcat-restrict-h1 --limit 1 --h1 -dofailtest $1 $2 fail-warmcat-restrict-stag --limit 1 -s -dofailtest $1 $2 fail-warmcat-restrict-h1-stag --limit 1 --h1 -s - -spawn "" $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost -l -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-pipe -l -p -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1 -l --h1 -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1-pipe -l --h1 -p -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-stag -l -s -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-pipe-stag -l -p -s -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1-stag -l --h1 -s -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1-pipe-stag -l --h1 -p -s - -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null -exit $FAILS - diff --git a/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt index 9c5780f5..f83182f6 100644 --- a/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt @@ -69,6 +69,72 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + + # + # instantiate the server per sai builder instance, they are running in the same + # machine context in parallel so they can tread on each other otherwise + # + set(PORT_HCP_SRV "7640") + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "0") + set(PORT_HCP_SRV 7641) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "1") + set(PORT_HCP_SRV 7642) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "2") + set(PORT_HCP_SRV 7643) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "3") + set(PORT_HCP_SRV 7644) + endif() + +# hack +if (NOT WIN32 AND LWS_WITH_SERVER) + + # + # Tests against built server running locally (needs daemonization...) + # + +if (WIN32) + add_test(NAME st_hcp_srv COMMAND cmd.exe /c start /b $ -s --port ${PORT_HCP_SRV}) + add_test(NAME ki_hcp_srv COMMAND taskkill /F /IM $ /T) +else() + add_test(NAME st_hcp_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + hcp_srv + $ + -r ${CMAKE_SOURCE_DIR}/destdir/usr/local/share/libwebsockets-test-server/ + -s --port ${PORT_HCP_SRV}) + add_test(NAME ki_hcp_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh hcp_srv + $ --port ${PORT_HCP_SRV}) +endif() + + set_tests_properties(st_hcp_srv PROPERTIES + WORKING_DIRECTORY . + FIXTURES_SETUP hcp_srv + TIMEOUT 800) + set_tests_properties(ki_hcp_srv PROPERTIES + FIXTURES_CLEANUP hcp_srv) + + add_test(NAME http-client-post COMMAND + lws-minimal-http-client-post -l --port ${PORT_HCP_SRV}) + add_test(NAME http-client-post-m COMMAND + lws-minimal-http-client-post -l -m --port ${PORT_HCP_SRV}) + add_test(NAME http-client-post-h1 COMMAND + lws-minimal-http-client-post -l --h1 --port ${PORT_HCP_SRV}) + add_test(NAME http-client-post-m-h1 COMMAND + lws-minimal-http-client-post -l -m --h1 --port ${PORT_HCP_SRV}) + set_tests_properties(http-client-post + http-client-post-m + http-client-post-h1 + http-client-post-m-h1 + PROPERTIES + FIXTURES_REQUIRED "hcp_srv" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client-post + TIMEOUT 20) +endif() + if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) diff --git a/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c b/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c index b291efb7..6a8cc5d5 100644 --- a/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c +++ b/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c @@ -189,6 +189,7 @@ int main(int argc, const char **argv) struct lws_context_creation_info info; struct lws_client_connect_info i; struct lws_context *context; + const char *p; int n = 0; signal(SIGINT, sigint_handler); @@ -245,6 +246,9 @@ int main(int argc, const char **argv) if (lws_cmdline_option(argc, argv, "--form1")) i.path = "/form1"; + if ((p = lws_cmdline_option(argc, argv, "--port"))) + i.port = atoi(p); + i.host = i.address; i.origin = i.address; i.method = "POST"; @@ -257,6 +261,8 @@ int main(int argc, const char **argv) for (n = 0; n < count_clients; n++) { i.pwsi = &client_wsi[n]; + lwsl_notice("%s: connecting to %s:%d\n", __func__, + i.address, i.port); if (!lws_client_connect_via_info(&i)) completed++; } diff --git a/minimal-examples/http-client/minimal-http-client-post/selftest.sh b/minimal-examples/http-client/minimal-http-client-post/selftest.sh deleted file mode 100755 index 8d3476f4..00000000 --- a/minimal-examples/http-client/minimal-http-client-post/selftest.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=8 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-h1 --h1 -dotest $1 $2 warmcat-m -m -dotest $1 $2 warmcat-m-h1 -m --h1 - -spawn "" $5 $1/libwebsockets-test-server -s -dotest $1 $2 localhost -l -d1151 -spawn $SPID $5 $1/libwebsockets-test-server -s -dotest $1 $2 localhost-h1 -l --h1 -spawn $SPID $5 $1/libwebsockets-test-server -s -dotest $1 $2 localhost-m -l -m -spawn $SPID $5 $1/libwebsockets-test-server -s -dotest $1 $2 localhost-m-h1 -l -m --h1 - -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null -exit $FAILS diff --git a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt index be0d758f..6dd0ba02 100644 --- a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt @@ -71,10 +71,21 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + # if (LWS_CTEST_INTERNET_AVAILABLE) + # add_test(NAME http-client-warmcat COMMAND lws-minimal-http-client --ignore-sigterm) + # add_test(NAME http-client-warmcat-h1 COMMAND lws-minimal-http-client --ignore-sigterm --h1) + # set_tests_properties(http-client-warmcat + # http-client-warmcat-h1 + # PROPERTIES + # WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client + # TIMEOUT 20) + # + #endif() + if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) add_dependencies(${SAMP} websockets_shared) else() target_link_libraries(${SAMP} websockets) endif() -endif() \ No newline at end of file +endif() diff --git a/minimal-examples/http-client/minimal-http-client/selftest.sh b/minimal-examples/http-client/minimal-http-client/selftest.sh deleted file mode 100755 index c065b444..00000000 --- a/minimal-examples/http-client/minimal-http-client/selftest.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=4 - -dotest $1 $2 warmcat -dotest $1 $2 warmcat-h1 --h1 - -spawn "" $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost -l -spawn $SPID $5/http-server/minimal-http-server-tls $1/lws-minimal-http-server-tls -dotest $1 $2 localhost-h1 -l --h1 - -kill $SPID 2>/dev/null -wait $SPID 2>/dev/null -exit $FAILS diff --git a/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c b/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c index 4711fc26..edc55bcc 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c +++ b/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c @@ -202,6 +202,9 @@ int main(int argc, const char **argv) info.ssl_private_key_filepath = "localhost-100y.key"; } + if ((p = lws_cmdline_option(argc, argv, "--port"))) + info.port = atoi(p); + if (lws_cmdline_option(argc, argv, "--303")) { lwsl_user("%s: using 303 redirect\n", __func__); use303 = 1; diff --git a/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c b/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c index 3cda6988..cb8c3136 100644 --- a/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c +++ b/minimal-examples/http-server/minimal-http-server-tls/minimal-http-server-tls.c @@ -52,24 +52,17 @@ int main(int argc, const char **argv) struct lws_context_creation_info info; struct lws_context *context; const char *p; - int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE - /* for LLL_ verbosity above NOTICE to be built into lws, - * lws must have been configured and built with - * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ - /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ - /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ - /* | LLL_DEBUG */; - - if ((p = lws_cmdline_option(argc, argv, "-d"))) - logs = atoi(p); - - lws_set_log_level(logs, NULL); - lwsl_user("LWS minimal http server TLS | visit https://localhost:7681\n"); + int n = 0; signal(SIGINT, sigint_handler); memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + lws_cmdline_option_handle_builtin(argc, argv, &info); + lwsl_user("LWS minimal http server TLS | visit https://localhost:7681\n"); + info.port = 7681; + if ((p = lws_cmdline_option(argc, argv, "--port"))) + info.port = atoi(p); info.mounts = &mount; info.error_document_404 = "/404.html"; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | diff --git a/minimal-examples/selftests-library.sh b/minimal-examples/selftests-library.sh deleted file mode 100755 index 01cbbd88..00000000 --- a/minimal-examples/selftests-library.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -if [ -z "$1" -o -z "$2" ] ; then - echo "required args missing" - exit 1 -fi - -IDX=$3 -TOT=$4 -MYTEST=`echo $0 | sed "s/\/[^\/]*\$//g" |sed "s/.*\///g"` -mkdir -p $2/$MYTEST -rm -f $2/$MYTEST/*.log $2/$MYTEST/*.result -FAILS=0 -WHICH=$IDX -SPID= -SCRIPT_DIR=`dirname $0` -SCRIPT_DIR=`readlink -f $SCRIPT_DIR` -LOGPATH=$2 - -feedback() { - if [ "$2" != "$4" ] ; then - FAILS=$(( $FAILS + 1 )) - echo -n -e "\e[31m" - fi - T=" --- killed --- " - if [ ! -z "`cat $LOGPATH/$MYTEST/$3.time`" ] ; then - T="`cat $LOGPATH/$MYTEST/$3.time | grep real | sed "s/.*\ //g"`" - T="$T `cat $LOGPATH/$MYTEST/$3.time | grep user | sed "s/.*\ //g"`" - T="$T `cat $LOGPATH/$MYTEST/$3.time | grep sys | sed "s/.*\ //g"`" - fi - printf "%-35s [ %3s/%3s ]: %3s : %8s : %s\n" $1 $WHICH $TOT $2 "$T" $3 - if [ "$2" != "0" ] ; then - echo -n -e "\e[0m" - fi - WHICH=$(( $WHICH + 1)) -} - -spawn() { - if [ ! -z "$1" ] ; then - if [ `ps $1 | wc -l` -eq 2 ]; then -# echo "prerequisite still up" - return 0 - fi - fi - - QQ=`pwd` - cd $SCRIPT_DIR - cd $2 - $3 $4 $5 > $LOGPATH/$MYTEST/serverside.log 2> $LOGPATH/$MYTEST/serverside.log & - SPID=$! - cd $QQ - sleep 0.5s -# echo "launched prerequisite $SPID" -} - -_dotest() { - EXPRES=0 - if [ ! -z "$4" ] ; then - EXPRES=$4 - fi - T=$3 -# echo "$1/lws-$MYTEST $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14}" - ( - { - /usr/bin/time -p /usr/bin/valgrind -q $1/lws-$MYTEST $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} > $2/$MYTEST/$T.log 2> $2/$MYTEST/$T.log ; - echo $? > $2/$MYTEST/$T.result - } 2> $2/$MYTEST/$T.time >/dev/null - ) >/dev/null 2> /dev/null & - W=$! - WT=0 - while [ $WT -le 820 ] ; do - kill -0 $W 2>/dev/null - if [ $? -ne 0 ] ; then - WT=10000 - else - if [ $WT -ge 800 ] ; then - WT=10000 - kill $W 2>/dev/null - wait $W 2>/dev/null - fi - fi - sleep 0.1s - WT=$(( $WT + 1 )) - done - - R=254 - if [ -e $2/$MYTEST/$T.result ] ; then - R=`cat $2/$MYTEST/$T.result` - cat $2/$MYTEST/$T.log | tail -n 3 > $2/$MYTEST/$T.time - if [ $R -ne $EXPRES ] ; then - pwd - echo Expected result $EXPRES but got $R - echo - cat $2/$MYTEST/$T.log - echo - fi - fi - - feedback $MYTEST $R $T $EXPRES -} - -dotest() -{ - _dotest $1 $2 $3 0 "$4" "$5" "$6" "$7" "$8" "$9" "${10}" "${11}" "${12}" "${13}" -} - -dofailtest() -{ - _dotest $1 $2 $3 1 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} -} diff --git a/minimal-examples/selftests.sh b/minimal-examples/selftests.sh deleted file mode 100755 index 77fbdd43..00000000 --- a/minimal-examples/selftests.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash -# -# run this from your build dir having configured -# -DLWS_WITH_MINIMAL_EXAMPLES=1 to get all the examples -# that apply built into ./bin -# -# Eg, -# -# build $ ../minimal-examples/selftests.sh - -echo -echo "----------------------------------------------" -echo "------- tests: lws minimal example selftests" -echo - -LOGGING_PATH=/tmp/logs - -# for mebedtls, we need the CA certs in ./build where we run from - -cp ../minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer . -cp ../minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer . - -MINEX=`dirname $0` -MINEX=`realpath $MINEX` -TESTS=0 -for i in `find $MINEX -name selftest.sh` ; do - BN=`echo -n "$i" | sed "s/\/[^\/]*\$//g" | sed "s/.*\///g"` - if [ -e `pwd`/bin/lws-$BN ] ; then - C=`cat $i | grep COUNT_TESTS= | cut -d= -f2` - TESTS=$(( $TESTS + $C )) - fi -done - -FAILS=0 -WH=1 - -for i in `find $MINEX -name selftest.sh` ; do - BN=`echo -n "$i" | sed "s/\/[^\/]*\$//g" | sed "s/.*\///g"` - if [ -e `pwd`/bin/lws-$BN ] ; then - C=`cat $i | grep COUNT_TESTS= | cut -d= -f2` - sh $i `pwd`/bin $LOGGING_PATH $WH $TESTS $MINEX - FAILS=$(( $FAILS + $? )) - - L=`ps fax | grep lws- | cut -d' ' -f2` - kill $L 2>/dev/null - kill -9 $L 2>/dev/null - wait $L 2>/dev/null - - WH=$(( $WH + $C )) - fi -done - -if [ $FAILS -eq 0 ] ; then - echo "All $TESTS passed" - exit 0 -else - echo "Failed: $FAILS / $TESTS" - exit 1 -fi - - diff --git a/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt index 31b51178..57bb3af9 100644 --- a/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt @@ -69,6 +69,14 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME ws-client-rx-warmcat COMMAND lws-minimal-ws-client-rx -t) + set_tests_properties(ws-client-rx-warmcat + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/ws-client/minimal-ws-client-rx + TIMEOUT 20) + + endif() if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) @@ -76,4 +84,4 @@ if (requirements) else() target_link_libraries(${SAMP} websockets) endif() -endif() \ No newline at end of file +endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh b/minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh deleted file mode 100644 index 070ef7f3..00000000 --- a/minimal-examples/ws-client/minimal-ws-client-rx/selftest.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 warmcat -t - -exit $FAILS diff --git a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt index 42fd9706..47850db9 100644 --- a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt @@ -89,6 +89,53 @@ require_lws_config(LWS_WITH_CLIENT 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) + # + # instantiate the server per sai builder instance, they are running in the same + # machine context in parallel so they can tread on each other otherwise + # + set(PORT_WCS_SRV "7620") + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "0") + set(PORT_WCS_SRV 7621) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "1") + set(PORT_WCS_SRV 7622) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "2") + set(PORT_WCS_SRV 7623) + endif() + if ("$ENV{SAI_INSTANCE_IDX}" STREQUAL "3") + set(PORT_WCS_SRV 7624) + endif() + +# hack +if (WIN32) +else() + +if (LWS_WITH_SERVER) +if (WIN32) + add_test(NAME st_wcs_srv COMMAND cmd.exe /c start /b $ -s --port ${PORT_WCS_SRV}) + add_test(NAME ki_wcs_srv COMMAND taskkill /F /IM $ /T) +else() + add_test(NAME st_wcs_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh + wcs_srv $ + -r ${CMAKE_SOURCE_DIR}/destdir/usr/local/share/libwebsockets-test-server/ + -s --port ${PORT_WCS_SRV}) + add_test(NAME ki_wcs_srv COMMAND + ${CMAKE_SOURCE_DIR}/scripts/ctest-background-kill.sh + wcs_srv $ --port ${PORT_WCS_SRV}) +endif() + + set_tests_properties(st_wcs_srv PROPERTIES WORKING_DIRECTORY . FIXTURES_SETUP wcs_srv TIMEOUT 800) + set_tests_properties(ki_wcs_srv PROPERTIES FIXTURES_CLEANUP wcs_srv) + + add_test(NAME ws-client-spam COMMAND lws-minimal-ws-client-spam --server localhost --port ${PORT_WCS_SRV} -l 32 -c 3) + set_tests_properties(ws-client-spam PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/ws-client/minimal-ws-client-spam + FIXTURES_REQUIRED "wcs_srv" + TIMEOUT 40) +endif() +endif() if (websockets_shared) target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) diff --git a/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c b/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c index 3809ef50..080346e3 100644 --- a/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c +++ b/minimal-examples/ws-client/minimal-ws-client-spam/minimal-ws-client-spam.c @@ -70,6 +70,7 @@ connect_client(int idx) clients[idx].state = CLIENT_CONNECTING; tries++; + lwsl_notice("%s: connection %s:%d\n", __func__, i.address, i.port); if (!lws_client_connect_via_info(&i)) { clients[idx].wsi = NULL; clients[idx].state = CLIENT_IDLE; @@ -258,6 +259,8 @@ int main(int argc, const char **argv) while (n >= 0 && !interrupted) n = lws_service(context, 0); + lwsl_notice("%s: exiting service loop\n", __func__); + lws_context_destroy(context); if (tries == limit && closed == tries) { diff --git a/minimal-examples/ws-client/minimal-ws-client-spam/selftest.sh b/minimal-examples/ws-client/minimal-ws-client-spam/selftest.sh deleted file mode 100755 index b9f2cde9..00000000 --- a/minimal-examples/ws-client/minimal-ws-client-spam/selftest.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -# -# $1: path to minimal example binaries... -# if lws is built with -DLWS_WITH_MINIMAL_EXAMPLES=1 -# that will be ./bin from your build dir -# -# $2: path for logs and results. The results will go -# in a subdir named after the directory this script -# is in -# -# $3: offset for test index count -# -# $4: total test count -# -# $5: path to ./minimal-examples dir in lws -# -# Test return code 0: OK, 254: timed out, other: error indication - -. $5/selftests-library.sh - -COUNT_TESTS=1 - -dotest $1 $2 warmcat - -exit $FAILS - diff --git a/plugins/protocol_lws_mirror.c b/plugins/protocol_lws_mirror.c index 15704519..380d6c2e 100644 --- a/plugins/protocol_lws_mirror.c +++ b/plugins/protocol_lws_mirror.c @@ -206,6 +206,15 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason, switch (reason) { case LWS_CALLBACK_ESTABLISHED: lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__); + if (!v) { + lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), + lws_get_protocol(wsi), + sizeof(struct per_vhost_data__lws_mirror)); + v = (struct per_vhost_data__lws_mirror *) + lws_protocol_vh_priv_get(lws_get_vhost(wsi), + lws_get_protocol(wsi)); + lws_pthread_mutex_init(&v->lock); + } /* * mirror instance name... defaults to "", but if URL includes @@ -332,13 +341,15 @@ bail1: return 1; /* disallow compression */ case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ - lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), + if (!v) { + lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), lws_get_protocol(wsi), sizeof(struct per_vhost_data__lws_mirror)); - v = (struct per_vhost_data__lws_mirror *) + v = (struct per_vhost_data__lws_mirror *) lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi)); - lws_pthread_mutex_init(&v->lock); + lws_pthread_mutex_init(&v->lock); + } break; case LWS_CALLBACK_PROTOCOL_DESTROY: diff --git a/scripts/ctest-background-kill.sh b/scripts/ctest-background-kill.sh new file mode 100755 index 00000000..4cbe12e2 --- /dev/null +++ b/scripts/ctest-background-kill.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# +# $SAI_INSTANCE_IDX - which instance of sai, 0+ +# $1 - background fixture name, unique within test space, like "multipostlocalsrv" +# $2 - executable +# $3+ - args + +echo "$0 $1 $2 $3 $4" >> /tmp/ctklog + +J=`basename $2`.$1.$SAI_INSTANCE_IDX +PI=`cat /tmp/sai-ctest-$J` +echo "Stage 1 kill $J 'kill $PI'" >> /tmp/ctklog + +# +# We expect our background process to still be around +# + +set +e +set +E +kill -0 $PI 2>&1 >> /tmp/ctklog +GONESKI=$? + +if [ $GONESKI -eq 0 ] ; then + kill $PI 2>&1 >> /tmp/ctklog + kill -9 $PI 2>&1 >> /tmp/ctklog + + kill -0 $PI 2>&1 + if [ $? -eq 0 ] ; then + # + # but in case it isn't enough, use ps to find the same executable started on the same port + # and kill that + # + A1=$3 + if [ -z "$A1" ] ; then + A1=$2 + fi + A2=$4 + if [ -z "$A2" ] ; then + A2=$2 + fi + + # sed is there to match up bsd/osx ps with linux + KL=`ps -Af | grep -v ctest-background-kill | grep -v grep | grep $2 | grep $A1 | grep $A2 | tr -s ' ' | sed "s/^\ //g" | cut -d' ' -f2` + if [ ! -z "$KL" ] ; then + echo "Stage 2 kill $J 'kill $KL'" >> /tmp/ctklog + kill $KL 2>&1 >> /tmp/ctklog + fi + fi +else + echo "Process already dead" >> /tmp/ctklog +fi + +exit $GONESKI + diff --git a/scripts/ctest-background.sh b/scripts/ctest-background.sh new file mode 100755 index 00000000..ebfd8c1b --- /dev/null +++ b/scripts/ctest-background.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# +# $SAI_INSTANCE_IDX - which instance of sai, 0+ +# $1 - background fixture name, unique within test space, like "multipostlocalserver" +# $2 - executable +# $3+ - args + +J=`basename $2`.$1.$SAI_INSTANCE_IDX +$2 $3 $4 $5 $6 $7 $8 $9 2>/tmp/ctest-background-$J 1>/dev/null 0 /tmp/sai-ctest-$J +# really we want to loop until the listen port is up +# on, eg, rpi it can be blocked at sd card and slow to start +# due to parallel tests and disc cache flush +sleep 1 +exit 0 + diff --git a/scripts/libwebsockets.spec b/scripts/libwebsockets.spec deleted file mode 100644 index 823ff0bb..00000000 --- a/scripts/libwebsockets.spec +++ /dev/null @@ -1,180 +0,0 @@ -Name: libwebsockets -Version: 4.0.0 -Release: 1%{?dist} -Summary: Websocket Server and Client Library - -Group: System Environment/Libraries -License: MIT -URL: https://libwebsockets.org -Source0: %{name}-%{version}.tar.gz -BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) - -BuildRequires: openssl-devel libuv-devel libev-devel cmake -Requires: openssl - -%description -Webserver server and client library - -%package devel -Summary: Development files for libwebsockets -Group: Development/Libraries -Requires: %{name} = %{version}-%{release} -Requires: openssl-devel - -%description devel -Development files for libwebsockets - -%prep -%setup -q - -%build -mkdir -p build -cd build -%cmake .. -DLWS_WITH_DISTRO_RECOMMENDED=1 -make - -%install -rm -rf $RPM_BUILD_ROOT -cd build -make install DESTDIR=$RPM_BUILD_ROOT - -%post -p /sbin/ldconfig -%postun -p /sbin/ldconfig - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root,-) -%attr(755,root,root) -"/usr/bin/libwebsockets-test-client" -"/usr/bin/libwebsockets-test-lejp" -"/usr/bin/libwebsockets-test-server" -"/usr/bin/libwebsockets-test-server-extpoll" -"/usr/bin/libwebsockets-test-sshd" -"/usr/bin/lwsws" -"/%{_libdir}/libwebsockets.so" -"/%{_libdir}/libwebsockets.so.16" -%dir "/usr/share/libwebsockets-test-server" -"/usr/share/libwebsockets-test-server/candide.zip" -"/usr/share/libwebsockets-test-server/favicon.ico" -%dir "/usr/share/libwebsockets-test-server/generic-table" -"/usr/share/libwebsockets-test-server/generic-table/index.html" -"/usr/share/libwebsockets-test-server/generic-table/lwsgt.js" -"/usr/share/libwebsockets-test-server/http2.png" -"/usr/share/libwebsockets-test-server/leaf.jpg" -"/usr/share/libwebsockets-test-server/libwebsockets-test-server.key.pem" -"/usr/share/libwebsockets-test-server/libwebsockets-test-server.pem" -"/usr/share/libwebsockets-test-server/libwebsockets.org-logo.svg" -"/usr/share/libwebsockets-test-server/lws-cgi-test.sh" -"/usr/share/libwebsockets-test-server/lws-common.js" -"/usr/share/libwebsockets-test-server/lws-ssh-test-keys" -"/usr/share/libwebsockets-test-server/lws-ssh-test-keys.pub" -%dir "/usr/share/libwebsockets-test-server/plugins" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_client_loopback_test.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_dumb_increment.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_fulltext_demo.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_acme_client.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_mirror.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_raw_test.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_server_status.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_ssh_base.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_sshd_demo.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_status.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_lws_table_dirlisting.so" -"/usr/share/libwebsockets-test-server/plugins/libprotocol_post_demo.so" -%dir "/usr/share/libwebsockets-test-server/private" -"/usr/share/libwebsockets-test-server/private/index.html" -%dir "/usr/share/libwebsockets-test-server/server-status" -"/usr/share/libwebsockets-test-server/server-status/lwsws-logo.png" -"/usr/share/libwebsockets-test-server/server-status/server-status.css" -"/usr/share/libwebsockets-test-server/server-status/server-status.html" -"/usr/share/libwebsockets-test-server/server-status/server-status.js" -"/usr/share/libwebsockets-test-server/test.css" -"/usr/share/libwebsockets-test-server/test.html" -"/usr/share/libwebsockets-test-server/test.js" -"/usr/share/libwebsockets-test-server/wss-over-h2.png" -%files devel -%defattr(-,root,root,-) -%dir "/usr/include/libwebsockets" -"/usr/include/libwebsockets.h" -"/usr/include/libwebsockets/lws-adopt.h" -"/usr/include/libwebsockets/lws-callbacks.h" -"/usr/include/libwebsockets/lws-cgi.h" -"/usr/include/libwebsockets/lws-client.h" -"/usr/include/libwebsockets/lws-context-vhost.h" -"/usr/include/libwebsockets/lws-dbus.h" -"/usr/include/libwebsockets/lws-diskcache.h" -"/usr/include/libwebsockets/lws-esp32.h" -"/usr/include/libwebsockets/lws-fts.h" -"/usr/include/libwebsockets/lws-genhash.h" -"/usr/include/libwebsockets/lws-genrsa.h" -"/usr/include/libwebsockets/lws-http.h" -"/usr/include/libwebsockets/lws-jose.h" -"/usr/include/libwebsockets/lws-jwk.h" -"/usr/include/libwebsockets/lws-jws.h" -"/usr/include/libwebsockets/lws-lejp.h" -"/usr/include/libwebsockets/lws-logs.h" -"/usr/include/libwebsockets/lws-lwsac.h" -"/usr/include/libwebsockets/lws-misc.h" -"/usr/include/libwebsockets/lws-network-helper.h" -"/usr/include/libwebsockets/lws-plugin-generic-sessions.h" -"/usr/include/libwebsockets/lws-protocols-plugins.h" -"/usr/include/libwebsockets/lws-purify.h" -"/usr/include/libwebsockets/lws-ring.h" -"/usr/include/libwebsockets/lws-service.h" -"/usr/include/libwebsockets/lws-sha1-base64.h" -"/usr/include/libwebsockets/lws-spa.h" -"/usr/include/libwebsockets/lws-stats.h" -"/usr/include/libwebsockets/lws-threadpool.h" -"/usr/include/libwebsockets/lws-timeout-timer.h" -"/usr/include/libwebsockets/lws-tokenize.h" -"/usr/include/libwebsockets/lws-vfs.h" -"/usr/include/libwebsockets/lws-write.h" -"/usr/include/libwebsockets/lws-writeable.h" -"/usr/include/libwebsockets/lws-ws-close.h" -"/usr/include/libwebsockets/lws-ws-ext.h" -"/usr/include/libwebsockets/lws-ws-state.h" -"/usr/include/libwebsockets/lws-x509.h" -"/usr/include/lws-plugin-ssh.h" -"/usr/include/lws_config.h" -%dir "/usr/lib/pkgconfig" -"/%{_libdir}/pkgconfig/libwebsockets.pc" -"/usr/lib/pkgconfig/libwebsockets_static.pc" -%dir "/usr/lib/cmake" -%dir "/usr/lib/cmake/libwebsockets" -"/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfig.cmake" -"/%{_libdir}/cmake/libwebsockets/LibwebsocketsConfigVersion.cmake" -"/%{_libdir}/cmake/libwebsockets/LibwebsocketsTargets-debug.cmake" -"/%{_libdir}/cmake/libwebsockets/LibwebsocketsTargets.cmake" - -%changelog -* Fri Aug 14 2019 Andy Green 3.2.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 3.2.0 release (last LGPLv2.1+SLE) - -* Fri Nov 23 2018 Andy Green 3.1.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 3.1.0 release - -* Fri May 4 2018 Andy Green 3.0.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 3.0.0 release - -* Mon Oct 16 2017 Andy Green 2.4.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.4.0 release - -* Fri Jul 28 2017 Andy Green 2.3.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.3.0 release - -* Mon Mar 06 2017 Andy Green 2.2.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.2.0 release - -* Thu Oct 06 2016 Andy Green 2.1.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.1.0 release - -* Thu May 05 2016 Andy Green 2.0.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 2.0.0 release - -* Tue Feb 16 2016 Andy Green 1.7.0-1 -- MAJOR SONAMEBUMP APICHANGES Upstream 1.7.0 release - -* Sun Jan 17 2016 Andrew Cooks 1.6.0-1 -- Bump version to 1.6.0 diff --git a/test-apps/test-server.c b/test-apps/test-server.c index 0da86b0d..2dc6769c 100644 --- a/test-apps/test-server.c +++ b/test-apps/test-server.c @@ -317,6 +317,7 @@ static struct option options[] = { { "ssl-cert", required_argument, NULL, 'C' }, { "ssl-key", required_argument, NULL, 'K' }, { "ssl-ca", required_argument, NULL, 'A' }, + { "resource-path", required_argument, NULL, 'r' }, #if defined(LWS_WITH_TLS) { "ssl-verify-client", no_argument, NULL, 'v' }, #if defined(LWS_HAVE_SSL_CTX_set1_param) @@ -329,10 +330,17 @@ static struct option options[] = { { "daemonize", no_argument, NULL, 'D' }, #endif { "pingpong-secs", required_argument, NULL, 'P' }, + { "ignore-sigterm", no_argument, NULL, 'I' }, + { NULL, 0, 0, 0 } }; #endif +static void +sigterm_catch(int sig) +{ +} + int main(int argc, char **argv) { struct lws_context_creation_info info; @@ -360,9 +368,9 @@ int main(int argc, char **argv) while (n >= 0) { #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32) - n = getopt_long(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:P:kU:n", options, NULL); + n = getopt_long(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:P:kU:niIr:", options, NULL); #else - n = getopt(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:P:kU:n"); + n = getopt(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:P:kU:nIr:"); #endif if (n < 0) continue; @@ -388,6 +396,12 @@ int main(int argc, char **argv) /* no dumb increment send */ test_options |= 1; break; + case 'I': + signal(SIGTERM, sigterm_catch); + break; + case 'r': + resource_path = optarg; + break; case 's': use_ssl = 1; opts |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; @@ -539,8 +553,8 @@ int main(int argc, char **argv) "!AES256-GCM-SHA384:" "!AES256-SHA256"; info.mounts = &mount; - info.ip_limit_ah = 24; /* for testing */ - info.ip_limit_wsi = 400; /* for testing */ + info.ip_limit_ah = 128; /* for testing */ + info.ip_limit_wsi = 800; /* for testing */ if (use_ssl) /* redirect guys coming on http */ diff --git a/win32port/version.rc.in b/win32port/version.rc.in index 8a70f2d3..0dd48fe6 100644 --- a/win32port/version.rc.in +++ b/win32port/version.rc.in @@ -1,12 +1,13 @@ #include +#define LWS_NUMVERSION @LWS_LIBRARY_VERSION_MAJOR@,@LWS_LIBRARY_VERSION_MINOR@,0 #define LWS_VERSION @LWS_LIBRARY_VERSION_MAJOR@,@LWS_LIBRARY_VERSION_MINOR@,@LWS_LIBRARY_VERSION_PATCH@,0 #define LWS_VERSION_STR "@LWS_LIBRARY_VERSION_MAJOR@.@LWS_LIBRARY_VERSION_MINOR@.@LWS_LIBRARY_VERSION_PATCH@\0" #define LWS_PACKAGE_NAME "@PACKAGE@\0" VS_VERSION_INFO VERSIONINFO - FILEVERSION LWS_VERSION - PRODUCTVERSION LWS_VERSION + FILEVERSION LWS_NUMVERSION + PRODUCTVERSION LWS_NUMVERSION FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS__WINDOWS32 -- Gitee From e4a9307b11b531f9e6850a59793386451dd3e746 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 10 May 2020 21:46:11 +0100 Subject: [PATCH 0111/1062] lejp: support outer element is array --- include/libwebsockets/lws-lejp.h | 1 + lib/misc/lejp.c | 40 +++++++++++++++++++++++++++----- test-apps/test-lejp.c | 4 ++-- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/include/libwebsockets/lws-lejp.h b/include/libwebsockets/lws-lejp.h index 0a294bbe..b8837bbf 100644 --- a/include/libwebsockets/lws-lejp.h +++ b/include/libwebsockets/lws-lejp.h @@ -255,6 +255,7 @@ struct lejp_ctx { uint8_t path_match_len; uint8_t wildcount; uint8_t pst_sp; /* parsing stack head */ + uint8_t outer_array; }; LWS_VISIBLE LWS_EXTERN void diff --git a/lib/misc/lejp.c b/lib/misc/lejp.c index 668bb434..2cda400b 100644 --- a/lib/misc/lejp.c +++ b/lib/misc/lejp.c @@ -77,6 +77,7 @@ lejp_construct(struct lejp_ctx *ctx, ctx->st[0].b = 0; ctx->sp = 0; ctx->ipos = 0; + ctx->outer_array = 0; ctx->path_match = 0; ctx->path_stride = 0; ctx->path[0] = '\0'; @@ -265,6 +266,23 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) switch (s) { case LEJP_IDLE: + if (!ctx->sp && c == '[') { + /* push */ + ctx->outer_array = 1; + ctx->st[ctx->sp].s = LEJP_MP_ARRAY_END; + c = LEJP_MP_VALUE; + ctx->path[ctx->pst[ctx->pst_sp].ppos++] = '['; + ctx->path[ctx->pst[ctx->pst_sp].ppos++] = ']'; + ctx->path[ctx->pst[ctx->pst_sp].ppos] = '\0'; + if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_ARRAY_START)) + goto reject_callback; + ctx->i[ctx->ipos++] = 0; + if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) { + ret = LEJP_REJECT_MP_DELIM_ISTACK; + goto reject; + } + goto add_stack_level; + } if (c != '{') { ret = LEJP_REJECT_IDLE_NO_BRACE; goto reject; @@ -484,6 +502,10 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) * smaller than the matching point */ ctx->path_match = 0; + if (ctx->outer_array && !ctx->sp) { /* ended on ] */ + n = LEJPCB_ARRAY_END; + goto completed; + } goto array_end; case 't': /* true */ @@ -641,7 +663,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) break; } if (c == ']') { - if (!ctx->sp) { /* JSON can't end on ] */ + if (!ctx->sp) { ret = LEJP_REJECT_MP_C_OR_E_UNDERF; goto reject; } @@ -651,6 +673,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY; goto reject; } + /* drop the path [n] bit */ if (ctx->sp) { ctx->pst[ctx->pst_sp].ppos = @@ -666,6 +689,11 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) */ ctx->path_match = 0; + if (ctx->outer_array && !ctx->sp) { /* ended on ] */ + n = LEJPCB_ARRAY_END; + goto completed; + } + /* do LEJP_MP_ARRAY_END processing */ goto redo_character; } @@ -674,12 +702,12 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) goto reject; } if (!ctx->sp) { + n = LEJPCB_OBJECT_END; +completed: lejp_check_path_match(ctx); - if (ctx->pst[ctx->pst_sp].callback(ctx, - LEJPCB_OBJECT_END)) - goto reject_callback; - if (ctx->pst[ctx->pst_sp].callback(ctx, - LEJPCB_COMPLETE)) + if (ctx->pst[ctx->pst_sp].callback(ctx, n) || + ctx->pst[ctx->pst_sp].callback(ctx, + LEJPCB_COMPLETE)) goto reject_callback; /* done, return unused amount */ diff --git a/test-apps/test-lejp.c b/test-apps/test-lejp.c index f8634607..37b32508 100644 --- a/test-apps/test-lejp.c +++ b/test-apps/test-lejp.c @@ -88,7 +88,7 @@ cb(struct lejp_ctx *ctx, char reason) int main(int argc, char *argv[]) { - int fd, n = 1, ret = 1, m; + int fd, n = 1, ret = 1, m = 0; struct lejp_ctx ctx; char buf[128]; @@ -112,7 +112,7 @@ main(int argc, char *argv[]) goto bail; } } - lwsl_notice("okay\n"); + lwsl_notice("okay (%d)\n", m); ret = 0; bail: lejp_destruct(&ctx); -- Gitee From c97b68272c6c473bf7f2712da0f3fb870c3c92e0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 11 May 2020 09:07:45 +0100 Subject: [PATCH 0112/1062] connect: enforce timeout for connect async wait This patch allows client connections to recover from a nonresponsive (ie, does not complete connect()) peer and continue to try subsequent DNS results. --- lib/core-net/private-lib-core-net.h | 1 + lib/roles/http/client/client-handshake.c | 40 +++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 811e4ef8..652d9832 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -680,6 +680,7 @@ struct lws { lws_sorted_usec_list_t sul_timeout; lws_sorted_usec_list_t sul_hrtimer; lws_sorted_usec_list_t sul_validity; + lws_sorted_usec_list_t sul_connect_timeout; struct lws_dll2 dll_buflist; /* guys with pending rxflow */ struct lws_dll2 same_vh_protocol; diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index c90abea5..5a4370d9 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -346,6 +346,20 @@ failed: return NULL; } +static void +lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul) +{ + struct lws *wsi = lws_container_of(sul, struct lws, sul_connect_timeout); + + /* + * This is used to constrain the time we're willing to wait for a + * connection before giving up on it and retrying. + */ + + lwsl_info("%s: connect wait timeout has fired\n", __func__); + lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL); +} + struct lws * lws_client_connect_3_connect(struct lws *wsi, const char *ads, const struct addrinfo *result, int n, void *opaque) @@ -392,6 +406,9 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, socklen_t sl = sizeof(int); int e = 0; + if (!result && !wsi->sul_connect_timeout.list.owner) + goto connect_to; + /* * this resets SO_ERROR after reading it. If there's an error * condition the connect definitively failed. @@ -668,6 +685,9 @@ ads_known: wsi->detlat.earliest_write_req_pre_write = lws_now_usecs(); #endif + if (!result && !wsi->sul_connect_timeout.list.owner) + goto connect_to; + m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, n); if (m == -1) { int errno_copy = LWS_ERRNO; @@ -698,6 +718,15 @@ ads_known: goto conn_good; #endif + /* + * Let's set a specialized timeout for the connect completion, + * it uses wsi->sul_connect_timeout just for this purpose + */ + + lws_sul_schedule(wsi->context, 0, &wsi->sul_connect_timeout, + lws_client_conn_wait_timeout, + wsi->context->timeout_secs * LWS_USEC_PER_SEC); + /* * must do specifically a POLLOUT poll to hear * about the connect completion @@ -709,7 +738,8 @@ ads_known: } conn_good: - + lws_sul_schedule(wsi->context, 0, &wsi->sul_connect_timeout, NULL, + LWS_SET_TIMER_USEC_CANCEL); lwsl_info("%s: Connection started %p\n", __func__, wsi->dns_results); /* the tcp connection has happend */ @@ -773,6 +803,12 @@ oom4: return NULL; +connect_to: + /* + * It looks like the sul_connect_timeout fired + */ + lwsl_info("%s: abandoning connect due to timeout\n", __func__); + try_next_result_fds: __remove_wsi_socket_from_fds(wsi); @@ -784,6 +820,8 @@ try_next_result_closesock: wsi->desc.sockfd = LWS_SOCK_INVALID; try_next_result: + lws_sul_schedule(wsi->context, 0, &wsi->sul_connect_timeout, + NULL, LWS_SET_TIMER_USEC_CANCEL); if (wsi->dns_results_next) { wsi->dns_results_next = wsi->dns_results_next->ai_next; if (wsi->dns_results_next) -- Gitee From 36ec353dacaaadb9475713b1024bf9b413a7729c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 26 May 2020 17:05:39 +0100 Subject: [PATCH 0113/1062] client: allow setting overall connect timeout from vh init Add a member to the vh init struct allowing control of the overall connection wait introduced in an earlier patch. Set it to 20s by default. The timeout_secs member controls the individual DNS result connect timeout and is reduced to 5s by default. --- include/libwebsockets/lws-context-vhost.h | 4 ++ lib/core-net/private-lib-core-net.h | 1 + lib/core-net/vhost.c | 6 +++ lib/core/context.c | 2 +- lib/core/private-lib-core.h | 3 -- lib/plat/windows/windows-fds.c | 2 +- lib/plat/windows/windows-service.c | 35 +++++++++--- lib/roles/http/client/client-handshake.c | 53 ++++++++++++------- lib/roles/private-lib-roles.h | 2 + .../minimal-http-client.c | 2 + .../minimal-http-client-hugeurl.c | 2 + .../minimal-http-client/minimal-http-client.c | 1 + .../minimal-ws-client-rx/minimal-ws-client.c | 2 + 13 files changed, 83 insertions(+), 32 deletions(-) diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index 268b3d5a..3022aea7 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -402,6 +402,10 @@ struct lws_context_creation_info { * library are protected from hanging forever by timeouts. If * nonzero, this member lets you set the timeout used in seconds. * Otherwise a default timeout is used. */ + unsigned int connect_timeout_secs; + /**< VHOST: client connections have this long to find a working server + * from the DNS results, or the whole connection times out. If zero, + * a default timeout is used */ const char *ecdh_curve; /**< VHOST: if NULL, defaults to initializing server with * "prime256v1" */ diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 652d9832..57c0c605 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -590,6 +590,7 @@ struct lws_vhost { int ka_interval; int keepalive_timeout; int timeout_secs_ah_idle; + int connect_timeout_secs; int count_bound_wsi; diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index ff73d019..c0b6de2e 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -512,6 +512,12 @@ lws_create_vhost(struct lws_context *context, vh->iface = info->iface; #if !defined(LWS_PLAT_FREERTOS) && !defined(OPTEE_TA) && !defined(WIN32) vh->bind_iface = info->bind_iface; +#endif +#if defined(LWS_WITH_CLIENT) + if (info->connect_timeout_secs) + vh->connect_timeout_secs = info->connect_timeout_secs; + else + vh->connect_timeout_secs = 20; #endif /* apply the context default lws_retry */ diff --git a/lib/core/context.c b/lib/core/context.c index 89c2f3a5..f0383a5e 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -548,7 +548,7 @@ lws_create_context(const struct lws_context_creation_info *info) if (info->timeout_secs) context->timeout_secs = info->timeout_secs; else - context->timeout_secs = AWAITING_TIMEOUT; + context->timeout_secs = 5; context->ws_ping_pong_interval = info->ws_ping_pong_interval; diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 4ac7ef84..f908a2f4 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -82,9 +82,6 @@ #ifndef SPEC_LATEST_SUPPORTED #define SPEC_LATEST_SUPPORTED 13 #endif -#ifndef AWAITING_TIMEOUT -#define AWAITING_TIMEOUT 30 -#endif #ifndef CIPHERS_LIST_STRING #define CIPHERS_LIST_STRING "DEFAULT" #endif diff --git a/lib/plat/windows/windows-fds.c b/lib/plat/windows/windows-fds.c index 2e7d6c9a..05a66208 100644 --- a/lib/plat/windows/windows-fds.c +++ b/lib/plat/windows/windows-fds.c @@ -73,7 +73,7 @@ delete_from_fd(struct lws_context *context, lws_sockfd_type fd) return 0; } - lwsl_err("Failed to find fd %d requested for " + lwsl_debug("Failed to find fd %d requested for " "delete in hashtable\n", fd); return 1; } diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index f265877b..1c3266e2 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -194,13 +194,34 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) pfd->revents = (short)networkevents.lNetworkEvents; err = networkevents.iErrorCode[FD_CONNECT_BIT]; - - if ((networkevents.lNetworkEvents & FD_CONNECT) && - err && err != LWS_EALREADY && - err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK && - err != WSAEINVAL) { - lwsl_debug("Unable to connect errno=%d\n", err); - pfd->revents |= LWS_POLLHUP; + if ((networkevents.lNetworkEvents & FD_CONNECT) && wsi_from_fd(context, pfd->fd) && !wsi_from_fd(context, pfd->fd)->udp) { + lwsl_debug("%s: FD_CONNECT: %p\n", __func__, wsi_from_fd(context, pfd->fd)); + pfd->revents &= ~LWS_POLLOUT; + if (err && err != LWS_EALREADY && + err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK && + err != WSAEINVAL) { + lwsl_debug("Unable to connect errno=%d\n", err); + + /* + * the connection has definitively failed... but + * do we have more DNS entries to try? + */ + if (wsi_from_fd(context, pfd->fd)->dns_results_next) { + lws_sul_schedule(context, 0, &wsi_from_fd(context, pfd->fd)-> + sul_connect_timeout, + lws_client_conn_wait_timeout, 1); + continue; + } else + pfd->revents |= LWS_POLLHUP; + } else + if (wsi_from_fd(context, pfd->fd)) { + if (wsi_from_fd(context, pfd->fd)->udp) + pfd->revents |= LWS_POLLHUP; + else + lws_client_connect_3_connect(wsi_from_fd(context, pfd->fd), + NULL, NULL, LWS_CONNECT_COMPLETION_GOOD, + NULL); + } } if (pfd->revents & LWS_POLLOUT) { diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 5a4370d9..479ca6ff 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -280,7 +280,7 @@ send_hs: * provoke service to issue the CONNECT directly. */ lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, - AWAITING_TIMEOUT); + wsi->context->timeout_secs); assert(lws_socket_is_valid(wsi->desc.sockfd)); @@ -356,6 +356,10 @@ lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul) * connection before giving up on it and retrying. */ +#if defined(WIN32) + wsi->dns_results_next = wsi->dns_results_next->ai_next; +#endif + lwsl_info("%s: connect wait timeout has fired\n", __func__); lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL); } @@ -380,6 +384,9 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, char ni[48]; int m; + if (n == LWS_CONNECT_COMPLETION_GOOD) + goto conn_good; + #if defined(LWS_WITH_IPV6) && defined(__ANDROID__) ipv6only = 0; #endif @@ -393,7 +400,6 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, if (!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) return wsi; -#if !defined(WIN32) /* * We can check using getsockopt if our connect actually completed. * Posix connect() allows nonblocking to redo the connect to @@ -406,22 +412,31 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, socklen_t sl = sizeof(int); int e = 0; - if (!result && !wsi->sul_connect_timeout.list.owner) + if (!result && /* no dns results... */ + !wsi->sul_connect_timeout.list.owner /* no ongoing connect timeout */) goto connect_to; - +#if defined(WIN32) + if (!connect(wsi->desc.sockfd, NULL, 0)) { + goto conn_good; + } else { + if (!LWS_ERRNO || LWS_ERRNO == WSAEINVAL || + LWS_ERRNO == WSAEWOULDBLOCK || LWS_ERRNO == WSAEALREADY) { + lwsl_info("%s: errno %d\n", __func__, errno); + return NULL; + } + lwsl_info("%s: connect check take as FAILED\n", __func__); + } +#else /* * this resets SO_ERROR after reading it. If there's an error * condition the connect definitively failed. */ if (!getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR, -#if defined(WIN32) - (char *) -#endif &e, &sl)) { if (!e) { - lwsl_info("%s: getsockopt check: conn OK\n", - __func__); + lwsl_debug("%s: getsockopt check: conn OK errno %d\n", + __func__, errno); goto conn_good; } @@ -429,12 +444,12 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, lwsl_debug("%s: getsockopt fd %d says err %d\n", __func__, wsi->desc.sockfd, e); } +#endif lwsl_debug("%s: getsockopt check: conn fail: errno %d\n", __func__, LWS_ERRNO); goto try_next_result_fds; } -#endif #if defined(LWS_WITH_UNIX_SOCK) if (ads && *ads == '+') { @@ -551,7 +566,8 @@ next_result: ni[0] = '\0'; lws_write_numeric_address(sa46.sa6.sin6_addr.s6_addr, 16, ni, sizeof(ni)); - lwsl_info("%s: %s ipv4->ipv6 %s\n", __func__, ads, ni); + lwsl_info("%s: %s ipv4->ipv6 %s\n", __func__, + ads ? ads : "(null)", ni); break; } #endif @@ -564,7 +580,7 @@ next_result: n = sizeof(struct sockaddr_in); lws_write_numeric_address((uint8_t *)&sa46.sa4.sin_addr.s_addr, 4, ni, sizeof(ni)); - lwsl_info("%s: %s ipv4 %s\n", __func__, ads, ni); + lwsl_info("%s: %s ipv4 %s\n", __func__, ads ? ads : "(null)", ni); break; case AF_INET6: #if defined(LWS_WITH_IPV6) @@ -581,7 +597,7 @@ next_result: sa46.sa6.sin6_port = htons(port); lws_write_numeric_address((uint8_t *)&sa46.sa6.sin6_addr, 16, ni, sizeof(ni)); - lwsl_info("%s: %s ipv6 %s\n", __func__, ads, ni); + lwsl_info("%s: %s ipv6 %s\n", __func__, ads ? ads : "(null)", ni); #else goto try_next_result; /* ipv4 only can't use this */ #endif @@ -653,7 +669,7 @@ ads_known: wsi->protocol = &wsi->vhost->protocols[0]; lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE, - wsi->context->timeout_secs); + wsi->vhost->connect_timeout_secs); iface = lws_wsi_client_stash_item(wsi, CIS_IFACE, _WSI_TOKEN_CLIENT_IFACE); @@ -685,9 +701,6 @@ ads_known: wsi->detlat.earliest_write_req_pre_write = lws_now_usecs(); #endif - if (!result && !wsi->sul_connect_timeout.list.owner) - goto connect_to; - m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, n); if (m == -1) { int errno_copy = LWS_ERRNO; @@ -719,8 +732,9 @@ ads_known: #endif /* - * Let's set a specialized timeout for the connect completion, - * it uses wsi->sul_connect_timeout just for this purpose + * Let's set a specialized timeout for this connect attempt + * completion, it uses wsi->sul_connect_timeout just for this + * purpose */ lws_sul_schedule(wsi->context, 0, &wsi->sul_connect_timeout, @@ -802,7 +816,6 @@ oom4: return NULL; - connect_to: /* * It looks like the sul_connect_timeout fired diff --git a/lib/roles/private-lib-roles.h b/lib/roles/private-lib-roles.h index 0d5008d3..78328b9f 100644 --- a/lib/roles/private-lib-roles.h +++ b/lib/roles/private-lib-roles.h @@ -341,6 +341,8 @@ enum { LWS_UPG_RET_BAIL }; +#define LWS_CONNECT_COMPLETION_GOOD (-99) + int lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot); diff --git a/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c b/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c index 4d0d88a6..b16a0ce4 100644 --- a/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c +++ b/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c @@ -259,6 +259,8 @@ int main(int argc, const char **argv) info.protocols = protocols; info.user = &args; info.register_notifier_list = na; + info.timeout_secs = 10; + info.connect_timeout_secs = 30; /* * since we know this lws context is only ever going to be used with diff --git a/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c b/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c index f0b90a28..7a02a9b7 100644 --- a/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c +++ b/minimal-examples/http-client/minimal-http-client-hugeurl/minimal-http-client-hugeurl.c @@ -162,6 +162,8 @@ int main(int argc, const char **argv) info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ info.protocols = protocols; info.pt_serv_buf_size = 8192; + info.timeout_secs = 10; + info.connect_timeout_secs = 30; /* * since we know this lws context is only ever going to be used with * one client wsis / fds / sockets at a time, let lws know it doesn't diff --git a/minimal-examples/http-client/minimal-http-client/minimal-http-client.c b/minimal-examples/http-client/minimal-http-client/minimal-http-client.c index f75d3042..248ddad0 100644 --- a/minimal-examples/http-client/minimal-http-client/minimal-http-client.c +++ b/minimal-examples/http-client/minimal-http-client/minimal-http-client.c @@ -282,6 +282,7 @@ int main(int argc, const char **argv) info.protocols = protocols; info.user = &args; info.register_notifier_list = na; + info.connect_timeout_secs = 30; /* * since we know this lws context is only ever going to be used with diff --git a/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c b/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c index e3092602..e827526f 100644 --- a/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c +++ b/minimal-examples/ws-client/minimal-ws-client-rx/minimal-ws-client.c @@ -99,6 +99,8 @@ int main(int argc, const char **argv) info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ info.protocols = protocols; + info.timeout_secs = 10; + info.connect_timeout_secs = 30; #if defined(LWS_WITH_MBEDTLS) /* * OpenSSL uses the system trust store. mbedTLS has to be told which -- Gitee From 71f6f9a1f93b8af664a6b108eda35545a89328ee Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 11 May 2020 14:05:36 +0100 Subject: [PATCH 0114/1062] win: deal with FD_CONNECT better POSIX connect() specifies it will signal POLLOUT available when the connect result is available. But windows has some non-posix nonsense. Improve the plat support to simulate the missing POLLOUT. --- lib/plat/windows/windows-service.c | 1 + lib/roles/http/client/client-handshake.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index 1c3266e2..ae16d973 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -54,6 +54,7 @@ _lws_plat_service_forced_tsi(struct lws_context *context, int tsi) return r; } +extern void lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul); int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 479ca6ff..d130ad35 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -346,7 +346,7 @@ failed: return NULL; } -static void +void lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul) { struct lws *wsi = lws_container_of(sul, struct lws, sul_connect_timeout); @@ -745,8 +745,10 @@ ads_known: * must do specifically a POLLOUT poll to hear * about the connect completion */ +#if !defined(WIN32) if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) goto try_next_result_fds; +#endif return wsi; } -- Gitee From ee3b4a4b8163e15726557365af8ac9bfb90be972 Mon Sep 17 00:00:00 2001 From: Sakthi Kannan Date: Mon, 11 May 2020 14:48:05 +0100 Subject: [PATCH 0115/1062] mqtt: avoid LRS_H1C_ISSUE_HANDSHAKE Otherwise we can get the client connection stalling since H1C has no meaning on mqtt. --- lib/roles/http/client/client-handshake.c | 79 ++++++++++++------------ 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index d130ad35..fcc1ecf8 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -197,57 +197,56 @@ send_hs: /* we are making our own connection */ + if (!rawish) { + if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2) + lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE); + } else { + /* for a method = "RAW" connection, this makes us + * established */ + #if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS) - /* we have connected if we got here */ + /* we have connected if we got here */ - if (lwsi_state(wsi) == LRS_WAITING_CONNECT && - (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { - int result; + if (lwsi_state(wsi) == LRS_WAITING_CONNECT && + (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { + int result; - /* - * We can retry this... just cook the SSL BIO - * the first time - */ + /* + * We can retry this... just cook the SSL BIO + * the first time + */ - result = lws_client_create_tls(wsi, &cce, 1); - lwsl_debug("%s: create_tls said %d\n", __func__, result); - switch (result) { - case CCTLS_RETURN_DONE: - break; - case CCTLS_RETURN_RETRY: - return wsi; - default: - goto failed; - } + result = lws_client_create_tls(wsi, &cce, 1); + lwsl_debug("%s: create_tls said %d\n", __func__, result); + switch (result) { + case CCTLS_RETURN_DONE: + break; + case CCTLS_RETURN_RETRY: + return wsi; + default: + goto failed; + } - /* - * We succeeded to negotiate a new client tls tunnel. - * If it's h2 alpn, we have arranged to send to h2 - * prefix and set our state to - * LRS_H2_WAITING_TO_SEND_HEADERS already. - */ + /* + * We succeeded to negotiate a new client tls tunnel. + * If it's h2 alpn, we have arranged to send to h2 + * prefix and set our state to + * LRS_H2_WAITING_TO_SEND_HEADERS already. + */ - lwsl_notice("%s: wsi %p: tls established st 0x%x\n", - __func__, wsi, lwsi_state(wsi)); + lwsl_notice("%s: wsi %p: tls established st 0x%x\n", + __func__, wsi, lwsi_state(wsi)); - if (lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS) - lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); - lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, - wsi->context->timeout_secs); + if (lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS) + lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); + lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, + wsi->context->timeout_secs); - goto provoke_service; - } + goto provoke_service; + } #endif - if (!rawish) { - if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2) - lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE); - } else { - /* for a method = "RAW" connection, this makes us - * established */ - - /* clear his established timeout */ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); -- Gitee From b3576e7205d630c9e25df62b971db890f3b7c40c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 11 May 2020 15:08:52 +0100 Subject: [PATCH 0116/1062] ss: make sure to use LWS_WRITE_HTTP_FINAL with SS EOM flag When most of ss-h2 was combined into ss-h1 during development, the h2 difference about needing HTTP_FINAL to signal h2 FIN flag was accidentally dropped. In many cases the peer can infer it, from, eg, content-length reached. But we need to replace explicitly doing it to cover all cases. --- lib/secure-streams/protocols/ss-h1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 4376f41c..ad06088f 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -514,7 +514,8 @@ malformed: lws_ptr_diff(p, buf + LWS_PRE), f); if (lws_write(wsi, buf + LWS_PRE, lws_ptr_diff(p, buf + LWS_PRE), - LWS_WRITE_HTTP) != (int)lws_ptr_diff(p, buf + LWS_PRE)) { + (f & LWSSS_FLAG_EOM) ? LWS_WRITE_HTTP_FINAL : LWS_WRITE_HTTP) != + (int)lws_ptr_diff(p, buf + LWS_PRE)) { lwsl_err("%s: write failed\n", __func__); return -1; } -- Gitee From 56233808036577cbd59a2836fbeeebde0f9572d2 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 12 May 2020 05:09:15 +0100 Subject: [PATCH 0117/1062] libev: fix destroy path and example typo https://github.com/warmcat/libwebsockets/issues/1913 --- lib/event-libs/libev/libev.c | 5 +---- .../minimal-http-server-eventlib-foreign.c | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/event-libs/libev/libev.c b/lib/event-libs/libev/libev.c index 9770cf1c..f58b8f91 100644 --- a/lib/event-libs/libev/libev.c +++ b/lib/event-libs/libev/libev.c @@ -235,11 +235,8 @@ elops_destroy_pt_ev(struct lws_context *context, int tsi) ev_timer_stop(pt->ev.io_loop, &pt->ev.hrtimer); ev_idle_stop(pt->ev.io_loop, &pt->ev.idle); - if (!pt->event_loop_foreign) { + if (!pt->event_loop_foreign) ev_signal_stop(pt->ev.io_loop, &pt->w_sigint.ev.watcher); - - ev_loop_destroy(pt->ev.io_loop); - } } static int diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c index 4317e148..332f08c5 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c +++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c @@ -306,7 +306,7 @@ foreign_event_loop_cleanup_libev(void) ev_timer_stop(loop_ev, &timer_outer_ev); ev_signal_stop(loop_ev, &sighandler_ev); - ev_run(loop_ev, UV_RUN_DEFAULT); + ev_run(loop_ev, 0); ev_loop_destroy(loop_ev); } -- Gitee From 71f2333e8f499203673dee430621c9046577eb32 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 12 May 2020 10:00:10 +0100 Subject: [PATCH 0118/1062] ios: import toolchain file This (BSD 3-clause) came from here https://raw.githubusercontent.com/cristeab/ios-cmake/master/toolchain/iOS.cmake and is necessary to build cmake projects properly using xcode / iOS SDK Add Sai build for iOS on mac, currently without tls --- .sai.json | 10 ++- contrib/iOS.cmake | 222 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 contrib/iOS.cmake diff --git a/.sai.json b/.sai.json index 294ffa30..bac40cc0 100644 --- a/.sai.json +++ b/.sai.json @@ -21,9 +21,14 @@ "build": "mkdir build;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j3 && make -j DESTDIR=../destdir install && ctest -j3 --output-on-failure ${cpack}", "default": false }, + "iOS": { + "build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";cmake .. -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DCMAKE_IOS_DEVELOPER_ROOT=/opt/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer -DCMAKE_TOOLCHAIN_FILE=contrib/iOS.cmake -DIOS_PLATFORM=OS ${cmake} && make -j", + "default": false + }, "OSX-catalina": { - "build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";cmake .. -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/openssl@1.1/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" + "build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";export MACOSX_DEPLOYMENT_TARGET=10.14 ; cmake .. -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/openssl@1.1/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, + "linkit-cross": { "build": "mkdir build;cd build;export CCACHE_DISABLE=1;cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/tmp -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake -DLWS_PLAT_FREERTOS=1 -DLWS_WITH_ZLIB=0 -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_HTTP_STREAM_COMPRESSION=0 -DLWS_WITH_MBEDTLS=1 -DLWS_WITH_FILE_OPS=0 ${cmake};make -j", "default": false @@ -102,7 +107,8 @@ "platforms": "windows-10" }, "nossl": { - "cmake": "-DLWS_WITH_SSL=OFF" + "cmake": "-DLWS_WITH_SSL=OFF", + "platforms": "iOS" }, "daemon": { "cmake": "-DLWS_WITHOUT_DAEMONIZE=OFF" diff --git a/contrib/iOS.cmake b/contrib/iOS.cmake new file mode 100644 index 00000000..fa80eadc --- /dev/null +++ b/contrib/iOS.cmake @@ -0,0 +1,222 @@ +# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake +# files which are included with CMake 2.8.4 +# It has been altered for iOS development + +# Options: +# +# IOS_PLATFORM = OS (default) or SIMULATOR or SIMULATOR64 +# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders +# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch. +# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch. +# +# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder +# By default this location is automatcially chosen based on the IOS_PLATFORM value above. +# If set manually, it will override the default location and force the user of a particular Developer Platform +# +# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder +# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value. +# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path. +# If set manually, this will force the use of a specific SDK version +# +# IOS_BITCODE = 1/0: Enable bitcode or not. Only iOS >= 6.0 device build can enable bitcode. Default is enabled. + +# Macros: +# +# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE) +# A convenience macro for setting xcode specific properties on targets +# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1") +# +# find_host_package (PROGRAM ARGS) +# A macro used to find executable programs on the host system, not within the iOS environment. +# Thanks to the android-cmake project for providing the command + +# Standard settings +set (CMAKE_SYSTEM_NAME Darwin) +set (CMAKE_SYSTEM_VERSION 1) +set(CMAKE_CROSSCOMPILING TRUE) +set (UNIX TRUE) +set (APPLE TRUE) +set (IOS TRUE) + +if(NOT DEFINED IOS_BITCODE) # check xcode/clang version? since xcode 7 + set(IOS_BITCODE 1) +endif() +set(IOS_BITCODE_MARKER 0) + +# Required as of cmake 2.8.10 +set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE) + +# Determine the cmake host system version so we know where to find the iOS SDKs +find_program (CMAKE_UNAME uname /bin /usr/bin /usr/local/bin) +if (CMAKE_UNAME) + exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) + string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}") +endif (CMAKE_UNAME) + +# Force the compilers to gcc for iOS +include (CMakeForceCompiler) +set (CMAKE_C_COMPILER /usr/bin/clang) +set (CMAKE_CXX_COMPILER /usr/bin/clang++) +set(CMAKE_AR ar CACHE FILEPATH "" FORCE) + +# Skip the platform compiler checks for cross compiling +set (CMAKE_CXX_COMPILER_WORKS TRUE) +set (CMAKE_C_COMPILER_WORKS TRUE) + +# All iOS/Darwin specific settings - some may be redundant +set (CMAKE_SHARED_LIBRARY_PREFIX "lib") +set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") +set (CMAKE_SHARED_MODULE_PREFIX "lib") +set (CMAKE_SHARED_MODULE_SUFFIX ".so") +set (CMAKE_MODULE_EXISTS 1) +set (CMAKE_DL_LIBS "") + +if(IOS_BITCODE) + set(BITCODE_FLAGS "-fembed-bitcode") + elseif(IOS_BITCODE_MARKER) + set(BITCODE_FLAGS "-fembed-bitcode-marker") + endif() + +set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") +set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") +set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") + +# Hidden visibilty is required for cxx on iOS +set (CMAKE_C_FLAGS_INIT "${BITCODE_FLAGS}") +set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden -fvisibility-inlines-hidden ${BITCODE_FLAGS}") + +set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}") +set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}") + +set (CMAKE_PLATFORM_HAS_INSTALLNAME 1) +set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names") +set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names") +set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") +set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") +set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a") + +# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree +# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache +# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun) +# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex +if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool) +endif () + +# Setup iOS platform unless specified manually with IOS_PLATFORM +if (NOT DEFINED IOS_PLATFORM) + set (IOS_PLATFORM "OS") +endif () +set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform") + +# Setup building for arm64 or not +if (NOT DEFINED BUILD_ARM64) + set (BUILD_ARM64 true) +endif () +set (BUILD_ARM64 ${BUILD_ARM64} CACHE STRING "Build arm64 arch or not") + +# Check the platform selection and setup for developer root +if (${IOS_PLATFORM} STREQUAL "OS") + set (IOS_PLATFORM_LOCATION "iPhoneOS.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos") +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") + set (IS_SIMULATOR true) + set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64") + set (IS_SIMULATOR true) + set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") +else () + message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR") +endif () + +# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT +# Note Xcode 4.3 changed the installation location, choose the most recent one available +exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR) +set (XCODE_POST_43_ROOT "${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/${IOS_PLATFORM_LOCATION}/Developer") +set (XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer") +if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) + if (EXISTS ${XCODE_POST_43_ROOT}) + set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT}) + elseif(EXISTS ${XCODE_PRE_43_ROOT}) + set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT}) + endif (EXISTS ${XCODE_POST_43_ROOT}) +endif () +set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform") + +# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT +if (NOT DEFINED CMAKE_IOS_SDK_ROOT) + file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*") + if (_CMAKE_IOS_SDKS) + list (SORT _CMAKE_IOS_SDKS) + list (REVERSE _CMAKE_IOS_SDKS) + list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT) + else (_CMAKE_IOS_SDKS) + message (FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.") + endif (_CMAKE_IOS_SDKS) + message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}") +endif () +set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK") + +# Set the sysroot default to the most recent SDK +set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support") + +# set the architecture for iOS +if (${IOS_PLATFORM} STREQUAL "OS") + set (IOS_ARCH arm64) +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") + set (IOS_ARCH i386) +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64") + set (IOS_ARCH x86_64) +endif () + +set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE STRING "Build architecture for iOS") + +# Set the find root to the iOS developer roots and to user defined paths +set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE STRING "iOS find search path root") + +# default to searching for frameworks first +set (CMAKE_FIND_FRAMEWORK FIRST) + +# set up the default search directories for frameworks +set (CMAKE_SYSTEM_FRAMEWORK_PATH + ${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks + ${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks + ${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks +) + +# only search the iOS sdks, not the remainder of the host filesystem +set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + + +# This little macro lets you set any XCode specific property +macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE) + set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE}) +endmacro (set_xcode_property) + + +# This macro lets you find executable programs on the host system +macro (find_host_package) + set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set (IOS FALSE) + + find_package(${ARGN}) + + set (IOS TRUE) + set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) + set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endmacro (find_host_package) + -- Gitee From 2d7be680de451ceab78a7948dc5512f85f9c4bfb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 13 May 2020 10:19:37 +0100 Subject: [PATCH 0119/1062] android: modernize toolchain file and add build README Add builder to .sai.json for just lws + mbedtls on aarch64 --- .sai.json | 8 ++ READMEs/README.build-android.md | 77 ++++++++++++++++++ contrib/android-make-script.sh | 116 ---------------------------- contrib/cross-aarch64-android.cmake | 28 ++++--- 4 files changed, 104 insertions(+), 125 deletions(-) create mode 100644 READMEs/README.build-android.md delete mode 100755 contrib/android-make-script.sh diff --git a/.sai.json b/.sai.json index bac40cc0..6bb9de04 100644 --- a/.sai.json +++ b/.sai.json @@ -21,6 +21,10 @@ "build": "mkdir build;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j3 && make -j DESTDIR=../destdir install && ctest -j3 --output-on-failure ${cpack}", "default": false }, + "android-aarch64": { + "build": "mkdir build;cd build;cmake .. -DCMAKE_TOOLCHAIN_FILE=../libwebsockets/contrib/cross-aarch64-android.cmake ${cmake} && make -j", + "default": false + }, "iOS": { "build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";cmake .. -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DCMAKE_IOS_DEVELOPER_ROOT=/opt/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer -DCMAKE_TOOLCHAIN_FILE=contrib/iOS.cmake -DIOS_PLATFORM=OS ${cmake} && make -j", "default": false @@ -76,6 +80,10 @@ # no distro -devel package for libuv "platforms": "not linux-centos-8-x8664" }, + "justmbedtls": { + "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITHOUT_TESTAPPS=1", + "platforms": "none, android-aarch64" + }, "mbedtls": { "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG", # no distro -devel package for mbedtls diff --git a/READMEs/README.build-android.md b/READMEs/README.build-android.md new file mode 100644 index 00000000..be7a980d --- /dev/null +++ b/READMEs/README.build-android.md @@ -0,0 +1,77 @@ +# Building for Android NDK + +If you have the ndk and prebuilt toolchains with that, you can simply build +lws library for your android app from one cmake and one make command. + +However if you want a tls lib, you have to take care of building and pointing +to that first. But if it's a cmake project like mbedtls, that also is just a +matter of one cmake and one make. + +## Installing NDK pieces + +There's probably a more direct way but the official way is install the whole +Android Studio and then run `sdkmanager` to install a recent NDK. + +I installed the sdk and ndk pieces into /opt/android/ and that's how the +`./contrib/cross-aarch64-android.cmake` toolchain file is shipped. You can +adapt some settings at the top of that file including the path if needed. + +## Fetching lws (needed first for cross toolchain file) + +It doesn't care where you put these projects, but for simplicity they should +be in the same parent dir, like + +``` + - /home/someone + - /home/someone/libwebsockets + - /home/someone/mbedtls +``` + +The reason is that building mbedtls need the cross toolchain file from +libwebsockets, that's also why we have to get libwebsockets first now but +build it later. + +``` +$ git clone https://libwebsockets.org/repo/libwebsockets +``` + +## Building mbedtls + +``` +$ git clone https://github.com/ARMmbed/mbedtls.git +$ cd mbedtls +$ mkdir build +$ cd build +$ rm -f CMakeCache.txt && \ + cmake .. -DCMAKE_TOOLCHAIN_FILE=../libwebsockets/contrib/cross-aarch64-android.cmake \ + -DUSE_SHARED_MBEDTLS_LIBRARY=1 \ + -DENABLE_PROGRAMS=0 \ + -Wno-dev && \ + make -j && \ + cmake --install . +``` + +The lws toolchain file sets the path to install into as the cross root path, so +despite it looks like the destination dir is missing for the install, it will +go into, eg `/opt/android/ndk/21.1.6352462/platforms/android-24/arch-arm64/lib/libmbedcrypto.a` +where lws will look for it + +## Building lws + +You don't need to explain where mbedtls can be found... lws will build with the +same toolchain file that sets the cross root to the same place as mbedtls, it +will easily find them there without any further hints. + +``` +$ mkdir build +$ cd build +$ rm -f CMakeCache.txt && \ + cmake .. -DCMAKE_TOOLCHAIN_FILE=../libwebsockets/contrib/cross-aarch64-android.cmake \ + -DLWS_WITH_MBEDTLS=1 \ + -DLWS_WITHOUT_TESTAPPS=1 && \ + make && \ + cmake --install . +``` + +That's it, both mbedtls and lws library and header files are installed into the +ndk cross root. diff --git a/contrib/android-make-script.sh b/contrib/android-make-script.sh deleted file mode 100755 index 1ef86074..00000000 --- a/contrib/android-make-script.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash - -# -# Build libwebsockets static library for Android -# - -# path to NDK -export NDK=/opt/ndk_r17/android-ndk-r17-beta2-linux-x86_64/android-ndk-r17-beta2 -export ANDROID_NDK=${NDK} -export TOOLCHAIN=${NDK}/toolchain -export CORSS_SYSROOT=${NDK}/sysroot -export SYSROOT=${NDK}/platforms/android-22/arch-arm -set -e - -# Download packages libz, libuv, mbedtls and libwebsockets -#zlib-1.2.8 -#libuv-1.x -#mbedtls-2.11.0 -#libwebsockets-3.0.0 - - -# create a local android toolchain -API=${3:-24} - -$NDK/build/tools/make-standalone-toolchain.sh \ - --toolchain=arm-linux-androideabi-4.9 \ - --arch=arm \ - --install-dir=`pwd`/android-toolchain-arm \ - --platform=android-$API \ - --stl=libc++ \ - --force \ - --verbose - -# setup environment to use the gcc/ld from the android toolchain -export INSTALL_PATH=/opt/libwebsockets_android/android-toolchain-arm -export TOOLCHAIN_PATH=`pwd`/android-toolchain-arm -export TOOL=arm-linux-androideabi -export NDK_TOOLCHAIN_BASENAME=${TOOLCHAIN_PATH}/bin/${TOOL} -export PATH=`pwd`/android-toolchain-arm/bin:$PATH -export CC=$NDK_TOOLCHAIN_BASENAME-gcc -export CXX=$NDK_TOOLCHAIN_BASENAME-g++ -export LINK=${CXX} -export LD=$NDK_TOOLCHAIN_BASENAME-ld -export AR=$NDK_TOOLCHAIN_BASENAME-ar -export RANLIB=$NDK_TOOLCHAIN_BASENAME-ranlib -export STRIP=$NDK_TOOLCHAIN_BASENAME-strip -export PLATFORM=android -export CFLAGS="D__ANDROID_API__=$API" - -# configure and build libuv -[ ! -f ./android-toolchain-arm/lib/libuv.so ] && { -cd libuv -echo "=============================================>> build libuv" - -PATH=$TOOLCHAIN_PATH:$PATH make clean -PATH=$TOOLCHAIN_PATH:$PATH make -PATH=$TOOLCHAIN_PATH:$PATH make install -echo "<<============================================= build libuv" -cd .. -} - -# configure and build zlib -[ ! -f ./android-toolchain-arm/lib/libz.so ] && { -cd zlib-1.2.8 -echo "=============================================>> build libz" - -PATH=$TOOLCHAIN_PATH:$PATH make clean -PATH=$TOOLCHAIN_PATH:$PATH make -PATH=$TOOLCHAIN_PATH:$PATH make install -echo "<<============================================= build libz" -cd .. -} - -# configure and build mbedtls -[ ! -f ./android-toolchain-arm/lib/libmbedtls.so ] && { -echo "=============================================>> build mbedtls" -PREFIX=$TOOLCHAIN_PATH -cd mbedtls-2.11.0 -[ ! -d build ] && mkdir build -cd build -export CFLAGS="$CFLAGS -fomit-frame-pointer" - -PATH=$TOOLCHAIN_PATH:$PATH cmake .. -DCMAKE_TOOLCHAIN_FILE=`pwd`/../cross-arm-android-gnueabi.cmake \ - -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_PATH} \ - -DCMAKE_BUILD_TYPE=RELEASE -DUSE_SHARED_MBEDTLS_LIBRARY=On - -PATH=$TOOLCHAIN_PATH:$PATH make clean -PATH=$TOOLCHAIN_PATH:$PATH make SHARED=1 -PATH=$TOOLCHAIN_PATH:$PATH make install -echo "<<============================================= build mbedtls" -cd ../.. -} - -# configure and build libwebsockets -[ ! -f ./android-toolchain-arm/lib/libwebsockets.so ] && { -cd libwebsockets -[ ! -d build ] && mkdir build -cd build -echo "=============================================>> build libwebsockets" - -PATH=$TOOLCHAIN_PATH:$PATH cmake .. -DCMAKE_TOOLCHAIN_FILE=`pwd`/../cross-arm-android-gnueabi.cmake \ - -DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_PATH} \ - -DLWS_WITH_LWSWS=1 \ - -DLWS_WITH_MBEDTLS=1 \ - -DLWS_WITHOUT_TESTAPPS=1 \ - -DLWS_MBEDTLS_LIBRARIES="${INSTALL_PATH}/lib/libmbedcrypto.a;${INSTALL_PATH}/lib/libmbedtls.a;${INSTALL_PATH}/lib/libmbedx509.a" \ - -DLWS_MBEDTLS_INCLUDE_DIRS=${INSTALL_PATH}/include \ - -DLWS_LIBUV_LIBRARIES=${INSTALL_PATH}/lib/libuv.so \ - -DLWS_LIBUV_INCLUDE_DIRS=${INSTALL_PATH}/include \ - -DLWS_ZLIB_LIBRARIES=${INSTALL_PATH}/lib/libz.so \ - -DLWS_ZLIB_INCLUDE_DIRS=${INSTALL_PATH}/include -PATH=$TOOLCHAIN_PATH:$PATH make -PATH=$TOOLCHAIN_PATH:$PATH make install -echo "<<============================================= build libwebsockets" -cd ../.. -} diff --git a/contrib/cross-aarch64-android.cmake b/contrib/cross-aarch64-android.cmake index efd004f1..a0b3f4e6 100644 --- a/contrib/cross-aarch64-android.cmake +++ b/contrib/cross-aarch64-android.cmake @@ -3,16 +3,27 @@ # # This can be used when running cmake in the following way: # cd build/ -# cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-aarch64-android.cmake +# cmake .. -DCMAKE_TOOLCHAIN_FILE=contrib/cross-aarch64-android.cmake # -# Target operating system name. -set(CMAKE_SYSTEM_NAME Linux) + +set(ANDROID_API_VER 24) +set(ABARCH1 arm64) set(CMAKE_SYSTEM_PROCESSOR aarch64) +set(NDK /opt/android/ndk/21.1.6352462/) +set(CROSS_SYSROOT "${NDK}/platforms/android-${ANDROID_API_VER}/arch-${ABARCH1}") +set(BUILD_ARCH linux-x86_64) -# Name of C compiler. -set(CMAKE_C_COMPILER "aarch64-linux-android-gcc") -set(CMAKE_CXX_COMPILER "aarch64-linux-android-g++") +# +# Rest should be computed from the above +# +set(TC_PATH ${NDK}/toolchains/llvm/prebuilt/${BUILD_ARCH}) +set(TC_BASE ${TC_PATH}/bin/${CMAKE_SYSTEM_PROCESSOR}-linux-android) +set(PLATFORM android) +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_C_COMPILER "${TC_BASE}${ANDROID_API_VER}-clang") +set(CMAKE_CXX_COMPILER "${TC_BASE}${ANDROID_API_VER}-clang++") +set(CMAKE_STAGING_PREFIX "${CROSS_SYSROOT}") # # Different build system distros set release optimization level to different @@ -31,11 +42,10 @@ if (CMAKE_BUILD_TYPE MATCHES RELEASE OR CMAKE_BUILD_TYPE MATCHES Release OR CMAK endif() #-nostdlib -SET(CMAKE_C_FLAGS "-DGCC_VER=\"\\\"$(GCC_VER)\\\"\" -DARM64=1 -D__LP64__=1 -Os -g3 -fpie -mstrict-align -fPIC -ffunction-sections -fdata-sections " CACHE STRING "" FORCE) +SET(CMAKE_C_FLAGS "-DGCC_VER=\"\\\"$(GCC_VER)\\\"\" -DARM64=1 -D__LP64__=1 -Os -g3 -fpie -mstrict-align -fPIC -ffunction-sections -fdata-sections -D__ANDROID_API__=${ANDROID_API_VER} -Wno-pointer-sign" CACHE STRING "" FORCE) -# Where to look for the target environment. (More paths can be added here) -#set(CMAKE_FIND_ROOT_PATH "") +set(CMAKE_FIND_ROOT_PATH "${CROSS_SYSROOT}") # Adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment only. -- Gitee From 280c81278dcb88c074aa19cbf8de809e366a9ece Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 13 May 2020 19:23:26 +0100 Subject: [PATCH 0120/1062] ws: remove now unused ws_ping_pong_interval https://github.com/warmcat/libwebsockets/issues/1915 --- include/libwebsockets/lws-context-vhost.h | 12 ------------ lib/core/context.c | 2 -- lib/core/private-lib-core.h | 1 - lib/roles/http/server/lejp-conf.c | 7 ++----- .../dbus-server/minimal-dbus-ws-proxy/main.c | 1 - .../minimal-ws-server-timer/minimal-ws-server.c | 1 - .../ws-server/minimal-ws-server/minimal-ws-server.c | 1 - test-apps/test-client.c | 13 +++---------- test-apps/test-server.c | 11 ++--------- 9 files changed, 7 insertions(+), 42 deletions(-) diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index 3022aea7..e0b71bf4 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -446,18 +446,6 @@ struct lws_context_creation_info { /**< VHOST: Any bits set here will be set as server SSL options */ long ssl_options_clear; /**< VHOST: Any bits set here will be cleared as server SSL options */ - unsigned short ws_ping_pong_interval; - /**< CONTEXT: 0 for none, else interval in seconds between sending - * PINGs on idle websocket connections. When the PING is sent, - * the PONG must come within the normal timeout_secs timeout period - * or the connection will be dropped. - * Any RX or TX traffic on the connection restarts the interval timer, - * so a connection which always sends or receives something at intervals - * less than the interval given here will never send PINGs / expect - * PONGs. Conversely as soon as the ws connection is established, an - * idle connection will do the PING / PONG roundtrip as soon as - * ws_ping_pong_interval seconds has passed without traffic - */ const struct lws_protocol_vhost_options *headers; /**< VHOST: pointer to optional linked list of per-vhost * canned headers that are added to server responses */ diff --git a/lib/core/context.c b/lib/core/context.c index f0383a5e..36ed5e0b 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -550,8 +550,6 @@ lws_create_context(const struct lws_context_creation_info *info) else context->timeout_secs = 5; - context->ws_ping_pong_interval = info->ws_ping_pong_interval; - lwsl_info(" default timeout (secs): %u\n", context->timeout_secs); if (info->max_http_header_data) diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index f908a2f4..08abcb5f 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -513,7 +513,6 @@ struct lws_context { short plugin_protocol_count; short plugin_extension_count; short server_string_len; - unsigned short ws_ping_pong_interval; unsigned short deprecation_pending_listen_close_count; #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) uint16_t ss_proxy_port; diff --git a/lib/roles/http/server/lejp-conf.c b/lib/roles/http/server/lejp-conf.c index 15789e8b..86b25508 100644 --- a/lib/roles/http/server/lejp-conf.c +++ b/lib/roles/http/server/lejp-conf.c @@ -40,7 +40,7 @@ static const char * const paths_global[] = { "global.init-ssl", "global.server-string", "global.plugin-dir", - "global.ws-pingpong-secs", + "global.ws-pingpong-secs", /* deprecated */ "global.timeout-secs", "global.reject-service-keywords[].*", "global.reject-service-keywords[]", @@ -328,8 +328,7 @@ lejp_globals_cb(struct lejp_ctx *ctx, char reason) a->plugin_dirs[a->count_plugin_dirs++] = a->p; break; - case LWJPGP_PINGPONG_SECS: - a->info->ws_ping_pong_interval = atoi(ctx->buf); + case LWJPGP_PINGPONG_SECS: /* deprecated */ return 0; case LWJPGP_TIMEOUT_SECS: @@ -403,7 +402,6 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) #if defined(LWS_WITH_SERVER) ss = a->info->server_string; #endif - i[2] = a->info->ws_ping_pong_interval; i[3] = a->info->timeout_secs; memset(a->info, 0, sizeof(*a->info)); @@ -413,7 +411,6 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) #if defined(LWS_WITH_SERVER) a->info->server_string = ss; #endif - a->info->ws_ping_pong_interval = i[2]; a->info->timeout_secs = i[3]; a->info->protocols = a->protocols; diff --git a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c index f926c801..066a20ac 100644 --- a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c +++ b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c @@ -79,7 +79,6 @@ int main(int argc, const char **argv) info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; info.port = CONTEXT_PORT_NO_LISTEN; - info.ws_ping_pong_interval = 30; info.protocols = protocols; info.pvo = &pvo; diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c index 4288767e..0fe5391c 100644 --- a/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c +++ b/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c @@ -111,7 +111,6 @@ int main(int argc, const char **argv) info.mounts = &mount; info.protocols = protocols; info.vhost_name = "localhost"; - info.ws_ping_pong_interval = 10; info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; diff --git a/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c index ea29f368..9e911ad4 100644 --- a/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c +++ b/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c @@ -85,7 +85,6 @@ int main(int argc, const char **argv) info.mounts = &mount; info.protocols = protocols; info.vhost_name = "localhost"; - info.ws_ping_pong_interval = 10; info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; diff --git a/test-apps/test-client.c b/test-apps/test-client.c index 73bb6d61..52478523 100644 --- a/test-apps/test-client.c +++ b/test-apps/test-client.c @@ -547,7 +547,6 @@ static struct option options[] = { { "longlived", no_argument, NULL, 'l' }, { "post", no_argument, NULL, 'o' }, { "once", no_argument, NULL, 'O' }, - { "pingpong-secs", required_argument, NULL, 'P' }, { "ssl-cert", required_argument, NULL, 'C' }, { "ssl-key", required_argument, NULL, 'K' }, { "ssl-ca", required_argument, NULL, 'A' }, @@ -575,8 +574,7 @@ static int ratelimit_connects(unsigned int *last, unsigned int secs) int main(int argc, char **argv) { int n = 0, m, ret = 0, port = 7681, use_ssl = 0, ietf_version = -1; - unsigned int rl_dumb = 0, rl_mirror = 0, do_ws = 1, pp_secs = 0, - do_multi = 0; + unsigned int rl_dumb = 0, rl_mirror = 0, do_ws = 1, do_multi = 0; struct lws_context_creation_info info; struct lws_client_connect_info i; struct lws_context *context; @@ -597,9 +595,9 @@ int main(int argc, char **argv) while (n >= 0) { #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32) - n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:P:moeO", options, NULL); + n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:moeO", options, NULL); #else - n = getopt(argc, argv, "Sjnuv:hsp:d:lC:K:A:P:moeO"); + n = getopt(argc, argv, "Sjnuv:hsp:d:lC:K:A:moeO"); #endif if (n < 0) continue; @@ -621,10 +619,6 @@ int main(int argc, char **argv) case 'e': flag_echo = 1; break; - case 'P': - pp_secs = atoi(optarg); - lwsl_notice("Setting pingpong interval to %d\n", pp_secs); - break; case 'j': justmirror = 1; break; @@ -709,7 +703,6 @@ int main(int argc, char **argv) info.protocols = protocols; info.gid = -1; info.uid = -1; - info.ws_ping_pong_interval = pp_secs; info.extensions = exts; /* diff --git a/test-apps/test-server.c b/test-apps/test-server.c index 2dc6769c..ddec2007 100644 --- a/test-apps/test-server.c +++ b/test-apps/test-server.c @@ -329,7 +329,6 @@ static struct option options[] = { #ifndef LWS_NO_DAEMONIZE { "daemonize", no_argument, NULL, 'D' }, #endif - { "pingpong-secs", required_argument, NULL, 'P' }, { "ignore-sigterm", no_argument, NULL, 'I' }, { NULL, 0, 0, 0 } @@ -352,7 +351,6 @@ int main(int argc, char **argv) char ca_path[1024] = ""; int uid = -1, gid = -1; int use_ssl = 0; - int pp_secs = 0; int opts = 0; int n = 0; #ifndef LWS_NO_DAEMONIZE @@ -368,9 +366,9 @@ int main(int argc, char **argv) while (n >= 0) { #if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32) - n = getopt_long(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:P:kU:niIr:", options, NULL); + n = getopt_long(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:kU:niIr:", options, NULL); #else - n = getopt(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:P:kU:nIr:"); + n = getopt(argc, argv, "eci:hsap:d:DC:K:A:R:vu:g:kU:nIr:"); #endif if (n < 0) continue; @@ -443,10 +441,6 @@ int main(int argc, char **argv) case 'A': lws_strncpy(ca_path, optarg, sizeof(ca_path)); break; - case 'P': - pp_secs = atoi(optarg); - lwsl_notice("Setting pingpong interval to %d\n", pp_secs); - break; #if defined(LWS_WITH_TLS) case 'v': use_ssl = 1; @@ -511,7 +505,6 @@ int main(int argc, char **argv) info.protocols = protocols; info.ssl_cert_filepath = NULL; info.ssl_private_key_filepath = NULL; - info.ws_ping_pong_interval = pp_secs; if (use_ssl) { if (strlen(resource_path) > sizeof(cert_path) - 32) { -- Gitee From d7ac7f4deb8f8a9da93f3e8fc4893f7978cce516 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 15 May 2020 18:21:56 +0100 Subject: [PATCH 0121/1062] unix domain: fix path name length Unlike any other sockaddr variant it turns out when sockaddr_un reports its sizeof() to connect() or listen(), it is trimmed to the used length of the sun_path[] member not including any trailing 0x00. Until now we worked fine, but our actual UDS paths have a large number of trailing 0x00 (shown as @ in most tools). Clients and servers can still interoperate if they both have this broken name. This patch fixes it to trim the sockaddr_un to the path length so the name is as you would expect. --- lib/core-net/network.c | 4 +++- lib/roles/http/client/client-handshake.c | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/core-net/network.c b/lib/core-net/network.c index 99e56199..e087cd10 100644 --- a/lib/core-net/network.c +++ b/lib/core-net/network.c @@ -215,7 +215,6 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port, #if defined(LWS_WITH_UNIX_SOCK) if (!port && LWS_UNIX_SOCK_ENABLED(vhost)) { v = (struct sockaddr *)&serv_unix; - n = sizeof(struct sockaddr_un); memset(&serv_unix, 0, sizeof(serv_unix)); serv_unix.sun_family = AF_UNIX; if (!iface) @@ -225,12 +224,15 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port, iface); return LWS_ITOSA_NOT_EXIST; } + n = sizeof(uint16_t) + strlen(iface); strcpy(serv_unix.sun_path, iface); if (serv_unix.sun_path[0] == '@') serv_unix.sun_path[0] = '\0'; else unlink(serv_unix.sun_path); + // lwsl_hexdump_notice(v, n); + } else #endif #if defined(LWS_WITH_IPV6) && !defined(LWS_PLAT_FREERTOS) diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index fcc1ecf8..f1f525cd 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -684,7 +684,10 @@ ads_known: #if defined(LWS_WITH_UNIX_SOCK) if (wsi->unix_skt) { psa = (const struct sockaddr *)&sau; - n = sizeof(sau); + if (sau.sun_path[0]) + n = sizeof(uint16_t) + strlen(sau.sun_path); + else + n = sizeof(uint16_t) + strlen(&sau.sun_path[1]) + 1; } else #endif -- Gitee From 2c46d3882fb72346a2ff96e3c32291d2f97417be Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 18 May 2020 06:14:19 +0100 Subject: [PATCH 0122/1062] client: reset: detach wsi from buflist pending owner on reset --- lib/core-net/close.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index ad6e9990..9f4d0920 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -82,7 +82,13 @@ __lws_reset_wsi(struct lws *wsi) wsi->user_space && !wsi->user_space_externally_allocated) lws_free_set_NULL(wsi->user_space); + /* + * Don't let buflist content or state from the wsi's previous life + * carry over to the new life + */ + lws_buflist_destroy_all_segments(&wsi->buflist); + lws_dll2_remove(&wsi->dll_buflist); lws_buflist_destroy_all_segments(&wsi->buflist_out); #if defined(LWS_WITH_UDP) lws_free_set_NULL(wsi->udp); -- Gitee From 33f8e219eb690b9023fba70fcfb8e9f50626610e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 18 May 2020 06:49:01 +0100 Subject: [PATCH 0123/1062] tls: defer listing of pending tls wsi to be managed by tls read only https://github.com/warmcat/libwebsockets/issues/1920 --- lib/core-net/service.c | 23 +++++++++++------------ lib/tls/mbedtls/mbedtls-ssl.c | 10 ++++++---- lib/tls/openssl/openssl-ssl.c | 10 ++++++---- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/lib/core-net/service.c b/lib/core-net/service.c index bad4b153..af16ffa4 100644 --- a/lib/core-net/service.c +++ b/lib/core-net/service.c @@ -587,18 +587,17 @@ lws_service_flag_pending(struct lws_context *context, int tsi) if (wsi->position_in_fds_table >= 0) { - pt->fds[wsi->position_in_fds_table].revents |= - pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN; - if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN) { - forced = 1; - /* - * he's going to get serviced now, take him off the - * list of guys with buffered SSL. If he still has some - * at the end of the service, he'll get put back on the - * list then. - */ - __lws_ssl_remove_wsi_from_buffered_list(wsi); - } + pt->fds[wsi->position_in_fds_table].revents |= + pt->fds[wsi->position_in_fds_table].events & + LWS_POLLIN; + if (pt->fds[wsi->position_in_fds_table].revents & + LWS_POLLIN) + /* + * We're not going to remove the wsi from the + * pending tls list. The processing will have + * to do it if he exhausts the pending tls. + */ + forced = 1; } } lws_end_foreach_dll_safe(p, p1); diff --git a/lib/tls/mbedtls/mbedtls-ssl.c b/lib/tls/mbedtls/mbedtls-ssl.c index f57a837f..f535aed4 100644 --- a/lib/tls/mbedtls/mbedtls-ssl.c +++ b/lib/tls/mbedtls/mbedtls-ssl.c @@ -136,10 +136,12 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) if (!wsi->tls.ssl) goto bail; - if (SSL_pending(wsi->tls.ssl) && - lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) - lws_dll2_add_head(&wsi->tls.dll_pending_tls, - &pt->tls.dll_pending_tls_owner); + if (SSL_pending(wsi->tls.ssl)) { + if (lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) + lws_dll2_add_head(&wsi->tls.dll_pending_tls, + &pt->tls.dll_pending_tls_owner); + } else + __lws_ssl_remove_wsi_from_buffered_list(wsi); return n; bail: diff --git a/lib/tls/openssl/openssl-ssl.c b/lib/tls/openssl/openssl-ssl.c index e1f8bd45..6c8f5bcd 100644 --- a/lib/tls/openssl/openssl-ssl.c +++ b/lib/tls/openssl/openssl-ssl.c @@ -297,10 +297,12 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) if (!wsi->tls.ssl) goto bail; - if (SSL_pending(wsi->tls.ssl) && - lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) - lws_dll2_add_head(&wsi->tls.dll_pending_tls, - &pt->tls.dll_pending_tls_owner); + if (SSL_pending(wsi->tls.ssl)) { + if (lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) + lws_dll2_add_head(&wsi->tls.dll_pending_tls, + &pt->tls.dll_pending_tls_owner); + } else + __lws_ssl_remove_wsi_from_buffered_list(wsi); return n; bail: -- Gitee From c1aac63a6dafa89c4fd74e753fd95363261dddc9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 19 May 2020 18:34:38 +0100 Subject: [PATCH 0124/1062] http: if no content length transaction completes at hangup If you encounter an h1 transaction with no content length and you parsed the headers, it actually means a hangup subsequently is an indication of a correct transaction completion. So take care to do the _COMPLETION callback under those circumstances too. --- lib/roles/http/client/client-http.c | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 8cf66a2c..ef0c7040 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -958,6 +958,21 @@ lws_client_interpret_server_handshake(struct lws *wsi) !wsi->http.rx_content_length) return !!lws_http_transaction_completed_client(wsi); + /* + * We can also get a case where it's http/1 and there's no + * content-length at all, so anything that comes is the body + * until it hangs up on us. With that situation, hanging up + * on us past this point should generate a valid + * LWS_CALLBACK_COMPLETED_CLIENT_HTTP. + * + * In that situation, he can't pipeline because in h1 there's + * no post-header in-band way to signal the end of the + * transaction except hangup. + * + * lws_http_transaction_completed_client() is the right guy to + * issue it when we see the peer has hung up on us. + */ + return 0; } @@ -1267,6 +1282,23 @@ lws_http_client_read(struct lws *wsi, char **buf, int *len) if (buffered < 0) { lwsl_debug("%s: SSL capable error\n", __func__); + + if (wsi->http.ah && + wsi->http.ah->parser_state == WSI_PARSING_COMPLETE && + !lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) + /* + * We had the headers from this stream, but as there + * was no content-length: we had to wait until the + * stream ended to inform the user code the transaction + * has completed to the best of our knowledge + */ + if (lws_http_transaction_completed_client(wsi)) + /* + * We're going to close anyway, but that api has + * warn_unused_result + */ + return -1; + return -1; } -- Gitee From b6641af88d39f9f7c979f4de8514e62dc5fde453 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 21 May 2020 12:20:47 +0100 Subject: [PATCH 0125/1062] api-test: lws_struct-json: add worked example Add support for implicit schema polymorphism --- include/libwebsockets/lws-struct.h | 3 +- lib/misc/lws-struct-lejp.c | 105 ++++++-- .../api-test-lws_struct-json/CMakeLists.txt | 2 +- .../api-test-lws_struct-json/README.md | 118 ++++++--- .../api-tests/api-test-lws_struct-json/main.c | 9 + .../api-test-lws_struct-json/test2.c | 234 ++++++++++++++++++ 6 files changed, 418 insertions(+), 53 deletions(-) create mode 100644 minimal-examples/api-tests/api-test-lws_struct-json/test2.c diff --git a/include/libwebsockets/lws-struct.h b/include/libwebsockets/lws-struct.h index 90e6b27e..dac26197 100644 --- a/include/libwebsockets/lws-struct.h +++ b/include/libwebsockets/lws-struct.h @@ -219,7 +219,8 @@ typedef struct lws_struct_serialize_st { } lws_struct_serialize_st_t; enum { - LSSERJ_FLAG_PRETTY = 1 + LSSERJ_FLAG_PRETTY = (1 << 0), + LSSERJ_FLAG_OMIT_SCHEMA = (1 << 1) }; typedef struct lws_struct_serialize { diff --git a/lib/misc/lws-struct-lejp.c b/lib/misc/lws-struct-lejp.c index 0d9009d4..7e7b53e3 100644 --- a/lib/misc/lws-struct-lejp.c +++ b/lib/misc/lws-struct-lejp.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -32,18 +32,62 @@ lws_struct_schema_only_lejp_cb(struct lejp_ctx *ctx, char reason) { lws_struct_args_t *a = (lws_struct_args_t *)ctx->user; const lws_struct_map_t *map = a->map_st[ctx->pst_sp]; - size_t n = a->map_entries_st[ctx->pst_sp]; + size_t n = a->map_entries_st[ctx->pst_sp], imp = 0; lejp_callback cb = map->lejp_cb; + if (reason == LEJPCB_PAIR_NAME && strcmp(ctx->path, "schema")) { + /* + * If not "schema", the schema is implicit rather than + * explicitly given, ie, he just goes ahead and starts using + * member names that imply a particular type. For example, he + * may have an implicit type normally, and a different one for + * exceptions that just starts using "error-message" or whatever + * and we can understand that's the exception type now. + * + * Let's look into each of the maps in the top level array + * and match the first one that mentions the name he gave here, + * and bind to the associated type / create a toplevel object + * of that type. + */ + + while (n--) { + const lws_struct_map_t *child = map->child_map; + int m, child_members = map->child_map_size; + + for (m = 0; m < child_members; m++) { + if (!strcmp(ctx->path, child->colname)) { + /* + * We matched on him... map is pointing + * to the right toplevel type, let's + * just pick up from there as if we + * matched the explicit schema name... + */ + ctx->path_match = 1; + imp = 1; + goto matched; + } + } + map++; + } + lwsl_notice("%s: can't match implicit schema %s\n", + __func__, ctx->path); + + return -1; + } + if (reason != LEJPCB_VAL_STR_END || ctx->path_match != 1) return 0; + /* If "schema", then look for a matching name in the map array */ + while (n--) { if (strcmp(ctx->buf, map->colname)) { map++; continue; } +matched: + a->dest = lwsac_use_zero(&a->ac, map->aux, a->ac_block_size); if (!a->dest) { lwsl_err("%s: OOT\n", __func__); @@ -62,6 +106,12 @@ lws_struct_schema_only_lejp_cb(struct lejp_ctx *ctx, char reason) a->map_st[ctx->pst_sp] = map->child_map; a->map_entries_st[ctx->pst_sp] = map->child_map_size; + lwsl_notice("%s: child map ofs_clist %d\n", __func__, + (int)a->map_st[ctx->pst_sp]->ofs_clist); + + if (imp) + return cb(ctx, reason); + return 0; } @@ -120,7 +170,7 @@ lws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason) if (reason == LEJPCB_OBJECT_START) { - if (map->type != LSMT_CHILD_PTR) { + if (map->type != LSMT_CHILD_PTR && map->type != LSMT_LIST) { ctx->pst[ctx->pst_sp].user = NULL; return 0; @@ -132,8 +182,16 @@ lws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason) n = args->map_entries_st[ctx->pst_sp]; } - if (reason == LEJPCB_OBJECT_END && pmap && pmap->type == LSMT_CHILD_PTR) - lejp_parser_pop(ctx); + if (reason == LEJPCB_OBJECT_END && pmap) { + if (pmap->type == LSMT_CHILD_PTR) + lejp_parser_pop(ctx); + + if (ctx->pst_sp) + pmap = &args->map_st[ctx->pst_sp - 1] + [ctx->pst[ctx->pst_sp - 1].path_match - 1]; + map = &args->map_st[ctx->pst_sp][ctx->path_match - 1]; + n = args->map_entries_st[ctx->pst_sp]; + } if (map->type == LSMT_SCHEMA) { @@ -176,6 +234,9 @@ lws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason) map = &args->map_st[ctx->pst_sp - 1][ctx->path_match - 1]; n = args->map_entries_st[ctx->pst_sp - 1]; + if (!ctx->pst_sp) + return 0; + if (pmap->type != LSMT_LIST && pmap->type != LSMT_CHILD_PTR) return 1; @@ -195,12 +256,13 @@ lws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason) return 1; } - lwsl_notice("%s: created child object size %d\n", __func__, - (int)pmap->aux); + lwsl_notice("%s: created '%s' object size %d\n", __func__, + pmap->colname, (int)pmap->aux); if (pmap->type == LSMT_LIST) { - list = (struct lws_dll2 *)((char *)ctx->pst[ctx->pst_sp].user + - map->ofs_clist); + list = (struct lws_dll2 *) + ((char *)ctx->pst[ctx->pst_sp].user + + pmap->ofs_clist); lws_dll2_add_tail(list, owner); } @@ -397,6 +459,10 @@ static const char * schema[] = { "schema" }; int lws_struct_json_init_parse(struct lejp_ctx *ctx, lejp_callback cb, void *user) { + /* + * By default we are looking to match on a toplevel member called + * "schema", against an LSM_SCHEMA + */ if (!cb) cb = lws_struct_schema_only_lejp_cb; lejp_construct(ctx, cb, user, schema, 1); @@ -636,13 +702,15 @@ lws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, len--; j = &js->st[++js->sp]; lws_struct_pretty(js, &buf, &len); - budget = lws_snprintf(dbuf, 15, "\"schema\":"); - if (js->flags & LSSERJ_FLAG_PRETTY) - dbuf[budget++] = ' '; - - budget += lws_snprintf(dbuf + budget, - sizeof(dbuf) - budget, - "\"%s\"", map->colname); + if (!(js->flags & LSSERJ_FLAG_OMIT_SCHEMA)) { + budget = lws_snprintf(dbuf, 15, "\"schema\":"); + if (js->flags & LSSERJ_FLAG_PRETTY) + dbuf[budget++] = ' '; + + budget += lws_snprintf(dbuf + budget, + sizeof(dbuf) - budget, + "\"%s\"", map->colname); + } if (js->sp != 1) @@ -654,8 +722,9 @@ lws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, j->map_entry = 0; j->obj = js->st[js->sp - 1].obj; j->dllpos = NULL; - /* we're actually at the same level */ - j->subsequent = 1; + if (!(js->flags & LSSERJ_FLAG_OMIT_SCHEMA)) + /* we're actually at the same level */ + j->subsequent = 1; j->idt = 1; break; default: diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt index 50287100..5fcdc786 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8) include(CheckCSourceCompiles) set(SAMP lws-api-test-lws_struct-json) -set(SRCS main.c) +set(SRCS main.c test2.c) # If we are being built as part of lws, confirm current build config supports # reqconfig, else skip building ourselves. diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/README.md b/minimal-examples/api-tests/api-test-lws_struct-json/README.md index ebe930d2..f21ba781 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/README.md +++ b/minimal-examples/api-tests/api-test-lws_struct-json/README.md @@ -17,40 +17,92 @@ Commandline option|Meaning ``` $ ./lws-api-test-lws_struct-json -[2019/03/30 22:09:09:2529] USER: LWS API selftest: lws_struct JSON -[2019/03/30 22:09:09:2625] NOTICE: main: ++++++++++++++++ test 1 -[2019/03/30 22:09:09:2812] NOTICE: builder.hostname = 'learn', timeout = 1800, targets (2) -[2019/03/30 22:09:09:2822] NOTICE: target.name 'target1' (target 0x543a830) -[2019/03/30 22:09:09:2824] NOTICE: target.name 'target2' (target 0x543a860) -[2019/03/30 22:09:09:2826] NOTICE: main: .... strarting serialization of test 1 -[2019/03/30 22:09:09:2899] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1"},{"name":"target2"}]} -[2019/03/30 22:09:09:2929] NOTICE: main: ++++++++++++++++ test 2 -[2019/03/30 22:09:09:2932] NOTICE: builder.hostname = 'learn', timeout = 0, targets (3) -[2019/03/30 22:09:09:2932] NOTICE: target.name 'target1' (target 0x543b060) -[2019/03/30 22:09:09:2933] NOTICE: target.name 'target2' (target 0x543b090) -[2019/03/30 22:09:09:2933] NOTICE: target.name 'target3' (target 0x543b0c0) -[2019/03/30 22:09:09:2934] NOTICE: main: .... strarting serialization of test 2 -[2019/03/30 22:09:09:2935] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":0,"targets":[{"name":"target1"},{"name":"target2"},{"name":"target3"}]} -[2019/03/30 22:09:09:2940] NOTICE: main: ++++++++++++++++ test 3 -[2019/03/30 22:09:09:2959] NOTICE: builder.hostname = 'learn', timeout = 1800, targets (2) -[2019/03/30 22:09:09:2960] NOTICE: target.name 'target1' (target 0x543b450) -[2019/03/30 22:09:09:2961] NOTICE: child 0x543b480, target.child.somename 'abc' -[2019/03/30 22:09:09:2961] NOTICE: target.name 'target2' (target 0x543b490) -[2019/03/30 22:09:09:2962] NOTICE: main: .... strarting serialization of test 3 -[2019/03/30 22:09:09:2969] NOTICE: ser says 1 -{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1","child":{"somename":"abc"}},{"name":"target2"}]} -[2019/03/30 22:09:09:2970] NOTICE: main: ++++++++++++++++ test 4 -[2019/03/30 22:09:09:2971] NOTICE: builder.hostname = 'learn', timeout = 1800, targets (0) -[2019/03/30 22:09:09:2971] NOTICE: main: .... strarting serialization of test 4 -[2019/03/30 22:09:09:2973] NOTICE: ser says 1 +[2020/05/21 16:36:57:0808] U: LWS API selftest: lws_struct JSON +[2020/05/21 16:36:57:1188] N: main: ++++++++++++++++ test 1 +[2020/05/21 16:36:57:1291] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1387] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1429] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1467] N: builder.hostname = 'learn', timeout = 1800, targets (2) +[2020/05/21 16:36:57:1490] N: target.name 'target1' (target 0x509fe30) +[2020/05/21 16:36:57:1495] N: target.name 'target2' (target 0x509fe68) +[2020/05/21 16:36:57:1500] N: main: .... strarting serialization of test 1 +{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1","someflag":true},{"name":"target2","someflag":false}]} +[2020/05/21 16:36:57:1648] N: main: ++++++++++++++++ test 2 +[2020/05/21 16:36:57:1649] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1650] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1651] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1652] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1653] N: builder.hostname = 'learn', timeout = 0, targets (3) +[2020/05/21 16:36:57:1653] N: target.name 'target1' (target 0x50a0660) +[2020/05/21 16:36:57:1654] N: target.name 'target2' (target 0x50a0698) +[2020/05/21 16:36:57:1655] N: target.name 'target3' (target 0x50a06d0) +[2020/05/21 16:36:57:1655] N: main: .... strarting serialization of test 2 +{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":0,"targets":[{"name":"target1","someflag":false},{"name":"target2","someflag":false},{"name":"target3","someflag":false}]} +[2020/05/21 16:36:57:1662] N: main: ++++++++++++++++ test 3 +[2020/05/21 16:36:57:1663] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1664] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1671] N: lws_struct_default_lejp_cb: created 'child' object size 8 +[2020/05/21 16:36:57:1685] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1685] N: builder.hostname = 'learn', timeout = 1800, targets (2) +[2020/05/21 16:36:57:1686] N: target.name 'target1' (target 0x50a0a50) +[2020/05/21 16:36:57:1687] N: child 0x50a0a88, target.child.somename 'abc' +[2020/05/21 16:36:57:1688] N: target.name 'target2' (target 0x50a0a98) +[2020/05/21 16:36:57:1688] N: main: .... strarting serialization of test 3 +{"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800,"targets":[{"name":"target1","someflag":false,"child":{"somename":"abc"}},{"name":"target2","someflag":false}]} +[2020/05/21 16:36:57:1697] N: main: ++++++++++++++++ test 4 +[2020/05/21 16:36:57:1698] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1699] N: builder.hostname = 'learn', timeout = 1800, targets (0) +[2020/05/21 16:36:57:1699] N: main: .... strarting serialization of test 4 {"schema":"com-warmcat-sai-builder","hostname":"learn","nspawn_timeout":1800} -[2019/03/30 22:09:09:2974] NOTICE: main: ++++++++++++++++ test 5 -[2019/03/30 22:09:09:2978] NOTICE: builder.hostname = '', timeout = 0, targets (0) -[2019/03/30 22:09:09:2979] NOTICE: main: .... strarting serialization of test 5 -[2019/03/30 22:09:09:2980] NOTICE: ser says 1 +[2020/05/21 16:36:57:1701] N: main: ++++++++++++++++ test 5 +[2020/05/21 16:36:57:1702] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1707] N: builder.hostname = '', timeout = 0, targets (0) +[2020/05/21 16:36:57:1708] N: main: .... strarting serialization of test 5 {"schema":"com-warmcat-sai-builder","hostname":"","nspawn_timeout":0} -[2019/03/30 22:09:09:2982] USER: Completed: PASS +[2020/05/21 16:36:57:1709] N: main: ++++++++++++++++ test 6 +[2020/05/21 16:36:57:1710] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1730] N: builder.hostname = 'PYvtan6kqppjnS0KpYTCaiOLsJkc7Xe', timeout = 0, targets (0) +[2020/05/21 16:36:57:1731] N: main: .... strarting serialization of test 6 +{"schema":"com-warmcat-sai-builder","hostname":"PYvtan6kqppjnS0KpYTCaiOLsJkc7Xe","nspawn_timeout":0} +[2020/05/21 16:36:57:1732] N: main: ++++++++++++++++ test 7 +[2020/05/21 16:36:57:1732] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1733] N: lws_struct_default_lejp_cb: created 'targets' object size 48 +[2020/05/21 16:36:57:1739] N: builder.hostname = '', timeout = 0, targets (1) +[2020/05/21 16:36:57:1751] N: target.name 'PYvtan6kqppjnS0KpYTCaiOLsJkc7XecAr1kcE0aCIciewYB+JcLG82mO1Vb1mJtjDwUjBxy2I6AzefzoWUWmqZbsv4MXR55j9bKlyz1liiSX63iO0x6JAwACMtE2MkgcLwR86TSWAD9D1QKIWqg5RJ/CRuVsW0DKAUMD52ql4JmPFuJpJgTq28z6PhYNzN3yI3bmQt6bzhA+A/xAsFzSBnb3MHYWzGMprr53FAP1ISo5Ec9i+2ehV40sG6Q470sH3PGQZ0YRPO7Sh/SyrSQ/scONmxRc3AcXl7X/CSs417ii+CV8sq3ZgcxKNB7tNfN7idNx3upZ00G2BZy9jSy03cLKKLNaNUt0TQsxXbH55uDHzSEeZWvxJgT6zB1NoMhdC02w+oXim94M6z6COCnqT3rgkGk8PHMry9Bkh4yVpRmzIRfMmln/lEhdZgxky2+g5hhlSIGJYDCrdynD9kCfvfy6KGOpNIi1X+mhbbWn4lnL9ZKihL/RrfOV+oV4R26IDq+KqUiJBENeo8/GXkGLUH/87iPyzXKEMavr6fkrK0vTGto8yEYxmOyaVz8phG5rwf4jJgmYNoMbGo8gWvhqO7UAGy2g7MWv+B/t1eZZ+1euLsNrWAsFJiFbQKgdFfQT3RjB14iU8knlQ8usoy+pXssY2ddGJGVcGC21oZvstK9eu1eRZftda/wP+N5unT1Hw7kCoVzqxHieiYt47EGIOaaQ7XjZDK6qPN6O/grHnvJZm2vBkxuXgsYVkRQ7AuTWIecphqFsq7Wbc1YNbMW47SVU5zMD0WaCqbaaI0t4uIzRvPlD8cpiiTzFTrEHlIBTf8/uZjjEGGLhJR1jPqA9D1Ej3ChV+ye6F9JTUMlozRMsGuF8U4btDzH5xdnmvRS4Ar6LKEtAXGkj2yuyJln+v4RIWj2xOGPJovOqiXwi0FyM61f8U8gj0OiNA2/QlvrqQVDF7sMXgjvaE7iQt5vMETteZlx+z3f+jTFM/aon5... +[2020/05/21 16:36:57:1752] N: main: .... strarting serialization of test 7 +{"schema":"com-warmcat-sai-builder","hostname":"","nspawn_timeout":0,"targets":[{"name":"PYvtan6kqppjnS0KpYTCaiOLsJkc7XecAr1kcE0aCIciewYB+JcLG82mO1Vb1mJtjDwUjBxy2I6AzefzoWUWmqZbsv4MXR55j9bKlyz1liiSX63iO0x6JAwACMtE2MkgcLwR86TSWAD9D1QKIWqg5RJ/CRuVsW0DKAUMD52ql4JmPFuJpJgTq28z6PhYNzN3yI3bmQt6bzhA+A/xAsFzSBnb3MHYWzGMprr53FAP1ISo5Ec9i+2ehV40sG6Q470sH3PGQZ0YRPO7Sh/SyrSQ/scONmxRc3AcXl7X/CSs417ii+CV8sq3ZgcxKNB7tNfN7idNx3upZ00G2BZy9jSy03cLKKLNaNUt0TQsxXbH55uDHzSEeZWvxJgT6zB1NoMhdC02w+oXim94M6z6COCnqT3rgkGk8PHMry9Bkh4yVpRmzIRfMmln/lEhdZgxky2+g5hhlSIGJYDCrdynD9kCfvfy6KGOpNIi1X+mhbbWn4lnL9ZKihL/RrfOV+oV4R26IDq+KqUiJBENeo8/GXkGLUH/87iPyzXKEMavr6fkrK0vTGto8yEYxmOyaVz8phG5rwf4jJgmYNoMbGo8gWvhqO7UAGy2g7MWv+B/t1eZZ+1euLsNrWAsFJiFbQKgdFfQT3RjB14iU8knlQ8usoy+pXssY2ddGJGVcGC21oZvstK9eu1eRZftda/wP+N5unT1Hw7kCoVzqxHieiYt47EGIOaaQ7XjZDK6qPN6O/grHnvJZm2vBkxuXgsYVkRQ7AuTWIecphqFsq7Wbc1YNbMW47SVU5zMD0WaCqbaaI0t4uIzRvPlD8cpiiTzFTrEHlIBTf8/uZjjEGGLhJR1jPqA9D1Ej3ChV+ye6F9JTUMlozRMsGuF8U4btDzH5xdnmvRS4Ar6LKEtAXGkj2yuyJln+v4RIWj2xOGPJovOqiXwi0FyM61f8U8gj0OiNA2/QlvrqQVDF7sMXgjvaE7iQt5vMETteZlx+z3f+jTFM/aon511W4+ZkRD+6AHwucvM9BEC","someflag":false}]} +[2020/05/21 16:36:57:1756] N: main: ++++++++++++++++ test 8 +[2020/05/21 16:36:57:1758] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1761] N: other.name = 'somename' +[2020/05/21 16:36:57:1763] N: main: .... strarting serialization of test 8 +{"schema":"com-warmcat-sai-other","name":"somename"} +{"schema":"meta.schema","t":{"name":"mytargetname","someflag":false},"e":{"hostname":"myhostname","nspawn_timeout":0}} +[2020/05/21 16:36:57:1785] N: Test set 2 +[2020/05/21 16:36:57:1791] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1795] N: Test set 2: 6: 071ab46ab4296e5de674c628fec17c55088254679f7714ad991f8c4873dca +[2020/05/21 16:36:57:1801] N: test2: start +[2020/05/21 16:36:57:1811] N: lws_struct_schema_only_lejp_cb: child map ofs_clist 0 +[2020/05/21 16:36:57:1815] N: lws_struct_default_lejp_cb: created 'config' object size 80 +[2020/05/21 16:36:57:1819] N: lws_struct_default_lejp_cb: created 'creds' object size 16 +[2020/05/21 16:36:57:1833] N: lws_struct_default_lejp_cb: created 'config' object size 80 +[2020/05/21 16:36:57:1834] N: lws_struct_default_lejp_cb: created 'creds' object size 16 +[2020/05/21 16:36:57:1837] N: test2: lejp_parse 0 +[2020/05/21 16:36:57:1841] N: t2_configs_dump: number of configs: 2 +[2020/05/21 16:36:57:1844] N: t2_config_dump: id1 '(null)' +[2020/05/21 16:36:57:1846] N: t2_config_dump: arg1 'val1' +[2020/05/21 16:36:57:1848] N: t2_config_dump: ssid '"nw2"' +[2020/05/21 16:36:57:1850] N: t2_config_dump: freq 0 +[2020/05/21 16:36:57:1852] N: t2_config_dump: arg2 0 +[2020/05/21 16:36:57:1854] N: t2_config_dump: priority 1 +[2020/05/21 16:36:57:1856] N: t2_config_dump: key1: "xxxxxxxxx", key2: (null) +[2020/05/21 16:36:57:1857] N: t2_config_dump: id1 '(null)' +[2020/05/21 16:36:57:1858] N: t2_config_dump: arg1 'val2' +[2020/05/21 16:36:57:1858] N: t2_config_dump: ssid '"nw1"' +[2020/05/21 16:36:57:1859] N: t2_config_dump: freq 11 +[2020/05/21 16:36:57:1859] N: t2_config_dump: arg2 1420887242594 +[2020/05/21 16:36:57:1860] N: t2_config_dump: priority 3 +[2020/05/21 16:36:57:1860] N: t2_config_dump: key1: "xxxxxxxxxxxxx", key2: (null) +{"config":[{"creds":{"key1":"\u0022xxxxxxxxx\u0022"},"arg1":"val1","ssid":"\u0022nw2\u0022","frequency":0,"arg2":0,"priority":1},{"creds":{"key1":"\u0022xxxxxxxxxxxxx\u0022"},"arg1":"val2","ssid":"\u0022nw1\u0022","frequency":11,"arg2":1420887242594,"priority":3}]} +[2020/05/21 16:36:57:1880] U: Completed: PASS ``` diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/main.c b/minimal-examples/api-tests/api-test-lws_struct-json/main.c index faa2650d..7f6ee20a 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/main.c +++ b/minimal-examples/api-tests/api-test-lws_struct-json/main.c @@ -16,6 +16,8 @@ #include +extern int test2(void); + /* * in this example, the JSON is for one "builder" object, which may specify * a child list "targets" of zero or more "target" objects. @@ -529,11 +531,18 @@ done: lwsl_notice("Test set 2: %d: %s\n", m, ((sai_cancel_t *)a.dest)->task_uuid); + lwsac_free(&a.ac); + + if (test2()) + goto bail; + lwsl_user("Completed: PASS\n"); return 0; bail: +if (test2()) + return 1; lwsl_user("Completed: FAIL\n"); return 1; diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/test2.c b/minimal-examples/api-tests/api-test-lws_struct-json/test2.c new file mode 100644 index 00000000..07f8178b --- /dev/null +++ b/minimal-examples/api-tests/api-test-lws_struct-json/test2.c @@ -0,0 +1,234 @@ +/* + * lws-api-test-lws_struct-json + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * lws_struct apis are used to serialize and deserialize your C structs and + * linked-lists in a standardized way that's very modest on memory but + * convenient and easy to maintain. + * + * This second test file shows a worked example for how to express a schema + * and both consume JSON -> struct and struct -> JSON for it. + */ + +#include + +static const char * const test2_json = +"{" + "\"config\":[" + "{" + "\"id1\":" "null," + "\"creds\":{" + "\"key1\":" "\"\\\"xxxxxxxxx\\\"\"," + "\"key2\":" "null" + "}," + "\"frequency\":" "0," + "\"arg1\":" "\"val1\"," + "\"arg2\":" "0," + "\"priority\":" "1," + "\"ssid\":" "\"\\\"nw2\\\"\"" + "}, {" + "\"id2\":" "null," + "\"creds\": {" + "\"key1\":" "\"\\\"xxxxxxxxxxxxx\\\"\"," + "\"key2\":" "null" + "}," + "\"frequency\":" "11," + "\"arg1\":" "\"val2\"," + "\"arg2\":" "1420887242594," + "\"priority\":" "3," + "\"ssid\":" "\"\\\"nw1\\\"\"" + "}" + "]" +"}"; + +static const char * const test2_json_expected = + "{\"config\":[{\"creds\":{\"key1\":\"\\u0022xxxxxxxxx\\u0022\"}," + "\"arg1\":\"val1\",\"ssid\":\"\\u0022nw2\\u0022\"," + "\"frequency\":0,\"arg2\":0,\"priority\":1}," + "{\"creds\":{\"key1\":\"\\u0022xxxxxxxxxxxxx\\u0022\"}," + "\"arg1\":\"val2\",\"ssid\":\"\\u0022nw1\\u0022\"," + "\"frequency\":11,\"arg2\":1420887242594,\"priority\":3}]}" +; + +/* + * level 3: Credentials object + */ + +typedef struct t2_cred { + const char *key1; + const char *key2; +} t2_cred_t; + +static const lws_struct_map_t lsm_t2_cred[] = { + LSM_STRING_PTR (t2_cred_t, key1, "key1"), + LSM_STRING_PTR (t2_cred_t, key2, "key2"), +}; + +/* + * level 2: Configuration object, containing a child credentials object + */ + +typedef struct t2_config { + lws_dll2_t list; + t2_cred_t *creds; + const char *id1; + const char *arg1; + const char *ssid; + unsigned int frequency; + unsigned long arg2; + unsigned int priority; +} t2_config_t; + +static const lws_struct_map_t lsm_t2_config[] = { + LSM_CHILD_PTR (t2_config_t, + creds, /* the child pointer member */ + t2_cred_t, /* the child type */ + NULL, lsm_t2_cred, /* map object for item type */ + "creds"), /* outer json object name */ + LSM_STRING_PTR (t2_config_t, id1, "id1"), + LSM_STRING_PTR (t2_config_t, arg1, "arg1"), + LSM_STRING_PTR (t2_config_t, ssid, "ssid"), + + LSM_UNSIGNED (t2_config_t, frequency, "frequency"), + LSM_UNSIGNED (t2_config_t, arg2, "arg2"), + LSM_UNSIGNED (t2_config_t, priority, "priority"), +}; + +/* + * level 1: list-of-configurations object + */ + +typedef struct t2_configs { + lws_dll2_owner_t configs; +} t2_configs_t; + +static const lws_struct_map_t lsm_t2_configs[] = { + LSM_LIST (t2_configs_t, configs, /* the list owner type/member */ + t2_config_t, list, /* the list item type/member */ + NULL, lsm_t2_config, /* map object for item type */ + "config"), /* outer json object name */ +}; + +/* + * For parsing, this lists the kind of object we expect to parse so the struct + * can be allocated polymorphically. + * + * Lws uses an explicit "schema" member so the type is known unambiguously. If + * in the incoming JSON the first member is not "schema", it will scan the + * maps listed here and instantiate the first object that has a member of that + * name. + */ + +static const lws_struct_map_t lsm_schema[] = { + LSM_SCHEMA (t2_configs_t, NULL, lsm_t2_configs, "t2"), + /* other schemata that might need parsing... */ +}; + + + +static int +t2_config_dump(struct lws_dll2 *d, void *user) +{ + t2_config_t *c = lws_container_of(d, t2_config_t, list); + + lwsl_notice("%s: id1 '%s'\n", __func__, c->id1); + lwsl_notice("%s: arg1 '%s'\n", __func__, c->arg1); + lwsl_notice("%s: ssid '%s'\n", __func__, c->ssid); + + lwsl_notice("%s: freq %d\n", __func__, c->frequency); + lwsl_notice("%s: arg2 %lu\n", __func__, c->arg2); + lwsl_notice("%s: priority %d\n", __func__, c->priority); + + lwsl_notice("%s: key1: %s, key2: %s\n", __func__, + c->creds->key1, c->creds->key2); + + return 0; +} + +static int +t2_configs_dump(t2_configs_t *t2cs) +{ + lwsl_notice("%s: number of configs: %d\n", __func__, + t2cs->configs.count); + + lws_dll2_foreach_safe(&t2cs->configs, NULL, t2_config_dump); + + return 0; +} + + +int +test2(void) +{ + lws_struct_serialize_t *ser; + struct lejp_ctx ctx; + lws_struct_args_t a; + t2_configs_t *top; + uint8_t buf[4096]; + size_t written; + int n, bad = 1; + + lwsl_notice("%s: start \n", __func__); + + memset(&a, 0, sizeof(a)); + a.map_st[0] = lsm_schema; + a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_schema); + a.ac_block_size = 512; + lws_struct_json_init_parse(&ctx, NULL, &a); + + n = lejp_parse(&ctx, (uint8_t *)test2_json, (int)strlen(test2_json)); + lwsl_notice("%s: lejp_parse %d\n", __func__, n); + if (n < 0) { + lwsl_err("%s: test2 JSON decode failed '%s'\n", + __func__, lejp_error_to_string(n)); + goto bail; + } + lwsac_info(a.ac); + + top = (t2_configs_t *)a.dest; /* the top level object */ + + if (!top) { + lwsl_err("%s: no top level object\n", __func__); + goto bail; + } + t2_configs_dump(top); + + /* 2. Let's reserialize the top level object and see what comes out */ + + ser = lws_struct_json_serialize_create(&lsm_schema[0], 1, + LSSERJ_FLAG_OMIT_SCHEMA, top); + if (!ser) { + lwsl_err("%s: unable to init serialization\n", __func__); + goto bail; + } + + do { + n = lws_struct_json_serialize(ser, buf, sizeof(buf), &written); + switch (n) { + case LSJS_RESULT_FINISH: + puts((const char *)buf); + break; + case LSJS_RESULT_CONTINUE: + case LSJS_RESULT_ERROR: + goto bail; + } + } while (n == LSJS_RESULT_CONTINUE); + + if (strcmp(test2_json_expected, (char *)buf)) { + lwsl_err("%s: expected %s\n", __func__, test2_json_expected); + goto bail; + } + + lws_struct_json_serialize_destroy(&ser); + + bad = 0; + +bail: + lwsac_free(&a.ac); + + return bad; +} -- Gitee From cabe0219555381f23b7231a1c481bbb60291a9c0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 14 May 2020 21:28:48 +0100 Subject: [PATCH 0126/1062] esp32: shift to support latest esp-idf Esp-idf has an improved but still kind of abused cmake- based build system now. If we see ESP_PLATFORM coming as a cmake var, we can know we are being built from inside the esp-idf config system. Leave the existing esp32 arrangements alone but triggered off ESP_PLATFORM, adapt to use the cross toolchain file and various quirks automatically. In this way you can build lws a part of your project in a much cleaner way. Prepare a minimal esp32 test app for use in Sai Adapt .sai.json to build for esp32 --- .sai.json | 8 +- CMakeLists.txt | 129 +- cmake/lws_config.h.in | 2 +- cmake/lws_config_private.h.in | 1 + contrib/cross-esp32.cmake | 12 +- include/libwebsockets/lws-esp32.h | 1 - include/libwebsockets/lws-freertos.h | 2 +- include/libwebsockets/lws-network-helper.h | 4 + lib/core-net/network.c | 13 +- lib/core/context.c | 2 +- lib/core/libwebsockets.c | 4 + lib/core/private-lib-core.h | 2 + lib/plat/freertos/freertos-file.c | 2 +- lib/plat/freertos/freertos-misc.c | 2 +- lib/plat/freertos/freertos-sockets.c | 2 +- lib/plat/freertos/private-lib-plat-freertos.h | 4 +- lib/roles/listen/ops-listen.c | 2 +- lib/secure-streams/policy-common.c | 2 +- lib/tls/mbedtls/mbedtls-server.c | 1 + lib/tls/mbedtls/mbedtls-ssl.c | 1 - lib/tls/mbedtls/private-lib-tls-mbedtls.h | 1 + .../embedded/lws-minimal-esp32/CMakeLists.txt | 21 + .../lws-minimal-esp32/main/CMakeLists.txt | 6 + .../main/lws-minimal-esp32.c | 102 ++ .../embedded/lws-minimal-esp32/sdkconfig | 1145 +++++++++++++++++ .../embedded/lws-minimal-esp32/sdkconfig.h | 426 ++++++ 26 files changed, 1797 insertions(+), 100 deletions(-) create mode 100644 minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt create mode 100644 minimal-examples/embedded/lws-minimal-esp32/main/CMakeLists.txt create mode 100644 minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c create mode 100644 minimal-examples/embedded/lws-minimal-esp32/sdkconfig create mode 100644 minimal-examples/embedded/lws-minimal-esp32/sdkconfig.h diff --git a/.sai.json b/.sai.json index 6bb9de04..8b58f048 100644 --- a/.sai.json +++ b/.sai.json @@ -40,13 +40,19 @@ "windows-10": { "build": "mkdir build && cd build && set SAI_CPACK=\"-G ZIP\" && cmake .. -DLWS_EXT_PTHREAD_INCLUDE_DIR=\"C:\\Program Files (x86)\\pthreads\\include\" -DLWS_EXT_PTHREAD_LIBRARIES=\"C:\\Program Files (x86)\\pthreads\\lib\\x64\\libpthreadGC2.a\" ${cmake} && cmake --build . --config DEBUG && set CTEST_OUTPUT_ON_FAILURE=1 && ctest . -C DEBUG -j4 --output-on-failure", "default": false + }, + "freertos-esp32": { + # official way to get sdkconfig.h is idf.py menuconfig, but + # no obvious way to do that in CI + "build": "rm -rf ebuild ; mkdir ebuild; cd ebuild; cp -rp ../minimal-examples/embedded/lws-minimal-esp32 . ; cd lws-minimal-esp32 ; . /opt/esp/esp-idf/export.sh ; ln -sf ../.. libwebsockets ; idf.py set-target esp32 && cp libwebsockets/minimal-examples/embedded/lws-minimal-esp32/sdkconfig . && cp sdkconfig.h build && idf.py build && cd build && /usr/local/bin/sai-device freertos-esp32 ESPPORT=0 ctest --output-on-failure", + "default": false } }, "configurations": { "default": { "cmake": "", - "platforms": "windows-10, linkit-cross, linux-debian-buster-arm32" + "platforms": "windows-10, linkit-cross, linux-debian-buster-arm32, freertos-esp32" }, "default-examples": { "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d5abe38..7eb5b7dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,11 @@ endif() set(LWS_ROLE_RAW 1) set(LWS_WITH_POLL 1) +if(ESP_PLATFORM) + set(LWS_ESP_PLATFORM 1) + set(CMAKE_TOOLCHAIN_FILE contrib/cross-esp32.cmake) + set(LWIP_PROVIDE_ERRNO 1) +endif() # it's at this point any toolchain file is brought in project(libwebsockets C) include(CTest) @@ -203,6 +208,7 @@ endif() if(ESP_PLATFORM) message(STATUS "ESP-IDF enabled") set(LWS_WITH_ESP32 ON) + set(LWS_WITH_ZLIB OFF) else() set(LWS_WITH_ESP32_HELPER OFF) endif() @@ -388,7 +394,7 @@ set(CPACK_PACKAGE_RELEASE 1) set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") set(CPACK_PACKAGE_VENDOR "andy@warmcat.com") set(CPACK_PACKAGE_CONTACT "andy@warmcat.com") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${CPACK_PACKAGE_VERSION}") set(SOVERSION "16") if(NOT CPACK_GENERATOR) if(UNIX) @@ -418,10 +424,19 @@ set(LWS_LIBRARY_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) set(LWS_LIBRARY_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR}) set(LWS_LIBRARY_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH}) +if (NOT CMAKE_MODULE_PATH) + set(CMAKE_MODULE_PATH "") +endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") -message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'") +if (CMAKE_TOOLCHAIN_FILE) + message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'") +endif() + +if (NOT LIB_SUFFIX) + set(LIB_SUFFIX "") +endif() if(WIN32) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/win32port/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/win32port/version.rc @ONLY) @@ -445,6 +460,10 @@ endif() include_directories(include plugins lib/core lib/core-net lib/event-libs include/abstract lib/tls lib/roles lib/event-libs/libuv lib/event-libs/poll lib/event-libs/libevent lib/event-libs/glib lib/event-libs/libev lib/jose/jwe lib/jose/jws lib/jose lib/misc lib/roles/http lib/roles/http/compression lib/roles/h1 lib/roles/h2 lib/roles/ws lib/roles/cgi lib/roles/dbus lib/roles/raw-proxy lib/abstract lib/system/async-dns lib/roles/mqtt) +if (ESP_PLATFORM) + include_directories($ENV{IDF_PATH}/components/freertos/include $ENV{IDF_PATH}/components/freertos/xtensa/include $ENV{IDF_PATH}/components/xtensa/include $ENV{IDF_PATH}/components/xtensa/esp32/include $ENV{IDF_PATH}/components/esp_common/include $ENV{IDF_PATH}/components/esp_timer/include $ENV{IDF_PATH}/components/soc/include $ENV{IDF_PATH}/components/soc/src/esp32/include $ENV{IDF_PATH}/components/lwip/port/esp32/include $ENV{IDF_PATH}/components/lwip/lwip/src/include $ENV{IDF_PATH}/components/lwip/port/esp32/include ${CMAKE_BINARY_DIR}/config $ENV{IDF_PATH}/components/esp_rom/include $ENV{IDF_PATH}/components/esp_system/include $ENV{IDF_PATH}/components/lwip/include/apps/sntp $ENV{IDF_PATH}/components/soc/soc/esp32/include $ENV{IDF_PATH}/components/heap/include $ENV{IDF_PATH}/components/mbedtls/mbedtls/include $ENV{IDF_PATH}/components/mbedtls/port/include $ENV{IDF_PATH}/components/esp_wifi/include $ENV{IDF_PATH}/components/esp_event/include $ENV{IDF_PATH}/components/esp_netif/include $ENV{IDF_PATH}/components/esp_eth/include $ENV{IDF_PATH}/components/driver/include $ENV{IDF_PATH}/components/soc/soc/include $ENV{IDF_PATH}/components/tcpip_adapter/include $ENV{IDF_PATH}/components/lwip/include/apps $ENV{IDF_PATH}/components/nvs_flash/include $ENV{IDF_PATH}/components/esp32/include $ENV{IDF_PATH}/components/spi_flash/include $ENV{IDF_PATH}/components/mdns/include $ENV{IDF_PATH}/components/lwip/lwip/src/include/lwip $ENV{IDF_PATH}/components/lwip/lwip/src/include $ENV{IDF_PATH}/components/lwip/lwip/src/include/lwip $ENV{IDF_PATH}/components/newlib/platform_include ) +endif() + if (LWS_WITH_SECURE_STREAMS) set(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM 1) endif() @@ -529,9 +548,9 @@ if (LWS_PLAT_FREERTOS) set(LWS_WITH_CUSTOM_HEADERS 0) endif() -if (LWS_WITH_ESP32) - set(LWS_WITH_ZIP_FOPS 1) -endif() +#if (LWS_WITH_ESP32) +# set(LWS_WITH_ZIP_FOPS 1) +#endif() if (WIN32) set(LWS_MAX_SMP 1) @@ -677,7 +696,7 @@ if (LWS_WITH_SSL AND LWS_WITH_WOLFSSL) endif() if (LWS_WITH_SSL AND LWS_WITH_MBEDTLS) - if ("${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "" AND NOT LWS_PLAT_FREERTOS) + if ((NOT LWS_MBEDTLS_LIBRARIES OR "${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR NOT LWS_MBEDTLS_INCLUDE_DIRS OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "") AND NOT LWS_PLAT_FREERTOS) find_path(LWS_MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) @@ -830,6 +849,9 @@ if (LWS_UNIX_SOCK) set(LWS_WITH_UNIX_SOCK 1) endif() +if (NOT LWS_MAX_SMP) + set(LWS_MAX_SMP 1) +endif() if ("${LWS_MAX_SMP}" STREQUAL "") set(LWS_MAX_SMP 1) endif() @@ -1039,6 +1061,16 @@ set(LWS_HAVE_WORKING_VFORK LWS_HAVE_VFORK) CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS) +if (NOT CMAKE_REQUIRED_FLAGS) + set(CMAKE_REQUIRED_FLAGS "") +endif() +if (NOT CMAKE_REQUIRED_INCLUDES) + set(CMAKE_REQUIRED_INCLUDES "") +endif() +if (NOT CMAKE_REQUIRED_LIBRARIES) + set(CMAKE_REQUIRED_LIBRARIES "") +endif() + CHECK_C_SOURCE_COMPILES("#include int main(void) { intptr_t test = 1; @@ -1771,6 +1803,8 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) endif() if (LWS_WITH_GCOV) set (GCOV_FLAGS "-fprofile-arcs -ftest-coverage ") + else() + set(GCOV_FLAGS "") endif() if (LWS_WITH_ASAN) @@ -1779,6 +1813,8 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) set (ASAN_FLAGS "${ASAN_FLAGS} -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=leak") endif() message("Enabling ASAN") + else() + set(ASAN_FLAGS "") endif() check_c_compiler_flag("-Wignored-qualifiers" LWS_GCC_HAS_IGNORED_QUALIFIERS) @@ -1833,7 +1869,9 @@ endif() source_group("Headers Private" FILES ${HDR_PRIVATE}) source_group("Headers Public" FILES ${HDR_PUBLIC}) source_group("Sources" FILES ${SOURCES}) -source_group("Resources" FILES ${RESOURCES}) +if (RESOURCES) + source_group("Resources" FILES ${RESOURCES}) +endif() # # Create the lib. @@ -1874,6 +1912,9 @@ if (LWS_WITH_STATIC) endif() if (LWS_WITH_SHARED) + if (NOT RESOURCES) + set(RESOURCES "") + endif() add_library(websockets_shared SHARED ${HDR_PRIVATE} ${HDR_PUBLIC} @@ -2226,6 +2267,10 @@ if (LWS_WITH_ZLIB) endif() endif() +if (NOT VARIA) + set(VARIA "") +endif() + CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param) CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_info_callback LWS_HAVE_SSL_SET_INFO_CALLBACK) CHECK_FUNCTION_EXISTS(${VARIA}X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host) @@ -3065,76 +3110,6 @@ set(CPACK_SOURCE_IGNORE_FILES $(CPACK_SOURCE_IGNORE_FILES) "/.git/" "/build/" "\ add_custom_target(dist COMMAND "${CMAKE_MAKE_PROGRAM}" package_source) -message("---------------------------------------------------------------------") -message(" Settings: (For more help do cmake -LH )") -message("---------------------------------------------------------------------") -message(" LWS_WITH_STATIC = ${LWS_WITH_STATIC}") -message(" LWS_WITH_SHARED = ${LWS_WITH_SHARED}") -message(" LWS_WITH_SSL = ${LWS_WITH_SSL} (SSL Support)") -message(" LWS_SSL_CLIENT_USE_OS_CA_CERTS = ${LWS_SSL_CLIENT_USE_OS_CA_CERTS}") -message(" LWS_WITH_WOLFSSL = ${LWS_WITH_WOLFSSL} (wolfSSL/CyaSSL replacement for OpenSSL)") -if (LWS_WITH_WOLFSSL) - message(" LWS_WOLFSSL_LIBRARIES = ${LWS_WOLFSSL_LIBRARIES}") - message(" LWS_WOLFSSL_INCLUDE_DIRS = ${LWS_WOLFSSL_INCLUDE_DIRS}") -endif() -message(" LWS_WITH_MBEDTLS = ${LWS_WITH_MBEDTLS} (mbedTLS replacement for OpenSSL)") -message(" LWS_WITHOUT_BUILTIN_SHA1 = ${LWS_WITHOUT_BUILTIN_SHA1}") -message(" LWS_WITHOUT_BUILTIN_GETIFADDRS = ${LWS_WITHOUT_BUILTIN_GETIFADDRS}") -message(" LWS_WITHOUT_CLIENT = ${LWS_WITHOUT_CLIENT}") -message(" LWS_WITHOUT_SERVER = ${LWS_WITHOUT_SERVER}") -message(" LWS_LINK_TESTAPPS_DYNAMIC = ${LWS_LINK_TESTAPPS_DYNAMIC}") -message(" LWS_WITHOUT_TESTAPPS = ${LWS_WITHOUT_TESTAPPS}") -message(" LWS_WITHOUT_TEST_SERVER = ${LWS_WITHOUT_TEST_SERVER}") -message(" LWS_WITHOUT_TEST_SERVER_EXTPOLL = ${LWS_WITHOUT_TEST_SERVER_EXTPOLL}") -message(" LWS_WITHOUT_TEST_PING = ${LWS_WITHOUT_TEST_PING}") -message(" LWS_WITHOUT_TEST_CLIENT = ${LWS_WITHOUT_TEST_CLIENT}") -message(" LWS_WITHOUT_EXTENSIONS = ${LWS_WITHOUT_EXTENSIONS}") -message(" LWS_WITHOUT_DAEMONIZE = ${LWS_WITHOUT_DAEMONIZE}") -message(" LWS_WITH_LIBEV = ${LWS_WITH_LIBEV}") -message(" LWS_WITH_LIBUV = ${LWS_WITH_LIBUV}") -message(" LWS_WITH_LIBEVENT = ${LWS_WITH_LIBEVENT}") -message(" LWS_WITH_GLIB = ${LWS_WITH_GLIB}") -message(" LWS_IPV6 = ${LWS_IPV6}") -message(" LWS_UNIX_SOCK = ${LWS_UNIX_SOCK}") -message(" LWS_WITH_HTTP2 = ${LWS_WITH_HTTP2}") -message(" LWS_ROLE_MQTT = ${LWS_ROLE_MQTT}") -message(" LWS_SSL_SERVER_WITH_ECDH_CERT = ${LWS_SSL_SERVER_WITH_ECDH_CERT}") -message(" LWS_MAX_SMP = ${LWS_MAX_SMP}") -message(" LWS_HAVE_PTHREAD_H = ${LWS_HAVE_PTHREAD_H}") -message(" LWS_WITH_CGI = ${LWS_WITH_CGI}") -message(" LWS_HAVE_OPENSSL_ECDH_H = ${LWS_HAVE_OPENSSL_ECDH_H}") -message(" LWS_HAVE_SSL_CTX_set1_param = ${LWS_HAVE_SSL_CTX_set1_param}") -message(" LWS_HAVE_RSA_SET0_KEY = ${LWS_HAVE_RSA_SET0_KEY}") -message(" LWS_WITH_HTTP_PROXY = ${LWS_WITH_HTTP_PROXY}") -message(" LIBHUBBUB_LIBRARIES = ${LIBHUBBUB_LIBRARIES}") -message(" PLUGINS = ${PLUGINS_LIST}") -message(" LWS_WITH_ACCESS_LOG = ${LWS_WITH_ACCESS_LOG}") -message(" LWS_WITH_SERVER_STATUS = ${LWS_WITH_SERVER_STATUS}") -message(" LWS_WITH_LEJP = ${LWS_WITH_LEJP}") -message(" LWS_WITH_LEJP_CONF = ${LWS_WITH_LEJP_CONF}") -# this is broken atm -#message(" LWS_WITH_SMTP = ${LWS_WITH_SMTP}") -message(" LWS_WITH_GENERIC_SESSIONS = ${LWS_WITH_GENERIC_SESSIONS}") -message(" LWS_STATIC_PIC = ${LWS_STATIC_PIC}") -message(" LWS_WITH_RANGES = ${LWS_WITH_RANGES}") -message(" LWS_PLAT_OPTEE = ${LWS_PLAT_OPTEE}") -message(" LWS_PLAT_FREERTOS = ${LWS_PLAT_FREERTOS}") -message(" LWS_WITH_ZIP_FOPS = ${LWS_WITH_ZIP_FOPS}") -message(" LWS_AVOID_SIGPIPE_IGN = ${LWS_AVOID_SIGPIPE_IGN}") -message(" LWS_WITH_STATS = ${LWS_WITH_STATS}") -message(" LWS_WITH_SOCKS5 = ${LWS_WITH_SOCKS5}") -message(" LWS_HAVE_SYS_CAPABILITY_H = ${LWS_HAVE_SYS_CAPABILITY_H}") -message(" LWS_HAVE_LIBCAP = ${LWS_HAVE_LIBCAP}") -message(" LWS_WITH_PEER_LIMITS = ${LWS_WITH_PEER_LIMITS}") -message(" LWS_HAVE_ATOLL = ${LWS_HAVE_ATOLL}") -message(" LWS_HAVE__ATOI64 = ${LWS_HAVE__ATOI64}") -message(" LWS_HAVE_STAT32I64 = ${LWS_HAVE_STAT32I64}") -message(" LWS_HAS_INTPTR_T = ${LWS_HAS_INTPTR_T}") -message(" LWS_WITH_EXPORT_LWSTARGETS = ${LWS_WITH_EXPORT_LWSTARGETS}") -message(" LWS_WITH_ABSTRACT = ${LWS_WITH_ABSTRACT}") - -message("---------------------------------------------------------------------") - # These will be available to parent projects including libwebsockets using add_subdirectory() set(LIBWEBSOCKETS_LIBRARIES ${LWS_LIBRARIES} CACHE STRING "Libwebsocket libraries") if (LWS_WITH_STATIC) diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 2b50635a..7610f600 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -16,6 +16,7 @@ LWS_LIBRARY_VERSION_PATCH #define LWS_MAX_SMP ${LWS_MAX_SMP} +#cmakedefine LWS_ESP_PLATFORM #cmakedefine LWS_LIBRARY_VERSION_NUMBER #cmakedefine LWS_EXT_PTHREAD_LIBRARIES @@ -181,4 +182,3 @@ #cmakedefine USE_OLD_CYASSL #cmakedefine USE_WOLFSSL -${LWS_SIZEOFPTR_CODE} diff --git a/cmake/lws_config_private.h.in b/cmake/lws_config_private.h.in index b0615b50..814e6641 100644 --- a/cmake/lws_config_private.h.in +++ b/cmake/lws_config_private.h.in @@ -5,6 +5,7 @@ #define _DEBUG #endif #endif +#cmakedefine LWIP_PROVIDE_ERRNO /* Define to 1 to use CyaSSL as a replacement for OpenSSL. * LWS_OPENSSL_SUPPORT needs to be set also for this to work. */ diff --git a/contrib/cross-esp32.cmake b/contrib/cross-esp32.cmake index 42882b5d..083654f0 100644 --- a/contrib/cross-esp32.cmake +++ b/contrib/cross-esp32.cmake @@ -9,11 +9,13 @@ # Target operating system name. set(CMAKE_SYSTEM_NAME Linux) -# Name of C compiler. -set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/xtensa-esp32-elf-gcc${EXECUTABLE_EXT}") -set(CMAKE_AR "${CROSS_PATH}/bin/xtensa-esp32-elf-ar${EXECUTABLE_EXT}") -set(CMAKE_RANLIB "${CROSS_PATH}/bin/xtensa-esp32-elf-ranlib${EXECUTABLE_EXT}") -set(CMAKE_LINKER "${CROSS_PATH}/bin/xtensa-esp32-elf-ld${EXECUTABLE_EXT}") +# assumed these are set up on the $PATH +set(TC xtensa-esp32-elf) + +set(CMAKE_C_COMPILER "${TC}-gcc${EXECUTABLE_EXT}") +set(CMAKE_AR "${TC}-ar${EXECUTABLE_EXT}") +set(CMAKE_RANLIB "${TC}-ranlib${EXECUTABLE_EXT}") +set(CMAKE_LINKER "${TC}-ld${EXECUTABLE_EXT}") # # Different build system distros set release optimization level to different diff --git a/include/libwebsockets/lws-esp32.h b/include/libwebsockets/lws-esp32.h index 1b046cef..49cb6377 100644 --- a/include/libwebsockets/lws-esp32.h +++ b/include/libwebsockets/lws-esp32.h @@ -150,4 +150,3 @@ extern uint16_t lws_esp32_sine_interp(int n); /* required in external code by esp32 plat (may just return if no leds) */ extern void lws_esp32_leds_timer_cb(TimerHandle_t th); -#endif /* LWS_AMAZON_RTOS */ diff --git a/include/libwebsockets/lws-freertos.h b/include/libwebsockets/lws-freertos.h index 5800b13a..407b387d 100644 --- a/include/libwebsockets/lws-freertos.h +++ b/include/libwebsockets/lws-freertos.h @@ -65,7 +65,7 @@ struct pollfd { #include "esp_wifi.h" #include "esp_system.h" #include "esp_event.h" -#include "esp_event_loop.h" +//#include "esp_event_loop.h" #include "nvs.h" #include "driver/gpio.h" #include "esp_spi_flash.h" diff --git a/include/libwebsockets/lws-network-helper.h b/include/libwebsockets/lws-network-helper.h index 81cf9456..3ba324a7 100644 --- a/include/libwebsockets/lws-network-helper.h +++ b/include/libwebsockets/lws-network-helper.h @@ -29,6 +29,10 @@ */ ///@{ +#if defined(LWS_ESP_PLATFORM) +#include +#endif + typedef union { #if defined(LWS_WITH_IPV6) struct sockaddr_in6 sa6; diff --git a/lib/core-net/network.c b/lib/core-net/network.c index e087cd10..40c5fff2 100644 --- a/lib/core-net/network.c +++ b/lib/core-net/network.c @@ -23,6 +23,7 @@ */ #include "private-lib-core.h" +#include #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) static int @@ -327,21 +328,21 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port, return LWS_ITOSA_NOT_EXIST; } } - if (uid && gid) { - if (chown(serv_unix.sun_path, uid, gid)) { + if (iface && iface[0] != '@' && uid && gid) { + if (chown(iface, uid, gid)) { lwsl_err("%s: failed to set %s perms %u:%u\n", - __func__, serv_unix.sun_path, + __func__, iface, (unsigned int)uid, (unsigned int)gid); return LWS_ITOSA_NOT_EXIST; } lwsl_notice("%s: vh %s unix skt %s perms %u:%u\n", - __func__, vhost->name, serv_unix.sun_path, + __func__, vhost->name, iface, (unsigned int)uid, (unsigned int)gid); - if (chmod(serv_unix.sun_path, 0660)) { + if (chmod(iface, 0660)) { lwsl_err("%s: failed to set %s to 0600 mode\n", - __func__, serv_unix.sun_path); + __func__, iface); return LWS_ITOSA_NOT_EXIST; } diff --git a/lib/core/context.c b/lib/core/context.c index 36ed5e0b..b3cc7f8e 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -445,7 +445,7 @@ lws_create_context(const struct lws_context_creation_info *info) } context->max_fds = rt.rlim_cur; #else -#if defined(WIN32) || defined(_WIN32) || defined(LWS_AMAZON_RTOS) +#if defined(WIN32) || defined(_WIN32) || defined(LWS_AMAZON_RTOS) || defined(LWS_ESP_PLATFORM) context->max_fds = getdtablesize(); #else context->max_fds = sysconf(_SC_OPEN_MAX); diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index 128bbbd5..4688b3e2 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -1091,10 +1091,12 @@ static const char * const builtins[] = { "--ignore-sigterm" }; +#if !defined(LWS_PLAT_FREERTOS) static void lws_sigterm_catch(int sig) { } +#endif void lws_cmdline_option_handle_builtin(int argc, const char **argv, @@ -1121,7 +1123,9 @@ lws_cmdline_option_handle_builtin(int argc, const char **argv, info->udp_loss_sim_rx_pc = m; break; case 3: +#if !defined(LWS_PLAT_FREERTOS) signal(SIGTERM, lws_sigterm_catch); +#endif break; } } diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 08abcb5f..5d2edb41 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -28,6 +28,7 @@ #include "lws_config.h" #include "lws_config_private.h" + #if defined(LWS_WITH_CGI) && defined(LWS_HAVE_VFORK) && \ !defined(NO_GNU_SOURCE_THIS_TIME) && !defined(_GNU_SOURCE) #define _GNU_SOURCE @@ -46,6 +47,7 @@ #include #include #include +#include #ifdef LWS_HAVE_INTTYPES_H #include diff --git a/lib/plat/freertos/freertos-file.c b/lib/plat/freertos/freertos-file.c index e19f87fc..e08d1749 100644 --- a/lib/plat/freertos/freertos-file.c +++ b/lib/plat/freertos/freertos-file.c @@ -135,7 +135,7 @@ lws_find_string_in_file(const char *filename, const char *string, int stringlen) q = string; n = 0; - while (n < sizeof(buf) - 1 && q != p) + while ((size_t)n < sizeof(buf) - 1 && q != p) buf[n++] = *q++; buf[n] = '\0'; diff --git a/lib/plat/freertos/freertos-misc.c b/lib/plat/freertos/freertos-misc.c index 3d59afdb..d0c9634a 100644 --- a/lib/plat/freertos/freertos-misc.c +++ b/lib/plat/freertos/freertos-misc.c @@ -43,7 +43,7 @@ lws_get_random(struct lws_context *context, void *buf, size_t len) uint8_t *p = (uint8_t *)&r; int b = 4; - if (len < b) + if (len < (size_t)b) b = len; len -= b; diff --git a/lib/plat/freertos/freertos-sockets.c b/lib/plat/freertos/freertos-sockets.c index 4efdd07f..625b72d3 100644 --- a/lib/plat/freertos/freertos-sockets.c +++ b/lib/plat/freertos/freertos-sockets.c @@ -23,7 +23,7 @@ */ #include "private-lib-core.h" - +#include #if defined(LWS_WITH_MBEDTLS) #if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) #include "mbedtls/net_sockets.h" diff --git a/lib/plat/freertos/private-lib-plat-freertos.h b/lib/plat/freertos/private-lib-plat-freertos.h index 04580c48..052f43ad 100644 --- a/lib/plat/freertos/private-lib-plat-freertos.h +++ b/lib/plat/freertos/private-lib-plat-freertos.h @@ -24,7 +24,9 @@ * Included from lib/private-lib-core.h if LWS_PLAT_FREERTOS */ +#if !defined(LWS_ESP_PLATFORM) #define SOMAXCONN 3 +#endif #if defined(LWS_AMAZON_RTOS) int @@ -43,7 +45,6 @@ #ifndef __cplusplus #include #endif - #include #include #if defined(LWS_AMAZON_RTOS) const char * @@ -68,6 +69,7 @@ gai_strerror(int); #if defined(LWS_WITH_ESP32) #include "lwip/apps/sntp.h" +#include #endif #include diff --git a/lib/roles/listen/ops-listen.c b/lib/roles/listen/ops-listen.c index 3cb2e998..c0ac6e5e 100644 --- a/lib/roles/listen/ops-listen.c +++ b/lib/roles/listen/ops-listen.c @@ -144,7 +144,7 @@ rops_handle_POLLIN_listen(struct lws_context_per_thread *pt, struct lws *wsi, fd.sockfd = accept_fd; cwsi = lws_adopt_descriptor_vhost(wsi->vhost, opts, fd, - NULL, NULL); + wsi->vhost->listen_accept_protocol, NULL); if (!cwsi) { lwsl_info("%s: vh %s: adopt failed\n", __func__, wsi->vhost->name); diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index fc8883a3..6f83ca0b 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -166,7 +166,7 @@ lws_ss_policy_set(struct lws_context *context, const char *name) else m = 0; - lwsl_notice("%s: %s, pad %d%c: %s\n", __func__, buf, m, '%', name); + lwsl_info("%s: %s, pad %d%c: %s\n", __func__, buf, m, '%', name); #endif /* Create vhosts for each type of trust store */ diff --git a/lib/tls/mbedtls/mbedtls-server.c b/lib/tls/mbedtls/mbedtls-server.c index f0dcb6e2..dcdf9d31 100644 --- a/lib/tls/mbedtls/mbedtls-server.c +++ b/lib/tls/mbedtls/mbedtls-server.c @@ -24,6 +24,7 @@ #include "private-lib-core.h" #include +#include int lws_tls_server_client_cert_verify_config(struct lws_vhost *vh) diff --git a/lib/tls/mbedtls/mbedtls-ssl.c b/lib/tls/mbedtls/mbedtls-ssl.c index f535aed4..ae2d209d 100644 --- a/lib/tls/mbedtls/mbedtls-ssl.c +++ b/lib/tls/mbedtls/mbedtls-ssl.c @@ -25,7 +25,6 @@ #include "private-lib-core.h" #include "private-lib-tls-mbedtls.h" - void lws_ssl_destroy(struct lws_vhost *vhost) { diff --git a/lib/tls/mbedtls/private-lib-tls-mbedtls.h b/lib/tls/mbedtls/private-lib-tls-mbedtls.h index dbd4f16a..b6b4e6bc 100644 --- a/lib/tls/mbedtls/private-lib-tls-mbedtls.h +++ b/lib/tls/mbedtls/private-lib-tls-mbedtls.h @@ -25,6 +25,7 @@ */ #include +#include struct lws_x509_cert { mbedtls_x509_crt cert; /* has a .next for linked-list / chain */ diff --git a/minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt b/minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt new file mode 100644 index 00000000..6cf7e915 --- /dev/null +++ b/minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.5) + +if (ESP_PLATFORM) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) + project(lws-minimal-esp32) + enable_testing() + + target_link_libraries(lws-minimal-esp32.elf websockets) + add_subdirectory(libwebsockets) + + add_test(NAME flashing COMMAND idf.py flash) + set_tests_properties(flashing PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + TIMEOUT 120) + + add_test(NAME boot COMMAND /usr/local/bin/sai-expect) + set_tests_properties(boot PROPERTIES + DEPENDS flashing + TIMEOUT 20) + +endif() diff --git a/minimal-examples/embedded/lws-minimal-esp32/main/CMakeLists.txt b/minimal-examples/embedded/lws-minimal-esp32/main/CMakeLists.txt new file mode 100644 index 00000000..c38b4767 --- /dev/null +++ b/minimal-examples/embedded/lws-minimal-esp32/main/CMakeLists.txt @@ -0,0 +1,6 @@ +idf_component_register(SRCS + "lws-minimal-esp32.c" + INCLUDE_DIRS "../libwebsockets/include;${IDF_PATH}/components/spi_flash/include;${IDF_PATH}/components/nvs_flash/include;${IDF_PATH}/components/mdns/include") + +target_link_libraries(${COMPONENT_LIB} websockets) +include_directories(../build/libwebsockets) diff --git a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c new file mode 100644 index 00000000..608238e8 --- /dev/null +++ b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c @@ -0,0 +1,102 @@ +/* + * lws-minimal-esp32 + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * Based on espressif Public Domain sample + */ + +#define LWIP_PROVIDE_ERRNO 1 +#define _ESP_PLATFORM_ERRNO_H_ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_spi_flash.h" +#include "esp_wifi.h" +#include +#include + +#include + +lws_sorted_usec_list_t sul; +int interrupted; + +static void +sul_cb(lws_sorted_usec_list_t *sul) +{ + interrupted = 1; +} + +void +app_main(void) +{ + wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); + struct lws_context_creation_info info; + struct lws_context *context; + esp_chip_info_t chip_info; + int n = 0; + + lws_set_log_level(15, NULL); + nvs_flash_init(); + esp_netif_init(); + + n = esp_wifi_init(&wic); + if (n) { + lwsl_err("%s: wifi init fail: %d\n", __func__, n); + goto spin; + } + + memset(&info, 0, sizeof(info)); + + lwsl_notice("LWS minimal build test\n"); + + esp_chip_info(&chip_info); + lwsl_notice("chip: %s (%d CPU cores) WiFi%s%s\n", + CONFIG_IDF_TARGET, chip_info.cores, + (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", + (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); + + lwsl_notice("silicon revision %d\n", chip_info.revision); + + lwsl_notice("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024), + (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); + + lwsl_notice("Free heap: %d\n", esp_get_free_heap_size()); + + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN; + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return; + } + + /* + * We just exit the event loop after 3s + */ + + lws_sul_schedule(context, 0, &sul, sul_cb, 3 * LWS_USEC_PER_SEC); + + while (n >= 0 && !interrupted) { + n = lws_service(context, 0); + taskYIELD(); + } + + lws_context_destroy(context); + + lwsl_notice("Completed: PASS\n"); +// fflush(stdout); +// esp_restart(); + +spin: + vTaskDelay(10); + taskYIELD(); + goto spin; +} + diff --git a/minimal-examples/embedded/lws-minimal-esp32/sdkconfig b/minimal-examples/embedded/lws-minimal-esp32/sdkconfig new file mode 100644 index 00000000..a90f41ca --- /dev/null +++ b/minimal-examples/embedded/lws-minimal-esp32/sdkconfig @@ -0,0 +1,1145 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_TARGET_ESP32=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +# +# Bootloader config +# +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +# CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V is not set +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_26M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="26m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_TRAX is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 +CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 +CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1 +CONFIG_BT_RESERVE_DRAM=0 +# end of Bluetooth + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# end of ADC configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# RTCIO configuration +# +# CONFIG_RTCIO_SUPPORT_RTC_GPIO_DESC is not set +# end of RTCIO configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE is not set +CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT is not set +CONFIG_EFUSE_MAX_BLK_LEN=192 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# end of ESP-TLS + +# +# ESP32-specific +# +CONFIG_ESP32_REV_MIN_0=y +# CONFIG_ESP32_REV_MIN_1 is not set +# CONFIG_ESP32_REV_MIN_2 is not set +# CONFIG_ESP32_REV_MIN_3 is not set +CONFIG_ESP32_REV_MIN=0 +CONFIG_ESP32_DPORT_WORKAROUND=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 +# CONFIG_ESP32_SPIRAM_SUPPORT is not set +# CONFIG_ESP32_TRAX is not set +CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32_ULP_COPROC_ENABLED is not set +CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_BROWNOUT_DET=y +CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_ESP32_BROWNOUT_DET_LVL=0 +CONFIG_ESP32_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +# CONFIG_ESP32_XTAL_FREQ_40 is not set +CONFIG_ESP32_XTAL_FREQ_26=y +# CONFIG_ESP32_XTAL_FREQ_AUTO is not set +CONFIG_ESP32_XTAL_FREQ=26 +# CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_ESP32_NO_BLOBS is not set +# CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +# CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set +CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5 +# end of ESP32-specific + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +# end of Power Management + +# +# ADC-Calibration +# +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_TX_GPIO=1 +CONFIG_ESP_CONSOLE_UART_RX_GPIO=3 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ETH_PHY_INTERFACE_RMII=y +# CONFIG_ETH_PHY_INTERFACE_MII is not set +CONFIG_ETH_RMII_CLK_INPUT=y +# CONFIG_ETH_RMII_CLK_OUTPUT is not set +CONFIG_ETH_RMII_CLK_IN_GPIO=0 +CONFIG_ETH_DMA_BUFFER_SIZE=512 +CONFIG_ETH_DMA_RX_BUFFER_NUM=10 +CONFIG_ETH_DMA_TX_BUFFER_NUM=10 +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +# CONFIG_ESP_TIMER_IMPL_FRC2 is not set +CONFIG_ESP_TIMER_IMPL_TG0_LAC=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +# CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# end of Wi-Fi + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# end of PHY + +# +# Core dump +# +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_SERIAL_TASK_PRIO=10 +# CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_FMB_TIMER_PORT_ENABLED=y +CONFIG_FMB_TIMER_GROUP=0 +CONFIG_FMB_TIMER_INDEX=0 +# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set +# end of Modbus configuration + +# +# FreeRTOS +# +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +# end of FreeRTOS + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_FRAG=y +# CONFIG_LWIP_IP_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set + +# +# DHCP server +# +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=6 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set + +# +# ICMP +# +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_ESP_LWIP_ASSERT=y +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DEBUG is not set + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +CONFIG_MBEDTLS_PSK_MODES=y +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# end of NVS + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +# end of Auto-detect flash chips +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TinyUSB +# + +# +# Descriptor configuration +# +CONFIG_USB_DESC_CUSTOM_VID=0x1234 +CONFIG_USB_DESC_CUSTOM_PID=0x5678 +# end of Descriptor configuration +# end of TinyUSB + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_TLS_V12 is not set +# end of Supplicant +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_SPIRAM_SUPPORT is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set +# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_TX_GPIO=1 +CONFIG_CONSOLE_UART_RX_GPIO=3 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_GDBSTUB is not set +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +# CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_MB_TIMER_PORT_ENABLED=y +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# End of deprecated options diff --git a/minimal-examples/embedded/lws-minimal-esp32/sdkconfig.h b/minimal-examples/embedded/lws-minimal-esp32/sdkconfig.h new file mode 100644 index 00000000..7e4fcfe0 --- /dev/null +++ b/minimal-examples/embedded/lws-minimal-esp32/sdkconfig.h @@ -0,0 +1,426 @@ +/* + * Automatically generated file. DO NOT EDIT. + * Espressif IoT Development Framework (ESP-IDF) Configuration Header + */ +#pragma once +#define CONFIG_IDF_CMAKE 1 +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 +#define CONFIG_SDK_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1 +#define CONFIG_APP_BUILD_GENERATE_BINARIES 1 +#define CONFIG_APP_BUILD_BOOTLOADER 1 +#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1 +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 16 +#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL_INFO 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL 3 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_ESPTOOLPY_FLASHFREQ_26M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "26m" +#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B 1 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_COMPILER_OPTIMIZATION_DEFAULT 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE 1 +#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1 +#define CONFIG_APPTRACE_DEST_NONE 1 +#define CONFIG_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0 +#define CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0 +#define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1 +#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_COAP_MBEDTLS_PSK 1 +#define CONFIG_COAP_LOG_DEFAULT_LEVEL 0 +#define CONFIG_ADC_DISABLE_DAC 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_ESP_TLS_USING_MBEDTLS 1 +#define CONFIG_ESP32_REV_MIN_0 1 +#define CONFIG_ESP32_REV_MIN 0 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ESP32_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_ESP32_BROWNOUT_DET 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL 0 +#define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESP32_RTC_CLK_SRC_INT_RC 1 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_ESP32_XTAL_FREQ_26 1 +#define CONFIG_ESP32_XTAL_FREQ 26 +#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 +#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 +#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 +#define CONFIG_ESP_CONSOLE_UART_NUM 0 +#define CONFIG_ESP_CONSOLE_UART_TX_GPIO 1 +#define CONFIG_ESP_CONSOLE_UART_RX_GPIO 3 +#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_ESP_INT_WDT 1 +#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESP_INT_WDT_CHECK_CPU1 1 +#define CONFIG_ESP_TASK_WDT 1 +#define CONFIG_ESP_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH 1 +#define CONFIG_ETH_ENABLED 1 +#define CONFIG_ETH_USE_ESP32_EMAC 1 +#define CONFIG_ETH_PHY_INTERFACE_RMII 1 +#define CONFIG_ETH_RMII_CLK_INPUT 1 +#define CONFIG_ETH_RMII_CLK_IN_GPIO 0 +#define CONFIG_ETH_DMA_BUFFER_SIZE 512 +#define CONFIG_ETH_DMA_RX_BUFFER_NUM 10 +#define CONFIG_ETH_DMA_TX_BUFFER_NUM 10 +#define CONFIG_ETH_USE_SPI_ETHERNET 1 +#define CONFIG_ESP_EVENT_POST_FROM_ISR 1 +#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_ESP_NETIF_TCPIP_LWIP 1 +#define CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER 1 +#define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 +#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_TIMER_IMPL_TG0_LAC 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_ESP32_WIFI_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_RX_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_FMB_COMM_MODE_RTU_EN 1 +#define CONFIG_FMB_COMM_MODE_ASCII_EN 1 +#define CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND 150 +#define CONFIG_FMB_MASTER_DELAY_MS_CONVERT 200 +#define CONFIG_FMB_QUEUE_LENGTH 20 +#define CONFIG_FMB_SERIAL_TASK_STACK_SIZE 2048 +#define CONFIG_FMB_SERIAL_BUF_SIZE 256 +#define CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB 8 +#define CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS 1000 +#define CONFIG_FMB_SERIAL_TASK_PRIO 10 +#define CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT 20 +#define CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 +#define CONFIG_FMB_CONTROLLER_STACK_SIZE 4096 +#define CONFIG_FMB_EVENT_QUEUE_TIMEOUT 20 +#define CONFIG_FMB_TIMER_PORT_ENABLED 1 +#define CONFIG_FMB_TIMER_GROUP 0 +#define CONFIG_FMB_TIMER_INDEX 0 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 +#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1 +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_HEAP_TRACING_OFF 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 +#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif" +#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define CONFIG_LWIP_TIMERS_ONDEMAND 1 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_LWIP_IP_FRAG 1 +#define CONFIG_LWIP_ESP_GRATUITOUS_ARP 1 +#define CONFIG_LWIP_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_LWIP_TCP_MAXRTX 12 +#define CONFIG_LWIP_TCP_SYNMAXRTX 6 +#define CONFIG_LWIP_TCP_MSS 1440 +#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 +#define CONFIG_LWIP_TCP_MSL 60000 +#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_LWIP_TCP_WND_DEFAULT 5744 +#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1 +#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 +#define CONFIG_LWIP_ESP_LWIP_ASSERT 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN 1 +#define CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#define CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN 4096 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL 1 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_MBEDTLS_HARDWARE_MPI 1 +#define CONFIG_MBEDTLS_HARDWARE_SHA 1 +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_MBEDTLS_PSK_MODES 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_SSL_PROTO_DTLS 1 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_MDNS_MAX_SERVICES 10 +#define CONFIG_MDNS_TASK_PRIORITY 1 +#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 +#define CONFIG_MDNS_TASK_AFFINITY 0x0 +#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 2000 +#define CONFIG_MDNS_TIMER_PERIOD_MS 100 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_OPENSSL_ASSERT_EXIT 1 +#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY 1 +#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_USB_DESC_CUSTOM_VID 0x1234 +#define CONFIG_USB_DESC_CUSTOM_PID 0x5678 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_VFS_SUPPORT_IO 1 +#define CONFIG_VFS_SUPPORT_DIR 1 +#define CONFIG_VFS_SUPPORT_SELECT 1 +#define CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_VFS_SUPPORT_TERMIOS 1 +#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 +#define CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN 128 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30 +#define CONFIG_WPA_MBEDTLS_CRYPTO 1 + +/* List of deprecated options */ +#define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC +#define CONFIG_BROWNOUT_DET CONFIG_ESP32_BROWNOUT_DET +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 +#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE +#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT +#define CONFIG_CONSOLE_UART_RX_GPIO CONFIG_ESP_CONSOLE_UART_RX_GPIO +#define CONFIG_CONSOLE_UART_TX_GPIO CONFIG_ESP_CONSOLE_UART_TX_GPIO +#define CONFIG_ESP32S2_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY +#define CONFIG_ESP32_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC CONFIG_ESP32_RTC_CLK_SRC_INT_RC +#define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP +#define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR +#define CONFIG_GARP_TMR_INTERVAL CONFIG_LWIP_GARP_TMR_INTERVAL +#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT +#define CONFIG_INT_WDT_CHECK_CPU1 CONFIG_ESP_INT_WDT_CHECK_CPU1 +#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS +#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO +#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT +#define CONFIG_MB_CONTROLLER_STACK_SIZE CONFIG_FMB_CONTROLLER_STACK_SIZE +#define CONFIG_MB_EVENT_QUEUE_TIMEOUT CONFIG_FMB_EVENT_QUEUE_TIMEOUT +#define CONFIG_MB_MASTER_DELAY_MS_CONVERT CONFIG_FMB_MASTER_DELAY_MS_CONVERT +#define CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND +#define CONFIG_MB_QUEUE_LENGTH CONFIG_FMB_QUEUE_LENGTH +#define CONFIG_MB_SERIAL_BUF_SIZE CONFIG_FMB_SERIAL_BUF_SIZE +#define CONFIG_MB_SERIAL_TASK_PRIO CONFIG_FMB_SERIAL_TASK_PRIO +#define CONFIG_MB_SERIAL_TASK_STACK_SIZE CONFIG_FMB_SERIAL_TASK_STACK_SIZE +#define CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP +#define CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX +#define CONFIG_MB_TIMER_PORT_ENABLED CONFIG_FMB_TIMER_PORT_ENABLED +#define CONFIG_MONITOR_BAUD_115200B CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR +#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR +#define CONFIG_REDUCE_PHY_TX_POWER CONFIG_ESP32_REDUCE_PHY_TX_POWER +#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN +#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS +#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE +#define CONFIG_SUPPORT_TERMIOS CONFIG_VFS_SUPPORT_TERMIOS +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE +#define CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 +#define CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S +#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY +#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE +#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX +#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL +#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS +#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS +#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ +#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE +#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT +#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX +#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT +#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH +#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY +#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH +#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE +#define CONFIG_TOOLPREFIX CONFIG_SDK_TOOLPREFIX +#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE -- Gitee From b3131fdfddf408a26203ba86844858758d01ae46 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 22 May 2020 16:47:40 +0100 Subject: [PATCH 0127/1062] cmakelist: Augean Stables refactor Establish a new distributed CMake architecture with CMake code related to a source directory moving to be in the subdir in its own CMakeLists.txt. In particular, there's now one in ./lib which calls through to ones further down the directory tree like ./lib/plat/xxx, ./lib/roles/xxx etc. This cuts the main CMakelists.txt from 98KB -> 33KB, about a 66% reduction, and it's much easier to maintain sub-CMakeLists.txt that are in the same directory as the sources they manage, and conceal all the details that that level. Child CMakelists.txt become responsible for: - include_directories() definition (this is not supported by CMake directly, it passes it back up via PARENT_SCOPE vars in helper macros) - Addition child CMakeLists.txt inclusion, for example toplevel -> role -> role subdir - Source file addition to the build - Dependent library path resolution... this is now a private thing in the child CMakeLists.txt, it just passes back any adaptations to include_directories() and the LIB_LIST without filling the parent namespace with the details --- .gitignore | 1 + CMakeLists-implied-options.txt | 381 +++ CMakeLists.txt | 2672 ++--------------- cmake/FindLibWebSockets.cmake | 33 - cmake/LwsCheckRequirements.cmake | 76 + ... => libwebsockets-config-version.cmake.in} | 0 ...cmake.in => libwebsockets-config.cmake.in} | 0 cmake/lws_config_private.h.in | 16 - include/libwebsockets.h | 26 +- lib/CMakeLists.txt | 309 ++ lib/abstract/CMakeLists.txt | 57 + lib/core-net/CMakeLists.txt | 80 + lib/core-net/connect.c | 2 + lib/core/CMakeLists.txt | 46 + lib/core/private-lib-core.h | 4 +- lib/event-libs/CMakeLists.txt | 59 + lib/event-libs/glib/CMakeLists.txt | 66 + lib/event-libs/libev/CMakeLists.txt | 76 + lib/event-libs/libevent/CMakeLists.txt | 61 + lib/event-libs/libuv/CMakeLists.txt | 69 + lib/event-libs/poll/CMakeLists.txt | 42 + lib/jose/CMakeLists.txt | 46 + lib/misc/CMakeLists.txt | 108 + lib/misc/threadpool/threadpool.c | 3 + lib/plat/freertos/CMakeLists.txt | 56 + lib/plat/optee/CMakeLists.txt | 49 + lib/plat/unix/CMakeLists.txt | 127 + lib/plat/windows/CMakeLists.txt | 103 + lib/roles/CMakeLists.txt | 88 + lib/roles/cgi/CMakeLists.txt | 42 + lib/roles/dbus/CMakeLists.txt | 62 + lib/roles/h1/CMakeLists.txt | 41 + lib/roles/h2/CMakeLists.txt | 44 + lib/roles/http/CMakeLists.txt | 90 + lib/roles/http/client/client-http.c | 2 + lib/roles/listen/CMakeLists.txt | 42 + lib/roles/mqtt/CMakeLists.txt | 48 + lib/roles/raw-file/CMakeLists.txt | 40 + lib/roles/raw-proxy/CMakeLists.txt | 42 + lib/roles/raw-skt/CMakeLists.txt | 46 + lib/roles/ws/CMakeLists.txt | 61 + lib/secure-streams/CMakeLists.txt | 129 + lib/system/CMakeLists.txt | 61 + lib/tls/CMakeLists.txt | 463 +++ lib/tls/mbedtls/CMakeLists.txt | 115 + lib/tls/mbedtls/lws-genaes.c | 2 + lib/tls/openssl/lws-genaes.c | 2 + lwsws/CMakeLists.txt | 61 + minimal-examples/CMakeLists.txt | 50 + .../protocols/smtp-client/CMakeLists.txt | 60 +- .../api-test-async-dns/CMakeLists.txt | 60 +- .../api-tests/api-test-dhcpc/CMakeLists.txt | 60 +- .../api-tests/api-test-fts/CMakeLists.txt | 60 +- .../api-test-gencrypto/CMakeLists.txt | 60 +- .../api-tests/api-test-jose/CMakeLists.txt | 60 +- .../api-tests/api-test-lws_dsh/CMakeLists.txt | 60 +- .../api-test-lws_sequencer/CMakeLists.txt | 60 +- .../api-test-lws_struct-json/CMakeLists.txt | 60 +- .../api-test-lws_struct_sqlite/CMakeLists.txt | 60 +- .../api-test-lws_tokenize/CMakeLists.txt | 60 +- .../api-tests/api-test-lwsac/CMakeLists.txt | 76 +- .../api-test-smtp_client/CMakeLists.txt | 60 +- .../minimal-ws-proxy/CMakeLists.txt | 61 +- .../crypto/minimal-crypto-jwe/CMakeLists.txt | 61 +- .../crypto/minimal-crypto-jwk/CMakeLists.txt | 61 +- .../crypto/minimal-crypto-jws/CMakeLists.txt | 60 +- .../crypto/minimal-crypto-x509/CMakeLists.txt | 60 +- .../minimal-dbus-client/CMakeLists.txt | 64 +- .../CMakeLists.txt | 67 +- .../minimal-dbus-server/CMakeLists.txt | 64 +- .../minimal-dbus-ws-proxy/CMakeLists.txt | 64 +- .../gtk/minimal-gtk/CMakeLists.txt | 61 +- .../minimal-http-client-attach/CMakeLists.txt | 83 +- .../CMakeLists.txt | 65 +- .../CMakeLists.txt | 64 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 61 +- .../minimal-http-client-multi/CMakeLists.txt | 62 +- .../minimal-http-client-post/CMakeLists.txt | 61 +- .../minimal-http-client/CMakeLists.txt | 64 +- .../CMakeLists.txt | 62 +- .../minimal-http-server-cgi/CMakeLists.txt | 64 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 63 +- .../CMakeLists.txt | 63 +- .../CMakeLists.txt | 65 +- .../CMakeLists.txt | 81 +- .../CMakeLists.txt | 63 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 64 +- .../CMakeLists.txt | 65 +- .../CMakeLists.txt | 64 +- .../CMakeLists.txt | 64 +- .../CMakeLists.txt | 62 +- .../minimal-http-server-proxy/CMakeLists.txt | 65 +- .../minimal-http-server-smp/CMakeLists.txt | 81 +- .../CMakeLists.txt | 76 - .../minimal-http-server-sse/CMakeLists.txt | 81 +- .../minimal-http-server-tls-80/CMakeLists.txt | 65 +- .../CMakeLists.txt | 65 +- .../minimal-http-server-tls/CMakeLists.txt | 65 +- .../minimal-http-server/CMakeLists.txt | 64 +- .../minimal-mqtt-client-multi/CMakeLists.txt | 63 +- .../minimal-mqtt-client/CMakeLists.txt | 61 +- .../raw/minimal-raw-adopt-tcp/CMakeLists.txt | 60 +- .../raw/minimal-raw-adopt-udp/CMakeLists.txt | 60 +- .../raw/minimal-raw-audio/CMakeLists.txt | 61 +- .../CMakeLists.txt | 62 +- .../raw/minimal-raw-file/CMakeLists.txt | 61 +- .../raw/minimal-raw-netcat/CMakeLists.txt | 60 +- .../minimal-raw-proxy-fallback/CMakeLists.txt | 60 +- .../raw/minimal-raw-proxy/CMakeLists.txt | 60 +- .../raw/minimal-raw-serial/CMakeLists.txt | 61 +- .../raw/minimal-raw-vhost/CMakeLists.txt | 60 +- .../CMakeLists.txt | 62 +- .../minimal-secure-streams-avs/CMakeLists.txt | 62 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 63 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 62 +- .../minimal-secure-streams-seq/CMakeLists.txt | 62 +- .../CMakeLists.txt | 62 +- .../CMakeLists.txt | 62 +- .../minimal-secure-streams/CMakeLists.txt | 62 +- .../minimal-ws-client-echo/CMakeLists.txt | 61 +- .../minimal-ws-client-ping/CMakeLists.txt | 79 +- .../minimal-ws-client-pmd-bulk/CMakeLists.txt | 61 +- .../minimal-ws-client-rx/CMakeLists.txt | 61 +- .../minimal-ws-client-spam/CMakeLists.txt | 79 +- .../minimal-ws-client-tx/CMakeLists.txt | 79 +- .../minimal-ws-client/CMakeLists.txt | 61 +- .../minimal-ws-broker/CMakeLists.txt | 60 +- .../minimal-ws-server-echo/CMakeLists.txt | 61 +- .../minimal-ws-server-pmd-bulk/CMakeLists.txt | 61 +- .../CMakeLists.txt | 61 +- .../minimal-ws-server-pmd/CMakeLists.txt | 61 +- .../minimal-ws-server-ring/CMakeLists.txt | 61 +- .../CMakeLists.txt | 79 +- .../CMakeLists.txt | 79 +- .../minimal-ws-server-threads/CMakeLists.txt | 79 +- .../minimal-ws-server-timer/CMakeLists.txt | 61 +- .../minimal-ws-server/CMakeLists.txt | 61 +- plugins/CMakeLists.txt | 222 ++ test-apps/CMakeLists.txt | 247 ++ test-apps/test-sshd.c | 2 +- 150 files changed, 4388 insertions(+), 8454 deletions(-) create mode 100644 CMakeLists-implied-options.txt delete mode 100644 cmake/FindLibWebSockets.cmake create mode 100644 cmake/LwsCheckRequirements.cmake rename cmake/{LibwebsocketsConfigVersion.cmake.in => libwebsockets-config-version.cmake.in} (100%) rename cmake/{LibwebsocketsConfig.cmake.in => libwebsockets-config.cmake.in} (100%) create mode 100644 lib/CMakeLists.txt create mode 100644 lib/abstract/CMakeLists.txt create mode 100644 lib/core-net/CMakeLists.txt create mode 100644 lib/core/CMakeLists.txt create mode 100644 lib/event-libs/CMakeLists.txt create mode 100644 lib/event-libs/glib/CMakeLists.txt create mode 100644 lib/event-libs/libev/CMakeLists.txt create mode 100644 lib/event-libs/libevent/CMakeLists.txt create mode 100644 lib/event-libs/libuv/CMakeLists.txt create mode 100644 lib/event-libs/poll/CMakeLists.txt create mode 100644 lib/jose/CMakeLists.txt create mode 100644 lib/misc/CMakeLists.txt create mode 100644 lib/plat/freertos/CMakeLists.txt create mode 100644 lib/plat/optee/CMakeLists.txt create mode 100644 lib/plat/unix/CMakeLists.txt create mode 100644 lib/plat/windows/CMakeLists.txt create mode 100644 lib/roles/CMakeLists.txt create mode 100644 lib/roles/cgi/CMakeLists.txt create mode 100644 lib/roles/dbus/CMakeLists.txt create mode 100644 lib/roles/h1/CMakeLists.txt create mode 100644 lib/roles/h2/CMakeLists.txt create mode 100644 lib/roles/http/CMakeLists.txt create mode 100644 lib/roles/listen/CMakeLists.txt create mode 100644 lib/roles/mqtt/CMakeLists.txt create mode 100644 lib/roles/raw-file/CMakeLists.txt create mode 100644 lib/roles/raw-proxy/CMakeLists.txt create mode 100644 lib/roles/raw-skt/CMakeLists.txt create mode 100644 lib/roles/ws/CMakeLists.txt create mode 100644 lib/secure-streams/CMakeLists.txt create mode 100644 lib/system/CMakeLists.txt create mode 100644 lib/tls/CMakeLists.txt create mode 100644 lib/tls/mbedtls/CMakeLists.txt create mode 100644 lwsws/CMakeLists.txt create mode 100644 minimal-examples/CMakeLists.txt create mode 100644 plugins/CMakeLists.txt create mode 100644 test-apps/CMakeLists.txt diff --git a/.gitignore b/.gitignore index bdbdb429..2919ceaf 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,4 @@ doc /bb-linkit/ /bq/ /cros/ +/q/ diff --git a/CMakeLists-implied-options.txt b/CMakeLists-implied-options.txt new file mode 100644 index 00000000..258073e8 --- /dev/null +++ b/CMakeLists-implied-options.txt @@ -0,0 +1,381 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# This part of the CMakeLists.txt defines internal logic between options + +if(IOS) + set(LWS_DETECTED_PLAT_IOS 1) +endif() + +# Workaround for ESP-IDF +# Detect ESP_PLATFORM environment flag, if exist, set LWS_WITH_ESP32. +# Otherwise the user may not be able to run configuration ESP-IDF in the first time. +if(ESP_PLATFORM) + message(STATUS "ESP-IDF enabled") + set(LWS_WITH_ESP32 ON) + set(LWS_WITH_ZLIB OFF) +else() + set(LWS_WITH_ESP32_HELPER OFF) +endif() + +if (LWS_WITH_ESP32) + set(LWS_PLAT_FREERTOS 1) +endif() + +if (LWS_PLAT_FREERTOS OR LWS_PLAT_OPTEE) + set(LWS_WITH_UDP 0) +endif() + +if (LWS_PLAT_FREERTOS) + message(STATUS "No LWS_WITH_DIR or LWS_WITH_LEJP_CONF") + set(LWS_WITH_DIR OFF) + set(LWS_WITH_LEJP_CONF OFF) + message("LWS_WITH_DIR ${LWS_WITH_DIR}") +else() + message(STATUS "Compiled with LWS_WITH_DIR and LWS_WITH_LEJP_CONF") + set(LWS_WITH_DIR ON) + set(LWS_WITH_LEJP_CONF ON) +endif() + +if (LWS_FOR_GITOHASHI) + set(LWS_WITH_THREADPOOL 1) + set(LWS_WITH_HTTP2 1) + set(LWS_UNIX_SOCK 1) + set(LWS_WITH_HTTP_PROXY 1) + set(LWS_WITH_FTS 1) + set(LWS_WITH_DISKCACHE 1) + set(LWS_WITH_LWSAC 1) + set(LWS_WITH_LEJP_CONF 1) + set(LWS_WITH_SPAWN 1) + set(LWS_WITH_FSMOUNT 1) + set(LWS_WITH_STRUCT_JSON 1) + set(LWS_WITH_STRUCT_SQLITE3 1) +endif() + +if(LWS_WITH_DISTRO_RECOMMENDED) + set(LWS_WITH_HTTP2 1) + set(LWS_WITH_LWSWS 1) + set(LWS_WITH_CGI 1) + set(LWS_IPV6 1) + set(LWS_WITH_ZIP_FOPS 1) + set(LWS_WITH_SOCKS5 1) + set(LWS_WITH_RANGES 1) + set(LWS_WITH_ACME 1) + set(LWS_WITH_SERVER_STATUS 1) + set(LWS_WITH_GLIB 1) + set(LWS_WITH_LIBUV 1) + set(LWS_WITH_LIBEV 1) + # libev + libevent cannot coexist at build-time + set(LWS_WITH_LIBEVENT 0) + set(LWS_WITHOUT_EXTENSIONS 0) + set(LWS_ROLE_DBUS 1) + set(LWS_WITH_FTS 1) + set(LWS_WITH_THREADPOOL 1) + set(LWS_UNIX_SOCK 1) + set(LWS_WITH_HTTP_PROXY 1) + set(LWS_WITH_DISKCACHE 1) + set(LWS_WITH_LWSAC 1) + set(LWS_WITH_LEJP_CONF 1) + set(LWS_WITH_PLUGINS 1) + set(LWS_ROLE_RAW_PROXY 1) + set(LWS_WITH_GENCRYPTO 1) + set(LWS_WITH_JOSE 1) + set(LWS_WITH_STRUCT_JSON 1) + set(LWS_WITH_STRUCT_SQLITE3 1) + set(LWS_WITH_SPAWN 1) +# libmount is problematic on Centos 8 / RHEL 8 +# set(LWS_WITH_FSMOUNT 1) + set(LWS_ROLE_MQTT 1) + set(LWS_WITH_SECURE_STREAMS 1) + set(LWS_WITH_SECURE_STREAMS_PROXY_API 1) + set(LWS_WITH_DIR 1) +endif() + +if (LWS_WITH_SECURE_STREAMS_PROXY_API) + set(LWS_WITH_LWS_DSH 1) + set(LWS_WITH_UNIX_SOCK 1) +endif() + +if (NOT LWS_WITH_NETWORK) + set(LWS_ROLE_MQTT 0) + set(LWS_ROLE_H1 0) + set(LWS_ROLE_WS 0) + set(LWS_ROLE_RAW 0) + set(LWS_WITHOUT_EXTENSIONS 1) + set(LWS_WITHOUT_SERVER 1) + set(LWS_WITHOUT_CLIENT 1) + set(LWS_WITH_HTTP2 0) + set(LWS_WITH_SOCKS5 0) + set(LWS_UNIX_SOCK 0) + set(LWS_WITH_HTTP_PROXY 0) + set(LWS_WITH_PLUGINS 0) + set(LWS_WITH_LWSWS 0) + set(LWS_WITH_CGI 0) + set(LWS_ROLE_RAW_PROXY 0) + set(LWS_WITH_PEER_LIMITS 0) + set(LWS_WITH_GENERIC_SESSIONS 0) + set(LWS_WITH_HTTP_STREAM_COMPRESSION 0) + set(LWS_WITH_HTTP_BROTLI 0) + set(LWS_WITH_POLL 0) + set(LWS_WITH_SEQUENCER 0) + set(LWS_ROLE_DBUS 0) + set(LWS_WITH_LWS_DSH 0) + set(LWS_WITH_THREADPOOL 0) +endif() + +if (LWS_WITH_CGI) + set(LWS_WITH_SPAWN 1) +endif() + +if (LWS_WITH_STRUCT_SQLITE3) + set(LWS_WITH_SQLITE3 1) +endif() + +if (LWS_WITH_HTTP_BASIC_AUTH) + # WWW_AUTHENTICATE used by basic auth is an "uncommon header" + set(LWS_WITH_HTTP_UNCOMMON_HEADERS 1) +endif() + +if (APPLE) + set(LWS_ROLE_DBUS 0) +endif() + +if(NOT DEFINED CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type") +endif() + +# microsoft... that's why you can't have nice things + +if (WIN32 OR LWS_PLAT_FREERTOS) + set(LWS_UNIX_SOCK 0) +endif() + +if (LWS_PLAT_FREERTOS) + set(LWS_WITH_LWSAC 0) + set(LWS_WITH_FTS 0) +endif() + +if (LWS_WITH_HTTP2) + set(LWS_ROLE_H2 1) +endif() +if (LWS_WITH_CGI) + set(LWS_ROLE_CGI 1) +endif() + +if (NOT LWS_ROLE_WS) + set(LWS_WITHOUT_EXTENSIONS 1) +endif() + +if (LWS_WITH_LWSWS) + message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV") + set(LWS_WITH_PLUGINS 1) + set(LWS_WITH_LIBUV 1) + set(LWS_WITH_ACCESS_LOG 1) + set(LWS_WITH_SERVER_STATUS 1) + set(LWS_WITH_LEJP 1) + set(LWS_WITH_LEJP_CONF 1) + set(LWS_WITH_PEER_LIMITS 1) + set(LWS_ROLE_RAW_PROXY 1) +endif() + +# sshd plugin +if (LWS_WITH_PLUGINS) + set(LWS_WITH_GENCRYPTO 1) +endif() + +if (LWS_ROLE_RAW_PROXY) + set (LWS_WITH_CLIENT 1) + set (LWS_WITH_SERVER 1) +endif() + +if (LWS_WITH_ACME) + set (LWS_WITH_CLIENT 1) + set (LWS_WITH_SERVER 1) + set (LWS_WITH_JOSE 1) +endif() + +if (LWS_WITH_JOSE) + set(LWS_WITH_LEJP 1) + set(LWS_WITH_GENCRYPTO 1) +endif() + +if (LWS_WITH_PLUGINS AND NOT LWS_WITH_LIBUV) +message(STATUS "LWS_WITH_PLUGINS --> Enabling LWS_WITH_LIBUV") + set(LWS_WITH_LIBUV 1) +endif() + +if (LWS_WITH_PLUGINS OR LWS_WITH_CGI) + # sshd plugin + set(LWS_WITH_GENCRYPTO 1) +endif() + +if (LWS_WITH_GENERIC_SESSIONS) + set(LWS_WITH_SQLITE3 1) + # set(LWS_WITH_SMTP 1) + set(LWS_WITH_STRUCT_SQLITE3 1) +endif() + +if (LWS_PLAT_FREERTOS) + set(LWS_WITH_SHARED OFF) + set(LWS_WITH_MBEDTLS ON) + # set(LWS_WITHOUT_CLIENT ON) + set(LWS_WITHOUT_TESTAPPS ON) + set(LWS_WITHOUT_EXTENSIONS ON) + set(LWS_WITH_PLUGINS OFF) + set(LWS_WITH_RANGES ON) + # this implies no pthreads in the lib + set(LWS_MAX_SMP 1) + set(LWS_HAVE_MALLOC 1) + set(LWS_HAVE_REALLOC 1) + set(LWS_HAVE_GETIFADDRS 1) + set(LWS_WITH_CUSTOM_HEADERS 0) +endif() + +#if (LWS_WITH_ESP32) +# set(LWS_WITH_ZIP_FOPS 1) +#endif() + +if (WIN32) +set(LWS_MAX_SMP 1) +endif() + +if (LWS_WITHOUT_SERVER) +set(LWS_WITH_LWSWS OFF) +endif() + +if (LWS_WITH_LEJP_CONF) + set(LWS_WITH_DIR 1) +endif() + +# confirm H1 relationships + +if (NOT LWS_ROLE_H1 AND LWS_ROLE_H2) + message(FATAL_ERROR "H2 requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND LWS_ROLE_WS) + message(FATAL_ERROR "WS requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND LWS_ROLE_CGI) + message(FATAL_ERROR "CGI requires LWS_ROLE_H1") +endif() + +# confirm HTTP relationships + +if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY) + message(FATAL_ERROR "LWS_WITH_LWSWS requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY) + message(FATAL_ERROR "LWS_WITH_HTTP_PROXY requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_RANGES) + message(FATAL_ERROR "LWS_WITH_RANGES requires LWS_ROLE_H1") +endif() + +if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_ACCESS_LOG) + message(FATAL_ERROR "LWS_WITH_ACCESS_LOG requires LWS_ROLE_H1") +endif() + +if (LWS_WITH_HTTP_PROXY AND (LWS_WITHOUT_CLIENT OR LWS_WITHOUT_SERVER)) + message("You have to enable both client and server for http proxy") + set(LWS_WITH_HTTP_PROXY 0) +endif() + +if (NOT LWS_WITHOUT_EXTENSIONS OR LWS_WITH_ZIP_FOPS) + set(LWS_WITH_ZLIB 1) +endif() + +if (LWS_WITH_SECURE_STREAMS) + set(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM 1) +endif() + +if (NOT (LWS_WITH_STATIC OR LWS_WITH_SHARED)) + message(FATAL_ERROR "Makes no sense to compile with neither static nor shared libraries.") +endif() + +if (LWS_WITHOUT_DAEMONIZE OR WIN32) + set(LWS_NO_DAEMONIZE 1) +endif() + +if (LWS_WITH_LIBEV) + set(LWS_WITH_LIBEV 1) +endif() + +if (LWS_WITH_LIBUV) + set(LWS_WITH_LIBUV 1) +endif() + +if (LWS_WITH_LIBEVENT) + set(LWS_WITH_LIBEVENT 1) +endif() + +if (LWS_IPV6) + set(LWS_WITH_IPV6 1) +endif() + +if (LWS_UNIX_SOCK) + set(LWS_WITH_UNIX_SOCK 1) +endif() + +if (NOT LWS_MAX_SMP) + set(LWS_MAX_SMP 1) +endif() +if ("${LWS_MAX_SMP}" STREQUAL "") + set(LWS_MAX_SMP 1) +endif() + +set(LWS_WITH_CLIENT 1) +if (LWS_WITHOUT_CLIENT) + set(LWS_WITH_CLIENT) +endif() +set(LWS_WITH_SERVER 1) +if (LWS_WITHOUT_SERVER) + set(LWS_WITH_SERVER) +endif() + +# using any abstract protocol enables LWS_WITH_ABSTRACT + +#if (LWS_WITH_SMTP) +# set(LWS_WITH_ABSTRACT 1) +#endif() + +if (LWS_WITH_LIBEV AND LWS_WITH_LIBEVENT) + message(FATAL_ERROR "Sorry libev and libevent conflict with each others' namespace, you can only have one or the other") +endif() + +if (LWS_SSL_SERVER_WITH_ECDH_CERT) + set(LWS_SSL_SERVER_WITH_ECDH_CERT 1) +endif() + +# LWS_OPENSSL_SUPPORT deprecated... use LWS_WITH_TLS +if (LWS_WITH_SSL OR LWS_WITH_MBEDTLS) + set(LWS_OPENSSL_SUPPORT 1) + set(LWS_WITH_TLS 1) +endif() + +if (NOT LWS_WITH_SSL) + set(LWS_WITHOUT_BUILTIN_SHA1 OFF PARENT_SCOPE) +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 7eb5b7dd..e817c378 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,42 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# + cmake_minimum_required(VERSION 2.8.9) +include(CheckFunctionExists) +include(CheckSymbolExists) +include(CheckIncludeFile) +include(CheckIncludeFiles) +include(CheckLibraryExists) +include(CheckTypeSize) +include(CheckCSourceCompiles) if(POLICY CMP0048) cmake_policy(SET CMP0048 NEW) endif() +#cmake_policy(SET CMP0076 NEW) + # General Advice # # For selecting between DEBUG / RELEASE, use -DCMAKE_BUILD_TYPE=DEBUG or =RELEASE @@ -17,11 +50,12 @@ endif() set(LWS_ROLE_RAW 1) set(LWS_WITH_POLL 1) -if(ESP_PLATFORM) +if (ESP_PLATFORM) set(LWS_ESP_PLATFORM 1) set(CMAKE_TOOLCHAIN_FILE contrib/cross-esp32.cmake) set(LWIP_PROVIDE_ERRNO 1) endif() + # it's at this point any toolchain file is brought in project(libwebsockets C) include(CTest) @@ -198,160 +232,42 @@ option(LWS_HTTP_HEADERS_ALL "Override header reduction optimization and include # End of user settings # -if(IOS) - set(LWS_DETECTED_PLAT_IOS 1) -endif() - -# Workaround for ESP-IDF -# Detect ESP_PLATFORM environment flag, if exist, set LWS_WITH_ESP32. -# Otherwise the user may not be able to run configuration ESP-IDF in the first time. -if(ESP_PLATFORM) - message(STATUS "ESP-IDF enabled") - set(LWS_WITH_ESP32 ON) - set(LWS_WITH_ZLIB OFF) -else() - set(LWS_WITH_ESP32_HELPER OFF) -endif() - -if (LWS_WITH_ESP32) - set(LWS_PLAT_FREERTOS 1) -endif() - -if (LWS_PLAT_FREERTOS OR LWS_PLAT_OPTEE) - set(LWS_WITH_UDP 0) -endif() - -if (LWS_PLAT_FREERTOS) - message(STATUS "No LWS_WITH_DIR or LWS_WITH_LEJP_CONF") - set(LWS_WITH_DIR OFF) - set(LWS_WITH_LEJP_CONF OFF) - message("LWS_WITH_DIR ${LWS_WITH_DIR}") -else() - message(STATUS "Compiled with LWS_WITH_DIR and LWS_WITH_LEJP_CONF") - set(LWS_WITH_DIR ON) - set(LWS_WITH_LEJP_CONF ON) -endif() - -if (LWS_FOR_GITOHASHI) - set(LWS_WITH_THREADPOOL 1) - set(LWS_WITH_HTTP2 1) - set(LWS_UNIX_SOCK 1) - set(LWS_WITH_HTTP_PROXY 1) - set(LWS_WITH_FTS 1) - set(LWS_WITH_DISKCACHE 1) - set(LWS_WITH_LWSAC 1) - set(LWS_WITH_LEJP_CONF 1) - set(LWS_WITH_SPAWN 1) - set(LWS_WITH_FSMOUNT 1) - set(LWS_WITH_STRUCT_JSON 1) - set(LWS_WITH_STRUCT_SQLITE3 1) -endif() - -if(LWS_WITH_DISTRO_RECOMMENDED) - set(LWS_WITH_HTTP2 1) - set(LWS_WITH_LWSWS 1) - set(LWS_WITH_CGI 1) - set(LWS_IPV6 1) - set(LWS_WITH_ZIP_FOPS 1) - set(LWS_WITH_SOCKS5 1) - set(LWS_WITH_RANGES 1) - set(LWS_WITH_ACME 1) - set(LWS_WITH_SERVER_STATUS 1) - set(LWS_WITH_GLIB 1) - set(LWS_WITH_LIBUV 1) - set(LWS_WITH_LIBEV 1) - # libev + libevent cannot coexist at build-time - set(LWS_WITH_LIBEVENT 0) - set(LWS_WITHOUT_EXTENSIONS 0) - set(LWS_ROLE_DBUS 1) - set(LWS_WITH_FTS 1) - set(LWS_WITH_THREADPOOL 1) - set(LWS_UNIX_SOCK 1) - set(LWS_WITH_HTTP_PROXY 1) - set(LWS_WITH_DISKCACHE 1) - set(LWS_WITH_LWSAC 1) - set(LWS_WITH_LEJP_CONF 1) - set(LWS_WITH_PLUGINS 1) - set(LWS_ROLE_RAW_PROXY 1) - set(LWS_WITH_GENCRYPTO 1) - set(LWS_WITH_JOSE 1) - set(LWS_WITH_STRUCT_JSON 1) - set(LWS_WITH_STRUCT_SQLITE3 1) - set(LWS_WITH_SPAWN 1) -# libmount is problematic on Centos 8 / RHEL 8 -# set(LWS_WITH_FSMOUNT 1) - set(LWS_ROLE_MQTT 1) - set(LWS_WITH_SECURE_STREAMS 1) - set(LWS_WITH_SECURE_STREAMS_PROXY_API 1) - set(LWS_WITH_DIR 1) -endif() - -if (LWS_WITH_SECURE_STREAMS_PROXY_API) - set(LWS_WITH_LWS_DSH 1) - set(LWS_WITH_UNIX_SOCK 1) -endif() - -if (NOT LWS_WITH_NETWORK) - set(LWS_ROLE_MQTT 0) - set(LWS_ROLE_H1 0) - set(LWS_ROLE_WS 0) - set(LWS_ROLE_RAW 0) - set(LWS_WITHOUT_EXTENSIONS 1) - set(LWS_WITHOUT_SERVER 1) - set(LWS_WITHOUT_CLIENT 1) - set(LWS_WITH_HTTP2 0) - set(LWS_WITH_SOCKS5 0) - set(LWS_UNIX_SOCK 0) - set(LWS_WITH_HTTP_PROXY 0) - set(LWS_WITH_PLUGINS 0) - set(LWS_WITH_LWSWS 0) - set(LWS_WITH_CGI 0) - set(LWS_ROLE_RAW_PROXY 0) - set(LWS_WITH_PEER_LIMITS 0) - set(LWS_WITH_GENERIC_SESSIONS 0) - set(LWS_WITH_HTTP_STREAM_COMPRESSION 0) - set(LWS_WITH_HTTP_BROTLI 0) - set(LWS_WITH_POLL 0) - set(LWS_WITH_SEQUENCER 0) - set(LWS_ROLE_DBUS 0) - set(LWS_WITH_LWS_DSH 0) - set(LWS_WITH_THREADPOOL 0) -endif() - -if (LWS_WITH_CGI) - set(LWS_WITH_SPAWN 1) -endif() - -if (LWS_WITH_STRUCT_SQLITE3) - set(LWS_WITH_SQLITE3 1) -endif() - -if (LWS_WITH_HTTP_BASIC_AUTH) - # WWW_AUTHENTICATE used by basic auth is an "uncommon header" - set(LWS_WITH_HTTP_UNCOMMON_HEADERS 1) -endif() - -if (APPLE) - set(LWS_ROLE_DBUS 0) -endif() +# sets of sub-options implied by other options +# +set(LIB_LIST) +set(LIB_LIST_AT_END) +set(LWS_LIBRARIES) +set(LWS_OPENSSL_SUPPORT 0) +include(CMakeLists-implied-options.txt) -if(NOT DEFINED CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type") -endif() +# +# Structural helpers for cmake in subdirs +# -# microsoft... that's why you can't have nice things +macro(add_subdir_include_directories arg1) + add_subdirectory(${arg1}) + include_directories(${_CMAKE_INC_LIST}) +endmacro() -if (WIN32 OR LWS_PLAT_FREERTOS) - set(LWS_UNIX_SOCK 0) -endif() +macro(exports_to_parent_scope) + set(SOURCES ${SOURCES} PARENT_SCOPE) + set(LIB_LIST ${LIB_LIST} PARENT_SCOPE) + get_property(_CURR DIRECTORY PROPERTY INCLUDE_DIRECTORIES) + set(_CMAKE_INC_LIST ${_CURR} PARENT_SCOPE) + set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE) +endmacro() -if (LWS_PLAT_FREERTOS) - set(LWS_WITH_LWSAC 0) - set(LWS_WITH_FTS 0) -endif() +macro(export_to_parent_intermediate) + set(SOURCES ${SOURCES} PARENT_SCOPE) + set(LIB_LIST ${LIB_LIST} PARENT_SCOPE) + set(_CMAKE_INC_LIST ${_CMAKE_INC_LIST} PARENT_SCOPE) + set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE) +endmacro() +# +# Try to find the current Git hash +# -# Try to find the current Git hash. find_package(Git) if(GIT_EXECUTABLE) execute_process( @@ -363,7 +279,7 @@ if(GIT_EXECUTABLE) set(LWS_BUILD_HASH ${GIT_HASH}) # append the build user and hostname - if(NOT LWS_REPRODUCIBLE) + if (NOT LWS_REPRODUCIBLE) execute_process( WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMAND "whoami" @@ -438,169 +354,12 @@ if (NOT LIB_SUFFIX) set(LIB_SUFFIX "") endif() -if(WIN32) +if (WIN32) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/win32port/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/win32port/version.rc @ONLY) set(RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/win32port/version.rc) endif() -if (LWS_WITH_HTTP2) - set(LWS_ROLE_H2 1) -endif() -if (LWS_WITH_CGI) - set(LWS_ROLE_CGI 1) -endif() - -if (NOT LWS_ROLE_WS) - set(LWS_WITHOUT_EXTENSIONS 1) -endif() - -if (LWS_WITH_MBEDTLS) - include_directories(lib/tls/mbedtls/wrapper/include) -endif() - -include_directories(include plugins lib/core lib/core-net lib/event-libs include/abstract lib/tls lib/roles lib/event-libs/libuv lib/event-libs/poll lib/event-libs/libevent lib/event-libs/glib lib/event-libs/libev lib/jose/jwe lib/jose/jws lib/jose lib/misc lib/roles/http lib/roles/http/compression lib/roles/h1 lib/roles/h2 lib/roles/ws lib/roles/cgi lib/roles/dbus lib/roles/raw-proxy lib/abstract lib/system/async-dns lib/roles/mqtt) - -if (ESP_PLATFORM) - include_directories($ENV{IDF_PATH}/components/freertos/include $ENV{IDF_PATH}/components/freertos/xtensa/include $ENV{IDF_PATH}/components/xtensa/include $ENV{IDF_PATH}/components/xtensa/esp32/include $ENV{IDF_PATH}/components/esp_common/include $ENV{IDF_PATH}/components/esp_timer/include $ENV{IDF_PATH}/components/soc/include $ENV{IDF_PATH}/components/soc/src/esp32/include $ENV{IDF_PATH}/components/lwip/port/esp32/include $ENV{IDF_PATH}/components/lwip/lwip/src/include $ENV{IDF_PATH}/components/lwip/port/esp32/include ${CMAKE_BINARY_DIR}/config $ENV{IDF_PATH}/components/esp_rom/include $ENV{IDF_PATH}/components/esp_system/include $ENV{IDF_PATH}/components/lwip/include/apps/sntp $ENV{IDF_PATH}/components/soc/soc/esp32/include $ENV{IDF_PATH}/components/heap/include $ENV{IDF_PATH}/components/mbedtls/mbedtls/include $ENV{IDF_PATH}/components/mbedtls/port/include $ENV{IDF_PATH}/components/esp_wifi/include $ENV{IDF_PATH}/components/esp_event/include $ENV{IDF_PATH}/components/esp_netif/include $ENV{IDF_PATH}/components/esp_eth/include $ENV{IDF_PATH}/components/driver/include $ENV{IDF_PATH}/components/soc/soc/include $ENV{IDF_PATH}/components/tcpip_adapter/include $ENV{IDF_PATH}/components/lwip/include/apps $ENV{IDF_PATH}/components/nvs_flash/include $ENV{IDF_PATH}/components/esp32/include $ENV{IDF_PATH}/components/spi_flash/include $ENV{IDF_PATH}/components/mdns/include $ENV{IDF_PATH}/components/lwip/lwip/src/include/lwip $ENV{IDF_PATH}/components/lwip/lwip/src/include $ENV{IDF_PATH}/components/lwip/lwip/src/include/lwip $ENV{IDF_PATH}/components/newlib/platform_include ) -endif() - -if (LWS_WITH_SECURE_STREAMS) - set(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM 1) -endif() - -if (LWS_PLAT_FREERTOS) - include_directories(lib/plat/freertos lib/plat/freertos/esp32) -else() - if (WIN32) - include_directories(lib/plat/windows) - else() - if (LWS_WITH_OPTEE) - include_directories(lib/plat/optee) - else() - include_directories(lib/plat/unix) - endif() - endif() -endif() - - -if (LWS_WITH_LWSWS) - message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV") - set(LWS_WITH_PLUGINS 1) - set(LWS_WITH_LIBUV 1) - set(LWS_WITH_ACCESS_LOG 1) - set(LWS_WITH_SERVER_STATUS 1) - set(LWS_WITH_LEJP 1) - set(LWS_WITH_LEJP_CONF 1) - set(LWS_WITH_PEER_LIMITS 1) - set(LWS_ROLE_RAW_PROXY 1) -endif() - -# sshd plugin -if (LWS_WITH_PLUGINS) - set(LWS_WITH_GENCRYPTO 1) -endif() - -if (LWS_ROLE_RAW_PROXY) - set (LWS_WITH_CLIENT 1) - set (LWS_WITH_SERVER 1) -endif() - -if (LWS_WITH_ACME) - set (LWS_WITH_CLIENT 1) - set (LWS_WITH_SERVER 1) - set (LWS_WITH_JOSE 1) -endif() - -if (LWS_WITH_JOSE) - set(LWS_WITH_LEJP 1) - set(LWS_WITH_GENCRYPTO 1) -endif() - -if (LWS_WITH_PLUGINS AND NOT LWS_WITH_LIBUV) -message(STATUS "LWS_WITH_PLUGINS --> Enabling LWS_WITH_LIBUV") - set(LWS_WITH_LIBUV 1) -endif() - -if (LWS_WITH_PLUGINS OR LWS_WITH_CGI) - # sshd plugin - set(LWS_WITH_GENCRYPTO 1) -endif() - -if (LWS_WITH_GENERIC_SESSIONS) - set(LWS_WITH_SQLITE3 1) - # set(LWS_WITH_SMTP 1) - set(LWS_WITH_STRUCT_SQLITE3 1) -endif() - -if (LWS_PLAT_FREERTOS) - set(LWS_WITH_SHARED OFF) - set(LWS_WITH_MBEDTLS ON) - # set(LWS_WITHOUT_CLIENT ON) - set(LWS_WITHOUT_TESTAPPS ON) - set(LWS_WITHOUT_EXTENSIONS ON) - set(LWS_WITH_PLUGINS OFF) - set(LWS_WITH_RANGES ON) - # this implies no pthreads in the lib - set(LWS_MAX_SMP 1) - set(LWS_HAVE_MALLOC 1) - set(LWS_HAVE_REALLOC 1) - set(LWS_HAVE_GETIFADDRS 1) - set(LWS_WITH_CUSTOM_HEADERS 0) -endif() - -#if (LWS_WITH_ESP32) -# set(LWS_WITH_ZIP_FOPS 1) -#endif() - -if (WIN32) -set(LWS_MAX_SMP 1) -endif() - -if (LWS_WITHOUT_SERVER) -set(LWS_WITH_LWSWS OFF) -endif() - -if (LWS_WITH_LEJP_CONF) - set(LWS_WITH_DIR 1) -endif() - -# confirm H1 relationships - -if (NOT LWS_ROLE_H1 AND LWS_ROLE_H2) - message(FATAL_ERROR "H2 requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND LWS_ROLE_WS) - message(FATAL_ERROR "WS requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND LWS_ROLE_CGI) - message(FATAL_ERROR "CGI requires LWS_ROLE_H1") -endif() - -# confirm HTTP relationships - -if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY) - message(FATAL_ERROR "LWS_WITH_LWSWS requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_HTTP_PROXY) - message(FATAL_ERROR "LWS_WITH_HTTP_PROXY requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_RANGES) - message(FATAL_ERROR "LWS_WITH_RANGES requires LWS_ROLE_H1") -endif() - -if (NOT LWS_ROLE_H1 AND NOT LWS_ROLE_H2 AND LWS_WITH_ACCESS_LOG) - message(FATAL_ERROR "LWS_WITH_ACCESS_LOG requires LWS_ROLE_H1") -endif() - - -if (LWS_WITH_HTTP_PROXY AND (LWS_WITHOUT_CLIENT OR LWS_WITHOUT_SERVER)) - message("You have to enable both client and server for http proxy") - set(LWS_WITH_HTTP_PROXY 0) -endif() +include_directories(include) # Allow the user to override installation directories. set(LWS_INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") @@ -608,44 +367,13 @@ set(LWS_INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executa set(LWS_INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") set(LWS_INSTALL_EXAMPLES_DIR bin CACHE PATH "Installation directory for example files") -# Allow the user to use the old CyaSSL options/library in stead of wolfSSL -if (LWS_WITH_CYASSL AND LWS_WITH_WOLFSSL) - message(FATAL_ERROR "LWS_WITH_CYASSL and LWS_WITH_WOLFSSL are mutually exclusive!") -endif() -if (LWS_WITH_CYASSL) - # Copy CyaSSL options to the wolfSSL options - set(LWS_WITH_WOLFSSL ${LWS_WITH_CYASSL} CACHE BOOL "Use wolfSSL/CyaSSL instead of OpenSSL" FORCE) - set(LWS_WOLFSSL_LIBRARIES ${LWS_CYASSL_LIBRARIES} CACHE PATH "Path to wolfSSL/CyaSSL libraries" FORCE) - set(LWS_WOLFSSL_INCLUDE_DIRS ${LWS_CYASSL_INCLUDE_DIRS} CACHE PATH "Path to wolfSSL/CyaSSL header files" FORCE) -endif() - -if (NOT (LWS_WITH_STATIC OR LWS_WITH_SHARED)) - message(FATAL_ERROR "Makes no sense to compile with neither static nor shared libraries.") -endif() - -if (NOT LWS_WITHOUT_EXTENSIONS OR LWS_WITH_ZIP_FOPS) - set(LWS_WITH_ZLIB 1) -endif() - # if you gave LWS_WITH_MINIZ, point to MINIZ here if not found # automatically set(LWS_ZLIB_LIBRARIES CACHE PATH "Path to the zlib/miniz library") set(LWS_ZLIB_INCLUDE_DIRS CACHE PATH "Path to the zlib/miniz include directory") -set(LWS_OPENSSL_LIBRARIES CACHE PATH "Path to the OpenSSL library") -set(LWS_OPENSSL_INCLUDE_DIRS CACHE PATH "Path to the OpenSSL include directory") -set(LWS_WOLFSSL_LIBRARIES CACHE PATH "Path to the wolfSSL library") -set(LWS_WOLFSSL_INCLUDE_DIRS CACHE PATH "Path to the wolfSSL include directory") -set(LWS_LIBEV_LIBRARIES CACHE PATH "Path to the libev library") -set(LWS_LIBEV_INCLUDE_DIRS CACHE PATH "Path to the libev include directory") -set(LWS_LIBUV_LIBRARIES CACHE PATH "Path to the libuv library") -set(LWS_LIBUV_INCLUDE_DIRS CACHE PATH "Path to the libuv include directory") set(LWS_SQLITE3_LIBRARIES CACHE PATH "Path to the sqlite3 library") set(LWS_SQLITE3_INCLUDE_DIRS CACHE PATH "Path to the sqlite3 include directory") -set(LWS_LIBEVENT_INCLUDE_DIRS CACHE PATH "Path to the libevent include directory") -set(LWS_LIBEVENT_LIBRARIES CACHE PATH "Path to the libevent library") -set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory") -set(LWS_GLIB_LIBRARIES CACHE PATH "Path to the glib library") set(LWS_LIBMOUNT_INCLUDE_DIRS CACHE PATH "Path to the libmount include directory") set(LWS_LIBMOUNT_LIBRARIES CACHE PATH "Path to the libmount library") # on unix, these are in the toolchain. On win32 you have to put them somewhere @@ -654,95 +382,10 @@ set(LWS_EXT_PTHREAD_INCLUDE_DIR CACHE PATH "Path to an external pthreads include set(LWS_EXT_PTHREAD_LIBRARIES CACHE PATH "Path to an external pthreads library") -if (NOT LWS_WITH_SSL) - set(LWS_WITHOUT_BUILTIN_SHA1 OFF) -endif() - -if (LWS_WITH_BORINGSSL) - # boringssl deprecated EVP_PKEY - set (LWS_WITH_GENHASH OFF) -endif() - -if (LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL AND NOT LWS_WITH_MBEDTLS) - if ("${LWS_OPENSSL_LIBRARIES}" STREQUAL "" OR "${LWS_OPENSSL_INCLUDE_DIRS}" STREQUAL "") - else() - if (NOT LWS_PLAT_FREERTOS) - set(OPENSSL_LIBRARIES ${LWS_OPENSSL_LIBRARIES}) - endif() - set(OPENSSL_INCLUDE_DIRS ${LWS_OPENSSL_INCLUDE_DIRS}) - set(OPENSSL_FOUND 1) - endif() -endif() - -if (LWS_WITH_SSL AND LWS_WITH_WOLFSSL) - if ("${LWS_WOLFSSL_LIBRARIES}" STREQUAL "" OR "${LWS_WOLFSSL_INCLUDE_DIRS}" STREQUAL "") - if (NOT WOLFSSL_FOUND) - if (LWS_WITH_CYASSL) - message(FATAL_ERROR "You must set LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS when LWS_WITH_CYASSL is turned on.") - else() - message(FATAL_ERROR "You must set LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS when LWS_WITH_WOLFSSL is turned on.") - endif() - endif() - else() - set(WOLFSSL_LIBRARIES ${LWS_WOLFSSL_LIBRARIES}) - set(WOLFSSL_INCLUDE_DIRS ${LWS_WOLFSSL_INCLUDE_DIRS}) - set(WOLFSSL_FOUND 1) - endif() - set(USE_WOLFSSL 1) - set(LWS_WITH_TLS 1) - if (LWS_WITH_CYASSL) - set(USE_OLD_CYASSL 1) - endif() -endif() - -if (LWS_WITH_SSL AND LWS_WITH_MBEDTLS) - if ((NOT LWS_MBEDTLS_LIBRARIES OR "${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR NOT LWS_MBEDTLS_INCLUDE_DIRS OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "") AND NOT LWS_PLAT_FREERTOS) - - find_path(LWS_MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) - - find_library(MBEDTLS_LIBRARY mbedtls) - find_library(MBEDX509_LIBRARY mbedx509) - find_library(MBEDCRYPTO_LIBRARY mbedcrypto) - - set(LWS_MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}") - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(MBEDTLS DEFAULT_MSG - LWS_MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) - - mark_as_advanced(LWS_MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) - - if ("${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "") - message(FATAL_ERROR "You must set LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS when LWS_WITH_MBEDTLS is turned on.") - endif() - endif() - set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES}) - set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS}) - set(MBEDTLS_FOUND 1) - set(USE_MBEDTLS 1) -endif() - if (LWS_WITH_HTTP_STREAM_COMPRESSION) set(LWS_WITH_ZLIB 1) endif() -if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - if ("${LWS_LIBMOUNT_LIBRARIES}" STREQUAL "" OR "${LWS_LIBMOUNT_INCLUDE_DIRS}" STREQUAL "") - - # libmount paths (this is only on Linux) - # - find_path( LIBMOUNT_INC_PATH NAMES "libmount/libmount.h") - find_library(LIBMOUNT_LIB_PATH NAMES "mount") - else() - set(LIBMOUNT_INC_PATH ${LWS_LIBMOUNT_INCLUDE_DIRS}) - set(LIBMOUNT_LIB_PATH ${LWS_LIBMOUNT_LIBRARIES}) - endif() - - if (NOT LIBMOUNT_INC_PATH OR NOT LIBMOUNT_LIB_PATH) - message(FATAL_ERROR " Unable to find libmount") - endif() -endif() - if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) if ("${LWS_ZLIB_LIBRARIES}" STREQUAL "" OR "${LWS_ZLIB_INCLUDE_DIRS}" STREQUAL "") else() @@ -752,41 +395,6 @@ if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) endif() endif() -if (LWS_WITH_LIBEV) - if ("${LWS_LIBEV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEV_INCLUDE_DIRS}" STREQUAL "") - else() - set(LIBEV_LIBRARIES ${LWS_LIBEV_LIBRARIES}) - set(LIBEV_INCLUDE_DIRS ${LWS_LIBEV_INCLUDE_DIRS}) - set(LIBEV_FOUND 1) - endif() -endif() - -if (LWS_WITH_LIBUV) - if ("${LWS_LIBUV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBUV_INCLUDE_DIRS}" STREQUAL "") - else() - set(LIBUV_LIBRARIES ${LWS_LIBUV_LIBRARIES}) - set(LIBUV_INCLUDE_DIRS ${LWS_LIBUV_INCLUDE_DIRS}) - set(LIBUV_FOUND 1) - endif() -endif() - -if (LWS_WITH_LIBEVENT) - if ("${LWS_LIBEVENT_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEVENT_INCLUDE_DIRS}" STREQUAL "") - else() - set(LIBEVENT_LIBRARIES ${LWS_LIBEVENT_LIBRARIES}) - set(LIBEVENT_INCLUDE_DIRS ${LWS_LIBEVENT_INCLUDE_DIRS}) - set(LIBEVENT_FOUND 1) - endif() -endif() - -if (LWS_WITH_GLIB) - if ("${LWS_GLIB_LIBRARIES}" STREQUAL "" OR "${LWS_GLIB_INCLUDE_DIRS}" STREQUAL "") - else() - set(LIBGLIB_LIBRARIES ${LWS_GLIB_LIBRARIES}) - set(LIBGLIB_INCLUDE_DIRS ${LWS_GLIB_INCLUDE_DIRS}) - set(LIBGLIB_FOUND 1) - endif() -endif() if (LWS_WITH_SQLITE3) if ("${LWS_SQLITE3_LIBRARIES}" STREQUAL "" OR "${LWS_SQLITE3_INCLUDE_DIRS}" STREQUAL "") @@ -797,96 +405,8 @@ if (LWS_WITH_SQLITE3) endif() endif() - -if (LWS_WITH_LIBEV AND LWS_WITH_LIBEVENT) - message(FATAL_ERROR "Sorry libev and libevent conflict with each others' namespace, you can only have one or the other") -endif() - -# The base dir where the test-apps look for the SSL certs. -set(LWS_OPENSSL_CLIENT_CERTS ../share CACHE PATH "Server SSL certificate directory") -if (WIN32) - set(LWS_OPENSSL_CLIENT_CERTS . CACHE PATH "Client SSL certificate directory") - - if (LWS_UNIX_SOCK) - set(LWS_UNIX_SOCK OFF) - message(WARNING "Windows does not support UNIX domain sockets") - endif() -else() - set(LWS_OPENSSL_CLIENT_CERTS /etc/pki/tls/certs/ CACHE PATH "Client SSL certificate directory") -endif() - -# LWS_OPENSSL_SUPPORT deprecated... use LWS_WITH_TLS -if (LWS_WITH_SSL OR LWS_WITH_MBEDTLS) - set(LWS_OPENSSL_SUPPORT 1) - set(LWS_WITH_TLS 1) -endif() - -if (LWS_SSL_CLIENT_USE_OS_CA_CERTS) - set(LWS_SSL_CLIENT_USE_OS_CA_CERTS 1) -endif() - -if (LWS_WITHOUT_DAEMONIZE OR WIN32) - set(LWS_NO_DAEMONIZE 1) -endif() - -if (LWS_WITH_LIBEV) - set(LWS_WITH_LIBEV 1) -endif() - -if (LWS_WITH_LIBUV) - set(LWS_WITH_LIBUV 1) -endif() - -if (LWS_WITH_LIBEVENT) - set(LWS_WITH_LIBEVENT 1) -endif() - -if (LWS_IPV6) - set(LWS_WITH_IPV6 1) -endif() - -if (LWS_UNIX_SOCK) - set(LWS_WITH_UNIX_SOCK 1) -endif() - -if (NOT LWS_MAX_SMP) - set(LWS_MAX_SMP 1) -endif() -if ("${LWS_MAX_SMP}" STREQUAL "") - set(LWS_MAX_SMP 1) -endif() - -set(LWS_WITH_CLIENT 1) -if (LWS_WITHOUT_CLIENT) - set(LWS_WITH_CLIENT) -endif() -set(LWS_WITH_SERVER 1) -if (LWS_WITHOUT_SERVER) - set(LWS_WITH_SERVER) -endif() - -# using any abstract protocol enables LWS_WITH_ABSTRACT - -#if (LWS_WITH_SMTP) -# set(LWS_WITH_ABSTRACT 1) -#endif() - - - -if (MINGW) - set(LWS_MINGW_SUPPORT 1) - set(CMAKE_C_FLAGS "-D__USE_MINGW_ANSI_STDIO ${CMAKE_C_FLAGS}") - add_definitions(-DWINVER=0x0601 -D_WIN32_WINNT=0x0601) -endif() - -if (LWS_SSL_SERVER_WITH_ECDH_CERT) - set(LWS_SSL_SERVER_WITH_ECDH_CERT 1) -endif() - include_directories("${PROJECT_BINARY_DIR}") -include(CheckCSourceCompiles) - # Check for different inline keyword versions. foreach(KEYWORD "inline" "__inline__" "__inline") set(CMAKE_REQUIRED_DEFINITIONS "-DKEYWORD=${KEYWORD}") @@ -918,22 +438,10 @@ SET(LWS_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}") # architectures, notably Mac OS X, need this. SET(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}") -include(CheckFunctionExists) -include(CheckSymbolExists) -include(CheckIncludeFile) -include(CheckIncludeFiles) -include(CheckLibraryExists) -include(CheckTypeSize) -include(CheckCSourceCompiles) - if (LWS_WITHOUT_BUILTIN_SHA1) set(LWS_SHA1_USE_OPENSSL_NAME 1) endif() -if (HAIKU) - set(CMAKE_REQUIRED_LIBRARIES network) -endif() - CHECK_C_SOURCE_COMPILES( "#include int main(int argc, char **argv) { return malloc_trim(0); } @@ -962,9 +470,6 @@ CHECK_FUNCTION_EXISTS(_atoi64 LWS_HAVE__ATOI64) CHECK_FUNCTION_EXISTS(_stat32i64 LWS_HAVE__STAT32I64) CHECK_FUNCTION_EXISTS(clock_gettime LWS_HAVE_CLOCK_GETTIME) -IF (CMAKE_SYSTEM_NAME STREQUAL Linux) - CHECK_FUNCTION_EXISTS(eventfd LWS_HAVE_EVENTFD) -endif() if (NOT LWS_HAVE_GETIFADDRS) if (LWS_WITHOUT_BUILTIN_GETIFADDRS) @@ -977,12 +482,22 @@ if (LWS_EXT_PTHREAD_INCLUDE_DIR) set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_EXT_PTHREAD_INCLUDE_DIR}) include_directories(${LWS_EXT_PTHREAD_INCLUDE_DIR}) - list(APPEND LIB_LIST ${LWS_EXT_PTHREAD_LIBRARIES}) + list(APPEND LIB_LIST_AT_END ${LWS_EXT_PTHREAD_LIBRARIES}) set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} " -DHAVE_STRUCT_TIMESPEC=1") endif() -CHECK_INCLUDE_FILE(dlfcn.h LWS_HAVE_DLFCN_H) -CHECK_INCLUDE_FILE(fcntl.h LWS_HAVE_FCNTL_H) +# +# add libs here that need to be at the end of the link order +# + +if (LWS_EXT_PTHREAD_INCLUDE_DIR) + list(APPEND LIB_LIST_AT_END ${LWS_EXT_PTHREAD_LIBRARIES}) +endif() + +if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) + list(APPEND LIB_LIST_AT_END "${ZLIB_LIBRARIES}") +endif() + CHECK_INCLUDE_FILE(in6addr.h LWS_HAVE_IN6ADDR_H) CHECK_INCLUDE_FILE(memory.h LWS_HAVE_MEMORY_H) CHECK_INCLUDE_FILE(netinet/in.h LWS_HAVE_NETINET_IN_H) @@ -1004,62 +519,16 @@ CHECK_INCLUDE_FILE(inttypes.h LWS_HAVE_INTTYPES_H) CHECK_LIBRARY_EXISTS(cap cap_set_flag "" LWS_HAVE_LIBCAP) -if (LWS_ROLE_DBUS) - if (NOT LWS_DBUS_LIB) - set(LWS_DBUS_LIB "dbus-1") - endif() - - if (NOT LWS_PLAT_FREERTOS) - find_package(PkgConfig QUIET) - pkg_check_modules(PC_DBUS1 dbus-1 QUIET) - list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) - list(APPEND LWS_DBUS_LIB ${PC_DBUS1_LIBRARIES}) +if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) + if (LWS_WITH_MINIZ) + CHECK_INCLUDE_FILE(miniz.h LWS_HAVE_ZLIB_H) + else() + CHECK_INCLUDE_FILE(zlib.h LWS_HAVE_ZLIB_H) endif() - - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1}) - - CHECK_C_SOURCE_COMPILES("#include - int main(void) { - return 0; - }" LWS_DBUS_CHECK_OK) endif() -if (LWS_WITH_LIBUV) -CHECK_INCLUDE_FILE(uv-version.h LWS_HAVE_UV_VERSION_H) - # libuv changed the location in 1.21.0. Retain both - # checks temporarily to ensure a smooth transition. - if (NOT LWS_HAVE_UV_VERSION_H) - CHECK_INCLUDE_FILE(uv/version.h LWS_HAVE_NEW_UV_VERSION_H) - endif() -endif() - -if (LWS_WITH_LIBEV) - CHECK_C_SOURCE_COMPILES( - "#include - int main(int argc, char **argv) { return EVBACKEND_LINUXAIO; } - " LWS_HAVE_EVBACKEND_LINUXAIO) - CHECK_C_SOURCE_COMPILES( - "#include - int main(int argc, char **argv) { return EVBACKEND_IOURING; } - " LWS_HAVE_EVBACKEND_IOURING) - -endif() - - -if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) - if (LWS_WITH_MINIZ) - CHECK_INCLUDE_FILE(miniz.h LWS_HAVE_ZLIB_H) - else() - CHECK_INCLUDE_FILE(zlib.h LWS_HAVE_ZLIB_H) - endif() -endif() - -# TODO: These can also be tested to see whether they actually work... -set(LWS_HAVE_WORKING_FORK LWS_HAVE_FORK) -set(LWS_HAVE_WORKING_VFORK LWS_HAVE_VFORK) - -CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS) +CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h" STDC_HEADERS) if (NOT CMAKE_REQUIRED_FLAGS) set(CMAKE_REQUIRED_FLAGS "") @@ -1077,21 +546,29 @@ CHECK_C_SOURCE_COMPILES("#include return 0; }" LWS_HAS_INTPTR_T) - if (LWS_HAVE_PTHREAD_H AND NOT LWS_PLAT_FREERTOS) - if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-pthread -Wno-error=unused-command-line-argument") - else() - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-pthread") - endif() +if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR + (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + set(COMPILER_IS_CLANG ON) +endif() - CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE - #include - int main(void) { - pthread_t th = 0; - pthread_setname_np(th, NULL); - return 0; - }" LWS_HAS_PTHREAD_SETNAME_NP) +if (LWS_HAVE_PTHREAD_H AND NOT LWS_PLAT_FREERTOS) + if (COMPILER_IS_CLANG) + set(LWS_PTHR_FLAGS "-pthread")# -Wno-error=unused-command-line-argument") + else() + set(LWS_PTHR_FLAGS "-pthread") endif() + + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${LWS_PTHR_FLAGS}) + list(APPEND LIB_LIST_AT_END ${LWS_PTHR_FLAGS}) + + CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE + #include + int main(void) { + pthread_t th = 0; + pthread_setname_np(th, NULL); + return 0; + }" LWS_HAS_PTHREAD_SETNAME_NP) +endif() CHECK_C_SOURCE_COMPILES("#include #include @@ -1117,680 +594,8 @@ if (NOT LWS_HAVE_REALLOC) set(realloc rpl_realloc) endif() -if (UNIX) - execute_process( COMMAND grep -c illumos /lib/ld.so.1 - OUTPUT_VARIABLE ILLUMOS ERROR_QUIET ) - # Chomp the \n at end of output. - string(REGEX REPLACE "[\n]+" "" ILLUMOS "${ILLUMOS}") - - if(NOT ${ILLUMOS} MATCHES "0") - add_definitions( "-D__illumos__" ) - set(ILLUMOS 1) - endif() -endif() - -if (MSVC) - # Turn off stupid microsoft security warnings. - add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) -endif(MSVC) - -include_directories("${PROJECT_SOURCE_DIR}/lib") - -# Group headers and sources. -# Some IDEs use this for nicer file structure. -set(HDR_PRIVATE - lib/core/private-lib-core.h) - -set(HDR_PUBLIC - "${PROJECT_SOURCE_DIR}/include/libwebsockets.h" - "${PROJECT_BINARY_DIR}/lws_config.h" - "${PROJECT_SOURCE_DIR}/plugins/ssh-base/include/lws-plugin-ssh.h" - ) - -set(SOURCES - lib/core/alloc.c - lib/core/buflist.c - lib/core/context.c - lib/core/lws_dll2.c - lib/core/libwebsockets.c - lib/core/logs.c - lib/system/system.c - lib/misc/base64-decode.c - lib/misc/lws-ring.c -) - -if (LWS_WITH_SPAWN) - if (UNIX) - list(APPEND SOURCES lib/plat/unix/unix-spawn.c) - endif() - if (WIN32) - list(APPEND SOURCES lib/plat/windows/windows-spawn.c) - endif() -endif() - -if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - list(APPEND SOURCES lib/misc/fsmount.c) -endif() - -if (LWS_WITH_FILE_OPS) - list(APPEND SOURCES lib/core/vfs.c) -endif() - -if (LWS_WITH_DEPRECATED_LWS_DLL) - list(APPEND SOURCES - lib/core/lws_dll.c) -endif() - -if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/core-net/dummy-callback.c - lib/core-net/output.c - lib/core-net/close.c - lib/core-net/network.c - lib/core-net/vhost.c - lib/core-net/pollfd.c - lib/core-net/service.c - lib/core-net/sorted-usec-list.c - lib/core-net/state.c - lib/core-net/stats.c - lib/core-net/wsi.c - lib/core-net/wsi-timeout.c - lib/core-net/adopt.c - lib/roles/pipe/ops-pipe.c - ) - - if (LWS_WITH_SYS_ASYNC_DNS) - list(APPEND SOURCES - lib/system/async-dns/async-dns.c - lib/system/async-dns/async-dns-parse.c) - endif() - - if (LWS_WITH_SYS_NTPCLIENT) - list(APPEND SOURCES - lib/system/ntpclient/ntpclient.c) - endif() - - if (LWS_WITH_SYS_DHCP_CLIENT) - list(APPEND SOURCES - lib/system/dhcpclient/dhcpclient.c) - endif() - - - if (LWS_WITH_DETAILED_LATENCY) - list(APPEND SOURCES - lib/core-net/detailed-latency.c) - endif() - - if (LWS_WITH_LWS_DSH) - list(APPEND SOURCES - lib/core-net/lws-dsh.c) - endif() - - if (LWS_WITH_SEQUENCER) - list(APPEND SOURCES - lib/core-net/sequencer.c) - endif() - - if (LWS_WITH_ABSTRACT) - list(APPEND SOURCES - lib/abstract/abstract.c - ) - if (LWS_WITH_SEQUENCER) - list(APPEND SOURCES - lib/abstract/test-sequencer.c) - endif() - endif() - - if (LWS_WITH_SECURE_STREAMS) - list(APPEND SOURCES - lib/secure-streams/secure-streams.c - lib/secure-streams/policy-common.c - lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c - lib/secure-streams/protocols/ss-raw.c - ) - if (NOT LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) - list(APPEND SOURCES - lib/secure-streams/policy-json.c - lib/secure-streams/system/fetch-policy/fetch-policy.c - ) - endif() - if (LWS_ROLE_H1) - list(APPEND SOURCES - lib/secure-streams/protocols/ss-h1.c - ) - endif() - if (LWS_ROLE_H2) - list(APPEND SOURCES - lib/secure-streams/protocols/ss-h2.c - ) - endif() - if (LWS_ROLE_WS) - list(APPEND SOURCES - lib/secure-streams/protocols/ss-ws.c - ) - endif() - if (LWS_ROLE_MQTT) - list(APPEND SOURCES - lib/secure-streams/protocols/ss-mqtt.c - ) - endif() - - if (LWS_WITH_SECURE_STREAMS_PROXY_API) - list(APPEND SOURCES - lib/secure-streams/secure-streams-serialize.c - lib/secure-streams/secure-streams-client.c - ) - endif() - - if (LWS_WITH_SECURE_STREAMS_PROXY_API) - list(APPEND SOURCES - lib/secure-streams/secure-streams-process.c - ) - endif() - - if (LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) - list(APPEND SOURCES - lib/secure-streams/system/auth-api.amazon.com/auth.c - ) - endif() - - endif() - - if (LWS_WITH_STATS) - list(APPEND SOURCES - lib/core-net/stats.c - ) - endif() -endif() - -if (LWS_WITH_DIR) - list(APPEND SOURCES lib/misc/dir.c) -endif() - -if (LWS_ROLE_MQTT AND LWS_WITH_CLIENT) - list(APPEND SOURCES - lib/roles/mqtt/mqtt.c - lib/roles/mqtt/ops-mqtt.c - lib/roles/mqtt/primitives.c - lib/roles/mqtt/client/client-mqtt.c - lib/roles/mqtt/client/client-mqtt-handshake.c - ) -endif() - -if (LWS_WITH_THREADPOOL AND LWS_HAVE_PTHREAD_H) - list(APPEND SOURCES lib/misc/threadpool/threadpool.c) -endif() - -if (LWS_ROLE_H1 OR LWS_ROLE_H2) - list(APPEND SOURCES - lib/roles/http/header.c - lib/roles/http/parsers.c) - if (LWS_WITH_HTTP_STREAM_COMPRESSION) - list(APPEND SOURCES - lib/roles/http/compression/stream.c - lib/roles/http/compression/deflate/deflate.c) - if (LWS_WITH_HTTP_BROTLI) - list(APPEND SOURCES - lib/roles/http/compression/brotli/brotli.c) - endif() - endif() -endif() - -if (LWS_ROLE_H1) - list(APPEND SOURCES - lib/roles/h1/ops-h1.c) -endif() - -if (LWS_ROLE_WS) - list(APPEND SOURCES - lib/roles/ws/ops-ws.c) - if (NOT LWS_WITHOUT_CLIENT) - list(APPEND SOURCES - lib/roles/ws/client-ws.c - lib/roles/ws/client-parser-ws.c) - endif() - if (NOT LWS_WITHOUT_SERVER) - list(APPEND SOURCES - lib/roles/ws/server-ws.c) - endif() -endif() - -if (LWS_ROLE_RAW) - list(APPEND SOURCES - lib/roles/raw-skt/ops-raw-skt.c) - if (LWS_ROLE_RAW_FILE) - list(APPEND SOURCES lib/roles/raw-file/ops-raw-file.c) - endif() - - if (LWS_WITH_ABSTRACT) - list(APPEND SOURCES - lib/abstract/transports/raw-skt.c) - endif() -endif() - -if (LWS_ROLE_RAW_PROXY) - list(APPEND SOURCES - lib/roles/raw-proxy/ops-raw-proxy.c) -endif() - -if (LWS_ROLE_CGI) - list(APPEND SOURCES - lib/roles/cgi/cgi-server.c - lib/roles/cgi/ops-cgi.c) -endif() - -if (LWS_ROLE_DBUS) - list(APPEND SOURCES - lib/roles/dbus/dbus.c) -endif() - -if (LWS_WITH_ACCESS_LOG) - list(APPEND SOURCES - lib/roles/http/server/access-log.c) -endif() - -if (LWS_WITH_PEER_LIMITS) - list(APPEND SOURCES - lib/misc/peer-limits.c) -endif() - -if (LWS_WITH_LWSAC) - list(APPEND SOURCES - lib/misc/lwsac/lwsac.c - lib/misc/lwsac/cached-file.c) -endif() - -if (LWS_WITH_FTS) - list(APPEND SOURCES - lib/misc/fts/trie.c - lib/misc/fts/trie-fd.c) -endif() - -if (LWS_WITH_DISKCACHE) - list(APPEND SOURCES - lib/misc/diskcache.c) -endif() - -if (LWS_WITH_STRUCT_JSON) - list(APPEND SOURCES - lib/misc/lws-struct-lejp.c) -endif() - -if (LWS_WITH_STRUCT_SQLITE3) - list(APPEND SOURCES - lib/misc/lws-struct-sqlite.c) -endif() - -if (NOT LWS_WITHOUT_CLIENT) - list(APPEND SOURCES - lib/core-net/connect.c - lib/core-net/client.c - lib/roles/http/client/client-http.c - lib/roles/http/client/client-handshake.c) -endif() - -if (NOT LWS_WITHOUT_SERVER) - list(APPEND SOURCES - lib/core-net/server.c) -endif() - -if (NOT LWS_WITHOUT_SERVER OR LWS_WITH_SECURE_STREAMS_PROCESS_API) - list(APPEND SOURCES - lib/roles/listen/ops-listen.c) -endif() - -if (LWS_WITH_MBEDTLS) - set(LWS_WITH_SSL ON) - - include_directories(lib/tls/mbedtls/wrapper/include) - include_directories(lib/tls/mbedtls/wrapper/include/platform) - include_directories(lib/tls/mbedtls/wrapper/include/internal) - include_directories(lib/tls/mbedtls/wrapper/include/openssl) - - if (LWS_WITH_NETWORK) - list(APPEND HDR_PRIVATE - lib/tls/mbedtls/wrapper/include/internal/ssl3.h - lib/tls/mbedtls/wrapper/include/internal/ssl_cert.h - lib/tls/mbedtls/wrapper/include/internal/ssl_code.h - lib/tls/mbedtls/wrapper/include/internal/ssl_dbg.h - lib/tls/mbedtls/wrapper/include/internal/ssl_lib.h - lib/tls/mbedtls/wrapper/include/internal/ssl_methods.h - lib/tls/mbedtls/wrapper/include/internal/ssl_pkey.h - lib/tls/mbedtls/wrapper/include/internal/ssl_stack.h - lib/tls/mbedtls/wrapper/include/internal/ssl_types.h - lib/tls/mbedtls/wrapper/include/internal/ssl_x509.h - lib/tls/mbedtls/wrapper/include/internal/tls1.h - lib/tls/mbedtls/wrapper/include/internal/x509_vfy.h) - - list(APPEND HDR_PRIVATE - lib/tls/mbedtls/wrapper/include/openssl/ssl.h) - - list(APPEND HDR_PRIVATE - lib/tls/mbedtls/wrapper/include/platform/ssl_pm.h - lib/tls/mbedtls/wrapper/include/platform/ssl_port.h) - - list(APPEND SOURCES - lib/tls/mbedtls/wrapper/library/ssl_cert.c - lib/tls/mbedtls/wrapper/library/ssl_lib.c - lib/tls/mbedtls/wrapper/library/ssl_methods.c - lib/tls/mbedtls/wrapper/library/ssl_pkey.c - lib/tls/mbedtls/wrapper/library/ssl_stack.c - lib/tls/mbedtls/wrapper/library/ssl_x509.c) - - list(APPEND SOURCES - lib/tls/mbedtls/wrapper/platform/ssl_pm.c - lib/tls/mbedtls/wrapper/platform/ssl_port.c) - endif() -endif() - -if (LWS_WITH_SSL) - list(APPEND SOURCES - lib/tls/tls.c - ) - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/tls/tls-network.c - ) - endif() - - if (LWS_WITH_MBEDTLS) - list(APPEND SOURCES - lib/tls/mbedtls/mbedtls-tls.c - lib/tls/mbedtls/mbedtls-x509.c - ) - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/tls/mbedtls/mbedtls-ssl.c - ) - endif() - if (LWS_WITH_GENCRYPTO) - list(APPEND SOURCES - lib/tls/mbedtls/lws-genhash.c - lib/tls/mbedtls/lws-genrsa.c - lib/tls/mbedtls/lws-genaes.c - lib/tls/lws-genec-common.c - lib/tls/mbedtls/lws-genec.c - lib/tls/mbedtls/lws-gencrypto.c - ) - endif() - else() - list(APPEND SOURCES - lib/tls/openssl/openssl-tls.c - lib/tls/openssl/openssl-x509.c - ) - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/tls/openssl/openssl-ssl.c - ) - endif() - if (LWS_WITH_GENCRYPTO) - list(APPEND SOURCES - lib/tls/openssl/lws-genhash.c - lib/tls/openssl/lws-genrsa.c - lib/tls/openssl/lws-genaes.c - lib/tls/lws-genec-common.c - lib/tls/openssl/lws-genec.c - lib/tls/openssl/lws-gencrypto.c - ) - endif() - endif() - - if (NOT LWS_WITHOUT_SERVER) - list(APPEND SOURCES - lib/tls/tls-server.c) - if (LWS_WITH_MBEDTLS) - list(APPEND SOURCES - lib/tls/mbedtls/mbedtls-server.c) - else() - list(APPEND SOURCES - lib/tls/openssl/openssl-server.c) - endif() - endif() - if (NOT LWS_WITHOUT_CLIENT) - list(APPEND SOURCES - lib/tls/tls-client.c) - if (LWS_WITH_MBEDTLS) - list(APPEND SOURCES - lib/tls/mbedtls/mbedtls-client.c) - else() - list(APPEND SOURCES - lib/tls/openssl/openssl-client.c) - endif() - - endif() -endif() - -if (NOT LWS_WITHOUT_BUILTIN_SHA1) - list(APPEND SOURCES - lib/misc/sha-1.c) -endif() - -if (LWS_WITH_HTTP2) - list(APPEND SOURCES - lib/roles/h2/http2.c - lib/roles/h2/hpack.c - lib/roles/h2/ops-h2.c) -endif() -# select the active platform files - -if (WIN32) - list(APPEND SOURCES - lib/plat/windows/windows-fds.c - lib/plat/windows/windows-file.c - lib/plat/windows/windows-init.c - lib/plat/windows/windows-misc.c - lib/plat/windows/windows-pipe.c - lib/plat/windows/windows-plugins.c - lib/plat/windows/windows-service.c - lib/plat/windows/windows-sockets.c - ) - if (LWS_WITH_SYS_ASYNC_DNS) - list(APPEND SOURCES lib/plat/windows/windows-resolv.c) - endif() -else() - - if (LWS_PLAT_OPTEE) - list(APPEND SOURCES - lib/plat/optee/lws-plat-optee.c - ) - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/plat/optee/network.c - ) - endif() - else() - if (LWS_PLAT_FREERTOS) - list(APPEND SOURCES - lib/plat/freertos/freertos-fds.c - lib/plat/freertos/freertos-init.c - lib/plat/freertos/freertos-misc.c - lib/plat/freertos/freertos-pipe.c - lib/plat/freertos/freertos-service.c - lib/plat/freertos/freertos-sockets.c - lib/misc/romfs.c) - if (LWS_WITH_ESP32_HELPER) - list(APPEND SOURCES lib/plat/freertos/esp32/esp32-helpers.c) - endif() - if (LWS_WITH_FILE_OPS) - list(APPEND SOURCES lib/plat/freertos/freertos-file.c) - endif() - if (LWS_WITH_SYS_ASYNC_DNS) - list(APPEND SOURCES lib/plat/freertos/freertos-resolv.c) - endif() - else() - set(LWS_PLAT_UNIX 1) - list(APPEND SOURCES - lib/plat/unix/unix-caps.c - lib/plat/unix/unix-misc.c - lib/plat/unix/unix-init.c - ) - if (LWS_WITH_FILE_OPS) - list(APPEND SOURCES lib/plat/unix/unix-file.c) - endif() - if (LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/plat/unix/unix-pipe.c - lib/plat/unix/unix-service.c - lib/plat/unix/unix-sockets.c - lib/plat/unix/unix-fds.c - ) - if (LWS_WITH_SYS_ASYNC_DNS) - if (LWS_PLAT_ANDROID) - list(APPEND SOURCES lib/plat/unix/android/android-resolv.c) - else() - list(APPEND SOURCES lib/plat/unix/unix-resolv.c) - endif() - endif() - endif() - - if (LWS_WITH_PLUGINS AND LWS_WITH_LIBUV) - list(APPEND SOURCES lib/plat/unix/unix-plugins.c) - endif() - endif() - endif() -endif() - -if (LWS_WITH_SOCKS5 AND NOT LWS_WITHOUT_CLIENT) - list(APPEND SOURCES - lib/core-net/socks5-client.c) -endif() - -if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_SERVER) - list(APPEND SOURCES - lib/roles/http/server/server.c - lib/roles/http/server/lws-spa.c) -endif() - -if (LWS_ROLE_WS AND NOT LWS_WITHOUT_EXTENSIONS) - list(APPEND HDR_PRIVATE - lib/roles/ws/ext/extension-permessage-deflate.h) - list(APPEND SOURCES - lib/roles/ws/ext/extension.c - lib/roles/ws/ext/extension-permessage-deflate.c) -endif() - -if (LWS_WITH_HTTP_PROXY) - list(APPEND SOURCES - lib/roles/http/server/rewrite.c) -endif() - -if (LWS_WITH_POLL AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/poll/poll.c) -endif() - -if (LWS_WITH_LIBUV AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/libuv/libuv.c) -endif() - -if (LWS_WITH_LIBEVENT AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/libevent/libevent.c) -endif() - -if (LWS_WITH_GLIB AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/glib/glib.c) -endif() - - -if (LWS_WITH_LIBEV AND LWS_WITH_NETWORK) - list(APPEND SOURCES - lib/event-libs/libev/libev.c) - # libev generates a big mess of warnings with gcc, maintainer claims gcc to blame - set_source_files_properties( lib/event-libs/libev/libev.c PROPERTIES COMPILE_FLAGS "-Wno-error" ) -endif() - -if (LWS_WITH_LEJP) - list(APPEND SOURCES - lib/misc/lejp.c) -endif() -if (LWS_WITH_LEJP_CONF AND LWS_WITH_NETWORK AND NOT LWS_PLAT_OPTEE) - list(APPEND SOURCES - "lib/roles/http/server/lejp-conf.c" - ) -endif() - -if (LWS_WITH_ABSTRACT) - list(APPEND SOURCES - lib/abstract/transports/unit-test.c) -endif() - -#if (LWS_WITH_SMTP) -# list(APPEND SOURCES -# lib/abstract/protocols/smtp/smtp.c -# lib/abstract/protocols/smtp/smtp-sequencer.c -# ) -#endif() - -if (LWS_WITH_RANGES) - list(APPEND SOURCES - lib/roles/http/server/ranges.c) -endif() - -if (LWS_WITH_ZIP_FOPS) - if (LWS_WITH_ZLIB) - list(APPEND SOURCES - lib/roles/http/server/fops-zip.c) - else() - message(FATAL_ERROR "Pre-zipped file support (LWS_WITH_ZIP_FOPS) requires ZLIB (LWS_WITH_ZLIB)") - endif() -endif() - -if (LWS_WITH_JOSE) - list(APPEND SOURCES - lib/jose/jwk/jwk.c - lib/jose/jws/jose.c - lib/jose/jws/jws.c - lib/jose/jwe/jwe.c - lib/jose/jwe/enc/aescbc.c - lib/jose/jwe/enc/aesgcm.c - lib/jose/jwe/enc/aeskw.c - lib/jose/jwe/jwe-rsa-aescbc.c - lib/jose/jwe/jwe-rsa-aesgcm.c - lib/jose/jwe/jwe-ecdh-es-aeskw.c - ) -endif() - -if (LWS_WITH_TLS AND (LWS_WITH_JOSE OR LWS_WITH_GENCRYPTO)) - list(APPEND SOURCES - lib/tls/lws-gencrypto-common.c) -endif() - -# Add helper files for Windows. -if (WIN32) - set(WIN32_HELPERS_PATH win32port/win32helpers) - include_directories(${WIN32_HELPERS_PATH}) - - if (WIN32) - list(APPEND SOURCES - ${WIN32_HELPERS_PATH}/gettimeofday.c - ) - - list(APPEND HDR_PRIVATE - ${WIN32_HELPERS_PATH}/gettimeofday.h - ) - endif(WIN32) - -else() - # Unix. - if (NOT LWS_WITHOUT_DAEMONIZE) - list(APPEND SOURCES - lib/misc/daemonize.c) - endif() -endif() -if (UNIX) - if (NOT LWS_HAVE_GETIFADDRS) - list(APPEND HDR_PRIVATE lib/misc/getifaddrs.h) - list(APPEND SOURCES lib/misc/getifaddrs.c) - endif() -endif() -if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(COMPILER_IS_CLANG ON) -endif() if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) include (CheckCCompilerFlag) @@ -1840,14 +645,6 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) endif() endif () -if (MSVC) - # Fail the build if any warnings - add_compile_options(/W3 /WX) -endif() - -if (LWS_PLAT_OPTEE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot ../../../../lib/libutils/isoc/include -I../../../../lib/libutils/isoc/include -I../../../../lib/libutils/ext/include" ) -endif() if ((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT LWS_WITHOUT_TESTAPPS) if (UNIX AND LWS_HAVE_PTHREAD_H) @@ -1866,6 +663,25 @@ if (COMPILER_IS_CLANG) endif() endif() +if (WINCE) + list(APPEND LIB_LIST_AT_END ws2.lib) +elseif (WIN32) + list(APPEND LIB_LIST_AT_END ws2_32.lib userenv.lib psapi.lib iphlpapi.lib) +endif() + +if (MSVC) + # Turn off pointless microsoft security warnings. + add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) + # Fail the build if any warnings + add_compile_options(/W3 /WX) +endif(MSVC) + +if (MINGW) + set(LWS_MINGW_SUPPORT 1) + set(CMAKE_C_FLAGS "-D__USE_MINGW_ANSI_STDIO ${CMAKE_C_FLAGS}") + add_definitions(-DWINVER=0x0601 -D_WIN32_WINNT=0x0601) +endif() + source_group("Headers Private" FILES ${HDR_PRIVATE}) source_group("Headers Public" FILES ${HDR_PUBLIC}) source_group("Sources" FILES ${SOURCES}) @@ -1873,141 +689,12 @@ if (RESOURCES) source_group("Resources" FILES ${RESOURCES}) endif() + # -# Create the lib. -# -set(LWS_LIBRARIES) - - -if (LWS_WITH_STATIC) - if (LWS_STATIC_PIC) - set(CMAKE_POSITION_INDEPENDENT_CODE ON) - endif() - add_library(websockets STATIC - ${HDR_PRIVATE} - ${HDR_PUBLIC} - ${SOURCES}) - list(APPEND LWS_LIBRARIES websockets) - - if (WIN32) - # Windows uses the same .lib ending for static libraries and shared - # library linker files, so rename the static library. - set_target_properties(websockets - PROPERTIES - OUTPUT_NAME websockets_static) - endif() - if (NOT LWS_WITH_SHARED) - add_custom_command( - TARGET websockets POST_BUILD - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets/ - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h - ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h - ) - endif() - -endif() - -if (LWS_WITH_SHARED) - if (NOT RESOURCES) - set(RESOURCES "") - endif() - add_library(websockets_shared SHARED - ${HDR_PRIVATE} - ${HDR_PUBLIC} - ${SOURCES} - ${RESOURCES}) - list(APPEND LWS_LIBRARIES websockets_shared) - - # We want the shared lib to be named "libwebsockets" - # not "libwebsocket_shared". - set_target_properties(websockets_shared - PROPERTIES - OUTPUT_NAME websockets) - - if (WIN32) - # Compile as DLL (export function declarations) - set_property( - TARGET websockets_shared - PROPERTY COMPILE_DEFINITIONS - LWS_DLL - LWS_INTERNAL) - endif() - - if (APPLE) - set_property(TARGET websockets_shared PROPERTY MACOSX_RPATH YES) - endif() - - - add_custom_command( - TARGET websockets_shared POST_BUILD - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets/ - ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/lws_config.h - ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h - ) - -endif() - -# Set the so version of the lib. -# Equivalent to LDFLAGS=-version-info x:x:x -if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) - foreach(lib ${LWS_LIBRARIES}) - set_target_properties(${lib} - PROPERTIES - SOVERSION ${SOVERSION}) - endforeach() -endif() - -set(LIB_LIST) - -# -# Find libraries. -# -if (LWS_EXT_PTHREAD_INCLUDE_DIR) - list(APPEND LIB_LIST ${LWS_EXT_PTHREAD_LIBRARIES}) -endif() - -# -# ZLIB (needed for deflate extension and if LWS_WITH_HTTP_STREAM_COMPRESSION) +# ZLIB (needed for deflate extension and if LWS_WITH_HTTP_STREAM_COMPRESSION) # if (LWS_WITH_ZLIB) - if (LWS_WITH_BUNDLED_ZLIB) - if (WIN32) - set(WIN32_ZLIB_PATH "win32port/zlib") - set(ZLIB_SRCS - ${WIN32_ZLIB_PATH}/adler32.c - ${WIN32_ZLIB_PATH}/compress.c - ${WIN32_ZLIB_PATH}/crc32.c - ${WIN32_ZLIB_PATH}/deflate.c - ${WIN32_ZLIB_PATH}/gzlib.c - ${WIN32_ZLIB_PATH}/gzread.c - ${WIN32_ZLIB_PATH}/gzwrite.c - ${WIN32_ZLIB_PATH}/infback.c - ${WIN32_ZLIB_PATH}/inffast.c - ${WIN32_ZLIB_PATH}/inflate.c - ${WIN32_ZLIB_PATH}/inftrees.c - ${WIN32_ZLIB_PATH}/trees.c - ${WIN32_ZLIB_PATH}/uncompr.c - ${WIN32_ZLIB_PATH}/zutil.c) - add_library(zlib_internal STATIC ${ZLIB_SRCS}) - set(ZLIB_INCLUDE_DIRS ${WIN32_ZLIB_PATH}) - get_property(ZLIB_LIBRARIES TARGET zlib_internal PROPERTY LOCATION) - set(ZLIB_FOUND 1) - # Make sure zlib_internal is compiled before the libs. - foreach (lib ${LWS_LIBRARIES}) - add_dependencies(${lib} zlib_internal) - endforeach() - else() - message(FATAL_ERROR "Don't have bundled zlib for that platform") - endif() - elseif (NOT ZLIB_FOUND) + if (NOT ZLIB_FOUND) if (LWS_WITH_MINIZ) find_package(Miniz REQUIRED) set(ZLIB_INCLUDE_DIRS ${MINIZ_INCLUDE_DIRS}) @@ -2021,158 +708,10 @@ if (LWS_WITH_ZLIB) include_directories(${ZLIB_INCLUDE_DIRS}) # done later at end of link list # list(APPEND LIB_LIST ${ZLIB_LIBRARIES}) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${ZLIB_LIBRARIES}) + list(APPEND LIB_LIST_AT_END ${ZLIB_LIBRARIES}) endif() -if (LWS_WITH_HTTP_BROTLI) - list(APPEND LIB_LIST brotlienc brotlidec brotlidec) -endif() - -# -# OpenSSL -# -if (LWS_WITH_SSL) - message("Compiling with SSL support") - set(chose_ssl 0) - if (LWS_WITH_WOLFSSL) - # Use wolfSSL as OpenSSL replacement. - # TODO: Add a find_package command for this also. - message("wolfSSL include dir: ${WOLFSSL_INCLUDE_DIRS}") - message("wolfSSL libraries: ${WOLFSSL_LIBRARIES}") - - # Additional to the root directory we need to include - # the wolfssl/ subdirectory which contains the OpenSSL - # compatibility layer headers. - - if (LWS_WITH_CYASSL) - foreach(inc ${WOLFSSL_INCLUDE_DIRS}) - set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/cyassl) - include_directories("${inc}" "${inc}/cyassl") - endforeach() - else() - foreach(inc ${WOLFSSL_INCLUDE_DIRS}) - set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/wolfssl) - include_directories("${inc}" "${inc}/wolfssl") - endforeach() - endif() - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) - set(VARIA wolfSSL_) - - list(APPEND LIB_LIST "${WOLFSSL_LIBRARIES}") - set(chose_ssl 1) - endif() - - if (LWS_WITH_MBEDTLS) - message("MBEDTLS include dir: ${MBEDTLS_INCLUDE_DIRS}") - message("MBEDTLS libraries: ${MBEDTLS_LIBRARIES}") - - foreach(inc ${MBEDTLS_INCLUDE_DIRS}) - include_directories("${inc}" "${inc}/mbedtls") - endforeach() - - list(APPEND LIB_LIST "${MBEDTLS_LIBRARIES}") - set(chose_ssl 1) - endif() - - if (NOT chose_ssl) - if (NOT OPENSSL_FOUND AND NOT LWS_WITH_BORINGSSL) - # TODO: Add support for STATIC also. - if (NOT LWS_PLAT_FREERTOS) - find_package(PkgConfig QUIET) - pkg_check_modules(PC_OPENSSL openssl QUIET) - find_package(OpenSSL REQUIRED) - list(APPEND OPENSSL_LIBRARIES ${PC_OPENSSL_LIBRARIES}) - endif() - set(OPENSSL_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}") - endif() - - message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIRS}") - if (NOT LWS_PLAT_FREERTOS) - message("OpenSSL libraries: ${OPENSSL_LIBRARIES}") - endif() - - include_directories("${OPENSSL_INCLUDE_DIRS}") - if (NOT LWS_PLAT_FREERTOS) - list(APPEND LIB_LIST ${OPENSSL_LIBRARIES}) - endif() - - if (NOT LWS_WITH_MBEDTLS) - # older (0.98) Openssl lacks this - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) - check_include_file(openssl/ecdh.h LWS_HAVE_OPENSSL_ECDH_H) - - if (LWS_SSL_SERVER_WITH_ECDH_CERT AND NOT LWS_HAVE_OPENSSL_ECDH_H) - message(FATAL_ERROR "Missing openssl/ecdh.h, so cannot use LWS_SSL_SERVER_WITH_ECDH_CERT") - endif() - else() - unset(LWS_HAVE_OPENSSL_ECDH_H) - endif(NOT LWS_WITH_MBEDTLS) - endif() - -endif(LWS_WITH_SSL) - -if (LWS_WITH_LIBEV) - if (NOT LIBEV_FOUND) - find_path(LIBEV_INCLUDE_DIRS NAMES ev.h) - find_library(LIBEV_LIBRARIES NAMES ev) - if(LIBEV_INCLUDE_DIRS AND LIBEV_LIBRARIES) - set(LIBEV_FOUND 1) - endif() - endif() - message("libev include dir: ${LIBEV_INCLUDE_DIRS}") - message("libev libraries: ${LIBEV_LIBRARIES}") - include_directories("${LIBEV_INCLUDE_DIRS}") - list(APPEND LIB_LIST ${LIBEV_LIBRARIES}) -endif(LWS_WITH_LIBEV) - -if (LWS_WITH_LIBUV) - if (NOT LIBUV_FOUND) - find_path(LIBUV_INCLUDE_DIRS NAMES uv.h) - find_library(LIBUV_LIBRARIES NAMES uv) - if(LIBUV_INCLUDE_DIRS AND LIBUV_LIBRARIES) - set(LIBUV_FOUND 1) - endif() - endif() - message("libuv include dir: ${LIBUV_INCLUDE_DIRS}") - message("libuv libraries: ${LIBUV_LIBRARIES}") - include_directories("${LIBUV_INCLUDE_DIRS}") - list(APPEND LIB_LIST ${LIBUV_LIBRARIES}) -endif() - -if (LWS_WITH_LIBEVENT) - if (NOT LIBEVENT_FOUND) - find_path(LIBEVENT_INCLUDE_DIRS NAMES event2/event.h) - find_library(LIBEVENT_LIBRARIES NAMES event) - if(LIBEVENT_INCLUDE_DIRS AND LIBEVENT_LIBRARIES) - set(LIBEVENT_FOUND 1) - endif() - endif() - message("libevent include dir: ${LIBEVENT_INCLUDE_DIRS}") - message("libevent libraries: ${LIBEVENT_LIBRARIES}") - include_directories("${LIBEVENT_INCLUDE_DIRS}") - list(APPEND LIB_LIST ${LIBEVENT_LIBRARIES}) -endif(LWS_WITH_LIBEVENT) - -if (LWS_WITH_GLIB) - include (FindPkgConfig) - if (NOT GLIB_FOUND) - find_path(GLIB_INCLUDE_DIRS NAMES glib-2.0/glib.h) - find_library(GLIB_LIBRARIES NAMES glib-2.0) - if(GLIB_INCLUDE_DIRS AND GLIB_LIBRARIES) - set(GLIB_FOUND 1) - endif() - if (GLIB_INCLUDE_DIRS) - set(GLIB_INCLUDE_DIRS "${GLIB_INCLUDE_DIRS}/glib-2.0") - endif() - endif() - PKG_SEARCH_MODULE(LWS_GLIB2 glib-2.0) - if (LWS_GLIB2_FOUND) - list(APPEND GLIB_INCLUDE_DIRS "${LWS_GLIB2_INCLUDE_DIRS}") - endif() - message("glib include dir: ${GLIB_INCLUDE_DIRS}") - message("glib libraries: ${GLIB_LIBRARIES}") - include_directories("${GLIB_INCLUDE_DIRS}") - list(APPEND LIB_LIST ${GLIB_LIBRARIES}) -endif(LWS_WITH_GLIB) if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") message("libmount include dir: ${LIBMOUNT_INC_PATH}") @@ -2203,756 +742,119 @@ if (LWS_WITH_HUBBUB) list(APPEND LIB_LIST ${LIBHUBBUB_LIBRARIES} ) endif() -if (LWS_ROLE_DBUS) - message("dbus include dir 1: ${LWS_DBUS_INCLUDE1}") - include_directories("${LWS_DBUS_INCLUDE1}") - list(APPEND LIB_LIST ${LWS_DBUS_LIB}) -endif() - # -# Platform specific libs. +# Append the "at end" pieces to the lib list # -if (WINCE) - list(APPEND LIB_LIST ws2.lib) -elseif (WIN32) - list(APPEND LIB_LIST ws2_32.lib userenv.lib psapi.lib iphlpapi.lib) -endif() - -if (${CMAKE_SYSTEM_NAME} MATCHES "QNX") - list(APPEND LIB_LIST socket) -endif() +list(APPEND LIB_LIST ${LIB_LIST_AT_END}) # -# add libs here that need to be at the end of the link order +# Second-level CMakeLists # -if (UNIX) - list(APPEND LIB_LIST m) -endif() - -if(ILLUMOS) - list(APPEND LIB_LIST socket) -endif() - -if (HAIKU) - list(APPEND LIB_LIST network) -endif() +include_directories("${PROJECT_SOURCE_DIR}/lib") +add_subdirectory(lib) -if (LWS_HAVE_LIBCAP) - list(APPEND LIB_LIST cap ) -endif() -if (UNIX) - list(APPEND LIB_LIST dl) -endif() -if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) - list(APPEND LIB_LIST "${ZLIB_LIBRARIES}") +if(WIN32 AND NOT CYGWIN) + set(DEF_INSTALL_CMAKE_DIR cmake) +else() + set(DEF_INSTALL_CMAKE_DIR lib${LIB_SUFFIX}/cmake/libwebsockets) endif() -# Setup the linking for all libs. -foreach (lib ${LWS_LIBRARIES}) - target_link_libraries(${lib} ${LIB_LIST}) -endforeach() - -set (temp ${CMAKE_REQUIRED_LIBRARIES}) -set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST} ${CMAKE_REQUIRED_LIBRARIES}) +set(LWS__INCLUDE_DIRS + "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}") -if (LWS_WITH_ZLIB) - if (LWS_WITH_BUNDLED_ZLIB) - if (WIN32) - # it's trying to delete internal zlib entry - LIST(REMOVE_AT CMAKE_REQUIRED_LIBRARIES 0 ) - endif() - endif() -endif() +configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config.cmake.in + ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/libwebsockets-config.cmake + @ONLY) -if (NOT VARIA) - set(VARIA "") -endif() +# Generate version info for both build-tree and install-tree. +configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config-version.cmake.in + ${PROJECT_BINARY_DIR}/libwebsockets-config-version.cmake + @ONLY) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_info_callback LWS_HAVE_SSL_SET_INFO_CALLBACK) -CHECK_FUNCTION_EXISTS(${VARIA}X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host) -CHECK_FUNCTION_EXISTS(${VARIA}RSA_set0_key LWS_HAVE_RSA_SET0_KEY) -CHECK_FUNCTION_EXISTS(${VARIA}X509_get_key_usage LWS_HAVE_X509_get_key_usage) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_PKEY_new_raw_private_key LWS_HAVE_SSL_CTX_EVP_PKEY_new_raw_private_key) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_get0_certificate LWS_HAVE_SSL_CTX_get0_certificate) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_get0_alpn_selected LWS_HAVE_SSL_get0_alpn_selected) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_alpn_protos LWS_HAVE_SSL_set_alpn_protos) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb8 LWS_HAVE_EVP_aes_128_cfb8) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb128 LWS_HAVE_EVP_aes_128_cfb128) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb8 LWS_HAVE_EVP_aes_192_cfb8) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb128 LWS_HAVE_EVP_aes_192_cfb128) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb8 LWS_HAVE_EVP_aes_256_cfb8) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb128 LWS_HAVE_EVP_aes_256_cfb128) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_xts LWS_HAVE_EVP_aes_128_xts) -CHECK_FUNCTION_EXISTS(${VARIA}RSA_verify_pss_mgf1 LWS_HAVE_RSA_verify_pss_mgf1) -CHECK_FUNCTION_EXISTS(${VARIA}HMAC_CTX_new LWS_HAVE_HMAC_CTX_new) -CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set_ciphersuites LWS_HAVE_SSL_CTX_set_ciphersuites) -if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) - if (UNIX) - set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) - endif() -CHECK_C_SOURCE_COMPILES("#include \nint main(void) { STACK_OF(X509) *c = NULL; SSL_CTX *ctx = NULL; return (int)SSL_CTX_get_extra_chain_certs_only(ctx, &c); }\n" LWS_HAVE_SSL_EXTRA_CHAIN_CERTS) -CHECK_C_SOURCE_COMPILES("#include \nint main(void) { EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX_free(md_ctx); return 0; }\n" LWS_HAVE_EVP_MD_CTX_free) -CHECK_FUNCTION_EXISTS(${VARIA}ECDSA_SIG_set0 LWS_HAVE_ECDSA_SIG_set0) -CHECK_FUNCTION_EXISTS(${VARIA}BN_bn2binpad LWS_HAVE_BN_bn2binpad) -CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_wrap LWS_HAVE_EVP_aes_128_wrap) -CHECK_FUNCTION_EXISTS(${VARIA}EC_POINT_get_affine_coordinates LWS_HAVE_EC_POINT_get_affine_coordinates) -endif() -if (LWS_WITH_MBEDTLS) - set(LWS_HAVE_TLS_CLIENT_METHOD 1) - if (NOT LWS_PLAT_FREERTOS) - # not supported in esp-idf openssl wrapper yet, but is in our version - set(LWS_HAVE_X509_VERIFY_PARAM_set1_host 1) - endif() +# Generate the config file for the build-tree. +set(LWS__INCLUDE_DIRS + "${PROJECT_SOURCE_DIR}/lib" + "${PROJECT_BINARY_DIR}") +set(LIBWEBSOCKETS_INCLUDE_DIRS ${LWS__INCLUDE_DIRS} CACHE PATH "Libwebsockets include directories") +configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config.cmake.in + ${PROJECT_BINARY_DIR}/libwebsockets-config.cmake + @ONLY) +set(LWS_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") - CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_alpn_protocols LWS_HAVE_mbedtls_ssl_conf_alpn_protocols) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_ca_chain LWS_HAVE_mbedtls_ssl_set_hs_ca_chain) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_own_cert LWS_HAVE_mbedtls_ssl_set_hs_own_cert) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_authmode LWS_HAVE_mbedtls_ssl_set_hs_authmode) - CHECK_FUNCTION_EXISTS(mbedtls_net_init LWS_HAVE_mbedtls_net_init) - CHECK_FUNCTION_EXISTS(mbedtls_md_setup LWS_HAVE_mbedtls_md_setup) # not on xenial 2.2 - CHECK_FUNCTION_EXISTS(mbedtls_rsa_complete LWS_HAVE_mbedtls_rsa_complete) # not on xenial 2.2 - CHECK_FUNCTION_EXISTS(mbedtls_internal_aes_encrypt LWS_HAVE_mbedtls_internal_aes_encrypt) # not on xenial 2.2 -else() -CHECK_FUNCTION_EXISTS(${VARIA}TLS_client_method LWS_HAVE_TLS_CLIENT_METHOD) -CHECK_FUNCTION_EXISTS(${VARIA}TLSv1_2_client_method LWS_HAVE_TLSV1_2_CLIENT_METHOD) +# Export targets (This is used for other CMake projects to easily find the libraries and include files). +if (LWS_WITH_EXPORT_LWSTARGETS) + export(TARGETS ${LWS_LIBRARIES} + FILE "${PROJECT_BINARY_DIR}/LibwebsocketsTargets.cmake") endif() -# ideally we want to use pipe2() -CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE\n#include \nint main(void) {int fd[2];\n return pipe2(fd, 0);\n}\n" LWS_HAVE_PIPE2) -# old mbedtls has everything in mbedtls/net.h +set(libwebsockets_DIR ${PROJECT_BINARY_DIR}) +set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +message("DIR ${libwebsockets_DIR} CMP ${CMAKE_MODULE_PATH}") -CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return 0;}\n" LWS_HAVE_MBEDTLS_NET_SOCKETS) +if (LWS_WITH_MINIMAL_EXAMPLES) + add_subdirectory(minimal-examples) +endif() -# tcp keepalive needs this on linux to work practically... but it only exists -# after kernel 2.6.37 +if (NOT LWS_WITHOUT_TESTAPPS) + add_subdirectory(test-apps) +endif() -CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return TCP_USER_TIMEOUT; }\n" LWS_HAVE_TCP_USER_TIMEOUT) +add_subdirectory(plugins) +add_subdirectory(lwsws) -set(CMAKE_REQUIRED_LIBRARIES ${temp}) # Generate the lws_config.h that includes all the public compilation settings. configure_file( "${PROJECT_SOURCE_DIR}/cmake/lws_config.h.in" "${PROJECT_BINARY_DIR}/lws_config.h") + +add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/include/lws_config.h + ${PROJECT_BINARY_DIR}/include/libwebsockets + ${PROJECT_BINARY_DIR}/include/libwebsockets.h + COMMENT "Creating build include dir" + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets.h + ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets.h + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libwebsockets/ + ${CMAKE_CURRENT_BINARY_DIR}/include/libwebsockets + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/lws_config.h + ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h + MAIN_DEPENDENCY ${PROJECT_BINARY_DIR}/lws_config.h +) -# Generate the lws_config.h that includes all the private compilation settings. -configure_file( - "${PROJECT_SOURCE_DIR}/cmake/lws_config_private.h.in" - "${PROJECT_BINARY_DIR}/lws_config_private.h") - -# Generate self-signed SSL certs for the test-server. - -if (LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL) - message("Searching for OpenSSL executable and dlls") - find_package(OpenSSLbins) - message("OpenSSL executable: ${OPENSSL_EXECUTABLE}") - if (OPENSSL_EXECUTABLE MATCHES "^$") - set(OPENSSL_EXECUTABLE openssl) - endif() - if (NOT OPENSSL_EXECUTABLE) - set(OPENSSL_EXECUTABLE openssl) - endif() +add_custom_target(GENHDR DEPENDS ${PROJECT_BINARY_DIR}/include/lws_config.h) -endif() +file(GLOB HDR_PUBLIC1 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} include/libwebsockets/*.h) +file(GLOB HDR_PUBLIC2 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} include/libwebsockets.h) +file(GLOB HDR_PUBLIC3 RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/include/lws_config.h) +list(APPEND HDR_PUBLIC ${HDR_PUBLIC1} ${HDR_PUBLIC2} ${HDR_PUBLIC3}) -set(GENCERTS 0) +set_source_files_properties(${HDR_PUBLIC} PROPERTIES GENERATED 1) -if (LWS_WITH_SSL AND OPENSSL_EXECUTABLE AND NOT LWS_WITHOUT_TEST_SERVER AND NOT LWS_WITHOUT_SERVER AND NOT LWS_WITHOUT_TESTAPPS) - set(GENCERTS 1) -endif() -if (LWS_PLAT_FREERTOS) - set(GENCERTS 1) +if (LWS_WITH_STATIC) + add_dependencies(websockets GENHDR) endif() -message(" GENCERTS = ${GENCERTS}") -if (GENCERTS) - message("Generating SSL Certificates for the test-server...") - - set(TEST_SERVER_SSL_KEY "${PROJECT_BINARY_DIR}/libwebsockets-test-server.key.pem") - set(TEST_SERVER_SSL_CERT "${PROJECT_BINARY_DIR}/libwebsockets-test-server.pem") - - if (WIN32) - if (MINGW) - message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -subj \"/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost\" -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") - execute_process( - COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -subj "/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost" -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" - RESULT_VARIABLE OPENSSL_RETURN_CODE) - else() - file(WRITE "${PROJECT_BINARY_DIR}/openssl_input.txt" - "GB\n" - "Erewhon\n" - "All around\n" - "libwebsockets-test\n" - "localhost\n" - "none@invalid.org\n\n" - ) - - # The "type" command is a bit picky with paths. - file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/openssl_input.txt" OPENSSL_INPUT_WIN_PATH) - message("OPENSSL_INPUT_WIN_PATH = ${OPENSSL_INPUT_WIN_PATH}") - message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") - - execute_process( - COMMAND cmd /c type "${OPENSSL_INPUT_WIN_PATH}" - COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" - RESULT_VARIABLE OPENSSL_RETURN_CODE - OUTPUT_QUIET ERROR_QUIET) - - message("\n") - endif() - - if (OPENSSL_RETURN_CODE) - message(WARNING "!!! Failed to generate SSL certificate for Test Server using cmd.exe !!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") - else() - message("SUCCSESFULLY generated SSL certificate") - endif() - else() - # Unix. - execute_process( - COMMAND printf "GB\\nErewhon\\nAll around\\nlibwebsockets-test\\n\\nlocalhost\\nnone@invalid.org\\n" - COMMAND "${OPENSSL_EXECUTABLE}" - req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" - RESULT_VARIABLE OPENSSL_RETURN_CODE - # OUTPUT_QUIET ERROR_QUIET - ) - - if (OPENSSL_RETURN_CODE) - message(WARNING "!!! Failed to generate SSL certificate for Test Server!!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") - else() - message("SUCCESSFULLY generated SSL certificate") - endif() - endif() - - list(APPEND TEST_SERVER_DATA - "${TEST_SERVER_SSL_KEY}" - "${TEST_SERVER_SSL_CERT}") +if (LWS_WITH_SHARED) + add_dependencies(websockets_shared GENHDR) endif() - -# -# Test applications # -set(TEST_APP_LIST) -if ((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) - # - # Helper function for adding a test app. - # - macro(create_test_app TEST_NAME MAIN_SRC S2 S3 S4 S5 S6) - - set(TEST_SRCS ${MAIN_SRC}) - set(TEST_HDR) - if ("${S2}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S2}) - endif() - if ("${S3}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S3}) - endif() - if ("${S4}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S4}) - endif() - if ("${S5}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S5}) - endif() - if ("${S6}" STREQUAL "") - else() - list(APPEND TEST_SRCS ${S6}) - endif() - if (WIN32) - list(APPEND TEST_SRCS - ${WIN32_HELPERS_PATH}/getopt.c - ${WIN32_HELPERS_PATH}/getopt_long.c - ${WIN32_HELPERS_PATH}/gettimeofday.c - ) - - list(APPEND TEST_HDR - ${WIN32_HELPERS_PATH}/getopt.h - ${WIN32_HELPERS_PATH}/gettimeofday.h - ) - endif(WIN32) - - source_group("Headers Private" FILES ${TEST_HDR}) - source_group("Sources" FILES ${TEST_SRCS}) - add_executable(${TEST_NAME} ${TEST_SRCS} ${TEST_HDR}) - - if (LWS_LINK_TESTAPPS_DYNAMIC) - if (NOT LWS_WITH_SHARED) - message(FATAL_ERROR "Build of the shared library is disabled. LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_SHARED.") - endif() - target_link_libraries(${TEST_NAME} websockets_shared) - add_dependencies(${TEST_NAME} websockets_shared) - else() - if (NOT LWS_WITH_STATIC) - message(FATAL_ERROR "Build of the static library is disabled. Disabled LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_STATIC.") - endif() - target_link_libraries(${TEST_NAME} websockets) - add_dependencies(${TEST_NAME} websockets) - if (UNIX AND LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) - target_link_libraries(${TEST_NAME} dl) - endif() - endif() - - if (LWS_WITH_HTTP_STREAM_COMPRESSION) - target_link_libraries(${TEST_NAME} z) - endif() - - # Set test app specific defines. - set_property(TARGET ${TEST_NAME} - PROPERTY COMPILE_DEFINITIONS - INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" - ) - - # Prefix the binary names with libwebsockets. - set_target_properties(${TEST_NAME} - PROPERTIES - OUTPUT_NAME libwebsockets-${TEST_NAME}) - - # Add to the list of tests. - list(APPEND TEST_APP_LIST ${TEST_NAME}) - endmacro() - - if (UNIX AND LWS_WITH_PLUGINS) - set(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") - if(NOT((${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") OR (${CMAKE_SYSTEM_NAME} MATCHES "QNX"))) - target_link_libraries(websockets dl) - endif() - endif() - - if (NOT LWS_WITHOUT_SERVER) - # - # test-server - # - if (NOT LWS_WITHOUT_TEST_SERVER) - create_test_app(test-server "test-apps/test-server.c" - "" - "" - "" - "" - "") - - if (LWS_WITH_CGI AND LWS_WITH_TLS) - create_test_app(test-sshd "test-apps/test-sshd.c" - "" - "" - "" - "" - "") - target_include_directories(test-sshd PRIVATE "${PROJECT_SOURCE_DIR}/plugins/ssh-base/include") - - endif() - - endif() - - # - # test-server-extpoll - # - if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL AND NOT WIN32) - create_test_app(test-server-extpoll - "test-apps/test-server.c" - "" - "" - "" - "" - "") - # Set defines for this executable only. - set_property( - TARGET test-server-extpoll - PROPERTY COMPILE_DEFINITIONS - EXTERNAL_POLL - INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" - ) - - # We need to link against winsock code. - if (WIN32) - target_link_libraries(test-server-extpoll ws2_32.lib) - endif(WIN32) - endif() - - if (LWS_WITH_LEJP) - create_test_app( - test-lejp - "test-apps/test-lejp.c" - "" - "" - "" - "" - "") - endif() - - # Data files for running the test server. - list(APPEND TEST_SERVER_DATA - "${PROJECT_SOURCE_DIR}/test-apps/favicon.ico" - "${PROJECT_SOURCE_DIR}/test-apps/leaf.jpg" - "${PROJECT_SOURCE_DIR}/test-apps/candide.zip" - "${PROJECT_SOURCE_DIR}/test-apps/libwebsockets.org-logo.svg" - "${PROJECT_SOURCE_DIR}/test-apps/http2.png" - "${PROJECT_SOURCE_DIR}/test-apps/wss-over-h2.png" - "${PROJECT_SOURCE_DIR}/test-apps/lws-common.js" - "${PROJECT_SOURCE_DIR}/test-apps/test.html" - "${PROJECT_SOURCE_DIR}/test-apps/test.css" - "${PROJECT_SOURCE_DIR}/test-apps/test.js") - - add_custom_command(TARGET test-server - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E make_directory "$/../share/libwebsockets-test-server") - - # Copy the file needed to run the server so that the test apps can - # reach them from their default output location - foreach (TEST_FILE ${TEST_SERVER_DATA}) - if (EXISTS ${TEST_FILE}) - add_custom_command(TARGET test-server - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy "${TEST_FILE}" "$/../share/libwebsockets-test-server" VERBATIM) - endif() - endforeach() - endif(NOT LWS_WITHOUT_SERVER) - - if (NOT LWS_WITHOUT_CLIENT) - # - # test-client - # - if (NOT LWS_WITHOUT_TEST_CLIENT) - create_test_app(test-client "test-apps/test-client.c" "" "" "" "" "") - endif() - - endif(NOT LWS_WITHOUT_CLIENT) - - - if (LWS_WITH_PLUGINS AND LWS_WITH_SHARED) - macro(create_plugin PLUGIN_NAME PLUGIN_INCLUDE MAIN_SRC S2 S3) - - set(PLUGIN_SRCS ${MAIN_SRC}) - - if ("${S2}" STREQUAL "") - else() - list(APPEND PLUGIN_SRCS ${S2}) - endif() - if ("${S3}" STREQUAL "") - else() - list(APPEND PLUGIN_SRCS ${S3}) - endif() - - if (WIN32) - list(APPEND PLUGIN_SRCS - ${WIN32_HELPERS_PATH}/getopt.c - ${WIN32_HELPERS_PATH}/getopt_long.c - ${WIN32_HELPERS_PATH}/gettimeofday.c - ) - - list(APPEND PLUGIN_HDR - ${WIN32_HELPERS_PATH}/getopt.h - ${WIN32_HELPERS_PATH}/gettimeofday.h - ) - endif(WIN32) - - source_group("Headers Private" FILES ${PLUGIN_HDR}) - source_group("Sources" FILES ${PLUGIN_SRCS}) - add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SRCS} ${PLUGIN_HDR}) - - target_link_libraries(${PLUGIN_NAME} websockets_shared) - add_dependencies(${PLUGIN_NAME} websockets_shared) - include_directories(${PLUGIN_INCLUDE}) - - # Set test app specific defines. - set_property(TARGET ${PLUGIN_NAME} - PROPERTY COMPILE_DEFINITIONS - INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/plugins" - ) - - SET_TARGET_PROPERTIES(${PLUGIN_NAME} - PROPERTIES COMPILE_FLAGS ${CMAKE_C_FLAGS}) - -# set_target_properties(${PLUGIN_NAME} -# PROPERTIES -# OUTPUT_NAME ${PLUGIN_NAME}) - - list(APPEND PLUGINS_LIST ${PLUGIN_NAME}) - - endmacro() - -if (LWS_ROLE_WS) - create_plugin(protocol_dumb_increment "" - "plugins/protocol_dumb_increment.c" "" "") - create_plugin(protocol_lws_mirror "" - "plugins/protocol_lws_mirror.c" "" "") - create_plugin(protocol_lws_status "" - "plugins/protocol_lws_status.c" "" "") - create_plugin(protocol_lws_table_dirlisting "" - "plugins/generic-table/protocol_table_dirlisting.c" "" "") - if (NOT WIN32) - create_plugin(protocol_lws_raw_test "" - "plugins/protocol_lws_raw_test.c" "" "") - - if (UNIX AND LWS_HAVE_PTHREAD_H) - create_plugin(protocol_deaddrop "" - "plugins/deaddrop/protocol_lws_deaddrop.c" "" "") - endif() - endif() - - if (LWS_WITH_SERVER_STATUS) - create_plugin(protocol_lws_server_status "" - "plugins/protocol_lws_server_status.c" "" "") - endif() - - if (NOT LWS_WITHOUT_CLIENT) - create_plugin(protocol_client_loopback_test "" - "plugins/protocol_client_loopback_test.c" "" "") - endif() - -endif(LWS_ROLE_WS) - - create_plugin(protocol_post_demo "" - "plugins/protocol_post_demo.c" "" "") - -if (LWS_ROLE_RAW_PROXY) - create_plugin(protocol_lws_raw_proxy "" - "plugins/raw-proxy/protocol_lws_raw_proxy.c" "" "") -endif() - -if (LWS_WITH_FTS) - create_plugin(protocol_fulltext_demo "" - "plugins/protocol_fulltext_demo.c" "" "") -endif() - - -if (LWS_WITH_SSL) - create_plugin(protocol_lws_ssh_base "plugins/ssh-base/include" - "plugins/ssh-base/sshd.c;plugins/ssh-base/telnet.c;plugins/ssh-base/kex-25519.c" "plugins/ssh-base/crypto/chacha.c;plugins/ssh-base/crypto/ed25519.c;plugins/ssh-base/crypto/fe25519.c;plugins/ssh-base/crypto/ge25519.c;plugins/ssh-base/crypto/poly1305.c;plugins/ssh-base/crypto/sc25519.c;plugins/ssh-base/crypto/smult_curve25519_ref.c" "") - create_plugin(protocol_lws_sshd_demo "plugins/ssh-base/include" "plugins/protocol_lws_sshd_demo.c" "" "") - - include_directories("${PROJECT_SOURCE_DIR}/plugins/ssh-base/include") -endif() - - - -if (LWS_WITH_ACME) - create_plugin(protocol_lws_acme_client "" - "plugins/acme-client/protocol_lws_acme_client.c" "" "") -endif() - -if (LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS) - create_plugin(protocol_generic_sessions "" - "plugins/generic-sessions/protocol_generic_sessions.c" - "plugins/generic-sessions/utils.c" - "plugins/generic-sessions/handlers.c") - - if (WIN32) - target_link_libraries(protocol_generic_sessions ${LWS_SQLITE3_LIBRARIES}) - else() - target_link_libraries(protocol_generic_sessions sqlite3 ) - endif(WIN32) - - create_plugin(protocol_lws_messageboard "" - "plugins/generic-sessions/protocol_lws_messageboard.c" "" "") - if (WIN32) - target_link_libraries(protocol_lws_messageboard ${LWS_SQLITE3_LIBRARIES}) - else() - target_link_libraries(protocol_lws_messageboard sqlite3 ) - endif(WIN32) - -endif(LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS) - - - endif(LWS_WITH_PLUGINS AND LWS_WITH_SHARED) - - # - # Copy OpenSSL dlls to the output directory on Windows. - # (Otherwise we'll get an error when trying to run) - # - if (WIN32 AND LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL) - if(OPENSSL_BIN_FOUND) - message("OpenSSL dlls found:") - message(" Libeay: ${LIBEAY_BIN}") - message(" SSLeay: ${SSLEAY_BIN}") - - foreach(TARGET_BIN ${TEST_APP_LIST}) - add_custom_command(TARGET ${TARGET_BIN} - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy "${LIBEAY_BIN}" "$" VERBATIM) - add_custom_command(TARGET ${TARGET_BIN} - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy "${SSLEAY_BIN}" "$" VERBATIM) - - # - # Win32: if we are using libuv, also need to copy it in the output dir - # - if (WIN32 AND LWS_WITH_LIBUV) - STRING(REPLACE ".lib" ".dll" LIBUV_BIN ${LIBUV_LIBRARIES}) - add_custom_command(TARGET ${TARGET_BIN} - POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy "${LIBUV_BIN}" "$" VERBATIM) - endif() - endforeach() - endif() - endif() -endif((LWS_ROLE_H1 OR LWS_ROLE_H2) AND NOT LWS_WITHOUT_TESTAPPS) - -if (LWS_WITH_LWSWS) - list(APPEND LWSWS_SRCS - "lwsws/main.c" - ) - - if (WIN32) - list(APPEND LWSWS_SRCS - ${WIN32_HELPERS_PATH}/getopt.c - ${WIN32_HELPERS_PATH}/getopt_long.c - ${WIN32_HELPERS_PATH}/gettimeofday.c - ) - - list(APPEND LWSWS_HDR - ${WIN32_HELPERS_PATH}/getopt.h - ${WIN32_HELPERS_PATH}/gettimeofday.h - ) - endif(WIN32) - - source_group("Headers Private" FILES ${LWSWS_HDR}) - source_group("Sources" FILES ${LWSWS_SRCS}) - add_executable("lwsws" ${LWSWS_SRCS} ${LWSWS_HDR}) - - target_link_libraries("lwsws" websockets_shared) - add_dependencies("lwsws" websockets_shared) - - # Set test app specific defines. - set_property(TARGET "lwsws" - PROPERTY COMPILE_DEFINITIONS - INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" - ) -endif (LWS_WITH_LWSWS) - -# secure streams plugins - -if (LWS_WITH_SECURE_STREAMS) - # - # Helper function for adding a secure stream plugin - # - macro(create_ss_plugin NAME S2 S3 S4 S5 S6) - - set(SSP_SRCS) - set(SSP_PUBLIC_HDR) - set(SSP_HDR) - - if ("${S2}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S2}) - endif() - if ("${S3}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S3}) - endif() - if ("${S4}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S4}) - endif() - if ("${S5}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S5}) - endif() - if ("${S6}" STREQUAL "") - else() - list(APPEND SSP_SRCS - lib/secure-streams/plugins/${NAME}/${S6}) - endif() - - source_group("Headers Private" FILES ${SSP_HDR}) - source_group("Sources" FILES ${SSP_SRCS}) - - add_library( ${NAME} STATIC - ${SSP_HDR} ${SSP_PUBLIC_HDR} ${SSP_SRCS} ) - - add_dependencies(${NAME} websockets_shared) - list(APPEND SS_PLUGINS_LIST ${NAME}) - endmacro() - - include_directories(lib/secure-streams) - - create_ss_plugin(ssp-h1url "h1url.c" "" "" "" "") -endif() - -if (UNIX) - -# Generate and install pkgconfig. -# (This is not indented, because the tabs will be part of the output) -file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets.pc" -"prefix=\"${CMAKE_INSTALL_PREFIX}\" -exec_prefix=\${prefix} -libdir=\${exec_prefix}/lib${LIB_SUFFIX} -includedir=\${prefix}/include - -Name: libwebsockets -Description: Websockets server and client library -Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} - -Libs: -L\${libdir} -lwebsockets -Cflags: -I\${includedir}" -) - - install(FILES "${PROJECT_BINARY_DIR}/libwebsockets.pc" - DESTINATION lib${LIB_SUFFIX}/pkgconfig) - -file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" -"prefix=\"${CMAKE_INSTALL_PREFIX}\" -exec_prefix=\${prefix} -libdir=\${exec_prefix}/lib${LIB_SUFFIX} -includedir=\${prefix}/include - -Name: libwebsockets_static -Description: Websockets server and client static library -Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} - -Libs: -L\${libdir} -lwebsockets_static -Libs.private: -Cflags: -I\${includedir}" -) - - install(FILES "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" - DESTINATION lib${LIB_SUFFIX}/pkgconfig) - - -endif(UNIX) - # # Installation preparations. # -if(WIN32 AND NOT CYGWIN) - set(DEF_INSTALL_CMAKE_DIR cmake) -else() - set(DEF_INSTALL_CMAKE_DIR lib${LIB_SUFFIX}/cmake/libwebsockets) -endif() - -set(LWS_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") - -# Export targets (This is used for other CMake projects to easily find the libraries and include files). -if (LWS_WITH_EXPORT_LWSTARGETS) - export(TARGETS ${LWS_LIBRARIES} - FILE "${PROJECT_BINARY_DIR}/LibwebsocketsTargets.cmake") -endif() - export(PACKAGE libwebsockets) -# Generate the config file for the build-tree. -set(LWS__INCLUDE_DIRS - "${PROJECT_SOURCE_DIR}/lib" - "${PROJECT_BINARY_DIR}") -set(LIBWEBSOCKETS_INCLUDE_DIRS ${LWS__INCLUDE_DIRS} CACHE PATH "Libwebsockets include directories") -configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfig.cmake.in - ${PROJECT_BINARY_DIR}/LibwebsocketsConfig.cmake - @ONLY) +install(DIRECTORY include/libwebsockets + DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev_headers) +install(FILES ${PROJECT_BINARY_DIR}/include/libwebsockets.h ${PROJECT_BINARY_DIR}/include/lws_config.h + DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev_headers) # Generate the config file for the installation tree. get_filename_component(LWS_ABSOLUTE_INSTALL_CMAKE_DIR ${LWS_INSTALL_CMAKE_DIR} ABSOLUTE) @@ -2962,139 +864,14 @@ file(RELATIVE_PATH "${LWS_ABSOLUTE_INSTALL_CMAKE_DIR}" "${LWS_ABSOLUTE_INSTALL_INCLUDE_DIR}") # Calculate the relative directory from the cmake dir. -# Note the EVENT_CMAKE_DIR is defined in JanssonConfig.cmake.in, -# we escape it here so it's evaluated when it is included instead -# so that the include dirs are given relative to where the -# config file is located. -set(LWS__INCLUDE_DIRS - "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}") -configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfig.cmake.in - ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibwebsocketsConfig.cmake - @ONLY) - -# Generate version info for both build-tree and install-tree. -configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfigVersion.cmake.in - ${PROJECT_BINARY_DIR}/LibwebsocketsConfigVersion.cmake - @ONLY) - - set_target_properties(${LWS_LIBRARIES} - PROPERTIES PUBLIC_HEADER "${HDR_PUBLIC}") - -# -# Installation. -# - -install(DIRECTORY include/libwebsockets - DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev_headers) - -# Install libs and headers. -install(TARGETS ${LWS_LIBRARIES} - EXPORT LibwebsocketsTargets - LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries - ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries - RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT libraries # Windows DLLs - PUBLIC_HEADER DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev) - -set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") -set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files") - -# Install test apps. -if (NOT LWS_WITHOUT_TESTAPPS) - install(TARGETS ${TEST_APP_LIST} - RUNTIME DESTINATION ${LWS_INSTALL_EXAMPLES_DIR} - COMPONENT examples) - set(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Example files") -endif() - -# lwsws -if (LWS_WITH_LWSWS) - install(TARGETS lwsws - RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT lwsws ) -endif() - -# Programs shared files used by the test-server. -if (NOT LWS_WITHOUT_TESTAPPS AND NOT LWS_WITHOUT_SERVER) - install(FILES ${TEST_SERVER_DATA} - DESTINATION share/libwebsockets-test-server - COMPONENT examples) - - install(FILES "${PROJECT_SOURCE_DIR}/test-apps/private/index.html" - DESTINATION share/libwebsockets-test-server/private - COMPONENT examples) -if (LWS_WITH_CGI) - set(CGI_TEST_SCRIPT "${PROJECT_SOURCE_DIR}/test-apps/lws-cgi-test.sh") - install(FILES ${CGI_TEST_SCRIPT} - PERMISSIONS OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ - DESTINATION share/libwebsockets-test-server - COMPONENT examples) - endif() -endif() - - -if (NOT LWS_WITHOUT_TEST_SERVER AND NOT LWS_WITHOUT_SERVER AND NOT LWS_WITHOUT_TESTAPPS) - install(FILES test-apps/lws-ssh-test-keys;test-apps/lws-ssh-test-keys.pub - DESTINATION share/libwebsockets-test-server - COMPONENT examples) -endif() - -# plugins - -if (LWS_WITH_PLUGINS) - install(TARGETS ${PLUGINS_LIST} - PERMISSIONS OWNER_WRITE OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ - DESTINATION share/libwebsockets-test-server/plugins - COMPONENT plugins) - - if (NOT WIN32) - install(FILES plugins/deaddrop/assets/index.html;plugins/deaddrop/assets/deaddrop.js;plugins/deaddrop/assets/deaddrop.css;plugins/deaddrop/assets/drop.svg - DESTINATION share/libwebsockets-test-server/deaddrop - COMPONENT plugins) - endif() - - -if (LWS_WITH_SERVER_STATUS) - install(FILES plugins/server-status.html;plugins/server-status.js;plugins/server-status.css;plugins/lwsws-logo.png - DESTINATION share/libwebsockets-test-server/server-status - COMPONENT examples) -endif() -if (LWS_WITH_GENERIC_SESSIONS) - install(FILES - plugins/generic-sessions/assets/lwsgs-logo.png - plugins/generic-sessions/assets/seats.jpg - plugins/generic-sessions/assets/failed-login.html - plugins/generic-sessions/assets/lwsgs.js - plugins/generic-sessions/assets/lwsgs.css - plugins/generic-sessions/assets/post-register-fail.html - plugins/generic-sessions/assets/post-register-ok.html - plugins/generic-sessions/assets/post-verify-ok.html - plugins/generic-sessions/assets/post-verify-fail.html - plugins/generic-sessions/assets/sent-forgot-ok.html - plugins/generic-sessions/assets/sent-forgot-fail.html - plugins/generic-sessions/assets/post-forgot-ok.html - plugins/generic-sessions/assets/post-forgot-fail.html - plugins/generic-sessions/assets/index.html - DESTINATION share/libwebsockets-test-server/generic-sessions - COMPONENT examples) - install(FILES plugins/generic-sessions/assets/successful-login.html - DESTINATION share/libwebsockets-test-server/generic-sessions/needauth - COMPONENT examples) - install(FILES plugins/generic-sessions/assets/admin-login.html - DESTINATION share/libwebsockets-test-server/generic-sessions/needadmin - COMPONENT examples) -endif() - - install(FILES - plugins/generic-table/assets/lwsgt.js - plugins/generic-table/assets/index.html - DESTINATION share/libwebsockets-test-server/generic-table - COMPONENT examples) - -endif() +set_target_properties(${LWS_LIBRARIES} + PROPERTIES PUBLIC_HEADER "${HDR_PUBLIC}") # Install the LibwebsocketsConfig.cmake and LibwebsocketsConfigVersion.cmake install(FILES - "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibwebsocketsConfig.cmake" - "${PROJECT_BINARY_DIR}/LibwebsocketsConfigVersion.cmake" + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/libwebsockets-config.cmake" + "${PROJECT_BINARY_DIR}/libwebsockets-config-version.cmake" + "${PROJECT_SOURCE_DIR}/cmake/LwsCheckRequirements.cmake" DESTINATION "${LWS_INSTALL_CMAKE_DIR}" COMPONENT dev) # Install exports for the install-tree. @@ -3110,41 +887,6 @@ set(CPACK_SOURCE_IGNORE_FILES $(CPACK_SOURCE_IGNORE_FILES) "/.git/" "/build/" "\ add_custom_target(dist COMMAND "${CMAKE_MAKE_PROGRAM}" package_source) -# These will be available to parent projects including libwebsockets using add_subdirectory() -set(LIBWEBSOCKETS_LIBRARIES ${LWS_LIBRARIES} CACHE STRING "Libwebsocket libraries") -if (LWS_WITH_STATIC) - set(LIBWEBSOCKETS_LIBRARIES_STATIC websockets CACHE STRING "Libwebsocket static library") -endif() -if (LWS_WITH_SHARED) - set(LIBWEBSOCKETS_LIBRARIES_SHARED websockets_shared CACHE STRING "Libwebsocket shared library") -endif() - -if (LWS_WITH_MINIMAL_EXAMPLES) - MACRO(SUBDIRLIST result curdir) - FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) - SET(dirlist "") - - FOREACH(child ${children}) - IF(IS_DIRECTORY ${curdir}/${child}) - LIST(APPEND dirlist ${child}) - ENDIF() - ENDFOREACH() - - SET(${result} ${dirlist}) - ENDMACRO() - - SUBDIRLIST(SUBDIRS "${PROJECT_SOURCE_DIR}/minimal-examples") - FOREACH(subdir ${SUBDIRS}) - - SUBDIRLIST(SUBDIRS2 "${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}") - FOREACH(subdir2 ${SUBDIRS2}) - if (EXISTS "${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}/CMakeLists.txt") - message("Processing ${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}") - add_subdirectory("${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}") - endif() - ENDFOREACH() - ENDFOREACH() -ENDIF() # This must always be last! include(CPack) diff --git a/cmake/FindLibWebSockets.cmake b/cmake/FindLibWebSockets.cmake deleted file mode 100644 index 1dfe1157..00000000 --- a/cmake/FindLibWebSockets.cmake +++ /dev/null @@ -1,33 +0,0 @@ -# This module tries to find libWebsockets library and include files -# -# LIBWEBSOCKETS_INCLUDE_DIR, path where to find libwebsockets.h -# LIBWEBSOCKETS_LIBRARY_DIR, path where to find libwebsockets.so -# LIBWEBSOCKETS_LIBRARIES, the library to link against -# LIBWEBSOCKETS_FOUND, If false, do not try to use libWebSockets -# -# This currently works probably only for Linux - -FIND_PATH ( LIBWEBSOCKETS_INCLUDE_DIR libwebsockets.h - /usr/local/include - /usr/include -) - -FIND_LIBRARY ( LIBWEBSOCKETS_LIBRARIES websockets - /usr/local/lib - /usr/lib -) - -GET_FILENAME_COMPONENT( LIBWEBSOCKETS_LIBRARY_DIR ${LIBWEBSOCKETS_LIBRARIES} PATH ) - -SET ( LIBWEBSOCKETS_FOUND "NO" ) -IF ( LIBWEBSOCKETS_INCLUDE_DIR ) - IF ( LIBWEBSOCKETS_LIBRARIES ) - SET ( LIBWEBSOCKETS_FOUND "YES" ) - ENDIF ( LIBWEBSOCKETS_LIBRARIES ) -ENDIF ( LIBWEBSOCKETS_INCLUDE_DIR ) - -MARK_AS_ADVANCED( - LIBWEBSOCKETS_LIBRARY_DIR - LIBWEBSOCKETS_INCLUDE_DIR - LIBWEBSOCKETS_LIBRARIES -) \ No newline at end of file diff --git a/cmake/LwsCheckRequirements.cmake b/cmake/LwsCheckRequirements.cmake new file mode 100644 index 00000000..b31298da --- /dev/null +++ b/cmake/LwsCheckRequirements.cmake @@ -0,0 +1,76 @@ +# If we are being built as part of lws, confirm current build config supports +# reqconfig, else skip building ourselves. +# +# If we are being built externally, confirm installed lws was configured to +# support reqconfig, else error out with a helpful message about the problem. +# +MACRO(require_lws_config reqconfig _val result) + + if (DEFINED ${reqconfig}) + if (${reqconfig}) + set (rq 1) + else() + set (rq 0) + endif() + else() + set(rq 0) + endif() + + if (${_val} EQUAL ${rq}) + set(SAME 1) + else() + set(SAME 0) + endif() + + if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) + if (${_val}) + message("${SAMP}: skipping as lws being built without ${reqconfig}") + else() + message("${SAMP}: skipping as lws built with ${reqconfig}") + endif() + set(${result} 0) + else() + if (LWS_WITH_MINIMAL_EXAMPLES) + set(MET ${SAME}) + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) + if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) + set(HAS_${reqconfig} 0) + else() + set(HAS_${reqconfig} 1) + endif() + if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) + set(MET 1) + else() + set(MET 0) + endif() + endif() + if (NOT MET) + if (${_val}) + message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") + else() + message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") + endif() + endif() + + endif() +ENDMACRO() + +MACRO(require_pthreads result) + CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) + if (NOT LWS_HAVE_PTHREAD_H) + if (LWS_WITH_MINIMAL_EXAMPLES) + set(${result} 0) + message("${SAMP}: skipping as no pthreads") + else() + message(FATAL_ERROR "threading support requires pthreads") + endif() + else() + if (WIN32) + set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) + else() + set(PTHREAD_LIB pthread) + endif() + endif() +ENDMACRO() + diff --git a/cmake/LibwebsocketsConfigVersion.cmake.in b/cmake/libwebsockets-config-version.cmake.in similarity index 100% rename from cmake/LibwebsocketsConfigVersion.cmake.in rename to cmake/libwebsockets-config-version.cmake.in diff --git a/cmake/LibwebsocketsConfig.cmake.in b/cmake/libwebsockets-config.cmake.in similarity index 100% rename from cmake/LibwebsocketsConfig.cmake.in rename to cmake/libwebsockets-config.cmake.in diff --git a/cmake/lws_config_private.h.in b/cmake/lws_config_private.h.in index 814e6641..51c72fcd 100644 --- a/cmake/lws_config_private.h.in +++ b/cmake/lws_config_private.h.in @@ -11,12 +11,6 @@ * LWS_OPENSSL_SUPPORT needs to be set also for this to work. */ #cmakedefine USE_CYASSL -/* Define to 1 if you have the header file. */ -#cmakedefine LWS_HAVE_DLFCN_H - -/* Define to 1 if you have the header file. */ -#cmakedefine LWS_HAVE_FCNTL_H - /* Define to 1 if you have the `fork' function. */ #cmakedefine LWS_HAVE_FORK @@ -33,19 +27,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine LWS_HAVE_MEMORY_H -/* Define to 1 if you have the `memset' function. */ -#cmakedefine LWS_HAVE_MEMSET - /* Define to 1 if you have the header file. */ #cmakedefine LWS_HAVE_NETINET_IN_H -/* Define to 1 if your system has a GNU libc compatible `realloc' function, - and to 0 otherwise. */ -#cmakedefine LWS_HAVE_REALLOC - -/* Define to 1 if you have the `socket' function. */ -#cmakedefine LWS_HAVE_SOCKET - /* Define to 1 if you have the header file. */ #cmakedefine LWS_HAVE_STDINT_H diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 8b26586e..f0f66c94 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -173,6 +173,19 @@ typedef unsigned long long lws_intptr_t; #endif +#ifndef LWS_EXTERN +#define LWS_EXTERN extern +#endif + +#ifdef _WIN32 +#define random rand +#else +#if !defined(LWS_PLAT_OPTEE) +#include +#include +#endif +#endif + #if defined(LWS_WITH_LIBEV) #include #endif /* LWS_WITH_LIBEV */ @@ -189,19 +202,6 @@ typedef unsigned long long lws_intptr_t; #include #endif /* LWS_WITH_LIBEVENT */ -#ifndef LWS_EXTERN -#define LWS_EXTERN extern -#endif - -#ifdef _WIN32 -#define random rand -#else -#if !defined(LWS_PLAT_OPTEE) -#include -#include -#endif -#endif - #if defined(LWS_WITH_TLS) #ifdef USE_WOLFSSL diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 00000000..9b6001c9 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,309 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +macro(add_subdir_include_dirs arg1) + add_subdirectory(${arg1}) + list(APPEND LWS_LIB_BUILD_INC_PATHS ${_CMAKE_INC_LIST}) +endmacro() + +# +# Plat specific build items +# + +if (LWS_PLAT_FREERTOS) + add_subdir_include_dirs(plat/freertos) + if (ESP_PLATFORM) + include_directories($ENV{IDF_PATH}/components/freertos/include + $ENV{IDF_PATH}/components/freertos/xtensa/include + $ENV{IDF_PATH}/components/xtensa/include + $ENV{IDF_PATH}/components/xtensa/esp32/include + $ENV{IDF_PATH}/components/esp_common/include + $ENV{IDF_PATH}/components/esp_timer/include + $ENV{IDF_PATH}/components/soc/include + $ENV{IDF_PATH}/components/soc/src/esp32/include + $ENV{IDF_PATH}/components/lwip/port/esp32/include + $ENV{IDF_PATH}/components/lwip/lwip/src/include + $ENV{IDF_PATH}/components/lwip/port/esp32/include + ${CMAKE_BINARY_DIR}/config + $ENV{IDF_PATH}/components/esp_rom/include + $ENV{IDF_PATH}/components/esp_system/include + $ENV{IDF_PATH}/components/lwip/include/apps/sntp + $ENV{IDF_PATH}/components/soc/soc/esp32/include + $ENV{IDF_PATH}/components/heap/include + $ENV{IDF_PATH}/components/mbedtls/mbedtls/include + $ENV{IDF_PATH}/components/mbedtls/port/include + $ENV{IDF_PATH}/components/esp_wifi/include + $ENV{IDF_PATH}/components/esp_event/include + $ENV{IDF_PATH}/components/esp_netif/include + $ENV{IDF_PATH}/components/esp_eth/include + $ENV{IDF_PATH}/components/driver/include + $ENV{IDF_PATH}/components/soc/soc/include + $ENV{IDF_PATH}/components/tcpip_adapter/include + $ENV{IDF_PATH}/components/lwip/include/apps + $ENV{IDF_PATH}/components/nvs_flash/include + $ENV{IDF_PATH}/components/esp32/include + $ENV{IDF_PATH}/components/spi_flash/include + $ENV{IDF_PATH}/components/mdns/include + $ENV{IDF_PATH}/components/lwip/lwip/src/include/lwip + $ENV{IDF_PATH}/components/lwip/lwip/src/include + $ENV{IDF_PATH}/components/lwip/lwip/src/include/lwip + $ENV{IDF_PATH}/components/newlib/platform_include ) + endif() + +else() + if (LWS_PLAT_OPTEE) + add_subdir_include_dirs(plat/optee) + else() + if (WIN32) + add_subdir_include_dirs(plat/windows) + else() + add_subdir_include_dirs(plat/unix) + endif() + endif() +endif() + +set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST} ${CMAKE_REQUIRED_LIBRARIES}) + +if (LWS_WITH_ZLIB) + if (LWS_WITH_BUNDLED_ZLIB) + if (WIN32) + # it's trying to delete internal zlib entry + LIST(REMOVE_AT CMAKE_REQUIRED_LIBRARIES 0 ) + endif() + endif() +endif() + + +# ideally we want to use pipe2() + +CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE\n#include \nint main(void) {int fd[2];\n return pipe2(fd, 0);\n}\n" LWS_HAVE_PIPE2) + +# tcp keepalive needs this on linux to work practically... but it only exists +# after kernel 2.6.37 + +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return TCP_USER_TIMEOUT; }\n" LWS_HAVE_TCP_USER_TIMEOUT) + +if (LWS_WITH_TLS) + add_subdir_include_dirs(tls) +endif() + +# Generate the lws_config.h that includes all the private compilation settings. +configure_file( + "${PROJECT_SOURCE_DIR}/cmake/lws_config_private.h.in" + "${PROJECT_BINARY_DIR}/lws_config_private.h") + +add_subdir_include_dirs(core) +add_subdir_include_dirs(misc) +add_subdir_include_dirs(system) +add_subdir_include_dirs(event-libs) + +if (LWS_WITH_NETWORK) + add_subdir_include_dirs(core-net) + if (LWS_WITH_ABSTRACT) + add_subdir_include_dirs(abstract) + endif() + add_subdir_include_dirs(roles) +endif() + +if (LWS_WITH_JOSE) + add_subdir_include_dirs(jose) +endif() + +if (LWS_WITH_SECURE_STREAMS) + add_subdir_include_dirs(secure-streams) +endif() + +if (LWS_WITH_STATIC) + if (LWS_STATIC_PIC) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + endif() + + add_library(websockets STATIC ${SOURCES})# ${HDR_PUBLIC}) + set_target_properties(websockets PROPERTIES LINKER_LANGUAGE C) + list(APPEND LWS_LIBRARIES websockets) + target_include_directories(websockets PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) + + if (WIN32) + # Windows uses the same .lib ending for static libraries and shared + # library linker files, so rename the static library. + set_target_properties(websockets + PROPERTIES + OUTPUT_NAME websockets_static) + endif() + + if (UNIX AND LWS_WITH_PLUGINS) + set (CMAKE_POSITION_INDEPENDENT_CODE ON) + if (NOT((${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") OR + (${CMAKE_SYSTEM_NAME} MATCHES "QNX"))) + if (LWS_WITH_STATIC) + target_link_libraries(websockets dl) + endif() + endif() +endif() + +endif() + +if (LWS_WITH_SHARED) + if (NOT RESOURCES) + set(RESOURCES "") + endif() + + add_library(websockets_shared SHARED ${SOURCES})# ${RESOURCES} ${HDR_PUBLIC}) + set_target_properties(websockets_shared PROPERTIES LINKER_LANGUAGE C) + list(APPEND LWS_LIBRARIES websockets_shared) + target_include_directories(websockets_shared PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) + + # We want the shared lib to be named "libwebsockets" + # not "libwebsocket_shared". + set_target_properties(websockets_shared + PROPERTIES + OUTPUT_NAME websockets) + + if (WIN32) + # Compile as DLL (export function declarations) + set_property( + TARGET websockets_shared + PROPERTY COMPILE_DEFINITIONS + LWS_DLL + LWS_INTERNAL) + endif() + + if (APPLE) + set_property(TARGET websockets_shared PROPERTY MACOSX_RPATH YES) + endif() + +endif() + +# +# expose the library private include dirs to plugins, test apps etc that are +# part of the lib build but different targets +# + +if (LWS_WITH_SHARED) + get_target_property(LWS_LIB_INCLUDES websockets_shared INCLUDE_DIRECTORIES) +else() + get_target_property(LWS_LIB_INCLUDES websockets INCLUDE_DIRECTORIES) +endif() + + +# Set the so version of the lib. +# Equivalent to LDFLAGS=-version-info x:x:x + +if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) + foreach(lib ${LWS_LIBRARIES}) + set_target_properties(${lib} + PROPERTIES + SOVERSION ${SOVERSION}) + endforeach() +endif() + + +# Setup the linking for all libs. +foreach (lib ${LWS_LIBRARIES}) + target_link_libraries(${lib} ${LIB_LIST}) +endforeach() + +# +# These will be available to parent projects including libwebsockets +# using add_subdirectory() +# +set(LIBWEBSOCKETS_LIBRARIES ${LWS_LIBRARIES} CACHE STRING "Libwebsocket libraries") +if (LWS_WITH_STATIC) + set(LIBWEBSOCKETS_LIBRARIES_STATIC websockets CACHE STRING "Libwebsocket static library") +endif() +if (LWS_WITH_SHARED) + set(LIBWEBSOCKETS_LIBRARIES_SHARED websockets_shared CACHE STRING "Libwebsocket shared library") +endif() + +# Install libs and headers. +install(TARGETS ${LWS_LIBRARIES} + EXPORT LibwebsocketsTargets + LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries + ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries + RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT libraries # Windows DLLs + PUBLIC_HEADER DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev) + +set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries" PARENT_SCOPE) +set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files" PARENT_SCOPE) + + +if (UNIX) + +# Generate and install pkgconfig. +# (This is not indented, because the tabs will be part of the output) +file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets.pc" +"prefix=\"${CMAKE_INSTALL_PREFIX}\" +exec_prefix=\${prefix} +libdir=\${exec_prefix}/lib${LIB_SUFFIX} +includedir=\${prefix}/include + +Name: libwebsockets +Description: Websockets server and client library +Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} + +Libs: -L\${libdir} -lwebsockets +Cflags: -I\${includedir}" +) + + install(FILES "${PROJECT_BINARY_DIR}/libwebsockets.pc" + DESTINATION lib${LIB_SUFFIX}/pkgconfig) + +file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" +"prefix=\"${CMAKE_INSTALL_PREFIX}\" +exec_prefix=\${prefix} +libdir=\${exec_prefix}/lib${LIB_SUFFIX} +includedir=\${prefix}/include + +Name: libwebsockets_static +Description: Websockets server and client static library +Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} + +Libs: -L\${libdir} -lwebsockets_static +Libs.private: +Cflags: -I\${includedir}" +) + + install(FILES "${PROJECT_BINARY_DIR}/libwebsockets_static.pc" + DESTINATION lib${LIB_SUFFIX}/pkgconfig) + +endif(UNIX) + + +# Keep explicit parent scope exports at end +# + +export_to_parent_intermediate() +set(LWS_PLAT_UNIX ${LWS_PLAT_UNIX} PARENT_SCOPE) +set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) +set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) +set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) +set(LWS_HAVE_PIPE2 ${LWS_HAVE_PIPE2} PARENT_SCOPE) +set(LWS_LIBRARIES ${LWS_LIBRARIES} PARENT_SCOPE) +set(WIN32_HELPERS_PATH ${WIN32_HELPERS_PATH} PARENT_SCOPE) +set(HDR_PRIVATE ${HDR_PRIVATE} PARENT_SCOPE) +set(ZLIB_FOUND ${ZLIB_FOUND} PARENT_SCOPE) +set(LIB_LIST_AT_END ${LIB_LIST_AT_END} PARENT_SCOPE) diff --git a/lib/abstract/CMakeLists.txt b/lib/abstract/CMakeLists.txt new file mode 100644 index 00000000..3496c6ee --- /dev/null +++ b/lib/abstract/CMakeLists.txt @@ -0,0 +1,57 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + abstract/abstract.c +) +if (LWS_WITH_SEQUENCER) + list(APPEND SOURCES + abstract/test-sequencer.c) +endif() + +list(APPEND SOURCES + abstract/transports/unit-test.c) + +#if (LWS_WITH_SMTP) +# list(APPEND SOURCES +# abstract/protocols/smtp/smtp.c +# abstract/protocols/smtp/smtp-sequencer.c +# ) +#endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff --git a/lib/core-net/CMakeLists.txt b/lib/core-net/CMakeLists.txt new file mode 100644 index 00000000..671b99fe --- /dev/null +++ b/lib/core-net/CMakeLists.txt @@ -0,0 +1,80 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +list(APPEND SOURCES + core-net/dummy-callback.c + core-net/output.c + core-net/close.c + core-net/network.c + core-net/vhost.c + core-net/pollfd.c + core-net/service.c + core-net/sorted-usec-list.c + core-net/state.c + core-net/wsi.c + core-net/wsi-timeout.c + core-net/adopt.c + roles/pipe/ops-pipe.c +) + +if (LWS_WITH_DETAILED_LATENCY) + list(APPEND SOURCES + core-net/detailed-latency.c) +endif() + +if (LWS_WITH_LWS_DSH) + list(APPEND SOURCES + core-net/lws-dsh.c) +endif() + +if (LWS_WITH_SEQUENCER) + list(APPEND SOURCES + core-net/sequencer.c) +endif() + +if (NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + core-net/connect.c + core-net/client.c) +endif() + +if (NOT LWS_WITHOUT_SERVER) + list(APPEND SOURCES + core-net/server.c) +endif() + +if (LWS_WITH_SOCKS5 AND NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + core-net/socks5-client.c) +endif() + +if (LWS_WITH_NETWORK AND LWS_WITH_STATS) + list(APPEND SOURCES + core-net/stats.c + ) +endif() + +exports_to_parent_scope() diff --git a/lib/core-net/connect.c b/lib/core-net/connect.c index 3601c536..320abc17 100644 --- a/lib/core-net/connect.c +++ b/lib/core-net/connect.c @@ -374,8 +374,10 @@ bail: bail2: #endif +#if defined(LWS_WITH_TLS) if (i->ssl_connection & LCCSCF_USE_SSL) lws_tls_restrict_return(i->context); +#endif if (i->pwsi) *i->pwsi = NULL; diff --git a/lib/core/CMakeLists.txt b/lib/core/CMakeLists.txt new file mode 100644 index 00000000..6b128ffe --- /dev/null +++ b/lib/core/CMakeLists.txt @@ -0,0 +1,46 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +list(APPEND SOURCES + core/alloc.c + core/buflist.c + core/context.c + core/lws_dll2.c + core/libwebsockets.c + core/logs.c +) + +if (LWS_WITH_FILE_OPS) + list(APPEND SOURCES core/vfs.c) +endif() + +if (LWS_WITH_DEPRECATED_LWS_DLL) + list(APPEND SOURCES + core/lws_dll.c) +endif() + +exports_to_parent_scope() + diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 5d2edb41..9a11ecca 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -133,6 +133,7 @@ #include "libwebsockets.h" + /* * Generic bidi tx credit management */ @@ -147,8 +148,9 @@ struct lws_tx_credit { uint8_t manual; }; - +#if defined(LWS_WITH_TLS) #include "private-lib-tls.h" +#endif #if defined(WIN32) || defined(_WIN32) // Visual studio older than 2015 and WIN_CE has only _stricmp diff --git a/lib/event-libs/CMakeLists.txt b/lib/event-libs/CMakeLists.txt new file mode 100644 index 00000000..237f484e --- /dev/null +++ b/lib/event-libs/CMakeLists.txt @@ -0,0 +1,59 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +# +# These can coexist, except libev conflicts with libevent +# + +if (LWS_WITH_POLL) + add_subdir_include_directories(poll) +endif() + +if (LWS_WITH_LIBUV) + add_subdir_include_directories(libuv) + set(LWS_HAVE_UV_VERSION_H ${LWS_HAVE_UV_VERSION_H} PARENT_SCOPE) + set(LWS_HAVE_NEW_UV_VERSION_H ${LWS_HAVE_NEW_UV_VERSION_H} PARENT_SCOPE) +endif() + +if (LWS_WITH_LIBEVENT) + add_subdir_include_directories(libevent) +endif() + +if (LWS_WITH_GLIB) + add_subdir_include_directories(glib) +endif() + +if (LWS_WITH_LIBEV) + add_subdir_include_directories(libev) + set(LWS_HAVE_EVBACKEND_LINUXAIO ${LWS_HAVE_EVBACKEND_LINUXAIO} PARENT_SCOPE) + set(LWS_HAVE_EVBACKEND_IOURING ${LWS_HAVE_EVBACKEND_IOURING} PARENT_SCOPE) +endif() + +# +# Keep explicit parent scope exports at end +# + +export_to_parent_intermediate() diff --git a/lib/event-libs/glib/CMakeLists.txt b/lib/event-libs/glib/CMakeLists.txt new file mode 100644 index 00000000..59857240 --- /dev/null +++ b/lib/event-libs/glib/CMakeLists.txt @@ -0,0 +1,66 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +set(LWS_GLIB_INCLUDE_DIRS CACHE PATH "Path to the glib include directory") +set(LWS_GLIB_LIBRARIES CACHE PATH "Path to the glib library") + +include (FindPkgConfig) +if (NOT GLIB_FOUND) + find_path(GLIB_INCLUDE_DIRS NAMES glib-2.0/glib.h) + find_library(GLIB_LIBRARIES NAMES glib-2.0) + if (GLIB_INCLUDE_DIRS AND GLIB_LIBRARIES) + set(GLIB_FOUND) + endif() + if (GLIB_INCLUDE_DIRS) + set(GLIB_INCLUDE_DIRS "${GLIB_INCLUDE_DIRS}/glib-2.0" PARENT_SCOPE) + endif() +endif() +PKG_SEARCH_MODULE(LWS_GLIB2 glib-2.0) +if (LWS_GLIB2_FOUND) + list(APPEND GLIB_INCLUDE_DIRS "${LWS_GLIB2_INCLUDE_DIRS}") +endif() + +message("glib include dir: ${GLIB_INCLUDE_DIRS}") +message("glib libraries: ${GLIB_LIBRARIES}") +include_directories("${GLIB_INCLUDE_DIRS}") +list(APPEND LIB_LIST ${GLIB_LIBRARIES}) + +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + event-libs/glib/glib.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/event-libs/libev/CMakeLists.txt b/lib/event-libs/libev/CMakeLists.txt new file mode 100644 index 00000000..a638fd51 --- /dev/null +++ b/lib/event-libs/libev/CMakeLists.txt @@ -0,0 +1,76 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +set(LWS_LIBEV_LIBRARIES CACHE PATH "Path to the libev library") +set(LWS_LIBEV_INCLUDE_DIRS CACHE PATH "Path to the libev include directory") + +if (NOT LIBEV_FOUND) + find_path(LIBEV_INCLUDE_DIRS NAMES ev.h) + find_library(LIBEV_LIBRARIES NAMES ev) +endif() +message("libev include dir: ${LIBEV_INCLUDE_DIRS}") +message("libev libraries: ${LIBEV_LIBRARIES}") +include_directories("${LIBEV_INCLUDE_DIRS}") +list(APPEND LIB_LIST ${LIBEV_LIBRARIES}) + +if ("${LWS_LIBEV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEV_INCLUDE_DIRS}" STREQUAL "") +else() + set(LIBEV_LIBRARIES ${LWS_LIBEV_LIBRARIES}) + set(LIBEV_INCLUDE_DIRS ${LWS_LIBEV_INCLUDE_DIRS}) +endif() + +list(APPEND SOURCES + event-libs/libev/libev.c) +# see README.build.md for discussion of why of the supported event libs, +# only libev cannot cope with -Werror +set_source_files_properties(event-libs/libev/libev.c + PROPERTIES COMPILE_FLAGS "-Wno-error" ) + +set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) + +CHECK_C_SOURCE_COMPILES( + "#include + int main(int argc, char **argv) { return EVBACKEND_LINUXAIO; } + " LWS_HAVE_EVBACKEND_LINUXAIO) + +CHECK_C_SOURCE_COMPILES( + "#include + int main(int argc, char **argv) { return EVBACKEND_IOURING; } + " LWS_HAVE_EVBACKEND_IOURING) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_HAVE_EVBACKEND_LINUXAIO ${LWS_HAVE_EVBACKEND_LINUXAIO} PARENT_SCOPE) +set(LWS_HAVE_EVBACKEND_IOURING ${LWS_HAVE_EVBACKEND_IOURING} PARENT_SCOPE) diff --git a/lib/event-libs/libevent/CMakeLists.txt b/lib/event-libs/libevent/CMakeLists.txt new file mode 100644 index 00000000..eb068958 --- /dev/null +++ b/lib/event-libs/libevent/CMakeLists.txt @@ -0,0 +1,61 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +set(LWS_LIBEVENT_INCLUDE_DIRS CACHE PATH "Path to the libevent include directory") +set(LWS_LIBEVENT_LIBRARIES CACHE PATH "Path to the libevent library") + +if (NOT LIBEVENT_FOUND) + find_path(LIBEVENT_INCLUDE_DIRS NAMES event2/event.h) + find_library(LIBEVENT_LIBRARIES NAMES event) +endif() +message("libevent include dir: ${LIBEVENT_INCLUDE_DIRS}") +message("libevent libraries: ${LIBEVENT_LIBRARIES}") +include_directories("${LIBEVENT_INCLUDE_DIRS}") +list(APPEND LIB_LIST ${LIBEVENT_LIBRARIES}) + +if ("${LWS_LIBEVENT_LIBRARIES}" STREQUAL "" OR "${LWS_LIBEVENT_INCLUDE_DIRS}" STREQUAL "") +else() + set(LIBEVENT_LIBRARIES ${LWS_LIBEVENT_LIBRARIES}) + set(LIBEVENT_INCLUDE_DIRS ${LWS_LIBEVENT_INCLUDE_DIRS}) + set(LIBEVENT_FOUND 1 PARENT_SCOPE) +endif() + +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + event-libs/libevent/libevent.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/event-libs/libuv/CMakeLists.txt b/lib/event-libs/libuv/CMakeLists.txt new file mode 100644 index 00000000..8154aa25 --- /dev/null +++ b/lib/event-libs/libuv/CMakeLists.txt @@ -0,0 +1,69 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +set(LWS_LIBUV_LIBRARIES CACHE PATH "Path to the libuv library") +set(LWS_LIBUV_INCLUDE_DIRS CACHE PATH "Path to the libuv include directory") + +if (NOT LIBUV_FOUND) + find_path(LIBUV_INCLUDE_DIRS NAMES uv.h) + find_library(LIBUV_LIBRARIES NAMES uv) +endif() +message("libuv include dir: ${LIBUV_INCLUDE_DIRS}") +message("libuv libraries: ${LIBUV_LIBRARIES}") +include_directories("${LIBUV_INCLUDE_DIRS}") +list(APPEND LIB_LIST ${LIBUV_LIBRARIES}) + +if ("${LWS_LIBUV_LIBRARIES}" STREQUAL "" OR "${LWS_LIBUV_INCLUDE_DIRS}" STREQUAL "") +else() + set(LIBUV_LIBRARIES ${LWS_LIBUV_LIBRARIES}) + set(LIBUV_INCLUDE_DIRS ${LWS_LIBUV_INCLUDE_DIRS}) +endif() + +CHECK_INCLUDE_FILE(uv-version.h LWS_HAVE_UV_VERSION_H) + # libuv changed the location in 1.21.0. Retain both + # checks temporarily to ensure a smooth transition. + if (NOT LWS_HAVE_UV_VERSION_H) + CHECK_INCLUDE_FILE(uv/version.h LWS_HAVE_NEW_UV_VERSION_H) + endif() + +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + event-libs/libuv/libuv.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_HAVE_UV_VERSION_H ${LWS_HAVE_UV_VERSION_H} PARENT_SCOPE) +set(LWS_HAVE_NEW_UV_VERSION_H ${LWS_HAVE_NEW_UV_VERSION_H} PARENT_SCOPE) diff --git a/lib/event-libs/poll/CMakeLists.txt b/lib/event-libs/poll/CMakeLists.txt new file mode 100644 index 00000000..ad634b94 --- /dev/null +++ b/lib/event-libs/poll/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - includes via include_directories +# +# and keep everything else private + +include_directories(../poll) + +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + event-libs/poll/poll.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/jose/CMakeLists.txt b/lib/jose/CMakeLists.txt new file mode 100644 index 00000000..2634f52c --- /dev/null +++ b/lib/jose/CMakeLists.txt @@ -0,0 +1,46 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(. ./jwe ./jws ./jwk) + +if (LWS_WITH_JOSE) + list(APPEND SOURCES + jose/jwk/jwk.c + jose/jws/jose.c + jose/jws/jws.c + jose/jwe/jwe.c + jose/jwe/enc/aescbc.c + jose/jwe/enc/aesgcm.c + jose/jwe/enc/aeskw.c + jose/jwe/jwe-rsa-aescbc.c + jose/jwe/jwe-rsa-aesgcm.c + jose/jwe/jwe-ecdh-es-aeskw.c + ) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/misc/CMakeLists.txt b/lib/misc/CMakeLists.txt new file mode 100644 index 00000000..a93961a7 --- /dev/null +++ b/lib/misc/CMakeLists.txt @@ -0,0 +1,108 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + misc/base64-decode.c + misc/lws-ring.c) + +if (LWS_WITH_FTS) + list(APPEND SOURCES + misc/fts/trie.c + misc/fts/trie-fd.c) +endif() + +if (LWS_WITH_DISKCACHE) + list(APPEND SOURCES + misc/diskcache.c) +endif() + +if (LWS_WITH_STRUCT_JSON) + list(APPEND SOURCES + misc/lws-struct-lejp.c) +endif() + +if (LWS_WITH_STRUCT_SQLITE3) + list(APPEND SOURCES + misc/lws-struct-sqlite.c) +endif() + +if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + list(APPEND SOURCES misc/fsmount.c) +endif() + +if (LWS_WITH_DIR) + list(APPEND SOURCES misc/dir.c) +endif() + +if (LWS_WITH_THREADPOOL AND LWS_HAVE_PTHREAD_H) + list(APPEND SOURCES misc/threadpool/threadpool.c) +endif() + +if (LWS_WITH_PEER_LIMITS) + list(APPEND SOURCES + misc/peer-limits.c) +endif() + +if (LWS_WITH_LWSAC) + list(APPEND SOURCES + misc/lwsac/lwsac.c + misc/lwsac/cached-file.c) +endif() + +if (NOT LWS_WITHOUT_BUILTIN_SHA1) + list(APPEND SOURCES + misc/sha-1.c) +endif() + +if (LWS_WITH_LEJP) + list(APPEND SOURCES + misc/lejp.c) +endif() + +if (UNIX) + if (NOT LWS_HAVE_GETIFADDRS) + list(APPEND HDR_PRIVATE misc/getifaddrs.h) + list(APPEND SOURCES misc/getifaddrs.c) + endif() +endif() + +if (NOT WIN32 AND NOT LWS_WITHOUT_DAEMONIZE) + list(APPEND SOURCES + misc/daemonize.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index 0e1a98c6..b7caf6c5 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -1050,6 +1050,9 @@ lws_threadpool_task_status(struct lws_threadpool_task *task, void **user) enum lws_threadpool_task_status status; struct lws_threadpool *tp = task->tp; + if (!tp) + return LWS_TP_STATUS_FINISHED; + *user = task->args.user; status = task->status; diff --git a/lib/plat/freertos/CMakeLists.txt b/lib/plat/freertos/CMakeLists.txt new file mode 100644 index 00000000..22b7e8d0 --- /dev/null +++ b/lib/plat/freertos/CMakeLists.txt @@ -0,0 +1,56 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(. esp32) + +list(APPEND SOURCES + plat/freertos/freertos-fds.c + plat/freertos/freertos-init.c + plat/freertos/freertos-misc.c + plat/freertos/freertos-pipe.c + plat/freertos/freertos-service.c + plat/freertos/freertos-sockets.c + misc/romfs.c) +if (LWS_WITH_ESP32_HELPER) + list(APPEND SOURCES plat/freertos/esp32/esp32-helpers.c) +endif() +if (LWS_WITH_FILE_OPS) + list(APPEND SOURCES plat/freertos/freertos-file.c) +endif() +if (LWS_WITH_SYS_ASYNC_DNS) + list(APPEND SOURCES plat/freertos/freertos-resolv.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() \ No newline at end of file diff --git a/lib/plat/optee/CMakeLists.txt b/lib/plat/optee/CMakeLists.txt new file mode 100644 index 00000000..b7402f36 --- /dev/null +++ b/lib/plat/optee/CMakeLists.txt @@ -0,0 +1,49 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + plat/optee/lws-plat-optee.c +) +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + plat/optee/network.c + ) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot ../../../../lib/libutils/isoc/include -I../../../../lib/libutils/isoc/include -I../../../../lib/libutils/ext/include" ) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/plat/unix/CMakeLists.txt b/lib/plat/unix/CMakeLists.txt new file mode 100644 index 00000000..f52a2407 --- /dev/null +++ b/lib/plat/unix/CMakeLists.txt @@ -0,0 +1,127 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +execute_process( COMMAND grep -c illumos /lib/ld.so.1 + OUTPUT_VARIABLE ILLUMOS ERROR_QUIET ) +# Chomp the \n at end of output. +string(REGEX REPLACE "[\n]+" "" ILLUMOS "${ILLUMOS}") + +if (NOT ${ILLUMOS} MATCHES "0") + add_definitions( "-D__illumos__" ) + set(ILLUMOS 1) +endif() + +set(LWS_PLAT_UNIX 1) +list(APPEND SOURCES + plat/unix/unix-caps.c + plat/unix/unix-misc.c + plat/unix/unix-init.c +) +if (LWS_WITH_FILE_OPS) + list(APPEND SOURCES plat/unix/unix-file.c) +endif() +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + plat/unix/unix-pipe.c + plat/unix/unix-service.c + plat/unix/unix-sockets.c + plat/unix/unix-fds.c + ) + if (LWS_WITH_SYS_ASYNC_DNS) + if (LWS_PLAT_ANDROID) + list(APPEND SOURCES plat/unix/android/android-resolv.c) + else() + list(APPEND SOURCES plat/unix/unix-resolv.c) + endif() + endif() +endif() + +if (LWS_WITH_PLUGINS AND LWS_WITH_LIBUV) + list(APPEND SOURCES plat/unix/unix-plugins.c) +endif() + +if (LWS_WITH_SPAWN) + list(APPEND SOURCES plat/unix/unix-spawn.c) +endif() + +if (HAIKU) + set(CMAKE_REQUIRED_LIBRARIES network) + list(APPEND LIB_LIST_AT_END network) +endif() + +IF (CMAKE_SYSTEM_NAME STREQUAL Linux) + CHECK_FUNCTION_EXISTS(eventfd LWS_HAVE_EVENTFD) +endif() + +list(APPEND LIB_LIST_AT_END m) + +if (ILLUMOS) + list(APPEND LIB_LIST_AT_END socket) +endif() + +if (LWS_HAVE_LIBCAP) + list(APPEND LIB_LIST_AT_END cap) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "QNX") + list(APPEND LIB_LIST_AT_END socket) +endif() + +list(APPEND LIB_LIST_AT_END dl) + +if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + if ("${LWS_LIBMOUNT_LIBRARIES}" STREQUAL "" OR "${LWS_LIBMOUNT_INCLUDE_DIRS}" STREQUAL "") + + # libmount paths (this is only on Linux) + # + find_path( LIBMOUNT_INC_PATH NAMES "libmount/libmount.h") + find_library(LIBMOUNT_LIB_PATH NAMES "mount") + else() + set(LIBMOUNT_INC_PATH ${LWS_LIBMOUNT_INCLUDE_DIRS} PARENT_SCOPE) + set(LIBMOUNT_LIB_PATH ${LWS_LIBMOUNT_LIBRARIES} PARENT_SCOPE) + endif() + + if (NOT LIBMOUNT_INC_PATH OR NOT LIBMOUNT_LIB_PATH) + message(FATAL_ERROR " Unable to find libmount") + endif() +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_PLAT_UNIX ${LWS_PLAT_UNIX} PARENT_SCOPE) +set(ILLUMOS ${ILLUMOS} PARENT_SCOPE) +set(LIB_LIST_AT_END ${LIB_LIST_AT_END} PARENT_SCOPE) +set(LWS_PLAT_UNIX ${LWS_PLAT_UNIX} PARENT_SCOPE) diff --git a/lib/plat/windows/CMakeLists.txt b/lib/plat/windows/CMakeLists.txt new file mode 100644 index 00000000..68b71cd6 --- /dev/null +++ b/lib/plat/windows/CMakeLists.txt @@ -0,0 +1,103 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + plat/windows/windows-fds.c + plat/windows/windows-file.c + plat/windows/windows-init.c + plat/windows/windows-misc.c + plat/windows/windows-pipe.c + plat/windows/windows-plugins.c + plat/windows/windows-service.c + plat/windows/windows-sockets.c + ) +if (LWS_WITH_SYS_ASYNC_DNS) + list(APPEND SOURCES plat/windows/windows-resolv.c) +endif() + +if (LWS_WITH_SPAWN) + list(APPEND SOURCES plat/windows/windows-spawn.c) +endif() + +if (LWS_WITH_ZLIB AND LWS_WITH_BUNDLED_ZLIB) + set(WIN32_ZLIB_PATH "win32port/zlib") + set(ZLIB_SRCS + ${WIN32_ZLIB_PATH}/adler32.c + ${WIN32_ZLIB_PATH}/compress.c + ${WIN32_ZLIB_PATH}/crc32.c + ${WIN32_ZLIB_PATH}/deflate.c + ${WIN32_ZLIB_PATH}/gzlib.c + ${WIN32_ZLIB_PATH}/gzread.c + ${WIN32_ZLIB_PATH}/gzwrite.c + ${WIN32_ZLIB_PATH}/infback.c + ${WIN32_ZLIB_PATH}/inffast.c + ${WIN32_ZLIB_PATH}/inflate.c + ${WIN32_ZLIB_PATH}/inftrees.c + ${WIN32_ZLIB_PATH}/trees.c + ${WIN32_ZLIB_PATH}/uncompr.c + ${WIN32_ZLIB_PATH}/zutil.c) + add_library(zlib_internal STATIC ${ZLIB_SRCS}) + set(ZLIB_INCLUDE_DIRS ${WIN32_ZLIB_PATH}) + get_property(ZLIB_LIBRARIES TARGET zlib_internal PROPERTY LOCATION) + set(ZLIB_FOUND 1) + # Make sure zlib_internal is compiled before the libs. + foreach (lib ${LWS_LIBRARIES}) + add_dependencies(${lib} zlib_internal) + endforeach() +endif() + +# Add helper files for Windows + +# (from ./lib perspective) +set(WIN32_HELPERS_PATH ../win32port/win32helpers) + +# from our perspective in ./lib/plat/windows +include_directories(../../${WIN32_HELPERS_PATH}) + +list(APPEND SOURCES + ${WIN32_HELPERS_PATH}/gettimeofday.c +) + +list(APPEND HDR_PRIVATE + ${WIN32_HELPERS_PATH}/gettimeofday.h +) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(WIN32_HELPERS_PATH ${WIN32_HELPERS_PATH} PARENT_SCOPE) +set(HDR_PRIVATE ${HDR_PRIVATE} PARENT_SCOPE) +set(ZLIB_FOUND ${ZLIB_FOUND} PARENT_SCOPE) +set(LIB_LIST_AT_END ${LIB_LIST_AT_END} PARENT_SCOPE) diff --git a/lib/roles/CMakeLists.txt b/lib/roles/CMakeLists.txt new file mode 100644 index 00000000..e92dd3e4 --- /dev/null +++ b/lib/roles/CMakeLists.txt @@ -0,0 +1,88 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +if (LWS_ROLE_MQTT) + add_subdir_include_directories(mqtt) +endif() + +if (LWS_ROLE_DBUS AND NOT LWS_PLAT_FREERTOS) + add_subdir_include_directories(dbus) +endif() + +if (LWS_ROLE_H1 OR LWS_ROLE_H2) + add_subdir_include_directories(http) +endif() + +if (LWS_ROLE_H1) + add_subdir_include_directories(h1) +endif() + +if (LWS_ROLE_H2) + add_subdir_include_directories(h2) +endif() + +if (LWS_ROLE_WS) + add_subdir_include_directories(ws) +endif() + +if (LWS_ROLE_RAW) + add_subdir_include_directories(raw-skt) +endif() + +if (LWS_ROLE_RAW_FILE) + add_subdir_include_directories(raw-file) +endif() + +if (LWS_WITH_CGI) + add_subdir_include_directories(cgi) +endif() + +if (LWS_ROLE_RAW_PROXY) + add_subdir_include_directories(raw-proxy) +endif() + +if (NOT LWS_WITHOUT_SERVER OR LWS_WITH_SECURE_STREAMS_PROCESS_API) + add_subdir_include_directories(listen) +endif() + +if (NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + roles/http/client/client-http.c + roles/http/client/client-handshake.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/roles/cgi/CMakeLists.txt b/lib/roles/cgi/CMakeLists.txt new file mode 100644 index 00000000..12c83e3a --- /dev/null +++ b/lib/roles/cgi/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/cgi/cgi-server.c + roles/cgi/ops-cgi.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/roles/dbus/CMakeLists.txt b/lib/roles/dbus/CMakeLists.txt new file mode 100644 index 00000000..e49d6717 --- /dev/null +++ b/lib/roles/dbus/CMakeLists.txt @@ -0,0 +1,62 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/dbus/dbus.c) + +if (NOT LWS_DBUS_LIB) + set(LWS_DBUS_LIB "dbus-1") +endif() + +find_package(PkgConfig QUIET) +pkg_check_modules(PC_DBUS1 dbus-1 QUIET) +list(APPEND LWS_DBUS_INCLUDE1 ${PC_DBUS1_INCLUDE_DIRS}) +list(APPEND LWS_DBUS_LIB ${PC_DBUS1_LIBRARIES}) + +set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1}) + +CHECK_C_SOURCE_COMPILES("#include +int main(void) { + return 0; +}" LWS_DBUS_CHECK_OK) + +message("dbus include dir 1: ${LWS_DBUS_INCLUDE1}") +include_directories("${LWS_DBUS_INCLUDE1}") +list(APPEND LIB_LIST ${LWS_DBUS_LIB}) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_DBUS_CHECK_OK ${LWS_DBUS_CHECK_OK} PARENT_SCOPE) diff --git a/lib/roles/h1/CMakeLists.txt b/lib/roles/h1/CMakeLists.txt new file mode 100644 index 00000000..3e129721 --- /dev/null +++ b/lib/roles/h1/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/h1/ops-h1.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/roles/h2/CMakeLists.txt b/lib/roles/h2/CMakeLists.txt new file mode 100644 index 00000000..97146021 --- /dev/null +++ b/lib/roles/h2/CMakeLists.txt @@ -0,0 +1,44 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/h2/http2.c + roles/h2/hpack.c + roles/h2/ops-h2.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff --git a/lib/roles/http/CMakeLists.txt b/lib/roles/http/CMakeLists.txt new file mode 100644 index 00000000..b858c0af --- /dev/null +++ b/lib/roles/http/CMakeLists.txt @@ -0,0 +1,90 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(. ./compression) + +list(APPEND SOURCES + roles/http/header.c + roles/http/parsers.c) + +if (NOT LWS_WITHOUT_SERVER) + list(APPEND SOURCES + roles/http/server/server.c + roles/http/server/lws-spa.c) +endif() + +if (LWS_WITH_HTTP_PROXY AND LWS_WITH_HUBBUB) + list(APPEND SOURCES + roles/http/server/rewrite.c) +endif() + +if (LWS_WITH_ACCESS_LOG) + list(APPEND SOURCES + roles/http/server/access-log.c) +endif() + +if (LWS_WITH_HTTP_STREAM_COMPRESSION) + list(APPEND SOURCES + roles/http/compression/stream.c + roles/http/compression/deflate/deflate.c) + + if (LWS_WITH_HTTP_BROTLI) + list(APPEND SOURCES + roles/http/compression/brotli/brotli.c) + list(APPEND LIB_LIST brotlienc brotlidec brotlidec) + endif() +endif() + +if (LWS_WITH_LEJP_CONF AND LWS_WITH_NETWORK AND NOT LWS_PLAT_OPTEE) + list(APPEND SOURCES + roles/http/server/lejp-conf.c + ) +endif() + +if (LWS_WITH_RANGES) + list(APPEND SOURCES + roles/http/server/ranges.c) +endif() + +if (LWS_WITH_ZIP_FOPS) + if (LWS_WITH_ZLIB) + list(APPEND SOURCES + roles/http/server/fops-zip.c) + else() + message(FATAL_ERROR "Pre-zipped file support (LWS_WITH_ZIP_FOPS) requires ZLIB (LWS_WITH_ZLIB)") + endif() +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() \ No newline at end of file diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index ef0c7040..6651e371 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -40,11 +40,13 @@ lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1) return CCTLS_RETURN_ERROR; } +#if defined(LWS_WITH_TLS) if (!wsi->transaction_from_pipeline_queue && lws_tls_restrict_borrow(wsi->context)) { *pcce = "tls restriction limit"; return CCTLS_RETURN_ERROR; } +#endif } if (!do_c1) diff --git a/lib/roles/listen/CMakeLists.txt b/lib/roles/listen/CMakeLists.txt new file mode 100644 index 00000000..035b2835 --- /dev/null +++ b/lib/roles/listen/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/listen/ops-listen.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff --git a/lib/roles/mqtt/CMakeLists.txt b/lib/roles/mqtt/CMakeLists.txt new file mode 100644 index 00000000..a9cfa54e --- /dev/null +++ b/lib/roles/mqtt/CMakeLists.txt @@ -0,0 +1,48 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +if (LWS_WITH_CLIENT) + list(APPEND SOURCES + roles/mqtt/mqtt.c + roles/mqtt/ops-mqtt.c + roles/mqtt/primitives.c + roles/mqtt/client/client-mqtt.c + roles/mqtt/client/client-mqtt-handshake.c + ) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/roles/raw-file/CMakeLists.txt b/lib/roles/raw-file/CMakeLists.txt new file mode 100644 index 00000000..4d9834c6 --- /dev/null +++ b/lib/roles/raw-file/CMakeLists.txt @@ -0,0 +1,40 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES roles/raw-file/ops-raw-file.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() \ No newline at end of file diff --git a/lib/roles/raw-proxy/CMakeLists.txt b/lib/roles/raw-proxy/CMakeLists.txt new file mode 100644 index 00000000..64f4eefd --- /dev/null +++ b/lib/roles/raw-proxy/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/raw-proxy/ops-raw-proxy.c) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff --git a/lib/roles/raw-skt/CMakeLists.txt b/lib/roles/raw-skt/CMakeLists.txt new file mode 100644 index 00000000..d618bb0c --- /dev/null +++ b/lib/roles/raw-skt/CMakeLists.txt @@ -0,0 +1,46 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/raw-skt/ops-raw-skt.c) + +if (LWS_WITH_ABSTRACT) + list(APPEND SOURCES + abstract/transports/raw-skt.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/roles/ws/CMakeLists.txt b/lib/roles/ws/CMakeLists.txt new file mode 100644 index 00000000..03840646 --- /dev/null +++ b/lib/roles/ws/CMakeLists.txt @@ -0,0 +1,61 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(.) + +list(APPEND SOURCES + roles/ws/ops-ws.c) + +if (NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + roles/ws/client-ws.c + roles/ws/client-parser-ws.c) +endif() + +if (NOT LWS_WITHOUT_SERVER) + list(APPEND SOURCES + roles/ws/server-ws.c) +endif() + +if (NOT LWS_WITHOUT_EXTENSIONS) + list(APPEND HDR_PRIVATE + roles/ws/ext/extension-permessage-deflate.h) + list(APPEND SOURCES + roles/ws/ext/extension.c + roles/ws/ext/extension-permessage-deflate.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() + diff --git a/lib/secure-streams/CMakeLists.txt b/lib/secure-streams/CMakeLists.txt new file mode 100644 index 00000000..d75f701d --- /dev/null +++ b/lib/secure-streams/CMakeLists.txt @@ -0,0 +1,129 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# + +# secure streams plugins + +include_directories(.) + + list(APPEND SOURCES + secure-streams/secure-streams.c + secure-streams/policy-common.c + secure-streams/system/captive-portal-detect/captive-portal-detect.c + secure-streams/protocols/ss-raw.c + ) + if (NOT LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) + list(APPEND SOURCES + secure-streams/policy-json.c + secure-streams/system/fetch-policy/fetch-policy.c + ) + endif() + if (LWS_ROLE_H1) + list(APPEND SOURCES + secure-streams/protocols/ss-h1.c + ) + endif() + if (LWS_ROLE_H2) + list(APPEND SOURCES + secure-streams/protocols/ss-h2.c + ) + endif() + if (LWS_ROLE_WS) + list(APPEND SOURCES + secure-streams/protocols/ss-ws.c + ) + endif() + if (LWS_ROLE_MQTT) + list(APPEND SOURCES + secure-streams/protocols/ss-mqtt.c + ) + endif() + + if (LWS_WITH_SECURE_STREAMS_PROXY_API) + list(APPEND SOURCES + secure-streams/secure-streams-serialize.c + secure-streams/secure-streams-client.c + ) + endif() + + if (LWS_WITH_SECURE_STREAMS_PROXY_API) + list(APPEND SOURCES + secure-streams/secure-streams-process.c + ) + endif() + + if (LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) + list(APPEND SOURCES + secure-streams/system/auth-api.amazon.com/auth.c + ) + endif() + + + # + # Helper function for adding a secure stream plugin + # + macro(create_ss_plugin NAME S2 S3 S4 S5 S6) + + set(SSP_SRCS) + set(SSP_PUBLIC_HDR) + set(SSP_HDR) + + if ("${S2}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S2}) + endif() + if ("${S3}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S3}) + endif() + if ("${S4}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S4}) + endif() + if ("${S5}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S5}) + endif() + if ("${S6}" STREQUAL "") + else() + list(APPEND SSP_SRCS plugins/${NAME}/${S6}) + endif() + + source_group("Headers Private" FILES ${SSP_HDR}) + source_group("Sources" FILES ${SSP_SRCS}) + + add_library( ${NAME} STATIC + ${SSP_HDR} ${SSP_PUBLIC_HDR} ${SSP_SRCS} ) + target_include_directories(${NAME} PRIVATE "${LWS_LIB_INCLUDES}" ${LWS_LIB_BUILD_INC_PATHS}) + + add_dependencies(${NAME} websockets_shared) + list(APPEND SS_PLUGINS_LIST ${NAME}) + endmacro() + + create_ss_plugin(ssp-h1url "h1url.c" "" "" "" "") + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/system/CMakeLists.txt b/lib/system/CMakeLists.txt new file mode 100644 index 00000000..a46122f4 --- /dev/null +++ b/lib/system/CMakeLists.txt @@ -0,0 +1,61 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(./async-dns) + +list(APPEND SOURCES + system/system.c) + +if (LWS_WITH_NETWORK) + + if (LWS_WITH_SYS_ASYNC_DNS) + list(APPEND SOURCES + system/async-dns/async-dns.c + system/async-dns/async-dns-parse.c) + endif() + + if (LWS_WITH_SYS_NTPCLIENT) + list(APPEND SOURCES + system/ntpclient/ntpclient.c) + endif() + + if (LWS_WITH_SYS_DHCP_CLIENT) + list(APPEND SOURCES + system/dhcpclient/dhcpclient.c) + endif() + +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt new file mode 100644 index 00000000..a1a534c2 --- /dev/null +++ b/lib/tls/CMakeLists.txt @@ -0,0 +1,463 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# +# This converts everything about the tls support into +# +# - entries on SOURCES (modifications set back in PARENT_SCOPE) +# - entries on LIB_LIST (modifications set back in PARENT_SCOPE) +# - include_directories() +# - Api build-time discovery results set in PARENT_SCOPE +# +# Everything else is handled privately here. + +include_directories(.) + +# Allow the user to use the old CyaSSL options/library in stead of wolfSSL +if (LWS_WITH_CYASSL AND LWS_WITH_WOLFSSL) + message(FATAL_ERROR "LWS_WITH_CYASSL and LWS_WITH_WOLFSSL are mutually exclusive!") +endif() + +if (LWS_WITH_CYASSL) + # Copy CyaSSL options to the wolfSSL options + set(LWS_WITH_WOLFSSL ${LWS_WITH_CYASSL} CACHE BOOL "Use wolfSSL/CyaSSL instead of OpenSSL" FORCE PARENT_SCOPE) + set(LWS_WOLFSSL_LIBRARIES ${LWS_CYASSL_LIBRARIES} CACHE PATH "Path to wolfSSL/CyaSSL libraries" FORCE PARENT_SCOPE) + set(LWS_WOLFSSL_INCLUDE_DIRS ${LWS_CYASSL_INCLUDE_DIRS} CACHE PATH "Path to wolfSSL/CyaSSL header files" FORCE PARENT_SCOPE) +endif() + +set(LWS_OPENSSL_LIBRARIES CACHE PATH "Path to the OpenSSL library") +set(LWS_OPENSSL_INCLUDE_DIRS CACHE PATH "Path to the OpenSSL include directory") +set(LWS_WOLFSSL_LIBRARIES CACHE PATH "Path to the wolfSSL library") +set(LWS_WOLFSSL_INCLUDE_DIRS CACHE PATH "Path to the wolfSSL include directory") + + +if (LWS_WITH_BORINGSSL) + # boringssl deprecated EVP_PKEY + set (LWS_WITH_GENHASH OFF PARENT_SCOPE) +endif() + +if (LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL AND NOT LWS_WITH_MBEDTLS) + if ("${LWS_OPENSSL_LIBRARIES}" STREQUAL "" OR "${LWS_OPENSSL_INCLUDE_DIRS}" STREQUAL "") + else() + if (NOT LWS_PLAT_FREERTOS) + set(OPENSSL_LIBRARIES ${LWS_OPENSSL_LIBRARIES}) + endif() + set(OPENSSL_INCLUDE_DIRS ${LWS_OPENSSL_INCLUDE_DIRS}) + set(OPENSSL_FOUND 1) + endif() +endif() + +if (LWS_WITH_SSL AND LWS_WITH_WOLFSSL) + if ("${LWS_WOLFSSL_LIBRARIES}" STREQUAL "" OR "${LWS_WOLFSSL_INCLUDE_DIRS}" STREQUAL "") + if (NOT WOLFSSL_FOUND) + if (LWS_WITH_CYASSL) + message(FATAL_ERROR "You must set LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS when LWS_WITH_CYASSL is turned on.") + else() + message(FATAL_ERROR "You must set LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS when LWS_WITH_WOLFSSL is turned on.") + endif() + endif() + else() + set(WOLFSSL_LIBRARIES ${LWS_WOLFSSL_LIBRARIES} PARENT_SCOPE) + set(WOLFSSL_INCLUDE_DIRS ${LWS_WOLFSSL_INCLUDE_DIRS} PARENT_SCOPE) + set(WOLFSSL_FOUND 1 PARENT_SCOPE) + endif() + set(USE_WOLFSSL 1 PARENT_SCOPE) + set(LWS_WITH_TLS 1 PARENT_SCOPE) + if (LWS_WITH_CYASSL) + set(USE_OLD_CYASSL 1 PARENT_SCOPE) + endif() +endif() + +if (LWS_SSL_CLIENT_USE_OS_CA_CERTS) + set(LWS_SSL_CLIENT_USE_OS_CA_CERTS 1 PARENT_SCOPE) +endif() + +if (LWS_WITH_MBEDTLS) + add_subdirectory(mbedtls) + include_directories(${_CMAKE_INC_LIST}) +endif() + +# The base dir where the test-apps look for the SSL certs. +set(LWS_OPENSSL_CLIENT_CERTS ../share CACHE PATH "Server SSL certificate directory") +if (WIN32) + set(LWS_OPENSSL_CLIENT_CERTS . CACHE PATH "Client SSL certificate directory" PARENT_SCOPE) + + if (LWS_UNIX_SOCK) + set(LWS_UNIX_SOCK OFF PARENT_SCOPE) + message(WARNING "Windows does not support UNIX domain sockets") + endif() +else() + set(LWS_OPENSSL_CLIENT_CERTS /etc/pki/tls/certs/ CACHE PATH "Client SSL certificate directory") +endif() + +if (LWS_WITH_SSL) + list(APPEND SOURCES + tls/tls.c) + if (LWS_WITH_NETWORK) + list(APPEND SOURCES + tls/tls-network.c) + endif() + + if (LWS_WITH_MBEDTLS) + list(APPEND SOURCES + tls/mbedtls/mbedtls-tls.c + tls/mbedtls/mbedtls-x509.c) + if (LWS_WITH_NETWORK) + list(APPEND SOURCES + tls/mbedtls/mbedtls-ssl.c) + endif() + if (LWS_WITH_GENCRYPTO) + list(APPEND SOURCES + tls/mbedtls/lws-genhash.c + tls/mbedtls/lws-genrsa.c + tls/mbedtls/lws-genaes.c + tls/lws-genec-common.c + tls/mbedtls/lws-genec.c + tls/mbedtls/lws-gencrypto.c) + endif() + else() + list(APPEND SOURCES + tls/openssl/openssl-tls.c + tls/openssl/openssl-x509.c) + if (LWS_WITH_NETWORK) + list(APPEND SOURCES + tls/openssl/openssl-ssl.c) + endif() + if (LWS_WITH_GENCRYPTO) + list(APPEND SOURCES + tls/openssl/lws-genhash.c + tls/openssl/lws-genrsa.c + tls/openssl/lws-genaes.c + tls/lws-genec-common.c + tls/openssl/lws-genec.c + tls/openssl/lws-gencrypto.c) + endif() + endif() + + if (NOT LWS_WITHOUT_SERVER) + list(APPEND SOURCES + tls/tls-server.c) + if (LWS_WITH_MBEDTLS) + list(APPEND SOURCES + tls/mbedtls/mbedtls-server.c) + else() + list(APPEND SOURCES + tls/openssl/openssl-server.c) + endif() + endif() + if (NOT LWS_WITHOUT_CLIENT) + list(APPEND SOURCES + tls/tls-client.c) + if (LWS_WITH_MBEDTLS) + list(APPEND SOURCES + tls/mbedtls/mbedtls-client.c) + else() + list(APPEND SOURCES + tls/openssl/openssl-client.c) + endif() + + endif() +endif() + +set(SOURCES ${SOURCES} PARENT_SCOPE) + +# +# OpenSSL +# +if (LWS_WITH_SSL) + message("Compiling with SSL support") + set(chose_ssl 0) + if (LWS_WITH_WOLFSSL) + # Use wolfSSL as OpenSSL replacement. + # TODO: Add a find_package command for this also. + message("wolfSSL include dir: ${WOLFSSL_INCLUDE_DIRS}") + message("wolfSSL libraries: ${WOLFSSL_LIBRARIES}") + + # Additional to the root directory we need to include + # the wolfssl/ subdirectory which contains the OpenSSL + # compatibility layer headers. + + if (LWS_WITH_CYASSL) + foreach(inc ${WOLFSSL_INCLUDE_DIRS}) + set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/cyassl PARENT_SCOPE) + include_directories("${inc}" "${inc}/cyassl") + endforeach() + else() + foreach(inc ${WOLFSSL_INCLUDE_DIRS}) + set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/wolfssl PARENT_SCOPE) + include_directories("${inc}" "${inc}/wolfssl") + endforeach() + endif() + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS} PARENT_SCOPE) + set(VARIA wolfSSL_) + + list(APPEND LIB_LIST "${WOLFSSL_LIBRARIES}") + set(chose_ssl 1) + endif() + + if (LWS_WITH_MBEDTLS) + message("MBEDTLS include dir: ${MBEDTLS_INCLUDE_DIRS}") + message("MBEDTLS libraries: ${MBEDTLS_LIBRARIES}") + + foreach(inc ${MBEDTLS_INCLUDE_DIRS}) + include_directories("${inc}" "${inc}/mbedtls") + endforeach() + + list(APPEND LIB_LIST "${MBEDTLS_LIBRARIES}") + set(chose_ssl 1) + endif() + + if (NOT chose_ssl) + if (NOT OPENSSL_FOUND AND NOT LWS_WITH_BORINGSSL) + # TODO: Add support for STATIC also. + if (NOT LWS_PLAT_FREERTOS) + find_package(PkgConfig QUIET) + pkg_check_modules(PC_OPENSSL openssl QUIET) + find_package(OpenSSL REQUIRED) + list(APPEND OPENSSL_LIBRARIES ${PC_OPENSSL_LIBRARIES}) + set(OPENSSL_LIBRARIES ${OPENSSL_LIBRARIES} PARENT_SCOPE) + endif() + set(OPENSSL_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}") + endif() + + message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIRS}") + if (NOT LWS_PLAT_FREERTOS) + message("OpenSSL libraries: ${OPENSSL_LIBRARIES}") + endif() + + if (OPENSSL_INCLUDE_DIRS) + include_directories("${OPENSSL_INCLUDE_DIRS}") + if (NOT LWS_PLAT_FREERTOS) + list(APPEND LIB_LIST ${OPENSSL_LIBRARIES}) + endif() + + if (NOT LWS_WITH_MBEDTLS) + # older (0.98) Openssl lacks this + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS} PARENT_SCOPE) + check_include_file(openssl/ecdh.h LWS_HAVE_OPENSSL_ECDH_H) + + if (LWS_SSL_SERVER_WITH_ECDH_CERT AND NOT LWS_HAVE_OPENSSL_ECDH_H) + message(FATAL_ERROR "Missing openssl/ecdh.h, so cannot use LWS_SSL_SERVER_WITH_ECDH_CERT") + endif() + else() + unset(LWS_HAVE_OPENSSL_ECDH_H PARENT_SCOPE) + endif(NOT LWS_WITH_MBEDTLS) + endif() + endif() + +endif(LWS_WITH_SSL) + +set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) +set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) + +if (NOT VARIA) + set(VARIA "") +endif() + +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_info_callback LWS_HAVE_SSL_SET_INFO_CALLBACK PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}RSA_set0_key LWS_HAVE_RSA_SET0_KEY PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}X509_get_key_usage LWS_HAVE_X509_get_key_usage PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_PKEY_new_raw_private_key LWS_HAVE_SSL_CTX_EVP_PKEY_new_raw_private_key PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_get0_certificate LWS_HAVE_SSL_CTX_get0_certificate PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_get0_alpn_selected LWS_HAVE_SSL_get0_alpn_selected PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_set_alpn_protos LWS_HAVE_SSL_set_alpn_protos PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb8 LWS_HAVE_EVP_aes_128_cfb8 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_cfb128 LWS_HAVE_EVP_aes_128_cfb128 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb8 LWS_HAVE_EVP_aes_192_cfb8 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_192_cfb128 LWS_HAVE_EVP_aes_192_cfb128 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb8 LWS_HAVE_EVP_aes_256_cfb8 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_256_cfb128 LWS_HAVE_EVP_aes_256_cfb128 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_xts LWS_HAVE_EVP_aes_128_xts PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}RSA_verify_pss_mgf1 LWS_HAVE_RSA_verify_pss_mgf1 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}HMAC_CTX_new LWS_HAVE_HMAC_CTX_new PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set_ciphersuites LWS_HAVE_SSL_CTX_set_ciphersuites PARENT_SCOPE) +if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) + if (UNIX) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl PARENT_SCOPE) + endif() +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { STACK_OF(X509) *c = NULL; SSL_CTX *ctx = NULL; return (int)SSL_CTX_get_extra_chain_certs_only(ctx, &c); }\n" LWS_HAVE_SSL_EXTRA_CHAIN_CERTS) +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX_free(md_ctx); return 0; }\n" LWS_HAVE_EVP_MD_CTX_free) +set(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS ${LWS_HAVE_SSL_EXTRA_CHAIN_CERTS} PARENT_SCOPE) +set(LWS_HAVE_EVP_MD_CTX_free ${LWS_HAVE_EVP_MD_CTX_free} PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}ECDSA_SIG_set0 LWS_HAVE_ECDSA_SIG_set0 PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}BN_bn2binpad LWS_HAVE_BN_bn2binpad PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_wrap LWS_HAVE_EVP_aes_128_wrap PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EC_POINT_get_affine_coordinates LWS_HAVE_EC_POINT_get_affine_coordinates PARENT_SCOPE) +endif() +if (LWS_WITH_MBEDTLS) + set(LWS_HAVE_TLS_CLIENT_METHOD 1 PARENT_SCOPE) + if (NOT LWS_PLAT_FREERTOS) + # not supported in esp-idf openssl wrapper yet, but is in our version + set(LWS_HAVE_X509_VERIFY_PARAM_set1_host 1 PARENT_SCOPE) + endif() + + CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_alpn_protocols LWS_HAVE_mbedtls_ssl_conf_alpn_protocols PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_ca_chain LWS_HAVE_mbedtls_ssl_set_hs_ca_chain PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_own_cert LWS_HAVE_mbedtls_ssl_set_hs_own_cert PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_authmode LWS_HAVE_mbedtls_ssl_set_hs_authmode PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_net_init LWS_HAVE_mbedtls_net_init PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_md_setup LWS_HAVE_mbedtls_md_setup PARENT_SCOPE) # not on xenial 2.2 + CHECK_FUNCTION_EXISTS(mbedtls_rsa_complete LWS_HAVE_mbedtls_rsa_complete PARENT_SCOPE) # not on xenial 2.2 + CHECK_FUNCTION_EXISTS(mbedtls_internal_aes_encrypt LWS_HAVE_mbedtls_internal_aes_encrypt PARENT_SCOPE) # not on xenial 2.2 +else() +CHECK_FUNCTION_EXISTS(${VARIA}TLS_client_method LWS_HAVE_TLS_CLIENT_METHOD PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}TLSv1_2_client_method LWS_HAVE_TLSV1_2_CLIENT_METHOD PARENT_SCOPE) +endif() + +# Generate self-signed SSL certs for the test-server. + +if (LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL) + message("Searching for OpenSSL executable and dlls") + find_package(OpenSSLbins) + message("OpenSSL executable: ${OPENSSL_EXECUTABLE}") + if (OPENSSL_EXECUTABLE MATCHES "^$") + set(OPENSSL_EXECUTABLE openssl) + endif() + if (NOT OPENSSL_EXECUTABLE) + set(OPENSSL_EXECUTABLE openssl) + endif() + +endif() + +set(GENCERTS 0) + +if (LWS_WITH_SSL AND OPENSSL_EXECUTABLE AND NOT LWS_WITHOUT_TEST_SERVER AND NOT LWS_WITHOUT_SERVER AND NOT LWS_WITHOUT_TESTAPPS) + set(GENCERTS 1) +endif() +if (LWS_PLAT_FREERTOS) + set(GENCERTS 1) +endif() +message(" GENCERTS = ${GENCERTS}") +if (GENCERTS) + message("Generating SSL Certificates for the test-server...") + + set(TEST_SERVER_SSL_KEY "${PROJECT_BINARY_DIR}/libwebsockets-test-server.key.pem") + set(TEST_SERVER_SSL_CERT "${PROJECT_BINARY_DIR}/libwebsockets-test-server.pem") + + if (WIN32) + if (MINGW) + message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -subj \"/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost\" -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") + execute_process( + COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -subj "/C=GB/ST=Erewhon/L=All around/O=libwebsockets-test/CN=localhost" -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" + RESULT_VARIABLE OPENSSL_RETURN_CODE) + else() + file(WRITE "${PROJECT_BINARY_DIR}/openssl_input.txt" + "GB\n" + "Erewhon\n" + "All around\n" + "libwebsockets-test\n" + "localhost\n" + "none@invalid.org\n\n" + ) + + # The "type" command is a bit picky with paths. + file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/openssl_input.txt" OPENSSL_INPUT_WIN_PATH) + message("OPENSSL_INPUT_WIN_PATH = ${OPENSSL_INPUT_WIN_PATH}") + message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"") + + execute_process( + COMMAND cmd /c type "${OPENSSL_INPUT_WIN_PATH}" + COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" + RESULT_VARIABLE OPENSSL_RETURN_CODE + OUTPUT_QUIET ERROR_QUIET) + + message("\n") + endif() + + if (OPENSSL_RETURN_CODE) + message(WARNING "!!! Failed to generate SSL certificate for Test Server using cmd.exe !!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") + else() + message("SUCCSESFULLY generated SSL certificate") + endif() + else() + # Unix. + execute_process( + COMMAND printf "GB\\nErewhon\\nAll around\\nlibwebsockets-test\\n\\nlocalhost\\nnone@invalid.org\\n" + COMMAND "${OPENSSL_EXECUTABLE}" + req -new -newkey rsa:2048 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}" + RESULT_VARIABLE OPENSSL_RETURN_CODE + # OUTPUT_QUIET ERROR_QUIET + ) + + if (OPENSSL_RETURN_CODE) + message(WARNING "!!! Failed to generate SSL certificate for Test Server!!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}") + else() + message("SUCCESSFULLY generated SSL certificate") + endif() + endif() + + list(APPEND TEST_SERVER_DATA + "${TEST_SERVER_SSL_KEY}" + "${TEST_SERVER_SSL_CERT}") +endif() + +# +# Copy OpenSSL dlls to the output directory on Windows. +# (Otherwise we'll get an error when trying to run) +# +if (MSVC AND LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL) + if(OPENSSL_BIN_FOUND) + message("OpenSSL dlls found:") + message(" Libeay: ${LIBEAY_BIN}") + message(" SSLeay: ${SSLEAY_BIN}") + + foreach(TARGET_BIN ${TEST_APP_LIST}) + add_custom_command(TARGET ${TARGET_BIN} + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${LIBEAY_BIN}" "$" VERBATIM) + add_custom_command(TARGET ${TARGET_BIN} + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${SSLEAY_BIN}" "$" VERBATIM) + + # + # Win32: if we are using libuv, also need to copy it in the output dir + # + if (MSVC AND LWS_WITH_LIBUV) + STRING(REPLACE ".lib" ".dll" LIBUV_BIN ${LIBUV_LIBRARIES}) + add_custom_command(TARGET ${TARGET_BIN} + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${LIBUV_BIN}" "$" VERBATIM) + endif() + endforeach() + endif() +endif() + +if (LWS_WITH_TLS AND (LWS_WITH_JOSE OR LWS_WITH_GENCRYPTO)) + list(APPEND SOURCES + tls/lws-gencrypto-common.c) +endif() + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) +set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) +set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) + \ No newline at end of file diff --git a/lib/tls/mbedtls/CMakeLists.txt b/lib/tls/mbedtls/CMakeLists.txt new file mode 100644 index 00000000..ad3ef327 --- /dev/null +++ b/lib/tls/mbedtls/CMakeLists.txt @@ -0,0 +1,115 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# +# The strategy is to only export to PARENT_SCOPE +# +# - changes to LIB_LIST +# - changes to SOURCES +# - includes via include_directories +# +# and keep everything else private + +include_directories(wrapper/include wrapper/include/internal) + + set(LWS_WITH_SSL ON) + + include_directories(wrapper/include) + include_directories(wrapper/include/platform) + include_directories(wrapper/include/internal) + include_directories(wrapper/include/openssl) + + if (LWS_WITH_NETWORK) + list(APPEND HDR_PRIVATE + tls/mbedtls/wrapper/include/internal/ssl3.h + tls/mbedtls/wrapper/include/internal/ssl_cert.h + tls/mbedtls/wrapper/include/internal/ssl_code.h + tls/mbedtls/wrapper/include/internal/ssl_dbg.h + tls/mbedtls/wrapper/include/internal/ssl_lib.h + tls/mbedtls/wrapper/include/internal/ssl_methods.h + tls/mbedtls/wrapper/include/internal/ssl_pkey.h + tls/mbedtls/wrapper/include/internal/ssl_stack.h + tls/mbedtls/wrapper/include/internal/ssl_types.h + tls/mbedtls/wrapper/include/internal/ssl_x509.h + tls/mbedtls/wrapper/include/internal/tls1.h + tls/mbedtls/wrapper/include/internal/x509_vfy.h) + + list(APPEND HDR_PRIVATE + tls/mbedtls/wrapper/include/openssl/ssl.h) + + list(APPEND HDR_PRIVATE + tls/mbedtls/wrapper/include/platform/ssl_pm.h + tls/mbedtls/wrapper/include/platform/ssl_port.h) + + list(APPEND SOURCES + tls/mbedtls/wrapper/library/ssl_cert.c + tls/mbedtls/wrapper/library/ssl_lib.c + tls/mbedtls/wrapper/library/ssl_methods.c + tls/mbedtls/wrapper/library/ssl_pkey.c + tls/mbedtls/wrapper/library/ssl_stack.c + tls/mbedtls/wrapper/library/ssl_x509.c) + + list(APPEND SOURCES + tls/mbedtls/wrapper/platform/ssl_pm.c + tls/mbedtls/wrapper/platform/ssl_port.c) + endif() + + + if ((NOT LWS_MBEDTLS_LIBRARIES OR "${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR + NOT LWS_MBEDTLS_INCLUDE_DIRS OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "") AND + NOT LWS_PLAT_FREERTOS) + + find_path(LWS_MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) + + find_library(MBEDTLS_LIBRARY mbedtls) + find_library(MBEDX509_LIBRARY mbedx509) + find_library(MBEDCRYPTO_LIBRARY mbedcrypto) + + set(LWS_MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}") + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(MBEDTLS DEFAULT_MSG + LWS_MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) + + mark_as_advanced(LWS_MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) + + if ("${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "") + message(FATAL_ERROR "You must set LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS when LWS_WITH_MBEDTLS is turned on.") + endif() + endif() + set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES}) + set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS}) + set(USE_MBEDTLS 1 PARENT_SCOPE) + include_directories(${MBEDTLS_INCLUDE_DIRS}) + + list(APPEND LIB_LIST ${MBEDTLS_LIBRARIES}) + +# old mbedtls has everything in mbedtls/net.h + +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return 0;}\n" LWS_HAVE_MBEDTLS_NET_SOCKETS) + +# +# Keep explicit parent scope exports at end +# + +exports_to_parent_scope() +set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) diff --git a/lib/tls/mbedtls/lws-genaes.c b/lib/tls/mbedtls/lws-genaes.c index a74a1696..4f4b85dd 100644 --- a/lib/tls/mbedtls/lws-genaes.c +++ b/lib/tls/mbedtls/lws-genaes.c @@ -25,7 +25,9 @@ * same whether you are using openssl or mbedtls hash functions underneath. */ #include "private-lib-core.h" +#if defined(LWS_WITH_JOSE) #include "private-lib-jose.h" +#endif static int operation_map[] = { MBEDTLS_AES_ENCRYPT, MBEDTLS_AES_DECRYPT }; diff --git a/lib/tls/openssl/lws-genaes.c b/lib/tls/openssl/lws-genaes.c index 360cd360..6ccb55dc 100644 --- a/lib/tls/openssl/lws-genaes.c +++ b/lib/tls/openssl/lws-genaes.c @@ -25,7 +25,9 @@ * same whether you are using openssl or mbedtls hash functions underneath. */ #include "private-lib-core.h" +#if defined(LWS_WITH_JOSE) #include "private-lib-jose.h" +#endif /* * Care: many openssl apis return 1 for success. These are translated to the diff --git a/lwsws/CMakeLists.txt b/lwsws/CMakeLists.txt new file mode 100644 index 00000000..cb34250e --- /dev/null +++ b/lwsws/CMakeLists.txt @@ -0,0 +1,61 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# + +if (LWS_WITH_LWSWS) + list(APPEND LWSWS_SRCS + "main.c" + ) + + if (WIN32) + list(APPEND LWSWS_SRCS + ${WIN32_HELPERS_PATH}/getopt.c + ${WIN32_HELPERS_PATH}/getopt_long.c + ${WIN32_HELPERS_PATH}/gettimeofday.c + ) + + list(APPEND LWSWS_HDR + ${WIN32_HELPERS_PATH}/getopt.h + ${WIN32_HELPERS_PATH}/gettimeofday.h + ) + endif(WIN32) + + source_group("Headers Private" FILES ${LWSWS_HDR}) + source_group("Sources" FILES ${LWSWS_SRCS}) + add_executable("lwsws" ${LWSWS_SRCS} ${LWSWS_HDR}) + + target_link_libraries("lwsws" websockets_shared ${LIB_LIST_AT_END}) + add_dependencies("lwsws" websockets_shared) + target_include_directories("lwsws" PRIVATE "${LWS_LIB_INCLUDES}" ${LWS_LIB_BUILD_INC_PATHS}) + + # Set test app specific defines. + set_property(TARGET "lwsws" + PROPERTY COMPILE_DEFINITIONS + INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" + ) + + install(TARGETS lwsws + RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT lwsws ) +endif (LWS_WITH_LWSWS) + + diff --git a/minimal-examples/CMakeLists.txt b/minimal-examples/CMakeLists.txt new file mode 100644 index 00000000..8591c2ef --- /dev/null +++ b/minimal-examples/CMakeLists.txt @@ -0,0 +1,50 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. + +MACRO(SUBDIRLIST result curdir) + FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) + SET(dirlist "") + + FOREACH(child ${children}) + IF (IS_DIRECTORY ${curdir}/${child}) + LIST(APPEND dirlist ${child}) + ENDIF() + ENDFOREACH() + + SET(${result} ${dirlist}) +ENDMACRO() + +include_directories(${LWS_LIB_BUILD_INC_PATHS}) +link_libraries(${LIB_LIST_AT_END}) + +SUBDIRLIST(SUBDIRS "${PROJECT_SOURCE_DIR}/minimal-examples") +FOREACH(subdir ${SUBDIRS}) + + SUBDIRLIST(SUBDIRS2 "${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}") + FOREACH(subdir2 ${SUBDIRS2}) + if (EXISTS "${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}/CMakeLists.txt") + message("Processing ${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}") + add_subdirectory("${PROJECT_SOURCE_DIR}/minimal-examples/${subdir}/${subdir2}") + endif() + ENDFOREACH() +ENDFOREACH() diff --git a/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt b/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt index 005a55b4..60ad5e48 100644 --- a/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt +++ b/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-smtp_client) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-smtp_client) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SMTP 1 requirements) diff --git a/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt b/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt index 461800d3..6a29ebc6 100644 --- a/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-async-dns) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-async-dns) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt b/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt index ade6249a..27887a22 100644 --- a/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-dhcpc) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-dhcpc) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SYS_DHCP_CLIENT 1 requirements) diff --git a/minimal-examples/api-tests/api-test-fts/CMakeLists.txt b/minimal-examples/api-tests/api-test-fts/CMakeLists.txt index aa4579fe..53256709 100644 --- a/minimal-examples/api-tests/api-test-fts/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-fts/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-fts) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-fts) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_FTS 1 requirements) diff --git a/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt index 0356ab82..4344bb57 100644 --- a/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-gencrypto) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-gencrypto) set(SRCS main.c lws-genaes.c lws-genec.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_GENCRYPTO 1 requirements) require_lws_config(LWS_WITH_JOSE 1 requirements) diff --git a/minimal-examples/api-tests/api-test-jose/CMakeLists.txt b/minimal-examples/api-tests/api-test-jose/CMakeLists.txt index 33ae85b6..32a9dcf6 100644 --- a/minimal-examples/api-tests/api-test-jose/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-jose/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-jose) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-jose) set(SRCS main.c jwk.c jws.c jwe.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) diff --git a/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt index 99aea9f7..6eb7e030 100644 --- a/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-lws_dsh) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_dsh) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_NETWORK 1 requirements) require_lws_config(LWS_WITH_LWS_DSH 1 requirements) diff --git a/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt index 07ff7c57..6e5101eb 100644 --- a/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-lws_sequencer) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_sequencer) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt index 5fcdc786..a752480c 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-lws_struct-json) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_struct-json) set(SRCS main.c test2.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_STRUCT_JSON 1 requirements) diff --git a/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt index 00ea42c1..e30388e1 100644 --- a/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-lws_struct-sqlite) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_struct-sqlite) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_STRUCT_SQLITE3 1 requirements) diff --git a/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt index 7eb968b2..0ab7308a 100644 --- a/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-api-test-lws_tokenize) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lws_tokenize) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - add_executable(${SAMP} ${SRCS}) add_test(NAME api-test-lws_tokenize COMMAND lws-api-test-lws_tokenize) diff --git a/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt b/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt index 7e147a73..ed394e95 100644 --- a/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt @@ -1,73 +1,19 @@ project(lws-api-test-lwsac) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-api-test-lwsac) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) +add_executable(${SAMP} ${SRCS}) +add_test(NAME api-test-lwsac COMMAND lws-api-test-lwsac) - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - add_executable(${SAMP} ${SRCS}) - add_test(NAME api-test-lwsac COMMAND lws-api-test-lwsac) - - if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) - add_dependencies(${SAMP} websockets_shared) - else() - target_link_libraries(${SAMP} websockets) - endif() +if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared) + add_dependencies(${SAMP} websockets_shared) +else() + target_link_libraries(${SAMP} websockets) +endif() diff --git a/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt b/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt index 42c93633..07715d0d 100644 --- a/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-unit-tests-smtp-client) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-unit-tests-smtp-client) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SMTP 1 requirements) diff --git a/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt b/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt index d33d3971..eaaa3068 100644 --- a/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt +++ b/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-proxy) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-proxy) set(SRCS minimal-ws-proxy.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt b/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt index b780a781..f43e1f9b 100644 --- a/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt +++ b/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt @@ -1,72 +1,17 @@ project(lws-crypto-jwe) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-crypto-jwe) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) if (requirements) - add_executable(${SAMP} ${SRCS}) if (websockets_shared) diff --git a/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt b/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt index 045f10c9..8649dc02 100644 --- a/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt +++ b/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt @@ -1,72 +1,17 @@ project(lws-crypto-jwk) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-crypto-jwk) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) if (requirements) - add_executable(${SAMP} ${SRCS}) if (websockets_shared) diff --git a/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt b/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt index 3be49cba..7fc01c99 100644 --- a/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt +++ b/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-crypto-jws) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-crypto-jws) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) diff --git a/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt b/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt index 5e37838a..e5b348bb 100644 --- a/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt +++ b/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-crypto-x509) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-crypto-x509) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_JOSE 1 requirements) diff --git a/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt b/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt index 3e361b4e..ee42b478 100644 --- a/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt +++ b/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt @@ -1,75 +1,19 @@ project(lws-minimal-dbus-client) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) include(CheckLibraryExists) +include(LwsCheckRequirements) set(SAMP lws-minimal-dbus-client) set(SRCS minimal-dbus-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_DBUS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -if (requirements) +if (NOT MSVC AND NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) if (NOT LWS_PLAT_FREERTOS) diff --git a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt index dbc8195f..c7443f5d 100644 --- a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt +++ b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt @@ -1,75 +1,16 @@ project(lws-minimal-dbus-ws-proxy-testclient) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) include(CheckLibraryExists) - -set(SAMP lws-minimal-dbus-ws-proxy-testclient) -set(SRCS minimal-dbus-ws-proxy-testclient.c) - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - +include(LwsCheckRequirements) set(requirements 1) require_lws_config(LWS_ROLE_DBUS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -if (requirements) +if (NOT MSVC AND NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) if (NOT LWS_PLAT_FREERTOS) diff --git a/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt b/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt index 105bb5cd..e809cc8c 100644 --- a/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt +++ b/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt @@ -1,75 +1,19 @@ project(lws-minimal-dbus-server) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) include(CheckLibraryExists) +include(LwsCheckRequirements) set(SAMP lws-minimal-dbus-server) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_DBUS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) -if (requirements) +if (NOT MSVC AND NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) if (NOT LWS_PLAT_FREERTOS) diff --git a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt index 9068a7b3..04844be7 100644 --- a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt +++ b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt @@ -1,77 +1,21 @@ project(lws-minimal-dbus-ws-proxy) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) include(CheckLibraryExists) +include(LwsCheckRequirements) set(SAMP lws-minimal-dbus-ws-proxy) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_DBUS 1 requirements) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -if (requirements) +if (NOT MSVC AND NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) if (NOT LWS_PLAT_FREERTOS) diff --git a/minimal-examples/gtk/minimal-gtk/CMakeLists.txt b/minimal-examples/gtk/minimal-gtk/CMakeLists.txt index fa4e46d3..6b33e25b 100644 --- a/minimal-examples/gtk/minimal-gtk/CMakeLists.txt +++ b/minimal-examples/gtk/minimal-gtk/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-gtk) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-gtk) set(SRCS main.c) - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt index 822bfbbe..a7938d1f 100644 --- a/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt @@ -1,96 +1,21 @@ project(lws-minimal-http-client-attach) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) Project(lws-minimal-http-client-attach) set(SAMP lws-minimal-http-client-attach) set(SRCS minimal-http-client-attach.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) -if (WIN32) - set(requirements 0) -endif() require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -if (requirements) +if (requirements AND NOT WIN32) add_executable(${SAMP} ${SRCS}) if (websockets_shared) diff --git a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt index b9d34fdc..e3616903 100644 --- a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt @@ -1,76 +1,19 @@ project(lws-minimal-http-client-captive-portal) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-captive-portal) set(SRCS minimal-http-client-captive-portal.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) -if (WIN32) - set(requirements 0) -endif() require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -if (requirements) +if (NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) diff --git a/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt index b97fb128..70773824 100644 --- a/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt @@ -1,73 +1,17 @@ project(lws-minimal-http-client-certinfo) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-certinfo) set(SRCS minimal-http-client-certinfo.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt index 09bb1de2..948d10d9 100644 --- a/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt @@ -1,69 +1,13 @@ project(lws-minimal-http-client-custom-headers) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-custom-headers) set(SRCS minimal-http-client-custom-headers.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt index fe195215..1dcbdb99 100644 --- a/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt @@ -1,69 +1,13 @@ project(lws-minimal-http-client-h2-rxflow) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-h2-rxflow) set(SRCS minimal-http-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H2 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt index d2f7415a..0805bc6d 100644 --- a/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-http-client-hugeurl) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-hugeurl) set(SRCS minimal-http-client-hugeurl.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt index 68466846..7ccc6d83 100644 --- a/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt @@ -1,69 +1,13 @@ project(lws-minimal-http-client-multi) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-multi) set(SRCS minimal-http-client-multi.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt index f83182f6..37d27967 100644 --- a/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-http-client-post) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client-post) set(SRCS minimal-http-client-post.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt index 6dd0ba02..49e11b83 100644 --- a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt @@ -1,69 +1,13 @@ -project(lws-minimal-http-client) +project(lws-minimal-http-client C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-client) set(SRCS minimal-http-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt index b3e921ff..5faf9746 100644 --- a/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-basicauth) +project(lws-minimal-http-server-basicauth C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-basicauth) set(SRCS minimal-http-server-basicauth.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt index e0580c21..3bb6def6 100644 --- a/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt @@ -1,69 +1,13 @@ -project(lws-minimal-http-server-cgi) +project(lws-minimal-http-server-cgi C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-cgi) set(SRCS minimal-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CGI 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt index 9e0c57f3..7c0ad4be 100644 --- a/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-custom-headers) +project(lws-minimal-http-server-custom-headers C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-custom-headers) set(SRCS minimal-http-server-custom-headers.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CUSTOM_HEADERS 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt index dbdfcc3b..ee150551 100644 --- a/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt @@ -1,6 +1,9 @@ -project(lws-minimal-http-server-deaddrop) +project(lws-minimal-http-server-deaddrop C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-deaddrop) set(SRCS minimal-http-server-deaddrop.c) @@ -9,63 +12,6 @@ set(SRCS minimal-http-server-deaddrop.c) # to the lws plugins dir so it can pick up the plugin source. Eg, # cmake . -DLWS_PLUGINS_DIR=~/libwebsockets/plugins -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_ROLE_WS 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt index f3a84474..0d579d68 100644 --- a/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt @@ -1,68 +1,13 @@ -project(lws-minimal-http-server-dynamic) +project(lws-minimal-http-server-dynamic C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-dynamic) set(SRCS minimal-http-server-dynamic.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt index c11deb6c..ff379de3 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt @@ -1,68 +1,13 @@ -project(lws-minimal-http-server-eventlib-demos) +project(lws-minimal-http-server-eventlib-demos C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-eventlib-demos) set(SRCS minimal-http-server-eventlib-demos.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_ROLE_WS 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt index 2e3b6d65..ebcfe8fd 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt @@ -1,74 +1,17 @@ -project(lws-minimal-http-server-eventlib-foreign) +project(lws-minimal-http-server-eventlib-foreign C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-eventlib-foreign) set(SRCS minimal-http-server-eventlib-foreign.c) - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) - - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(LWS_WITH_LIBUV)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBUV) CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(LWS_WITH_LIBEVENT)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBEVENT) CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(LWS_WITH_LIBEV)\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" LWS_WITH_LIBEV) diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt index 25c0b314..4243d76f 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt @@ -1,87 +1,14 @@ -project(lws-minimal-http-server-eventlib-smp) +project(lws-minimal-http-server-eventlib-smp C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-eventlib-smp) set(SRCS minimal-http-server-eventlib-smp.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt index e712b8a7..5d89fcfd 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt @@ -1,68 +1,13 @@ -project(lws-minimal-http-server-eventlib) +project(lws-minimal-http-server-eventlib C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-eventlib) set(SRCS minimal-http-server-eventlib.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt index b1dc6375..2dec8623 100644 --- a/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-form-get) +project(lws-minimal-http-server-form-get C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-form-get) set(SRCS minimal-http-server-form-get.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt index 310e675e..664ed06f 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-form-post-file) +project(lws-minimal-http-server-form-post-file C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-form-post-file) set(SRCS minimal-http-server-form-post-file.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt index a748c60a..d7872d83 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-form-post-lwsac) +project(lws-minimal-http-server-form-post-lwsac C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-form-post-lwsac) set(SRCS minimal-http-server-form-post.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt index ee9c7643..9c17a794 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-form-post) +project(lws-minimal-http-server-form-post C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-form-post) set(SRCS minimal-http-server-form-post.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt index 4a9c8862..b80bcbcb 100644 --- a/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt @@ -1,71 +1,15 @@ -project(lws-minimal-http-server-fulltext-search) +project(lws-minimal-http-server-fulltext-search C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-fulltext-search) set(SRCS minimal-http-server.c) include_directories(../../../plugins) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_FTS 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt index b62fe168..c298dd7c 100644 --- a/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt @@ -1,72 +1,17 @@ -project(lws-minimal-http-server-generic-sessions) +project(lws-minimal-http-server-generic-sessions C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-generic-sessions) set(SRCS minimal-http-server-generic-sessions.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) require_lws_config(LWS_WITH_GENERIC_SESSIONS 1 requirements) require_lws_config(LWS_WITH_LIBUV 1 requirements) require_lws_config(LWS_WITH_PLUGINS 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt index 21f45c9a..4321f6d3 100644 --- a/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt @@ -1,69 +1,13 @@ -project(lws-minimal-http-server-h2-long-poll) +project(lws-minimal-http-server-h2-long-poll C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-h2-long-poll) set(SRCS minimal-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt index d12e9f94..1e4a756e 100644 --- a/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt @@ -1,69 +1,13 @@ -project(lws-minimal-http-server-mimetypes) +project(lws-minimal-http-server-mimetypes C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-mimetypes) set(SRCS minimal-http-server-mimetypes.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt index fc813a37..9db33227 100644 --- a/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt @@ -1,67 +1,13 @@ -project(lws-minimal-http-server-multivhost) +project(lws-minimal-http-server-multivhost C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-multivhost) set(SRCS minimal-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt index a54a4dc0..082507e7 100644 --- a/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt @@ -1,73 +1,18 @@ -project(lws-minimal-http-server-proxy) +project(lws-minimal-http-server-proxy C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-proxy) set(SRCS minimal-http-server-proxy.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) require_lws_config(LWS_WITH_HTTP_PROXY 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt index ab9c8336..ea0d4771 100644 --- a/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt @@ -1,87 +1,14 @@ -project(lws-minimal-http-server-smp) +project(lws-minimal-http-server-smp C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-smp) set(SRCS minimal-http-server-smp.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt index 384f0a78..604ef00b 100644 --- a/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt @@ -6,82 +6,6 @@ include(CheckCSourceCompiles) set(SAMP lws-minimal-http-server-sse-ring) set(SRCS minimal-http-server-sse-ring.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt index 781ae309..9970d3ca 100644 --- a/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt @@ -1,86 +1,13 @@ -project(lws-minimal-http-server-sse) +project(lws-minimal-http-server-sse C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-sse) set(SRCS minimal-http-server-sse.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) diff --git a/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt index 60af8b5d..44082ffc 100644 --- a/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt @@ -1,72 +1,17 @@ -project(lws-minimal-http-server-tls-80) +project(lws-minimal-http-server-tls-80 C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-tls-80) set(SRCS minimal-http-server-tls-80.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt index 03bd1baa..ab88835e 100644 --- a/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt @@ -1,72 +1,17 @@ -project(lws-minimal-http-server-tls-mem) +project(lws-minimal-http-server-tls-mem C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-tls-mem) set(SRCS minimal-http-server-tls-mem.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt index 2f381daf..73a07211 100644 --- a/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt @@ -1,72 +1,17 @@ -project(lws-minimal-http-server-tls) +project(lws-minimal-http-server-tls C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server-tls) set(SRCS minimal-http-server-tls.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) -require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/http-server/minimal-http-server/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server/CMakeLists.txt index 483877fc..54b412ef 100644 --- a/minimal-examples/http-server/minimal-http-server/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server/CMakeLists.txt @@ -1,69 +1,13 @@ -project(lws-minimal-http-server) +project(lws-minimal-http-server C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-http-server) set(SRCS minimal-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt index 1528be8c..2e91b417 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt +++ b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt @@ -1,68 +1,13 @@ +project(lws-minimal-mqtt-client-multi C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-mqtt-client-multi) set(SRCS minimal-mqtt-client-multi.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_MQTT 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt b/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt index f22c58bd..3d729068 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt +++ b/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt @@ -1,68 +1,11 @@ +project(lws-minimal-mqtt-client C) cmake_minimum_required(VERSION 2.8) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-mqtt-client) set(SRCS minimal-mqtt-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_MQTT 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt b/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt index 573d7985..38ced079 100644 --- a/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-minimal-raw-adopt-tcp) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-adopt-tcp) set(SRCS minimal-raw-adopt-tcp.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt b/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt index a05e3397..b41ec507 100644 --- a/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-minimal-raw-adopt-udp) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-adopt-udp) set(SRCS minimal-raw-adopt-udp.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt b/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt index 44c15f92..ca007d4c 100644 --- a/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-raw-audio) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-audio) set(SRCS audio.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_ALSA 1 requirements) require_lws_config(LWS_WITH_NETWORK 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt b/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt index ff417c2c..45361e92 100644 --- a/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt @@ -1,69 +1,13 @@ project(lws-minimal-raw-fallback-http-server) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-fallback-http-server) set(SRCS minimal-raw-fallback-http-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-file/CMakeLists.txt b/minimal-examples/raw/minimal-raw-file/CMakeLists.txt index 75d0bf25..60e2f755 100644 --- a/minimal-examples/raw/minimal-raw-file/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-file/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-raw-file) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-file) set(SRCS minimal-raw-file.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt b/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt index b6b1124b..c848c731 100644 --- a/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-minimal-raw-netcat) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-netcat) set(SRCS minimal-raw-netcat.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt b/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt index 42684787..c83e5f66 100644 --- a/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt @@ -1,6 +1,9 @@ project(lws-minimal-raw-proxy-fallback) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-proxy-fallback) set(SRCS minimal-raw-proxy-fallback.c) @@ -9,63 +12,6 @@ set(SRCS minimal-raw-proxy-fallback.c) # to the lws plugins dir so it can pick up the plugin source. Eg, # cmake . -DLWS_PLUGINS_DIR=~/libwebsockets/plugins -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_RAW_PROXY 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt b/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt index c16c658f..27aa5ee2 100644 --- a/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt @@ -1,6 +1,9 @@ project(lws-minimal-raw-proxy) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-proxy) set(SRCS minimal-raw-proxy.c) @@ -9,63 +12,6 @@ set(SRCS minimal-raw-proxy.c) # to the lws plugins dir so it can pick up the plugin source. Eg, # cmake . -DLWS_PLUGINS_DIR=~/libwebsockets/plugins -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_RAW_PROXY 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt b/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt index 2cbb66e7..b7061782 100644 --- a/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-raw-serial) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-serial) set(SRCS minimal-raw-file.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt b/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt index 8da1a0ac..9e1f1993 100644 --- a/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-minimal-raw-vhost) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-raw-vhost) set(SRCS minimal-raw-vhost.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt index 0fb81078..1a7b6b49 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt @@ -1,67 +1,13 @@ +project(lws-minimal-secure-streams-alexa C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-alexa) set(SRCS main.c alexa.c audio.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt index e336dad3..0c4d91d8 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt @@ -1,66 +1,12 @@ +project(lws-minimal-secure-streams-avs C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-avs) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt index 38dd3006..c18fec9f 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt @@ -1,67 +1,13 @@ +project(lws-minimal-secure-streams-client-tx C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-client-tx) set(SRCS minimal-secure-streams-client-tx.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt index b53fb9bb..1fd06ea7 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt @@ -1,67 +1,12 @@ -project(minimal-secure-streams-metadata) +project(lws-minimal-secure-streams-metadata C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-metadata) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt index 5aec9b00..0ed47004 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt @@ -1,66 +1,12 @@ +project(lws-minimal-secure-streams-policy2c C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-policy2c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_ROLE_H2 1 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt index 60e105ec..e27cbd7d 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt @@ -1,67 +1,13 @@ +project(lws-minimal-secure-streams-proxy C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-proxy) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt index cd466d90..093fda6f 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt @@ -1,67 +1,13 @@ +project(lws-minimal-secure-streams-seq C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-seq) set(SRCS minimal-secure-streams.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt index e32bcbd7..1cbfe002 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt @@ -1,67 +1,13 @@ +project(lws-minimal-secure-streams-sink C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-sink) set(SRCS main.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt index df7290f2..a54f7387 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt @@ -1,66 +1,12 @@ +project(lws-minimal-secure-streams-staticpolicy C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams-staticpolicy) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) diff --git a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt index f24d2a87..257e8f83 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt @@ -1,66 +1,12 @@ +project(lws-minimal-secure-streams C) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-secure-streams) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - endif() -ENDMACRO() - - set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) diff --git a/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt index a998ccba..eae57afb 100644 --- a/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-client-echo) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-echo) set(SRCS minimal-ws-client-echo.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt index c6d11332..887dc21e 100644 --- a/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt @@ -1,87 +1,14 @@ project(lws-minimal-ws-client-ping) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-ping) set(SRCS minimal-ws-client-ping.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) diff --git a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt index e4a1e312..08a00c9c 100644 --- a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-client-pmd-bulk) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-pmd-bulk) set(SRCS minimal-ws-client-pmd-bulk.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt index 57bb3af9..7f5fe2fb 100644 --- a/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-client-rx) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-rx) set(SRCS minimal-ws-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt index 47850db9..d8efb1d1 100644 --- a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt @@ -1,87 +1,14 @@ project(lws-minimal-ws-client-spam) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-spam) set(SRCS minimal-ws-client-spam.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) diff --git a/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt index 70fd5e27..274a28e7 100644 --- a/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt @@ -1,87 +1,14 @@ project(lws-minimal-ws-client-tx) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client-tx) set(SRCS minimal-ws-client.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) diff --git a/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt index b3a4e982..e936d1eb 100644 --- a/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt @@ -1,69 +1,14 @@ project(lws-minimal-ws-client-ping) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-client) set(SRCS minimal-ws-client.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt index 4a1d9521..70082d1d 100644 --- a/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt @@ -1,67 +1,13 @@ project(lws-minimal-ws-broker) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-broker) set(SRCS minimal-ws-broker.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt index d424d593..523d823c 100644 --- a/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-server-echo) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-echo) set(SRCS minimal-ws-server-echo.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt index 35fa2564..b9cfaa6e 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-server-pmd-bulk) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-pmd-bulk) set(SRCS minimal-ws-server-pmd-bulk.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt index 8bc97063..6d0347f2 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-server-pmd-corner) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-pmd-corner) set(SRCS minimal-ws-server-pmd-corner.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt index fe558213..2651af7f 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-server-pmd) cmake_minimum_required(VERSION 2.8.9) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-pmd) set(SRCS minimal-ws-server-pmd.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt index 20bfc2e3..b235a6b0 100644 --- a/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-server-ring) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-ring) set(SRCS minimal-ws-server-ring.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt index f557ca2b..96f2aee6 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt @@ -1,87 +1,14 @@ project(lws-minimal-ws-server-threadpool) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-threadpool) set(SRCS minimal-ws-server-threadpool.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt index bf2ef9d5..8a5b92ab 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt @@ -1,87 +1,14 @@ project(lws-minimal-ws-server-threads-smp) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-threads-smp) set(SRCS minimal-ws-server.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_pthreads(requirements) require_lws_config(LWS_ROLE_WS 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt index c8bbb072..f359ab5b 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt @@ -1,87 +1,14 @@ project(lws-minimal-ws-server-threads) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckIncludeFile) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-threads) set(SRCS minimal-ws-server.c) -MACRO(require_pthreads result) - CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) - if (NOT LWS_HAVE_PTHREAD_H) - if (LWS_WITH_MINIMAL_EXAMPLES) - set(${result} 0) - message("${SAMP}: skipping as no pthreads") - else() - message(FATAL_ERROR "threading support requires pthreads") - endif() - else() - if (WIN32) - set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) - else() - set(PTHREAD_LIB pthread) - endif() - endif() -ENDMACRO() - -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) if (WIN32) set(requirements 0) diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt index 1ad57a91..ee6dc79f 100644 --- a/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-server-timer) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server-timer) set(SRCS minimal-ws-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt index c4e2911c..1f2e6f8a 100644 --- a/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt @@ -1,68 +1,13 @@ project(lws-minimal-ws-server) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) include(CheckCSourceCompiles) +include(LwsCheckRequirements) set(SAMP lws-minimal-ws-server) set(SRCS minimal-ws-server.c) -# If we are being built as part of lws, confirm current build config supports -# reqconfig, else skip building ourselves. -# -# If we are being built externally, confirm installed lws was configured to -# support reqconfig, else error out with a helpful message about the problem. -# -MACRO(require_lws_config reqconfig _val result) - - if (DEFINED ${reqconfig}) - if (${reqconfig}) - set (rq 1) - else() - set (rq 0) - endif() - else() - set(rq 0) - endif() - - if (${_val} EQUAL ${rq}) - set(SAME 1) - else() - set(SAME 0) - endif() - - if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME}) - if (${_val}) - message("${SAMP}: skipping as lws being built without ${reqconfig}") - else() - message("${SAMP}: skipping as lws built with ${reqconfig}") - endif() - set(${result} 0) - else() - if (LWS_WITH_MINIMAL_EXAMPLES) - set(MET ${SAME}) - else() - CHECK_C_SOURCE_COMPILES("#include \nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig}) - if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig}) - set(HAS_${reqconfig} 0) - else() - set(HAS_${reqconfig} 1) - endif() - if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val})) - set(MET 1) - else() - set(MET 0) - endif() - endif() - if (NOT MET) - if (${_val}) - message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}") - else() - message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project") - endif() - endif() - - endif() -ENDMACRO() - set(requirements 1) require_lws_config(LWS_ROLE_WS 1 requirements) require_lws_config(LWS_WITH_SERVER 1 requirements) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 00000000..571ab518 --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,222 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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_directories(.) + +link_libraries(${LIB_LIST_AT_END}) + +if (LWS_WITH_PLUGINS AND LWS_WITH_SHARED) + macro(create_plugin PLUGIN_NAME PLUGIN_INCLUDE MAIN_SRC S2 S3) + + set(PLUGIN_SRCS ${MAIN_SRC}) + + if ("${S2}" STREQUAL "") + else() + list(APPEND PLUGIN_SRCS ${S2}) + endif() + if ("${S3}" STREQUAL "") + else() + list(APPEND PLUGIN_SRCS ${S3}) + endif() + + if (WIN32) + list(APPEND PLUGIN_SRCS + ../${WIN32_HELPERS_PATH}/getopt.c + ../${WIN32_HELPERS_PATH}/getopt_long.c + ../${WIN32_HELPERS_PATH}/gettimeofday.c + ) + + list(APPEND PLUGIN_HDR + ../${WIN32_HELPERS_PATH}/getopt.h + ../${WIN32_HELPERS_PATH}/gettimeofday.h + ) + endif(WIN32) + + source_group("Headers Private" FILES ${PLUGIN_HDR}) + source_group("Sources" FILES ${PLUGIN_SRCS}) + add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SRCS} ${PLUGIN_HDR}) + + target_link_libraries(${PLUGIN_NAME} websockets_shared) + add_dependencies(${PLUGIN_NAME} websockets_shared) + + target_include_directories(${PLUGIN_NAME} PRIVATE ${PLUGIN_INCLUDE} ${LWS_LIB_BUILD_INC_PATHS}) + + # Set test app specific defines. + set_property(TARGET ${PLUGIN_NAME} + PROPERTY COMPILE_DEFINITIONS + INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/plugins" + ) + + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# SET_TARGET_PROPERTIES(${PLUGIN_NAME} +# PROPERTIES COMPILE_FLAGS ${CMAKE_C_FLAGS}) + +# set_target_properties(${PLUGIN_NAME} +# PROPERTIES +# OUTPUT_NAME ${PLUGIN_NAME}) + + list(APPEND PLUGINS_LIST ${PLUGIN_NAME}) + + endmacro() + +if (LWS_ROLE_WS) + create_plugin(protocol_dumb_increment "" + "protocol_dumb_increment.c" "" "") + create_plugin(protocol_lws_mirror "" + "protocol_lws_mirror.c" "" "") + create_plugin(protocol_lws_status "" + "protocol_lws_status.c" "" "") + create_plugin(protocol_lws_table_dirlisting "" + "generic-table/protocol_table_dirlisting.c" "" "") + if (NOT WIN32) + create_plugin(protocol_lws_raw_test "" + "protocol_lws_raw_test.c" "" "") + + if (UNIX AND LWS_HAVE_PTHREAD_H) + create_plugin(protocol_deaddrop "" + "deaddrop/protocol_lws_deaddrop.c" "" "") + endif() + endif() + + if (LWS_WITH_SERVER_STATUS) + create_plugin(protocol_lws_server_status "" + "protocol_lws_server_status.c" "" "") + endif() + + if (NOT LWS_WITHOUT_CLIENT) + create_plugin(protocol_client_loopback_test "" + "protocol_client_loopback_test.c" "" "") + endif() + +endif(LWS_ROLE_WS) + + create_plugin(protocol_post_demo "" + "protocol_post_demo.c" "" "") + +if (LWS_ROLE_RAW_PROXY) + create_plugin(protocol_lws_raw_proxy "" + "raw-proxy/protocol_lws_raw_proxy.c" "" "") +endif() + +if (LWS_WITH_FTS) + create_plugin(protocol_fulltext_demo "" + "protocol_fulltext_demo.c" "" "") +endif() + + +if (LWS_WITH_SSL) + create_plugin(protocol_lws_ssh_base "ssh-base/include" + "ssh-base/sshd.c;ssh-base/telnet.c;ssh-base/kex-25519.c" "ssh-base/crypto/chacha.c;ssh-base/crypto/ed25519.c;ssh-base/crypto/fe25519.c;ssh-base/crypto/ge25519.c;ssh-base/crypto/poly1305.c;ssh-base/crypto/sc25519.c;ssh-base/crypto/smult_curve25519_ref.c" "") + create_plugin(protocol_lws_sshd_demo "ssh-base/include" "protocol_lws_sshd_demo.c" "" "") + + include_directories("${PROJECT_SOURCE_DIR}/plugins/ssh-base/include") +endif() + + + +if (LWS_WITH_ACME) + create_plugin(protocol_lws_acme_client "" + "acme-client/protocol_lws_acme_client.c" "" "") +endif() + +if (LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS) + create_plugin(protocol_generic_sessions "" + "generic-sessions/protocol_generic_sessions.c" + "generic-sessions/utils.c" + "generic-sessions/handlers.c") + + if (WIN32) + target_link_libraries(protocol_generic_sessions ${LWS_SQLITE3_LIBRARIES}) + else() + target_link_libraries(protocol_generic_sessions sqlite3 ) + endif(WIN32) + + create_plugin(protocol_lws_messageboard "" + "generic-sessions/protocol_lws_messageboard.c" "" "") + if (WIN32) + target_link_libraries(protocol_lws_messageboard ${LWS_SQLITE3_LIBRARIES}) + else() + target_link_libraries(protocol_lws_messageboard sqlite3 ) + endif(WIN32) + +endif(LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS) + + +endif(LWS_WITH_PLUGINS AND LWS_WITH_SHARED) + + +# plugins + +if (LWS_WITH_PLUGINS) + install(TARGETS ${PLUGINS_LIST} + PERMISSIONS OWNER_WRITE OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ + DESTINATION share/libwebsockets-test-server/plugins + COMPONENT plugins) + + if (NOT WIN32) + install(FILES deaddrop/assets/index.html;deaddrop/assets/deaddrop.js;deaddrop/assets/deaddrop.css;deaddrop/assets/drop.svg + DESTINATION share/libwebsockets-test-server/deaddrop + COMPONENT plugins) + endif() + + +if (LWS_WITH_SERVER_STATUS) + install(FILES server-status.html;server-status.js;server-status.css;lwsws-logo.png + DESTINATION share/libwebsockets-test-server/server-status + COMPONENT examples) +endif() +if (LWS_WITH_GENERIC_SESSIONS) + install(FILES + generic-sessions/assets/lwsgs-logo.png + generic-sessions/assets/seats.jpg + generic-sessions/assets/failed-login.html + generic-sessions/assets/lwsgs.js + generic-sessions/assets/lwsgs.css + generic-sessions/assets/post-register-fail.html + generic-sessions/assets/post-register-ok.html + generic-sessions/assets/post-verify-ok.html + generic-sessions/assets/post-verify-fail.html + generic-sessions/assets/sent-forgot-ok.html + generic-sessions/assets/sent-forgot-fail.html + generic-sessions/assets/post-forgot-ok.html + generic-sessions/assets/post-forgot-fail.html + generic-sessions/assets/index.html + DESTINATION share/libwebsockets-test-server/generic-sessions + COMPONENT examples) + install(FILES generic-sessions/assets/successful-login.html + DESTINATION share/libwebsockets-test-server/generic-sessions/needauth + COMPONENT examples) + install(FILES generic-sessions/assets/admin-login.html + DESTINATION share/libwebsockets-test-server/generic-sessions/needadmin + COMPONENT examples) +endif() + + install(FILES + generic-table/assets/lwsgt.js + generic-table/assets/index.html + DESTINATION share/libwebsockets-test-server/generic-table + COMPONENT examples) + +endif() diff --git a/test-apps/CMakeLists.txt b/test-apps/CMakeLists.txt new file mode 100644 index 00000000..e7b6023f --- /dev/null +++ b/test-apps/CMakeLists.txt @@ -0,0 +1,247 @@ +# +# libwebsockets - small server side websockets and web server implementation +# +# Copyright (C) 2010 - 2020 Andy Green +# +# 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. +# + +# +# Test applications +# + +set(TEST_APP_LIST) +if ((LWS_ROLE_H1 OR LWS_ROLE_H2)) + # + # Helper function for adding a test app. + # + macro(create_test_app TEST_NAME MAIN_SRC S2 S3 S4 S5 S6) + + set(TEST_SRCS ${MAIN_SRC}) + set(TEST_HDR) + if ("${S2}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S2}) + endif() + if ("${S3}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S3}) + endif() + if ("${S4}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S4}) + endif() + if ("${S5}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S5}) + endif() + if ("${S6}" STREQUAL "") + else() + list(APPEND TEST_SRCS ${S6}) + endif() + if (WIN32) + list(APPEND TEST_SRCS + ../${WIN32_HELPERS_PATH}/getopt.c + ../${WIN32_HELPERS_PATH}/getopt_long.c + ../${WIN32_HELPERS_PATH}/gettimeofday.c + ) + + list(APPEND TEST_HDR + ../${WIN32_HELPERS_PATH}/getopt.h + ../${WIN32_HELPERS_PATH}/gettimeofday.h + ) + endif(WIN32) + + source_group("Headers Private" FILES ${TEST_HDR}) + source_group("Sources" FILES ${TEST_SRCS}) + add_executable(${TEST_NAME} ${TEST_SRCS} ${TEST_HDR}) + + if (LWS_LINK_TESTAPPS_DYNAMIC) + if (NOT LWS_WITH_SHARED) + message(FATAL_ERROR "Build of the shared library is disabled. LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_SHARED.") + endif() + target_link_libraries(${TEST_NAME} websockets_shared) + add_dependencies(${TEST_NAME} websockets_shared) + else() + if (NOT LWS_WITH_STATIC) + message(FATAL_ERROR "Build of the static library is disabled. Disabled LWS_LINK_TESTAPPS_DYNAMIC must be combined with LWS_WITH_STATIC.") + endif() + target_link_libraries(${TEST_NAME} websockets) + add_dependencies(${TEST_NAME} websockets) + if (UNIX AND LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) + target_link_libraries(${TEST_NAME} dl) + endif() + endif() + + target_include_directories(${TEST_NAME} PRIVATE "${LWS_LIB_INCLUDES}" ${LWS_LIB_BUILD_INC_PATHS}) + target_compile_options(${TEST_NAME} PRIVATE ${LWS_PTHR_FLAGS}) + + if (LWS_WITH_HTTP_STREAM_COMPRESSION) + target_link_libraries(${TEST_NAME} z) + endif() + + # Set test app specific defines. + set_property(TARGET ${TEST_NAME} + PROPERTY COMPILE_DEFINITIONS + INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" + ) + + # Prefix the binary names with libwebsockets. + set_target_properties(${TEST_NAME} + PROPERTIES + OUTPUT_NAME libwebsockets-${TEST_NAME}) + + target_link_libraries(${TEST_NAME} ${LIB_LIST_AT_END}) + + # Add to the list of tests. + list(APPEND TEST_APP_LIST ${TEST_NAME}) + endmacro() + + if (NOT LWS_WITHOUT_SERVER) + # + # test-server + # + if (NOT LWS_WITHOUT_TEST_SERVER) + create_test_app(test-server "test-server.c" + "" + "" + "" + "" + "") + + if (LWS_WITH_CGI AND LWS_WITH_TLS) + create_test_app(test-sshd "test-sshd.c" + "" + "" + "" + "" + "") + target_include_directories(test-sshd PRIVATE "${PROJECT_SOURCE_DIR}/plugins/ssh-base/include") + + endif() + + endif() + + # + # test-server-extpoll + # + if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL AND NOT WIN32) + create_test_app(test-server-extpoll + "test-server.c" + "" + "" + "" + "" + "") + # Set defines for this executable only. + set_property( + TARGET test-server-extpoll + PROPERTY COMPILE_DEFINITIONS + EXTERNAL_POLL + INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" + ) + + # We need to link against winsock code. + if (WIN32) + target_link_libraries(test-server-extpoll ws2_32.lib) + endif(WIN32) + endif() + + if (LWS_WITH_LEJP) + create_test_app( + test-lejp + "test-lejp.c" + "" + "" + "" + "" + "") + endif() + + # Data files for running the test server. + list(APPEND TEST_SERVER_DATA + "${PROJECT_SOURCE_DIR}/test-apps/favicon.ico" + "${PROJECT_SOURCE_DIR}/test-apps/leaf.jpg" + "${PROJECT_SOURCE_DIR}/test-apps/candide.zip" + "${PROJECT_SOURCE_DIR}/test-apps/libwebsockets.org-logo.svg" + "${PROJECT_SOURCE_DIR}/test-apps/http2.png" + "${PROJECT_SOURCE_DIR}/test-apps/wss-over-h2.png" + "${PROJECT_SOURCE_DIR}/test-apps/lws-common.js" + "${PROJECT_SOURCE_DIR}/test-apps/test.html" + "${PROJECT_SOURCE_DIR}/test-apps/test.css" + "${PROJECT_SOURCE_DIR}/test-apps/test.js") + + add_custom_command(TARGET test-server + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E make_directory "$/../share/libwebsockets-test-server") + + # Copy the file needed to run the server so that the test apps can + # reach them from their default output location + foreach (TEST_FILE ${TEST_SERVER_DATA}) + if (EXISTS ${TEST_FILE}) + add_custom_command(TARGET test-server + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${TEST_FILE}" "$/../share/libwebsockets-test-server" VERBATIM) + endif() + endforeach() + endif(NOT LWS_WITHOUT_SERVER) + + if (NOT LWS_WITHOUT_CLIENT) + # + # test-client + # + if (NOT LWS_WITHOUT_TEST_CLIENT) + create_test_app(test-client "test-client.c" "" "" "" "" "") + endif() + + endif(NOT LWS_WITHOUT_CLIENT) +endif((LWS_ROLE_H1 OR LWS_ROLE_H2)) + +# Install test apps. + +install(TARGETS ${TEST_APP_LIST} + RUNTIME DESTINATION ${LWS_INSTALL_EXAMPLES_DIR} + COMPONENT examples) +set(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Example files") + +# Programs shared files used by the test-server + +if (NOT LWS_WITHOUT_SERVER) + install(FILES ${TEST_SERVER_DATA} + DESTINATION share/libwebsockets-test-server + COMPONENT examples) + + install(FILES "${PROJECT_SOURCE_DIR}/test-apps/private/index.html" + DESTINATION share/libwebsockets-test-server/private + COMPONENT examples) +if (LWS_WITH_CGI) + set(CGI_TEST_SCRIPT "${PROJECT_SOURCE_DIR}/test-apps/lws-cgi-test.sh") + install(FILES ${CGI_TEST_SCRIPT} + PERMISSIONS OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ + DESTINATION share/libwebsockets-test-server + COMPONENT examples) + endif() +endif() + + +if (NOT LWS_WITHOUT_TEST_SERVER AND NOT LWS_WITHOUT_SERVER) + install(FILES lws-ssh-test-keys;lws-ssh-test-keys.pub + DESTINATION share/libwebsockets-test-server + COMPONENT examples) +endif() diff --git a/test-apps/test-sshd.c b/test-apps/test-sshd.c index 69d831e9..6d68b41e 100644 --- a/test-apps/test-sshd.c +++ b/test-apps/test-sshd.c @@ -33,7 +33,7 @@ #include #include #include - +#include /* import the whole of lws-plugin-sshd-base statically */ #include -- Gitee From 3d8b2f9d8886f592d6f1140792af0a4c067f2ddb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 24 May 2020 12:24:22 +0100 Subject: [PATCH 0128/1062] docs: add bug report template md The ease of dropping bug reports is making it a bit asymmetrical in terms of the complexity of even trying to figure out what is being told, let alone writing a reproducer and trying it. Ask for more effort from reporters and provide "first aid" suggestions and filtering in the template, so at least some of the support requests will get fixed by people doing that before I need to hear about it. --- bug_report.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 bug_report.md diff --git a/bug_report.md b/bug_report.md new file mode 100644 index 00000000..7958af07 --- /dev/null +++ b/bug_report.md @@ -0,0 +1,37 @@ +** What version of lws ** + +"vx.y.z" or "01234567 from master thismorning" etc + +If it's much older than last stable release, we will likely suggest you try that or master. + +** What platform and arch? ** + +"Fedora 32 x86_64" or "OSX Catalina" etc + +** What parts of lws does it involve? ** + +dunno / core / client / server +raw / http / ws / mqtt / other (give me a hint) + +** How can I reproduce the problem just using lws code? ** + +We can't guess your problem especially in your code. It's great if you can give us a way to +realize our own failure clearly with a reproducer that uses our own code. + +Try to remove your code from the equation by trying the same flow on an lws minimal example and provide a little diff against that. We can find out if it's only on your platform, or only on that version, or only in your code from that quickly, and if something to fix in lws, I can confirm it really is fixed using the same test. + +** Describe the bug ** + + "fails" --> this word is a red flag you didn't try to debug the issue much... exactly how does it "fail", what evidence is it leaving like logs or return codes or traces? + "hangs" --> this word is a red flag you didn't try to debug the issue much... exactly what does it mean, whole device frozen? Spinning 100% cpu? Just idle? Building on fire? Have you tried it via strace or similar if it seems frozen to see what it's doing? Attach a debugger like gdb -p pid and get a backtrace? perf top if Linux to see what it spends its time on. + "crashes" --> what happens if you run under valgrind? You know lws is not threadsafe except for lws_cancel_service(), right... + "sucks" --> let's discuss you writing a patch to improve whatever it is + +** Additional data ** + +Build problems? Describe the toolchain and paste the warnings / errors. + +Crash? Get a usable backtrace by building with `cmake .. -DCMAKE_BUILD_TYPE=DEBUG` and run under gdb, lldb, or valgrind. + +Mysterious happenings? Get verbose lws logs by building with `cmake .. -DCMAKE_BUILD_TYPE=DEBUG` and run with `lws_set_log_level(1151, NULL)`, on the example apps they all take a switch like -d1151. + -- Gitee From 0b0482c1273c822c1989f2c1b7250ac8ace181c4 Mon Sep 17 00:00:00 2001 From: dev31337 Date: Sun, 24 May 2020 14:06:54 +0100 Subject: [PATCH 0129/1062] listen: handle denied FILTER_NETWORK_CONNECTION correctly --- lib/roles/listen/ops-listen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/listen/ops-listen.c b/lib/roles/listen/ops-listen.c index c0ac6e5e..4d4fff18 100644 --- a/lib/roles/listen/ops-listen.c +++ b/lib/roles/listen/ops-listen.c @@ -130,7 +130,7 @@ rops_handle_POLLIN_listen(struct lws_context_per_thread *pt, struct lws *wsi, (void *)(lws_intptr_t)accept_fd, 0)) { lwsl_debug("Callback denied net connection\n"); compatible_close(accept_fd); - return LWS_HPI_RET_PLEASE_CLOSE_ME; + return LWS_HPI_RET_HANDLED; } if (!(wsi->vhost->options & -- Gitee From ef787e578c5d23a28736fa5faaedcf88f853ca89 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 24 May 2020 14:08:47 +0100 Subject: [PATCH 0130/1062] lws_struct: clean warning on windows --- lib/misc/lws-struct-lejp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/misc/lws-struct-lejp.c b/lib/misc/lws-struct-lejp.c index 7e7b53e3..c808adad 100644 --- a/lib/misc/lws-struct-lejp.c +++ b/lib/misc/lws-struct-lejp.c @@ -52,7 +52,7 @@ lws_struct_schema_only_lejp_cb(struct lejp_ctx *ctx, char reason) while (n--) { const lws_struct_map_t *child = map->child_map; - int m, child_members = map->child_map_size; + int m, child_members = (int)map->child_map_size; for (m = 0; m < child_members; m++) { if (!strcmp(ctx->path, child->colname)) { -- Gitee From 4f3e012cdd41e90aa1e41bfc0ce7da6579d4c3dd Mon Sep 17 00:00:00 2001 From: dev31337 Date: Sun, 24 May 2020 17:14:51 +0100 Subject: [PATCH 0131/1062] PEER_LIMITS: make sure to close socketfd on deny --- lib/core-net/adopt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index d9f87a7f..0c6a69df 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -343,6 +343,7 @@ lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info) lws_stats_bump(&info->vh->context->pt[0], LWSSTATS_C_PEER_LIMIT_WSI_DENIED, 1); + compatible_close(info->fd.sockfd); return NULL; } } -- Gitee From 90c7e789eb9a326cdedec54535c867a3fdd718ab Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 24 May 2020 19:44:46 +0100 Subject: [PATCH 0132/1062] PEER_LIMITS: modernize to sa46 and add notification cb There are a bunch of sa46-aware lws apis for formatting, etc sa46 in ./include/libwebsockets/lws-network-helper.h --- include/libwebsockets/lws-context-vhost.h | 13 +++++ lib/core-net/adopt.c | 7 ++- lib/core-net/private-lib-core-net.h | 5 +- lib/core/context.c | 1 + lib/core/private-lib-core.h | 7 +-- lib/misc/peer-limits.c | 59 ++++++++++++----------- 6 files changed, 56 insertions(+), 36 deletions(-) diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index e0b71bf4..09c2b126 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -237,6 +237,10 @@ struct lws_ss_plugin; typedef int (*lws_context_ready_cb_t)(struct lws_context *context); +typedef int (*lws_peer_limits_notify_t)(struct lws_context *ctx, + lws_sockfd_type sockfd, + lws_sockaddr46 *sa46); + /** struct lws_context_creation_info - parameters to create context and /or vhost with * * This is also used to create vhosts.... if LWS_SERVER_OPTION_EXPLICIT_VHOSTS @@ -738,6 +742,15 @@ struct lws_context_creation_info { /**< 0 = inherit the initial ulimit for files / sockets from the startup * environment. Nonzero = try to set the limit for this process. */ +#if defined(LWS_WITH_PEER_LIMITS) + lws_peer_limits_notify_t pl_notify_cb; + /**< CONTEXT: NULL, or a callback to receive notifications each time a + * connection is being dropped because of peer limits. + * + * The callback provides the context, and an lws_sockaddr46 with the + * peer address and port. + */ +#endif /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 0c6a69df..5d95f63c 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -338,11 +338,16 @@ lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info) if (peer && info->vh->context->ip_limit_wsi && peer->count_wsi >= info->vh->context->ip_limit_wsi) { - lwsl_notice("Peer reached wsi limit %d\n", + lwsl_info("Peer reached wsi limit %d\n", info->vh->context->ip_limit_wsi); lws_stats_bump(&info->vh->context->pt[0], LWSSTATS_C_PEER_LIMIT_WSI_DENIED, 1); + if (info->vh->context->pl_notify_cb) + info->vh->context->pl_notify_cb( + info->vh->context, + info->fd.sockfd, + &peer->sa46); compatible_close(info->fd.sockfd); return NULL; } diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 57c0c605..cb04c32a 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -187,10 +187,11 @@ struct lws_peer { struct lws_peer *next; struct lws_peer *peer_wait_list; + lws_sockaddr46 sa46; + time_t time_created; time_t time_closed_all; - uint8_t addr[32]; uint32_t hash; uint32_t count_wsi; uint32_t total_wsi; @@ -198,8 +199,6 @@ struct lws_peer { #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) struct lws_peer_role_http http; #endif - - uint8_t af; }; #endif diff --git a/lib/core/context.c b/lib/core/context.c index b3cc7f8e..6358f88f 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -661,6 +661,7 @@ lws_create_context(const struct lws_context_creation_info *info) context->ip_limit_ah = info->ip_limit_ah; context->ip_limit_wsi = info->ip_limit_wsi; + context->pl_notify_cb = info->pl_notify_cb; #endif lwsl_info(" mem: context: %5lu B (%ld ctx + (%ld thr x %d))\n", diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 9a11ecca..feb54351 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -432,9 +432,10 @@ struct lws_context { #endif #if defined(LWS_WITH_PEER_LIMITS) - struct lws_peer **pl_hash_table; - struct lws_peer *peer_wait_list; - time_t next_cull; + struct lws_peer **pl_hash_table; + struct lws_peer *peer_wait_list; + lws_peer_limits_notify_t pl_notify_cb; + time_t next_cull; #endif const lws_system_ops_t *system_ops; diff --git a/lib/misc/peer-limits.c b/lib/misc/peer-limits.c index 796e6c9e..d2e38176 100644 --- a/lib/misc/peer-limits.c +++ b/lib/misc/peer-limits.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -60,42 +60,32 @@ struct lws_peer * lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd) { struct lws_context *context = vhost->context; - socklen_t rlen = 0; - void *q; - uint8_t *q8; struct lws_peer *peer; + lws_sockaddr46 sa46; + socklen_t rlen = 0; uint32_t hash = 0; - int n, af = AF_INET; - struct sockaddr_storage addr; + uint8_t *q8; + void *q; + int n; if (vhost->options & LWS_SERVER_OPTION_UNIX_SOCK) return NULL; -#ifdef LWS_WITH_IPV6 - if (LWS_IPV6_ENABLED(vhost)) { - af = AF_INET6; - } -#endif - rlen = sizeof(addr); - if (getpeername(sockfd, (struct sockaddr*)&addr, &rlen)) + rlen = sizeof(sa46); + if (getpeername(sockfd, (struct sockaddr*)&sa46, &rlen)) /* eg, udp doesn't have to have a peer */ return NULL; #ifdef LWS_WITH_IPV6 - if (af == AF_INET) + if (sa46.sa4.sin_family == AF_INET6) { + q = &sa46.sa6.sin6_addr; + rlen = sizeof(sa46.sa6.sin6_addr); + } else #endif { - struct sockaddr_in *s = (struct sockaddr_in *)&addr; - q = &s->sin_addr; - rlen = sizeof(s->sin_addr); - } -#ifdef LWS_WITH_IPV6 - else { - struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; - q = &s->sin6_addr; - rlen = sizeof(s->sin6_addr); + q = &sa46.sa4.sin_addr; + rlen = sizeof(sa46.sa4.sin_addr); } -#endif q8 = q; for (n = 0; n < (int)rlen; n++) @@ -107,9 +97,21 @@ lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd) lws_start_foreach_ll(struct lws_peer *, peerx, context->pl_hash_table[hash]) { - if (peerx->af == af && !memcmp(q, peerx->addr, rlen)) { - lws_context_unlock(context); /* === */ - return peerx; + if (peerx->sa46.sa4.sin_family == sa46.sa4.sin_family) { +#if defined(LWS_WITH_IPV6) + if (sa46.sa4.sin_family == AF_INET6 && + !memcmp(q, &peerx->sa46.sa6.sin6_addr, rlen)) + goto hit; +#endif + if (sa46.sa4.sin_family == AF_INET && + !memcmp(q, &peerx->sa46.sa4.sin_addr, rlen)) { +#if defined(LWS_WITH_IPV6) +hit: +#endif + lws_context_unlock(context); /* === */ + + return peerx; + } } } lws_end_foreach_ll(peerx, next); @@ -125,9 +127,8 @@ lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd) context->count_peers++; peer->next = context->pl_hash_table[hash]; peer->hash = hash; - peer->af = af; + peer->sa46 = sa46; context->pl_hash_table[hash] = peer; - memcpy(peer->addr, q, rlen); time(&peer->time_created); /* * On creation, the peer has no wsi attached, so is created on the -- Gitee From 10146575a24813103cfcc75265ba0e530dba1cbe Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 25 May 2020 05:40:13 +0100 Subject: [PATCH 0133/1062] clean: turn down verbosity on some debugging printfs --- lib/core/context.c | 2 -- lib/tls/tls-server.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index 6358f88f..489da5d4 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -1049,8 +1049,6 @@ lws_context_destroy3(struct lws_context *context) #if defined(LWS_WITH_NETWORK) - lwsl_err("%s\n", __func__); - context->finalize_destroy_after_internal_loops_stopped = 1; if (context->event_loop_ops->destroy_context2) context->event_loop_ops->destroy_context2(context); diff --git a/lib/tls/tls-server.c b/lib/tls/tls-server.c index 8b1ae6f1..9d4ecc99 100644 --- a/lib/tls/tls-server.c +++ b/lib/tls/tls-server.c @@ -275,7 +275,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd, char f * fail out... * */ - lwsl_warn("%s: PEEKed 0 (from_pollin %d)\n", + lwsl_debug("%s: PEEKed 0 (from_pollin %d)\n", __func__, from_pollin); if (!from_pollin) /* -- Gitee From 4ff9b4f96eb7ab953a0753cf86386620c8d10458 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 25 May 2020 12:36:30 +0100 Subject: [PATCH 0134/1062] ss: add api test with ctest integration Tests via httpbin.org --- lib/roles/http/client/client-handshake.c | 4 - .../api-test-secure-streams/CMakeLists.txt | 28 ++ .../api-test-secure-streams/README.md | 21 + .../api-tests/api-test-secure-streams/main.c | 384 ++++++++++++++++++ 4 files changed, 433 insertions(+), 4 deletions(-) create mode 100644 minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt create mode 100644 minimal-examples/api-tests/api-test-secure-streams/README.md create mode 100644 minimal-examples/api-tests/api-test-secure-streams/main.c diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index f1f525cd..27408c34 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -355,10 +355,6 @@ lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul) * connection before giving up on it and retrying. */ -#if defined(WIN32) - wsi->dns_results_next = wsi->dns_results_next->ai_next; -#endif - lwsl_info("%s: connect wait timeout has fired\n", __func__); lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL); } diff --git a/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt b/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt new file mode 100644 index 00000000..998c2c49 --- /dev/null +++ b/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt @@ -0,0 +1,28 @@ +project(lws-api-test-secure-streams) +cmake_minimum_required(VERSION 2.8) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(requirements 1) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) + +if (requirements) + + add_executable(${PROJECT_NAME} main.c) + + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME api-test-secure-streams COMMAND ${PROJECT_NAME}) + set_tests_properties(api-test-secure-streams + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/api-tests/api-test-secure-streams + TIMEOUT 20) + endif() + + if (websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared) + add_dependencies(${PROJECT_NAME} websockets_shared) + else() + target_link_libraries(${PROJECT_NAME} websockets) + endif() + +endif() diff --git a/minimal-examples/api-tests/api-test-secure-streams/README.md b/minimal-examples/api-tests/api-test-secure-streams/README.md new file mode 100644 index 00000000..a5a220a5 --- /dev/null +++ b/minimal-examples/api-tests/api-test-secure-streams/README.md @@ -0,0 +1,21 @@ +# lws api test Secure Streams + +Performs some tests against httpbin.org server +to check Secure Streams client performance + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` + $ ./lws-api-test-secure-streams +``` + diff --git a/minimal-examples/api-tests/api-test-secure-streams/main.c b/minimal-examples/api-tests/api-test-secure-streams/main.c new file mode 100644 index 00000000..7ba0ae1a --- /dev/null +++ b/minimal-examples/api-tests/api-test-secure-streams/main.c @@ -0,0 +1,384 @@ +/* + * lws-api-test-secure-streams + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * Let's exercise some basic SS / h1 functionality against httpbin.org + */ + +#include +#include +#include + +static int interrupted, bad = 1; +static lws_state_notify_link_t nl; +static struct lws_context *context; + +static const char * const default_ss_policy = + "{" + "\"release\":" "\"01234567\"," + "\"product\":" "\"myproduct\"," + "\"schema-version\":" "1," +#if defined(VIA_LOCALHOST_SOCKS) + "\"via-socks5\":" "\"127.0.0.1:1080\"," +#endif + + "\"retry\": [" /* named backoff / retry strategies */ + "{\"default\": {" + "\"backoff\": [" "1000," + "2000," + "3000," + "5000," + "10000" + "]," + "\"conceal\":" "5," + "\"jitterpc\":" "20," + "\"svalidping\":" "30," + "\"svalidhup\":" "35" + "}}" + "]," + "\"certs\": [" /* named individual certificates in BASE64 DER */ + /* + * Let's Encrypt certs for warmcat.com / libwebsockets.org + * + * We fetch the real policy from there using SS and switch to + * using that. + */ + + "{\"amz_root_ca1\": \"" + "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF" + "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6" + "b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL" + "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv" + "b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj" + "ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM" + "9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw" + "IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6" + "VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L" + "93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm" + "jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC" + "AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA" + "A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI" + "U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs" + "N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv" + "o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU" + "5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy" + "rqXRfboQnoZsG4q5WTP468SQvvG5" + "\"}" + "]," + "\"trust_stores\": [" /* named cert chains */ + "{" + "\"name\": \"amz\"," + "\"stack\": [" + "\"amz_root_ca1\"" + "]" + "}" + "]," + "\"s\": [" + /* + * "fetch_policy" decides from where the real policy + * will be fetched, if present. Otherwise the initial + * policy is treated as the whole, hardcoded, policy. + */ + "{\"httpbin_get\": {" + "\"endpoint\":" "\"httpbin.org\"," + "\"port\":" "443," + "\"protocol\":" "\"h1\"," + "\"http_method\":" "\"GET\"," + "\"http_url\":" "\"/get\"," + "\"tls\":" "true," + "\"opportunistic\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"amz\"" + "}}," + "{\"httpbin_get404\": {" + "\"endpoint\":" "\"httpbin.org\"," + "\"port\":" "443," + "\"protocol\":" "\"h1\"," + "\"http_method\":" "\"GET\"," + "\"http_url\":" "\"/status/404\"," + "\"tls\":" "true," + "\"opportunistic\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"amz\"" + "}}," + "{\"httpbin_post\": {" + "\"endpoint\":" "\"httpbin.org\"," + "\"port\":" "443," + "\"protocol\":" "\"h1\"," + "\"http_method\":" "\"POST\"," + "\"http_url\":" "\"/post\"," + "\"tls\":" "true," + "\"opportunistic\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"amz\"" + "}}" + "}" + "]}" +; + +typedef struct atss { + const lws_ss_info_t *ssi; + size_t send; + char expect_nack; +} atss_t; + +static const atss_t *next_test; + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + lws_sorted_usec_list_t sul; + size_t payload; + size_t sent; + char seen_eom; + char ended_well; +} myss_t; + +/* secure streams payload interface */ + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_hexdump_info(buf, len); + + m->payload += len; + + if (!(flags & LWSSS_FLAG_EOM)) + m->seen_eom = 1; + + return 0; +} + +static int +myss_tx_get(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + return 1; /* nothing to send */ +} + +static int +myss_tx_post(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + myss_t *m = (myss_t *)userobj; + size_t budget = (next_test->send - m->sent); + + if (!budget) + return 1; + + if (*len < budget) + budget = *len; + + if (!m->sent) + *flags |= LWSSS_FLAG_SOM; + + memset(buf, 0x55, budget); + *len = budget; + m->sent += budget; + if (m->sent != next_test->send) + lws_ss_request_tx(m->ss); + else + *flags |= LWSSS_FLAG_EOM; + + return 0; +} + +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_notice("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_client_connect(m->ss); + if (next_test->send) + lws_ss_request_tx_len(m->ss, (unsigned long)next_test->send); + break; + case LWSSSCS_ALL_RETRIES_FAILED: + lwsl_notice("%s: Connection failed\n", __func__); + interrupted = 1; + break; + case LWSSSCS_QOS_NACK_REMOTE: + if (next_test->expect_nack) + goto happy; + lwsl_notice("%s: remote NACK\n", __func__); + interrupted = 1; + break; + case LWSSSCS_QOS_ACK_REMOTE: + /* + * To be satisfied, we want to see the ACK_REMOTE indicating + * that the transaction went through; that we had the payload + * EOM; and that we saw at least 200 + posted bytes response + */ + + if (!m->seen_eom || m->payload < 200 + next_test->send) { + lwsl_warn("%s: ACK_REMOTE but eom %d, payload %d\n", + __func__, m->seen_eom, (int)m->payload); + interrupted = 1; + return -1; + } + +happy: + /* when we disconnect, we can go happily */ + m->ended_well = 1; + + if (!(++next_test)->ssi) { + lwsl_notice("%s: completed all tests\n", __func__); + bad = 0; + interrupted = 1; + break; + } + if (lws_ss_create(context, 0, next_test->ssi, + NULL, NULL, NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + break; + + case LWSSSCS_DISCONNECTED: + if (!m->ended_well) { + lwsl_warn("%s: DISCONNECTED without good end\n", + __func__); + interrupted = 1; + } + break; + default: + break; + } + + return 0; +} + +static const lws_ss_info_t ssi_get = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .rx = myss_rx, + .tx = myss_tx_get, + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = "httpbin_get" +}, ssi_get404 = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .rx = myss_rx, + .tx = myss_tx_get, + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = "httpbin_get404" +}, ssi_post = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .rx = myss_rx, + .tx = myss_tx_post, + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = "httpbin_post" +}; + +static const atss_t test_list[] = { + { .ssi = &ssi_get }, + { .ssi = &ssi_get404, .expect_nack = 1 }, + { .ssi = &ssi_post, .send = 4096 }, + { .ssi = NULL } +}; + + +static int +app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + struct lws_context *context = lws_system_context_from_system_mgr(mgr); + + /* + * For the things we care about, let's notice if we are trying to get + * past them when we haven't solved them yet, and make the system + * state wait while we trigger the dependent action. + */ + switch (target) { + + case LWS_SYSTATE_OPERATIONAL: + if (current == LWS_SYSTATE_OPERATIONAL) { + + next_test = &test_list[0]; + + if (lws_ss_create(context, 0, next_test->ssi, + NULL, NULL, NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + break; + } + + return 0; +} + +static lws_state_notify_link_t * const app_notifier_list[] = { + &nl, NULL +}; + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + int n = 0; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS secure streams test client [-d]\n"); + + /* these options are mutually exclusive if given */ + + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; + info.pss_policies_json = default_ss_policy; + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | + LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW; + + /* integrate us with lws system state management when context created */ + + nl.name = "app"; + nl.notify_cb = app_system_state_nf; + info.register_notifier_list = app_notifier_list; + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + /* the event loop */ + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} -- Gitee From b6e215ee7f7cb187abba835d662b4eaa70edabd8 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Wed, 27 May 2020 15:06:33 +0900 Subject: [PATCH 0135/1062] openssl: fix improper use of negative value --- lib/tls/openssl/openssl-ssl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/tls/openssl/openssl-ssl.c b/lib/tls/openssl/openssl-ssl.c index 6c8f5bcd..57e298f9 100644 --- a/lib/tls/openssl/openssl-ssl.c +++ b/lib/tls/openssl/openssl-ssl.c @@ -368,6 +368,7 @@ lws_ssl_info_callback(const SSL *ssl, int where, int ret) struct lws *wsi; struct lws_context *context; struct lws_ssl_info si; + int fd; #ifndef USE_WOLFSSL context = (struct lws_context *)SSL_CTX_get_ex_data( @@ -380,7 +381,12 @@ lws_ssl_info_callback(const SSL *ssl, int where, int ret) #endif if (!context) return; - wsi = wsi_from_fd(context, SSL_get_fd(ssl)); + + fd = SSL_get_fd(ssl); + if (fd < 0 || (fd - lws_plat_socket_offset()) < 0) + return; + + wsi = wsi_from_fd(context, fd); if (!wsi) return; -- Gitee From c9c152baba1fbd6e2b061b16a5c987a80309caee Mon Sep 17 00:00:00 2001 From: Jakov Smolic Date: Tue, 26 May 2020 16:35:16 +0200 Subject: [PATCH 0136/1062] CMakeLists: add the option to disable Werror https://github.com/warmcat/libwebsockets/pull/1926 Signed-off-by: Jakov Smolic --- CMakeLists.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e817c378..f9524318 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,11 @@ include(CTest) option(LWS_WITH_DISTRO_RECOMMENDED "Enable features recommended for distro packaging" OFF) option(LWS_FOR_GITOHASHI "Enable features recommended for use with gitohashi" OFF) +# +# Compiler features +# +option(DISABLE_WERROR "Avoid treating compiler warnings as fatal errors" OFF) + # # Major individual features # @@ -637,12 +642,15 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) set(CMAKE_C_FLAGS "-fanalyzer ${CMAKE_C_FLAGS}" ) endif() - # always warn all and Werror, and generate debug info + # always warn all and generate debug info if (UNIX AND NOT LWS_PLAT_FREERTOS) - set(CMAKE_C_FLAGS "-g -Wall -Wsign-compare -Wstrict-aliasing -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" ) + set(CMAKE_C_FLAGS "-g -Wall -Wsign-compare -Wstrict-aliasing -Wuninitialized ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS} ${ASAN_FLAGS}" ) else() - set(CMAKE_C_FLAGS "-g -Wall -Wsign-compare -Wuninitialized -Werror ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) + set(CMAKE_C_FLAGS "-g -Wall -Wsign-compare -Wuninitialized ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) endif() + if ("${DISABLE_WERROR}" STREQUAL "OFF") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + endif() endif () -- Gitee From 911898ad7067f9c7796aa4508d494993de8d97a9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 24 May 2020 13:57:21 +0100 Subject: [PATCH 0137/1062] windows: recent win10 support Unix Domain Allow selection of Unix Domain Sockets on windows since it is supported for the last couple of years on windows 10 https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ ... if only they could add a full set of posix pieces to go with it (and abstract namespace UDS which doesn't work apparently) so that the parts dealing with uid / gid don't have to be disabled. --- CMakeLists-implied-options.txt | 4 +--- CMakeLists.txt | 2 +- lib/core-net/network.c | 4 ++-- lib/core/private-lib-core.h | 2 +- lib/plat/windows/private-lib-plat-windows.h | 4 ++++ lib/roles/http/client/client-handshake.c | 4 ++-- lib/tls/CMakeLists.txt | 5 ----- 7 files changed, 11 insertions(+), 14 deletions(-) diff --git a/CMakeLists-implied-options.txt b/CMakeLists-implied-options.txt index 258073e8..94fe5991 100644 --- a/CMakeLists-implied-options.txt +++ b/CMakeLists-implied-options.txt @@ -164,9 +164,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type") endif() -# microsoft... that's why you can't have nice things - -if (WIN32 OR LWS_PLAT_FREERTOS) +if (LWS_PLAT_FREERTOS) set(LWS_UNIX_SOCK 0) endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index f9524318..81476079 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ option(LWS_WITH_HTTP2 "Compile with server support for HTTP/2" ON) option(LWS_WITH_LWSWS "Libwebsockets Webserver" OFF) option(LWS_WITH_CGI "Include CGI (spawn process with network-connected stdin/out/err) APIs" OFF) option(LWS_IPV6 "Compile with support for ipv6" OFF) -option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket" OFF) +option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket if OS supports it" ON) option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF) option(LWS_WITH_HTTP_PROXY "Support for active HTTP proxying" OFF) option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" OFF) diff --git a/lib/core-net/network.c b/lib/core-net/network.c index 40c5fff2..61518acb 100644 --- a/lib/core-net/network.c +++ b/lib/core-net/network.c @@ -225,7 +225,7 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port, iface); return LWS_ITOSA_NOT_EXIST; } - n = sizeof(uint16_t) + strlen(iface); + n = (int)(sizeof(uint16_t) + strlen(iface)); strcpy(serv_unix.sun_path, iface); if (serv_unix.sun_path[0] == '@') serv_unix.sun_path[0] = '\0'; @@ -315,7 +315,7 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port, return LWS_ITOSA_NOT_EXIST; } -#if defined(LWS_WITH_UNIX_SOCK) +#if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32) if (!port && LWS_UNIX_SOCK_ENABLED(vhost)) { uid_t uid = vhost->context->uid; gid_t gid = vhost->context->gid; diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index feb54351..85e4ac39 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -706,7 +706,7 @@ lws_plat_init(struct lws_context *context, LWS_EXTERN int lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop); -#if defined(LWS_WITH_UNIX_SOCK) +#if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32) int lws_plat_user_colon_group_to_ids(const char *u_colon_g, uid_t *puid, gid_t *pgid); #endif diff --git a/lib/plat/windows/private-lib-plat-windows.h b/lib/plat/windows/private-lib-plat-windows.h index 558aedf5..03cffd17 100644 --- a/lib/plat/windows/private-lib-plat-windows.h +++ b/lib/plat/windows/private-lib-plat-windows.h @@ -64,6 +64,10 @@ #include #include +#if defined(LWS_WITH_UNIX_SOCK) +#include +#endif + #if !defined(LWS_HAVE_ATOLL) #if defined(LWS_HAVE__ATOI64) #define atoll _atoi64 diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 27408c34..be5a761c 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -681,9 +681,9 @@ ads_known: if (wsi->unix_skt) { psa = (const struct sockaddr *)&sau; if (sau.sun_path[0]) - n = sizeof(uint16_t) + strlen(sau.sun_path); + n = (int)(sizeof(uint16_t) + strlen(sau.sun_path)); else - n = sizeof(uint16_t) + strlen(&sau.sun_path[1]) + 1; + n = (int)(sizeof(uint16_t) + strlen(&sau.sun_path[1]) + 1); } else #endif diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index a1a534c2..310389e8 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -101,11 +101,6 @@ endif() set(LWS_OPENSSL_CLIENT_CERTS ../share CACHE PATH "Server SSL certificate directory") if (WIN32) set(LWS_OPENSSL_CLIENT_CERTS . CACHE PATH "Client SSL certificate directory" PARENT_SCOPE) - - if (LWS_UNIX_SOCK) - set(LWS_UNIX_SOCK OFF PARENT_SCOPE) - message(WARNING "Windows does not support UNIX domain sockets") - endif() else() set(LWS_OPENSSL_CLIENT_CERTS /etc/pki/tls/certs/ CACHE PATH "Client SSL certificate directory") endif() -- Gitee From 6d52147476647b66b01d40008246cf7e562ed8a5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 27 May 2020 09:53:34 +0100 Subject: [PATCH 0138/1062] sai.json: gentoo --- .sai.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.sai.json b/.sai.json index 8b58f048..f112850e 100644 --- a/.sai.json +++ b/.sai.json @@ -14,6 +14,9 @@ "linux-fedora-32-x86_64": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, + "gentoo-amd64": { + "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G ZIP\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" + }, "linux-centos-8-x8664": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, @@ -58,6 +61,10 @@ "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", "platforms": "windows-10, linux-debian-buster-arm32" }, + "unix-domain": { + "cmake": "-DUNIX_SOCK=1", + "platforms": "windows-10" + }, "lws_system": { "cmake": "-DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=RELEASE -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", "platforms": "windows-10" -- Gitee From 9290053f5b6acf3eaca02de44fea52f24eba8910 Mon Sep 17 00:00:00 2001 From: Jed Lu Date: Wed, 27 May 2020 13:38:44 +0100 Subject: [PATCH 0139/1062] ss: Support content-length on PUT as well as PUSH --- lib/secure-streams/protocols/ss-h1.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index ad06088f..4d1568b5 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -364,10 +364,11 @@ malformed: } /* - * Content-length on POST if we have the length information + * Content-length on POST / PUT if we have the length information */ - if (!strcmp(h->policy->u.http.method, "POST") && + if ((!strcmp(h->policy->u.http.method, "POST") || + !strcmp(h->policy->u.http.method, "PUT")) && wsi->http.writeable_len) { if (!(h->policy->flags & LWSSSPOLF_HTTP_NO_CONTENT_LENGTH)) { -- Gitee From f71b6035c8aea4e2ad57782b70fc9d2cc9e2e3f4 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 27 May 2020 15:55:58 +0100 Subject: [PATCH 0140/1062] sai: switch to 64bit rpi4 --- .sai.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.sai.json b/.sai.json index f112850e..3fe06599 100644 --- a/.sai.json +++ b/.sai.json @@ -20,7 +20,7 @@ "linux-centos-8-x8664": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, - "linux-debian-buster-arm32": { + "ubuntu-focal-aarch64": { "build": "mkdir build;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j3 && make -j DESTDIR=../destdir install && ctest -j3 --output-on-failure ${cpack}", "default": false }, @@ -55,11 +55,11 @@ "configurations": { "default": { "cmake": "", - "platforms": "windows-10, linkit-cross, linux-debian-buster-arm32, freertos-esp32" + "platforms": "windows-10, linkit-cross, ubuntu-focal-aarch64, freertos-esp32" }, "default-examples": { "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", - "platforms": "windows-10, linux-debian-buster-arm32" + "platforms": "windows-10, ubuntu-focal-aarch64" }, "unix-domain": { "cmake": "-DUNIX_SOCK=1", @@ -79,7 +79,7 @@ }, "distro_recommended": { "cmake": "-DLWS_WITH_DISTRO_RECOMMENDED=1", - "platforms": "not linkit-cross, not windows-10, linux-debian-buster-arm32", + "platforms": "not linkit-cross, not windows-10, ubuntu-focal-aarch64", "cpack": "&& cpack $SAI_CPACK", "artifacts": "build/*.rpm, build/*.deb, build/*.zip" }, -- Gitee From 2b21c2d608da80d93e1e2df8090ba95f25f87f68 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 28 May 2020 06:17:19 +0100 Subject: [PATCH 0141/1062] async-dns: callback should leave caller deletion to caller The guy calling the callback with LADNS_RET_FAILED is going to inform his caller that it failed... let him decide to close and fail the connection attempt. --- lib/roles/http/client/client-handshake.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index be5a761c..9983bb12 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -467,7 +467,11 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, #if defined(LWS_WITH_SYS_ASYNC_DNS) if (n == LADNS_RET_FAILED) { lwsl_notice("%s: adns failed %s\n", __func__, ads); - goto oom4; + /* + * Caller that is giving us LADNS_RET_FAILED will deal + * with cleanup + */ + return NULL; } #endif -- Gitee From 9bf1392b1340ebc11b756b33b52d284347373d3c Mon Sep 17 00:00:00 2001 From: Jed Lu Date: Thu, 28 May 2020 13:09:56 +0100 Subject: [PATCH 0142/1062] ss: http: allow rideshare to gate EOM When rideshare is in use, the scope of the EOM is the rideshare section. --- lib/secure-streams/protocols/ss-h1.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 4d1568b5..b75c5b87 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -27,6 +27,10 @@ #include #if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) +#define LWS_WITH_SS_RIDESHARE +#endif + +#if defined(LWS_WITH_SS_RIDESHARE) static int ss_http_multipart_parser(lws_ss_handle_t *h, void *in, size_t len) { @@ -163,6 +167,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], *end = &buf[sizeof(buf) - 1]; int f = 0, m, status, txr; + char conceal_eom = 0; size_t buflen; switch (reason) { @@ -235,7 +240,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, */ lws_validity_confirmed(wsi); -#if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_SS_RIDESHARE) if (lws_hdr_copy(wsi, (char *)buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_TYPE) > 0 && @@ -397,7 +402,7 @@ malformed: if (!h) return 0; -#if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_SS_RIDESHARE) if (h->u.http.boundary[0]) return ss_http_multipart_parser(h, in, len); #endif @@ -455,7 +460,7 @@ malformed: if (!h->rideshare) h->rideshare = h->policy; -#if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_SS_RIDESHARE) if (!h->inside_msg && h->rideshare->u.http.multipart_name) lws_client_http_multipart(wsi, h->rideshare->u.http.multipart_name, @@ -486,19 +491,21 @@ malformed: p += buflen; if (f & LWSSS_FLAG_EOM) { -#if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_SS_RIDESHARE) + conceal_eom = 1; /* end of rideshares */ if (!h->rideshare->rideshare_streamtype) { lws_client_http_body_pending(wsi, 0); if (h->rideshare->u.http.multipart_name) lws_client_http_multipart(wsi, NULL, NULL, NULL, (char **)&p, (char *)end); + conceal_eom = 0; } else { #endif h->rideshare = lws_ss_policy_lookup(wsi->context, h->rideshare->rideshare_streamtype); lws_callback_on_writable(wsi); -#if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_SS_RIDESHARE) } #endif @@ -515,7 +522,8 @@ malformed: lws_ptr_diff(p, buf + LWS_PRE), f); if (lws_write(wsi, buf + LWS_PRE, lws_ptr_diff(p, buf + LWS_PRE), - (f & LWSSS_FLAG_EOM) ? LWS_WRITE_HTTP_FINAL : LWS_WRITE_HTTP) != + (!conceal_eom && (f & LWSSS_FLAG_EOM)) ? + LWS_WRITE_HTTP_FINAL : LWS_WRITE_HTTP) != (int)lws_ptr_diff(p, buf + LWS_PRE)) { lwsl_err("%s: write failed\n", __func__); return -1; @@ -564,7 +572,7 @@ secstream_connect_munge_h1(lws_ss_handle_t *h, char *buf, size_t len, if (!pbasis) return 0; -#if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) +#if defined(LWS_WITH_SS_RIDESHARE) if (h->policy->flags & LWSSSPOLF_HTTP_MULTIPART) i->ssl_connection |= LCCSCF_HTTP_MULTIPART_MIME; -- Gitee From 8a765d78ffbd825f95acf0b745dade6c08c75084 Mon Sep 17 00:00:00 2001 From: Arenoros Date: Thu, 28 May 2020 21:55:08 +0300 Subject: [PATCH 0143/1062] windows: fix VS cmake build error #1929 --- CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 81476079..ec80b206 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -563,8 +563,10 @@ if (LWS_HAVE_PTHREAD_H AND NOT LWS_PLAT_FREERTOS) set(LWS_PTHR_FLAGS "-pthread") endif() - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${LWS_PTHR_FLAGS}) - list(APPEND LIB_LIST_AT_END ${LWS_PTHR_FLAGS}) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LWS_PTHR_FLAGS}) + if (NOT WIN32 AND NOT MSVC) + list(APPEND LIB_LIST_AT_END ${LWS_PTHR_FLAGS}) + endif() CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE #include @@ -716,7 +718,7 @@ if (LWS_WITH_ZLIB) include_directories(${ZLIB_INCLUDE_DIRS}) # done later at end of link list # list(APPEND LIB_LIST ${ZLIB_LIBRARIES}) - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${ZLIB_LIBRARIES}) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${ZLIB_LIBRARIES}) list(APPEND LIB_LIST_AT_END ${ZLIB_LIBRARIES}) endif() -- Gitee From 9f5bc01c949f7a39349b321b12e342d4f5e1f285 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 29 May 2020 08:24:07 +0100 Subject: [PATCH 0144/1062] cpack: keep elaborated patch string but use just number in lws --- CMakeLists.txt | 7 +++++-- cmake/lws_config.h.in | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec80b206..f0a92a79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -309,7 +309,9 @@ set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_PACKAGE_NAME "${PACKAGE}") set(CPACK_PACKAGE_VERSION_MAJOR "4") set(CPACK_PACKAGE_VERSION_MINOR "0") -set(CPACK_PACKAGE_VERSION_PATCH "99-${LWS_BUILD_HASH}") +set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "99") + +set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH_NUMBER}-${LWS_BUILD_HASH}") set(CPACK_PACKAGE_RELEASE 1) set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") @@ -343,7 +345,8 @@ set(CPACK_DEBIAN_PACKAGE_SOURCE ON) set(LWS_LIBRARY_VERSION ${CPACK_PACKAGE_VERSION}) set(LWS_LIBRARY_VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) set(LWS_LIBRARY_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR}) -set(LWS_LIBRARY_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH}) +set(LWS_LIBRARY_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH_NUMBER}) +set(LWS_LIBRARY_VERSION_PATCH_ELABORATED ${CPACK_PACKAGE_VERSION_PATCH}) if (NOT CMAKE_MODULE_PATH) set(CMAKE_MODULE_PATH "") diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 7610f600..6a461bbd 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -9,7 +9,9 @@ #define LWS_INSTALL_DATADIR "${CMAKE_INSTALL_PREFIX}/share" #define LWS_LIBRARY_VERSION_MAJOR ${LWS_LIBRARY_VERSION_MAJOR} #define LWS_LIBRARY_VERSION_MINOR ${LWS_LIBRARY_VERSION_MINOR} +#define LWS_LIBRARY_VERSION_PATCH_ELABORATED ${LWS_LIBRARY_VERSION_PATCH_ELABORATED} #define LWS_LIBRARY_VERSION_PATCH ${LWS_LIBRARY_VERSION_PATCH} + /* LWS_LIBRARY_VERSION_NUMBER looks like 1005001 for e.g. version 1.5.1 */ #define LWS_LIBRARY_VERSION_NUMBER (LWS_LIBRARY_VERSION_MAJOR * 1000000) + \ (LWS_LIBRARY_VERSION_MINOR * 1000) + \ -- Gitee From f98e4a845c1b627ab15b8e9f77e5621c00257a0d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 29 May 2020 09:51:40 +0100 Subject: [PATCH 0145/1062] sai: add f32 plus openssl-v3 combination --- .sai.json | 4 ++++ lib/tls/CMakeLists.txt | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.sai.json b/.sai.json index 3fe06599..bc7469bd 100644 --- a/.sai.json +++ b/.sai.json @@ -57,6 +57,10 @@ "cmake": "", "platforms": "windows-10, linkit-cross, ubuntu-focal-aarch64, freertos-esp32" }, + "openssl-v3": { + "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\"", + "platforms": "none,linux-fedora-32-x86_64" + }, "default-examples": { "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", "platforms": "windows-10, ubuntu-focal-aarch64" diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index 310389e8..9fcc7829 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -264,6 +264,9 @@ endif(LWS_WITH_SSL) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) + if (UNIX) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) + endif() if (NOT VARIA) set(VARIA "") @@ -288,10 +291,8 @@ CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_xts LWS_HAVE_EVP_aes_128_xts PARENT_SC CHECK_FUNCTION_EXISTS(${VARIA}RSA_verify_pss_mgf1 LWS_HAVE_RSA_verify_pss_mgf1 PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}HMAC_CTX_new LWS_HAVE_HMAC_CTX_new PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set_ciphersuites LWS_HAVE_SSL_CTX_set_ciphersuites PARENT_SCOPE) + if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) - if (UNIX) - set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl PARENT_SCOPE) - endif() CHECK_C_SOURCE_COMPILES("#include \nint main(void) { STACK_OF(X509) *c = NULL; SSL_CTX *ctx = NULL; return (int)SSL_CTX_get_extra_chain_certs_only(ctx, &c); }\n" LWS_HAVE_SSL_EXTRA_CHAIN_CERTS) CHECK_C_SOURCE_COMPILES("#include \nint main(void) { EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX_free(md_ctx); return 0; }\n" LWS_HAVE_EVP_MD_CTX_free) set(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS ${LWS_HAVE_SSL_EXTRA_CHAIN_CERTS} PARENT_SCOPE) @@ -301,6 +302,7 @@ CHECK_FUNCTION_EXISTS(${VARIA}BN_bn2binpad LWS_HAVE_BN_bn2binpad PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_wrap LWS_HAVE_EVP_aes_128_wrap PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}EC_POINT_get_affine_coordinates LWS_HAVE_EC_POINT_get_affine_coordinates PARENT_SCOPE) endif() + if (LWS_WITH_MBEDTLS) set(LWS_HAVE_TLS_CLIENT_METHOD 1 PARENT_SCOPE) if (NOT LWS_PLAT_FREERTOS) @@ -455,4 +457,4 @@ set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) - \ No newline at end of file + -- Gitee From d5773c01be3d0bdb2e1c764b03c9f95fdbf75181 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 29 May 2020 11:07:22 +0100 Subject: [PATCH 0146/1062] openssl-v3: deal with deprecated SSL_CTX_load_verify_locations Add Sai for openssl-v3 and for boringssl --- .sai.json | 10 +++++++--- CMakeLists.txt | 18 ++++++++++-------- READMEs/README.ctest.md | 15 ++++++++------- cmake/lws_config.h.in | 2 ++ lib/roles/cgi/ops-cgi.c | 4 ++-- lib/tls/CMakeLists.txt | 4 ++++ lib/tls/openssl/openssl-client.c | 10 ++++++++++ lib/tls/openssl/openssl-server.c | 5 +++++ 8 files changed, 48 insertions(+), 20 deletions(-) diff --git a/.sai.json b/.sai.json index bc7469bd..b3c4e2ba 100644 --- a/.sai.json +++ b/.sai.json @@ -41,7 +41,7 @@ "default": false }, "windows-10": { - "build": "mkdir build && cd build && set SAI_CPACK=\"-G ZIP\" && cmake .. -DLWS_EXT_PTHREAD_INCLUDE_DIR=\"C:\\Program Files (x86)\\pthreads\\include\" -DLWS_EXT_PTHREAD_LIBRARIES=\"C:\\Program Files (x86)\\pthreads\\lib\\x64\\libpthreadGC2.a\" ${cmake} && cmake --build . --config DEBUG && set CTEST_OUTPUT_ON_FAILURE=1 && ctest . -C DEBUG -j4 --output-on-failure", + "build": "mkdir build && cd build && set SAI_CPACK=\"-G ZIP\" && cmake .. -DLWS_OPENSSL_LIBRARIES=\"C:\\Program Files\\OpenSSL\\lib\\libssl.lib;C:\\Program Files\\OpenSSL\\lib\\libcrypto.lib\" -DLWS_OPENSSL_INCLUDE_DIRS=\"C:\\Program Files\\OpenSSL\\include\" -DLWS_EXT_PTHREAD_INCLUDE_DIR=\"C:\\Program Files (x86)\\pthreads\\include\" -DLWS_EXT_PTHREAD_LIBRARIES=\"C:\\Program Files (x86)\\pthreads\\lib\\x64\\libpthreadGC2.a\" ${cmake} && cmake --build . --config DEBUG && set CTEST_OUTPUT_ON_FAILURE=1 && ctest . -C DEBUG -j4 --output-on-failure", "default": false }, "freertos-esp32": { @@ -57,8 +57,12 @@ "cmake": "", "platforms": "windows-10, linkit-cross, ubuntu-focal-aarch64, freertos-esp32" }, - "openssl-v3": { - "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\"", + "default-examples-openssl-v3": { + "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1", + "platforms": "none,linux-fedora-32-x86_64" + }, + "default-examples-boringssl": { + "cmake": "cmake .. -DLWS_WITH_BORINGSSL=1 -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/boringssl/include\" -DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/boringssl/build/ssl/libssl.so;/usr/local/src/boringssl/build/crypto/libcrypto.so\" -DLWS_WITH_MINIMAL_EXAMPLES=1", "platforms": "none,linux-fedora-32-x86_64" }, "default-examples": { diff --git a/CMakeLists.txt b/CMakeLists.txt index f0a92a79..ec0e8d5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -560,15 +560,17 @@ if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR endif() if (LWS_HAVE_PTHREAD_H AND NOT LWS_PLAT_FREERTOS) - if (COMPILER_IS_CLANG) - set(LWS_PTHR_FLAGS "-pthread")# -Wno-error=unused-command-line-argument") - else() - set(LWS_PTHR_FLAGS "-pthread") - endif() - - set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LWS_PTHR_FLAGS}) if (NOT WIN32 AND NOT MSVC) - list(APPEND LIB_LIST_AT_END ${LWS_PTHR_FLAGS}) + if (COMPILER_IS_CLANG) + set(LWS_PTHR_FLAGS "-pthread")# -Wno-error=unused-command-line-argument") + else() + set(LWS_PTHR_FLAGS "-pthread") + endif() + + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LWS_PTHR_FLAGS}) + if (NOT WIN32 AND NOT MSVC) + list(APPEND LIB_LIST_AT_END ${LWS_PTHR_FLAGS}) + endif() endif() CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE diff --git a/READMEs/README.ctest.md b/READMEs/README.ctest.md index 142f33f6..48db124a 100644 --- a/READMEs/README.ctest.md +++ b/READMEs/README.ctest.md @@ -1,6 +1,6 @@ ## Using CTest with lws -### Prerequisites +### Updating ancient cmake You need a recent cmake to have the CTest tests work properly, if you're on an older distro you need to update your cmake. Luckily Kitware provide a repo for @@ -29,6 +29,13 @@ The main tests just need `-DLWS_WITH_MINIMAL_EXAMPLES=1`. You can optionally se `-DLWS_CTEST_INTERNET_AVAILABLE=0` to indicate you can't run the tests that need internet connectivity. +## Preparing to run the tests + +The tests have to spawn by script some "test buddies", for example the client +tests have to run a test server from the built lws image. For that reason you +have to do a side-install into `./destdir` using `make install DESTDIR=../destdir` +from the build directory before all the tests will work properly. + ## Running the tests CMake puts the test action into a build-host type specific form, for unix type @@ -57,10 +64,4 @@ warmcat.com or libwebsockets.org additionally. For that reason it's good practice to set the `WORKING_DIRECTORY` property to the home dir of the example app in all cases. -### SIGTERM from CTest... - -After a lot of headscratching I realized some tests were failing simply because -CTest was firing SIGTERMs at them for whatever reason. I added a commandline -option `--ignore-sigterm` in `lws_cmdline_option_handle_builtin()` to allow the -test to defeat this, and then it continues and completes fine. diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 6a461bbd..9136a8a0 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -71,6 +71,8 @@ #cmakedefine LWS_HAVE_RSA_SET0_KEY #cmakedefine LWS_HAVE_RSA_verify_pss_mgf1 #cmakedefine LWS_HAVE_SSL_CTX_get0_certificate +#cmakedefine LWS_HAVE_SSL_CTX_load_verify_file +#cmakedefine LWS_HAVE_SSL_CTX_load_verify_dir #cmakedefine LWS_HAVE_SSL_CTX_set1_param #cmakedefine LWS_HAVE_SSL_CTX_set_ciphersuites #cmakedefine LWS_HAVE_SSL_EXTRA_CHAIN_CERTS diff --git a/lib/roles/cgi/ops-cgi.c b/lib/roles/cgi/ops-cgi.c index 63863c38..4da28ba7 100644 --- a/lib/roles/cgi/ops-cgi.c +++ b/lib/roles/cgi/ops-cgi.c @@ -92,8 +92,8 @@ lws_cgi_sul_cb(lws_sorted_usec_list_t *sul) lws_cgi_kill_terminated(pt); - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_cgi, - 3 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner, &pt->sul_cgi, + 3 * LWS_US_PER_SEC); } static int diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index 9fcc7829..44aa0030 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -293,6 +293,8 @@ CHECK_FUNCTION_EXISTS(${VARIA}HMAC_CTX_new LWS_HAVE_HMAC_CTX_new PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set_ciphersuites LWS_HAVE_SSL_CTX_set_ciphersuites PARENT_SCOPE) if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) + # we don't want to confuse what's in or out of the wrapper with + # what's in an openssl also installed on the build host CHECK_C_SOURCE_COMPILES("#include \nint main(void) { STACK_OF(X509) *c = NULL; SSL_CTX *ctx = NULL; return (int)SSL_CTX_get_extra_chain_certs_only(ctx, &c); }\n" LWS_HAVE_SSL_EXTRA_CHAIN_CERTS) CHECK_C_SOURCE_COMPILES("#include \nint main(void) { EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX_free(md_ctx); return 0; }\n" LWS_HAVE_EVP_MD_CTX_free) set(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS ${LWS_HAVE_SSL_EXTRA_CHAIN_CERTS} PARENT_SCOPE) @@ -301,6 +303,8 @@ CHECK_FUNCTION_EXISTS(${VARIA}ECDSA_SIG_set0 LWS_HAVE_ECDSA_SIG_set0 PARENT_SCOP CHECK_FUNCTION_EXISTS(${VARIA}BN_bn2binpad LWS_HAVE_BN_bn2binpad PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_wrap LWS_HAVE_EVP_aes_128_wrap PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}EC_POINT_get_affine_coordinates LWS_HAVE_EC_POINT_get_affine_coordinates PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_load_verify_file LWS_HAVE_SSL_CTX_load_verify_file PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_load_verify_dir LWS_HAVE_SSL_CTX_load_verify_dir PARENT_SCOPE) endif() if (LWS_WITH_MBEDTLS) diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 1a6e5350..1fa83b62 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -722,15 +722,25 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, /* openssl init for cert verification (for client sockets) */ if (!ca_filepath && (!ca_mem || !ca_mem_len)) { +#if defined(LWS_HAVE_SSL_CTX_load_verify_dir) + if (!SSL_CTX_load_verify_dir( + vh->tls.ssl_client_ctx, LWS_OPENSSL_CLIENT_CERTS)) +#else if (!SSL_CTX_load_verify_locations( vh->tls.ssl_client_ctx, NULL, LWS_OPENSSL_CLIENT_CERTS)) +#endif lwsl_err("Unable to load SSL Client certs from %s " "(set by LWS_OPENSSL_CLIENT_CERTS) -- " "client ssl isn't going to work\n", LWS_OPENSSL_CLIENT_CERTS); } else if (ca_filepath) { +#if defined(LWS_HAVE_SSL_CTX_load_verify_file) + if (!SSL_CTX_load_verify_file( + vh->tls.ssl_client_ctx, ca_filepath)) { +#else if (!SSL_CTX_load_verify_locations( vh->tls.ssl_client_ctx, ca_filepath, NULL)) { +#endif lwsl_err( "Unable to load SSL Client certs " "file from %s -- client ssl isn't " diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index 9adfbb89..41bec6f1 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -519,8 +519,13 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, #endif if (info->ssl_ca_filepath && +#if defined(LWS_HAVE_SSL_CTX_load_verify_file) + !SSL_CTX_load_verify_file(vhost->tls.ssl_ctx, + info->ssl_ca_filepath)) { +#else !SSL_CTX_load_verify_locations(vhost->tls.ssl_ctx, info->ssl_ca_filepath, NULL)) { +#endif lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n", __func__); } -- Gitee From 286cf4357a2fe2540cf38837c59f946d2b0d7263 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 28 May 2020 12:48:17 +0100 Subject: [PATCH 0147/1062] sul: multiple timer domains Adapt the pt sul owner list to be an array, and define two different lists, one that acts like before and is the default for existing users, and another that has the ability to cooperate with systemwide suspend to restrict the interval spent suspended so that it will wake in time for the earliest thing on this wake-suspend sul list. Clean the api a bit and add lws_sul_cancel() that only needs the sul as the argument. Add a flag for client creation info to indicate that this client connection is important enough that, eg, validity checking it to detect silently dead connections should go on the wake-suspend sul list. That flag is exposed in secure streams policy so it can be added to a streamtype with "swake_validity": true Deprecate out the old vhost timer stuff that predates sul. Add a flag LWS_WITH_DEPRECATED_THINGS in cmake so users can get it back temporarily before it will be removed in a v4.2. Adapt all remaining in-tree users of it to use explicit suls. --- CMakeLists.txt | 2 +- READMEs/README.lws_sul.md | 37 ++++ include/libwebsockets/lws-client.h | 4 +- .../libwebsockets/lws-secure-streams-policy.h | 4 + include/libwebsockets/lws-sequencer.h | 2 + include/libwebsockets/lws-system.h | 4 + include/libwebsockets/lws-timeout-timer.h | 101 +++++++++-- lib/core-net/connect.c | 3 + lib/core-net/private-lib-core-net.h | 20 ++- lib/core-net/sequencer.c | 19 +- lib/core-net/sorted-usec-list.c | 170 +++++++++++------- lib/core-net/vhost.c | 3 +- lib/core-net/wsi-timeout.c | 25 ++- lib/core/context.c | 14 +- lib/event-libs/glib/glib.c | 3 +- lib/event-libs/libev/libev.c | 6 +- lib/event-libs/libevent/libevent.c | 6 +- lib/event-libs/libuv/libuv.c | 6 +- lib/plat/freertos/freertos-service.c | 4 +- lib/plat/optee/network.c | 4 +- lib/plat/unix/unix-init.c | 7 +- lib/plat/unix/unix-service.c | 2 +- lib/plat/unix/unix-spawn.c | 9 +- lib/plat/windows/windows-service.c | 4 +- lib/plat/windows/windows-spawn.c | 17 +- lib/roles/cgi/ops-cgi.c | 8 +- lib/roles/dbus/dbus.c | 9 +- lib/roles/http/client/client-handshake.c | 6 +- lib/roles/mqtt/mqtt.c | 9 +- lib/roles/mqtt/ops-mqtt.c | 3 +- lib/roles/ws/server-ws.c | 3 +- lib/secure-streams/README.md | 8 + lib/secure-streams/policy-json.c | 7 + lib/secure-streams/protocols/ss-h1.c | 6 +- lib/secure-streams/protocols/ss-mqtt.c | 2 +- lib/secure-streams/protocols/ss-raw.c | 2 +- lib/secure-streams/protocols/ss-ws.c | 5 +- lib/secure-streams/secure-streams-client.c | 3 +- lib/secure-streams/secure-streams.c | 9 +- lib/system/dhcpclient/dhcpclient.c | 18 +- lib/system/ntpclient/ntpclient.c | 6 +- lib/tls/tls-server.c | 10 +- lwsws/main.c | 2 +- .../minimal-ws-proxy/protocol_lws_minimal.c | 37 ++-- .../CMakeLists.txt | 12 +- .../minimal-dbus-ws-proxy-testclient.c | 103 +++++------ .../minimal-http-client.c | 3 +- .../minimal-http-server.c | 3 +- .../raw/minimal-raw-serial/minimal-raw-file.c | 2 +- .../minimal-secure-streams-alexa/alexa.c | 9 +- .../minimal-secure-streams-avs/avs.c | 8 +- .../minimal-secure-streams-client-tx.c | 3 +- .../protocol_lws_minimal_client_echo.c | 52 +++--- .../protocol_lws_minimal_pmd_bulk.c | 40 ++--- .../minimal-ws-client-tx/minimal-ws-client.c | 36 ++-- .../protocol_lws_minimal_threadpool.c | 39 ++-- plugins/protocol_lws_server_status.c | 21 +-- 57 files changed, 557 insertions(+), 403 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec0e8d5f..3bb87145 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,7 +218,7 @@ option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" OFF) option(LWS_WITH_ZLIB "Include zlib support (required for extensions)" OFF) option(LWS_WITH_BUNDLED_ZLIB "Use bundled zlib version (Windows only)" ${LWS_WITH_BUNDLED_ZLIB_DEFAULT}) option(LWS_WITH_MINIZ "Use miniz instead of zlib" OFF) -option(LWS_WITH_DEPRECATED_LWS_DLL "Migrate to lws_dll2 instead ASAP" OFF) +option(LWS_WITH_DEPRECATED_THINGS "Temporary workaround for deprecated apis" OFF) option(LWS_WITH_SEQUENCER "lws_seq_t support" ON) option(LWS_WITH_EXTERNAL_POLL "Support external POLL integration using callback messages (not recommended)" OFF) option(LWS_WITH_LWS_DSH "Support lws_dsh_t Disordered Shared Heap" OFF) diff --git a/READMEs/README.lws_sul.md b/READMEs/README.lws_sul.md index 1908f100..f1cae4e2 100644 --- a/READMEs/README.lws_sul.md +++ b/READMEs/README.lws_sul.md @@ -60,3 +60,40 @@ In the case you destroy your object and need to cancel the scheduled callback, u lws_sul_schedule(context, 0, &sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL); ``` +# lws_sul2 and system suspend + +In v4.1, alongside the existing `lws_sul` apis there is a refactor and additional +functionality aimed at negotiating system suspend, while remaining completely +backwards-compatible with v3.2+ lws_sul apis. + +Devicewide suspend is basically the withdrawal of CPU availability for an unbounded +amount of time, so what may have been scheduled by the user code may miss its time +slot because the cpu was down and nothing is getting serviced. Whether that is +actively desirable, OK, a big disaster, or a failure that will be corrected at other +layers at the cost of, eg, some additional latency, depends on the required device +behaviours and the function of the user code that was scheduled, and its meaning to +the system. + +Before v4.1, lws just offers the same scheduling service for everything both internal +and arranged by user code, and has no way to know what is critical for the device to +operate as intended, and so must force wake from suspend, or if for that scheduled +event 'failure [to get the event] is an option'. + +For example locally-initiated periodic keepalive pings not happening may allow +persistently dead (ie, no longer passing data) connections to remain unrenewed, but +eventually when suspend ends for another reason, the locally-initiated PING probes +will resume and it will be discovered and if the connectivity allows, corrected. + +If the device's function can handle the latency of there being no connectivity in +suspend under those conditions until it wakes for another reason, it's OK for these +kind of timeouts to be suppressed during suspend and basically take the power saving +instead. If for a particular device it's intolerable to ever have a silently dead +connection for more than a very short time compared to suspend durations, then these +kind of timeouts must have the priority to wake the whole device from suspend so +they continue to operate unimpeded. + +That is just one example, lws offers generic scheduler services the user code can +exploit for any purpose, including mission-critical ones. The changes give the user +code a way to tell lws if a particular scheduled event is important enough to the +system operation to wake the system from devicewide suspend. + diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index e957b3a3..b8693f18 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -58,7 +58,9 @@ enum lws_client_connect_ssl_connection_flags { * HTTP/2: always possible... uses parallel streams */ LCCSCF_MUXABLE_STREAM = (1 << 17), - LCCSCF_H2_PRIOR_KNOWLEDGE = (1 << 18) + LCCSCF_H2_PRIOR_KNOWLEDGE = (1 << 18), + LCCSCF_WAKE_SUSPEND__VALIDITY = (1 << 19), + /* our validity checks are important enough to wake from suspend */ }; /** struct lws_client_connect_info - parameters to connect with when using diff --git a/include/libwebsockets/lws-secure-streams-policy.h b/include/libwebsockets/lws-secure-streams-policy.h index 86ed2de0..7b798d5e 100644 --- a/include/libwebsockets/lws-secure-streams-policy.h +++ b/include/libwebsockets/lws-secure-streams-policy.h @@ -116,6 +116,10 @@ enum { /**< set up lws_system client cert */ LWSSSPOLF_LOCAL_SINK = (1 << 13), /**< expected to bind to a local sink only */ + LWSSSPOLF_WAKE_SUSPEND__VALIDITY = (1 << 14), + /**< this stream's idle validity checks are critical enough we + * should arrange to wake from suspend to perform them + */ }; typedef struct lws_ss_trust_store { diff --git a/include/libwebsockets/lws-sequencer.h b/include/libwebsockets/lws-sequencer.h index a08f6132..7189788b 100644 --- a/include/libwebsockets/lws-sequencer.h +++ b/include/libwebsockets/lws-sequencer.h @@ -87,6 +87,8 @@ typedef struct lws_seq_info { lws_seq_event_cb cb; /* seq callback */ const char *name; /* seq name */ const lws_retry_bo_t *retry; /* retry policy */ + uint8_t wakesuspend:1; /* important enough to + * wake system */ } lws_seq_info_t; /** diff --git a/include/libwebsockets/lws-system.h b/include/libwebsockets/lws-system.h index 1f437068..bf946e47 100644 --- a/include/libwebsockets/lws-system.h +++ b/include/libwebsockets/lws-system.h @@ -169,6 +169,10 @@ typedef struct lws_system_ops { * Start the check that proceeds asynchronously, and report the results * by calling lws_captive_portal_detect_result() api */ + + uint32_t wake_latency_us; + /**< time taken for this device to wake from suspend, in us + */ } lws_system_ops_t; /** diff --git a/include/libwebsockets/lws-timeout-timer.h b/include/libwebsockets/lws-timeout-timer.h index 75f59ddb..5eb97598 100644 --- a/include/libwebsockets/lws-timeout-timer.h +++ b/include/libwebsockets/lws-timeout-timer.h @@ -146,6 +146,8 @@ lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us); LWS_VISIBLE LWS_EXTERN void lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs); +#if defined(LWS_WITH_DEPRECATED_THINGS) + /* * lws_timed_callback_vh_protocol() - calls back a protocol on a vhost after * the specified delay in seconds @@ -155,6 +157,8 @@ lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs); * \param reason: callback reason * \param secs: how many seconds in the future to do the callback. * + * DEPRECATED since v4.1 + * * Callback the specified protocol with a fake wsi pointing to the specified * vhost and protocol, with the specified reason, at the specified time in the * future. @@ -168,7 +172,8 @@ lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs); LWS_VISIBLE LWS_EXTERN int lws_timed_callback_vh_protocol(struct lws_vhost *vh, const struct lws_protocols *prot, - int reason, int secs); + int reason, int secs) +LWS_WARN_DEPRECATED; /* * lws_timed_callback_vh_protocol_us() - calls back a protocol on a vhost after @@ -179,6 +184,8 @@ lws_timed_callback_vh_protocol(struct lws_vhost *vh, * \param reason: callback reason * \param us: how many us in the future to do the callback. * + * DEPRECATED since v4.1 + * * Callback the specified protocol with a fake wsi pointing to the specified * vhost and protocol, with the specified reason, at the specified time in the * future. @@ -192,7 +199,10 @@ lws_timed_callback_vh_protocol(struct lws_vhost *vh, LWS_VISIBLE LWS_EXTERN int lws_timed_callback_vh_protocol_us(struct lws_vhost *vh, const struct lws_protocols *prot, int reason, - lws_usec_t us); + lws_usec_t us) +LWS_WARN_DEPRECATED; + +#endif struct lws_sorted_usec_list; @@ -200,34 +210,98 @@ typedef void (*sul_cb_t)(struct lws_sorted_usec_list *sul); typedef struct lws_sorted_usec_list { struct lws_dll2 list; /* simplify the code by keeping this at start */ - sul_cb_t cb; lws_usec_t us; + sul_cb_t cb; + uint32_t latency_us; /* us it may safely be delayed */ } lws_sorted_usec_list_t; +/* + * There are multiple sul owners to allow accounting for, a) events that must + * wake from suspend, and b) events that can be missued due to suspend + */ +#define LWS_COUNT_PT_SUL_OWNERS 2 + +#define LWSSULLI_MISS_IF_SUSPENDED 0 +#define LWSSULLI_WAKE_IF_SUSPENDED 1 /* - * lws_sul_schedule() - schedule a callback + * lws_sul2_schedule() - schedule a callback * * \param context: the lws_context * \param tsi: the thread service index (usually 0) + * \param flags: LWSSULLI_... * \param sul: pointer to the sul element - * \param cb: the scheduled callback - * \param us: the delay before the callback arrives, or - * LWS_SET_TIMER_USEC_CANCEL to cancel it. * * Generic callback-at-a-later time function. The callback happens on the * event loop thread context. * * Although the api has us resultion, the actual resolution depends on the - * platform and is commonly 1ms. + * platform and may be, eg, 1ms. * * This doesn't allocate and doesn't fail. * - * You can call it again with another us value to change the delay. + * If flags contains LWSSULLI_WAKE_IF_SUSPENDED, the scheduled event is placed + * on a sul owner list that, if the system has entered low power suspend mode, + * tries to arrange that the system should wake from platform suspend just + * before the event is due. Scheduled events without this flag will be missed + * in the case the system is in suspend and nothing else happens to have woken + * it. + * + * You can call it again with another us value to change the delay or move the + * event to a different owner (ie, wake or miss on suspend). + */ +LWS_VISIBLE LWS_EXTERN void +lws_sul2_schedule(struct lws_context *context, int tsi, int flags, + lws_sorted_usec_list_t *sul); + +/* + * lws_sul_cancel() - cancel scheduled callback + * + * \param sul: pointer to the sul element + * + * If it's scheduled, remove the sul from its owning sorted list. + * If not scheduled, it's a NOP. */ LWS_VISIBLE LWS_EXTERN void -lws_sul_schedule(struct lws_context *context, int tsi, - lws_sorted_usec_list_t *sul, sul_cb_t cb, lws_usec_t us); +lws_sul_cancel(lws_sorted_usec_list_t *sul); + +/* + * lws_sul_earliest_wakeable_event() - get earliest wake-from-suspend event + * + * \param ctx: the lws context + * \param pearliest: pointer to lws_usec_t to take the result + * + * Either returns 1 if no pending event, or 0 and sets *pearliest to the + * MONOTONIC time of the current earliest next expected event. + */ +LWS_VISIBLE LWS_EXTERN int +lws_sul_earliest_wakeable_event(struct lws_context *ctx, lws_usec_t *pearliest); + +/* + * For backwards compatibility + * + * If us is LWS_SET_TIMER_USEC_CANCEL, the sul is removed from the scheduler. + * New code can use lws_sul_cancel() + */ + +#define lws_sul_schedule(ctx, tsi, sul, _cb, _us) {\ + if ((lws_usec_t)_us == (lws_usec_t)LWS_SET_TIMER_USEC_CANCEL) \ + lws_sul_cancel(sul); \ + else { \ + (sul)->cb = _cb; \ + (sul)->us = lws_now_usecs() + _us; \ + lws_sul2_schedule(ctx, tsi, LWSSULLI_MISS_IF_SUSPENDED, sul); \ + }} + +#define lws_sul_schedule_wakesuspend(ctx, tsi, sul, _cb, _us) {\ + if ((lws_usec_t)_us == (lws_usec_t)LWS_SET_TIMER_USEC_CANCEL) \ + lws_sul_cancel(sul); \ + else { \ + (sul)->cb = _cb; \ + (sul)->us = lws_now_usecs() + _us; \ + lws_sul2_schedule(ctx, tsi, LWSSULLI_WAKE_IF_SUSPENDED, sul); \ + }} + /* * lws_validity_confirmed() - reset the validity timer for a network connection @@ -257,10 +331,9 @@ lws_validity_confirmed(struct lws *wsi); */ LWS_VISIBLE LWS_EXTERN int -__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul, - lws_usec_t us); +__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul); LWS_VISIBLE LWS_EXTERN lws_usec_t -__lws_sul_service_ripe(lws_dll2_owner_t *own, lws_usec_t usnow); +__lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow); ///@} diff --git a/lib/core-net/connect.c b/lib/core-net/connect.c index 320abc17..6c517c70 100644 --- a/lib/core-net/connect.c +++ b/lib/core-net/connect.c @@ -77,6 +77,9 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) wsi->detlat.earliest_write_req_pre_write = lws_now_usecs(); #endif + if (i->ssl_connection & LCCSCF_WAKE_SUSPEND__VALIDITY) + wsi->conn_validity_wakesuspend = 1; + wsi->vhost = NULL; if (!i->vhost) { struct lws_vhost *v = i->context->vhost_list; diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index cb04c32a..559d1aca 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -77,6 +77,10 @@ enum lws_ssl_capable_status { LWS_SSL_CAPABLE_MORE_SERVICE = -4, /* general retry */ }; +#define __lws_sul_insert_us(owner, sul, _us) \ + (sul)->us = lws_now_usecs() + _us; \ + __lws_sul_insert(owner, sul) + /* * @@ -267,12 +271,11 @@ struct client_info_stash { #define LWS_H2_FRAME_HEADER_LENGTH 9 -int -__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul, - lws_usec_t us); lws_usec_t -__lws_sul_service_ripe(lws_dll2_owner_t *own, lws_usec_t usnow); +__lws_sul_service_ripe(lws_dll2_owner_t *own, int num_own, lws_usec_t usnow); + +#if defined(LWS_WITH_DEPRECATED_THINGS) struct lws_timed_vh_protocol { struct lws_timed_vh_protocol *next; @@ -283,6 +286,8 @@ struct lws_timed_vh_protocol { int tsi_req; }; +#endif + /* * lws_dsh */ @@ -367,7 +372,7 @@ struct lws_context_per_thread { lws_dll2_owner_t ss_client_owner; #endif - struct lws_dll2_owner pt_sul_owner; + struct lws_dll2_owner pt_sul_owner[LWS_COUNT_PT_SUL_OWNERS]; #if defined (LWS_WITH_SEQUENCER) lws_sorted_usec_list_t sul_seq_heartbeat; @@ -572,7 +577,9 @@ struct lws_vhost { struct lws_vhost_tls tls; #endif +#if defined(LWS_WITH_DEPRECATED_THINGS) struct lws_timed_vh_protocol *timed_vh_protocol_list; +#endif void *user; int listen_port; @@ -800,6 +807,7 @@ struct lws { unsigned int validity_hup:1; unsigned int skip_fallback:1; unsigned int file_desc:1; + unsigned int conn_validity_wakesuspend:1; unsigned int could_have_pending:1; /* detect back-to-back writes */ unsigned int outer_will_close:1; @@ -1160,8 +1168,10 @@ void lws_sum_stats(const struct lws_context *ctx, struct lws_conn_stats *cs); #endif +#if defined(LWS_WITH_DEPRECATED_THINGS) int __lws_timed_callback_remove(struct lws_vhost *vh, struct lws_timed_vh_protocol *p); +#endif int LWS_WARN_UNUSED_RESULT __insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi); diff --git a/lib/core-net/sequencer.c b/lib/core-net/sequencer.c index d2da6ba3..42b43cd3 100644 --- a/lib/core-net/sequencer.c +++ b/lib/core-net/sequencer.c @@ -53,7 +53,8 @@ typedef struct lws_sequencer { lws_usec_t time_created; lws_usec_t timeout; /* 0 or time we timeout */ - char going_down; + uint8_t going_down:1; + uint8_t wakesuspend:1; } lws_seq_t; #define QUEUE_SANITY_LIMIT 10 @@ -77,8 +78,8 @@ lws_sul_seq_heartbeat_cb(lws_sorted_usec_list_t *sul) /* schedule the next one */ - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_seq_heartbeat, - LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_seq_heartbeat, LWS_US_PER_SEC); } int @@ -87,8 +88,8 @@ lws_seq_pt_init(struct lws_context_per_thread *pt) pt->sul_seq_heartbeat.cb = lws_sul_seq_heartbeat_cb; /* schedule the first heartbeat */ - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_seq_heartbeat, - LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_seq_heartbeat, LWS_US_PER_SEC); return 0; } @@ -106,6 +107,7 @@ lws_seq_create(lws_seq_info_t *i) seq->pt = pt; seq->name = i->name; seq->retry = i->retry; + seq->wakesuspend = i->wakesuspend; *i->puser = (void *)&seq[1]; @@ -242,7 +244,8 @@ lws_seq_queue_event(lws_seq_t *seq, lws_seq_events_t e, void *data, void *aux) lws_dll2_add_tail(&seqe->seq_event_list, &seq->seq_event_owner); seq->sul_pending.cb = lws_seq_sul_pending_cb; - __lws_sul_insert(&seq->pt->pt_sul_owner, &seq->sul_pending, 1); + __lws_sul_insert_us(&seq->pt->pt_sul_owner[seq->wakesuspend], + &seq->sul_pending, 1); lws_pt_unlock(seq->pt); /* } pt ------------------------------------- */ @@ -300,8 +303,10 @@ lws_seq_timeout_us(lws_seq_t *seq, lws_usec_t us) { seq->sul_timeout.cb = lws_seq_sul_timeout_cb; /* list is always at the very top of the sul */ - return __lws_sul_insert(&seq->pt->pt_sul_owner, + __lws_sul_insert_us(&seq->pt->pt_sul_owner[seq->wakesuspend], (lws_sorted_usec_list_t *)&seq->sul_timeout.list, us); + + return 0; } lws_seq_t * diff --git a/lib/core-net/sorted-usec-list.c b/lib/core-net/sorted-usec-list.c index d12a3312..04de5916 100644 --- a/lib/core-net/sorted-usec-list.c +++ b/lib/core-net/sorted-usec-list.c @@ -43,69 +43,57 @@ sul_compare(const lws_dll2_t *d, const lws_dll2_t *i) return 0; } +/* + * notice owner was chosen already, and sul->us was already computed + */ + int -__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul, - lws_usec_t us) +__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul) { - lws_usec_t now = lws_now_usecs(); lws_dll2_remove(&sul->list); - if (us == LWS_SET_TIMER_USEC_CANCEL) { - /* we are clearing the timeout */ - sul->us = 0; - - return 0; - } - - sul->us = now + us; assert(sul->cb); /* * we sort the pt's list of sequencers with pending timeouts, so it's - * cheap to check it every second + * cheap to check it every poll wait */ lws_dll2_add_sorted(&sul->list, own, sul_compare); -#if 0 // defined(_DEBUG) - { - lws_usec_t worst = 0; - int n = 1; - - lwsl_info("%s: own %p: count %d\n", __func__, own, own->count); - - lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, - lws_dll2_get_head(own)) { - lws_sorted_usec_list_t *sul = (lws_sorted_usec_list_t *)p; - lwsl_info("%s: %d: %llu (+%lld)\n", __func__, n++, - (unsigned long long)sul->us, - (long long)(sul->us - now)); - if (sul->us < worst) { - lwsl_err("%s: wrongly sorted sul entry!\n", - __func__); - assert(0); - } - worst = sul->us; - } lws_end_foreach_dll_safe(p, tp); - } -#endif - return 0; } void -lws_sul_schedule(struct lws_context *context, int tsi, - lws_sorted_usec_list_t *sul, sul_cb_t cb, lws_usec_t us) +lws_sul_cancel(lws_sorted_usec_list_t *sul) { - struct lws_context_per_thread *pt = &context->pt[tsi]; + lws_dll2_remove(&sul->list); + + /* we are clearing the timeout and leaving ourselves detached */ + sul->us = 0; +} - sul->cb = cb; +void +lws_sul2_schedule(struct lws_context *context, int tsi, int flags, + lws_sorted_usec_list_t *sul) +{ + struct lws_context_per_thread *pt = &context->pt[tsi]; - __lws_sul_insert(&pt->pt_sul_owner, sul, us); + __lws_sul_insert( + &pt->pt_sul_owner[!!(flags & LWSSULLI_WAKE_IF_SUSPENDED)], sul); } +/* + * own points to the first in an array of length own_len + * + * While any sul list owner has a "ripe", ie, ready to handle sul we do them + * strictly in order of sul time. When nobody has a ripe sul we return 0, if + * actually nobody has any sul, or the interval between usnow and the next + * earliest scheduled event on any list. + */ + lws_usec_t -__lws_sul_service_ripe(lws_dll2_owner_t *own, lws_usec_t usnow) +__lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow) { struct lws_context_per_thread *pt = (struct lws_context_per_thread *) lws_container_of(own, struct lws_context_per_thread, @@ -114,36 +102,94 @@ __lws_sul_service_ripe(lws_dll2_owner_t *own, lws_usec_t usnow) if (pt->attach_owner.count) lws_system_do_attach(pt); - while (lws_dll2_get_head(own)) { + /* must be at least 1 */ + assert(own_len); + + /* + * Of the own_len sul owning lists, the earliest next sul could be on + * any of them. We have to find it and handle each in turn until no + * ripe sul left on any owning list, and we can exit. + * + * This ensures the ripe sul are handled strictly in the right order no + * matter which owning list they are on. + */ - /* .list is always first member in lws_sorted_usec_list_t */ - lws_sorted_usec_list_t *sul = (lws_sorted_usec_list_t *) - lws_dll2_get_head(own); + do { + lws_sorted_usec_list_t *hit = NULL; + lws_usec_t lowest; + int n = 0; + + for (n = 0; n < own_len; n++) { + lws_sorted_usec_list_t *sul; + if (!own[n].count) + continue; + sul = (lws_sorted_usec_list_t *) + lws_dll2_get_head(&own[n]); + + if (!hit || sul->us <= lowest) { + hit = sul; + lowest = sul->us; + } + } - assert(sul->us); /* shouldn't be on the list otherwise */ + if (!hit) + return 0; - if (sul->us > usnow) - return sul->us - usnow; + if (lowest > usnow) + return lowest - usnow; + + /* his moment has come... remove him from his owning list */ + + lws_dll2_remove(&hit->list); + hit->us = 0; - /* his moment has come... remove him from timeout list */ - lws_dll2_remove(&sul->list); - sul->us = 0; pt->inside_lws_service = 1; - sul->cb(sul); + hit->cb(hit); pt->inside_lws_service = 0; - /* - * The callback may have done any mixture of delete - * and add sul entries... eg, close a wsi may pull out - * multiple entries making iterating it statefully - * unsafe. Always restart at the current head of list. - */ + } while (1); + + /* unreachable */ + + return 0; +} + +/* + * Earliest wakeable event on any pt + */ + +int +lws_sul_earliest_wakeable_event(struct lws_context *ctx, lws_usec_t *pearliest) +{ + struct lws_context_per_thread *pt; + int n = 0, hit = -1; + lws_usec_t lowest; + + for (n = 0; n < ctx->count_threads; n++) { + pt = &ctx->pt[n]; + + lws_pt_lock(pt, __func__); + + if (pt->pt_sul_owner[LWSSULLI_WAKE_IF_SUSPENDED].count) { + lws_sorted_usec_list_t *sul = (lws_sorted_usec_list_t *) + lws_dll2_get_head(&pt->pt_sul_owner[ + LWSSULLI_WAKE_IF_SUSPENDED]); + + if (hit == -1 || sul->us < lowest) { + hit = n; + lowest = sul->us; + } + } + + lws_pt_unlock(pt); } - /* - * Nothing left to take care of in the list (cannot return 0 otherwise - * because we will service anything equal to usnow rather than return) - */ + + if (hit == -1) + /* there is no pending event */ + return 1; + + *pearliest = lowest; return 0; } diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index c0b6de2e..dd6349d0 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -1098,13 +1098,14 @@ __lws_vhost_destroy2(struct lws_vhost *vh) } lws_end_foreach_dll_safe(d, d1); #endif +#if defined(LWS_WITH_DEPRECATED_THINGS) /* * destroy any pending timed events */ while (vh->timed_vh_protocol_list) __lws_timed_callback_remove(vh, vh->timed_vh_protocol_list); - +#endif /* * let the protocols destroy the per-vhost protocol objects */ diff --git a/lib/core-net/wsi-timeout.c b/lib/core-net/wsi-timeout.c index cfbb7d2b..7fd29449 100644 --- a/lib/core-net/wsi-timeout.c +++ b/lib/core-net/wsi-timeout.c @@ -61,7 +61,8 @@ __lws_set_timer_usecs(struct lws *wsi, lws_usec_t us) struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; wsi->sul_hrtimer.cb = lws_sul_hrtimer_cb; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_hrtimer, us); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &wsi->sul_hrtimer, us); } void @@ -126,8 +127,9 @@ __lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs) struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; wsi->sul_timeout.cb = lws_sul_wsitimeout_cb; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_timeout, - ((lws_usec_t)secs) * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &wsi->sul_timeout, + ((lws_usec_t)secs) * LWS_US_PER_SEC); lwsl_debug("%s: %p: %d secs, reason %d\n", __func__, wsi, secs, reason); @@ -178,7 +180,8 @@ lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us) return; lws_pt_lock(pt, __func__); - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_timeout, us); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &wsi->sul_timeout, us); lwsl_notice("%s: %p: %llu us, reason %d\n", __func__, wsi, (unsigned long long)us, reason); @@ -187,6 +190,8 @@ lws_set_timeout_us(struct lws *wsi, enum pending_timeout reason, lws_usec_t us) lws_pt_unlock(pt); } +#if defined(LWS_WITH_DEPRECATED_THINGS) + /* requires context + vh lock */ int @@ -276,6 +281,8 @@ lws_timed_callback_vh_protocol(struct lws_vhost *vh, ((lws_usec_t)secs) * LWS_US_PER_SEC); } +#endif + static void lws_validity_cb(lws_sorted_usec_list_t *sul) { @@ -308,8 +315,9 @@ lws_validity_cb(lws_sorted_usec_list_t *sul) assert(rbo->secs_since_valid_hangup > rbo->secs_since_valid_ping); wsi->validity_hup = 1; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_validity, - ((uint64_t)rbo->secs_since_valid_hangup - + __lws_sul_insert_us(&pt->pt_sul_owner[!!wsi->conn_validity_wakesuspend], + &wsi->sul_validity, + ((uint64_t)rbo->secs_since_valid_hangup - rbo->secs_since_valid_ping) * LWS_US_PER_SEC); } @@ -339,8 +347,9 @@ _lws_validity_confirmed_role(struct lws *wsi) rbo->secs_since_valid_ping, wsi->validity_hup); - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_validity, - ((uint64_t)(wsi->validity_hup ? + __lws_sul_insert_us(&pt->pt_sul_owner[!!wsi->conn_validity_wakesuspend], + &wsi->sul_validity, + ((uint64_t)(wsi->validity_hup ? rbo->secs_since_valid_hangup : rbo->secs_since_valid_ping)) * LWS_US_PER_SEC); } diff --git a/lib/core/context.c b/lib/core/context.c index 489da5d4..425acc0e 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -62,7 +62,8 @@ lws_sul_stats_cb(lws_sorted_usec_list_t *sul) lws_stats_log_dump(pt->context); - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_stats, 10 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_stats, 10 * LWS_US_PER_SEC); } #endif #if defined(LWS_WITH_PEER_LIMITS) @@ -74,7 +75,8 @@ lws_sul_peer_limits_cb(lws_sorted_usec_list_t *sul) lws_peer_cull_peer_wait_list(pt->context); - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_peer_limits, 10 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_peer_limits, 10 * LWS_US_PER_SEC); } #endif @@ -742,13 +744,13 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_STATS) context->pt[0].sul_stats.cb = lws_sul_stats_cb; - __lws_sul_insert(&context->pt[0].pt_sul_owner, &context->pt[0].sul_stats, - 10 * LWS_US_PER_SEC); + __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &context->pt[0].sul_stats, 10 * LWS_US_PER_SEC); #endif #if defined(LWS_WITH_PEER_LIMITS) context->pt[0].sul_peer_limits.cb = lws_sul_peer_limits_cb; - __lws_sul_insert(&context->pt[0].pt_sul_owner, - &context->pt[0].sul_peer_limits, 10 * LWS_US_PER_SEC); + __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &context->pt[0].sul_peer_limits, 10 * LWS_US_PER_SEC); #endif #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) diff --git a/lib/event-libs/glib/glib.c b/lib/event-libs/glib/glib.c index ada7627d..386f144f 100644 --- a/lib/event-libs/glib/glib.c +++ b/lib/event-libs/glib/glib.c @@ -157,7 +157,8 @@ lws_glib_hrtimer_cb(void *p) lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { ms = us / LWS_US_PER_MS; if (!ms) diff --git a/lib/event-libs/libev/libev.c b/lib/event-libs/libev/libev.c index f58b8f91..e9248c84 100644 --- a/lib/event-libs/libev/libev.c +++ b/lib/event-libs/libev/libev.c @@ -32,7 +32,8 @@ lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0); ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer); @@ -60,7 +61,8 @@ lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents) /* account for hrtimer */ lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0); ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer); diff --git a/lib/event-libs/libevent/libevent.c b/lib/event-libs/libevent/libevent.c index 786c4f88..bd59d30f 100644 --- a/lib/event-libs/libevent/libevent.c +++ b/lib/event-libs/libevent/libevent.c @@ -32,7 +32,8 @@ lws_event_hrtimer_cb(int fd, short event, void *p) lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { tv.tv_sec = us / LWS_US_PER_SEC; tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC); @@ -76,7 +77,8 @@ lws_event_idle_timer_cb(int fd, short event, void *p) /* account for hrtimer */ lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) { tv.tv_sec = us / LWS_US_PER_SEC; tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC); diff --git a/lib/event-libs/libuv/libuv.c b/lib/event-libs/libuv/libuv.c index 2b0883e6..ac116a82 100644 --- a/lib/event-libs/libuv/libuv.c +++ b/lib/event-libs/libuv/libuv.c @@ -36,7 +36,8 @@ lws_uv_sultimer_cb(uv_timer_t *timer lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) uv_timer_start(&pt->uv.sultimer, lws_uv_sultimer_cb, LWS_US_TO_MS(us), 0); @@ -66,7 +67,8 @@ lws_uv_idle(uv_idle_t *handle /* account for sultimer */ lws_pt_lock(pt, __func__); - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us) uv_timer_start(&pt->uv.sultimer, lws_uv_sultimer_cb, LWS_US_TO_MS(us), 0); diff --git a/lib/plat/freertos/freertos-service.c b/lib/plat/freertos/freertos-service.c index d36b1ec1..f528bd1d 100644 --- a/lib/plat/freertos/freertos-service.c +++ b/lib/plat/freertos/freertos-service.c @@ -110,7 +110,9 @@ again: lws_pt_lock(pt, __func__); /* don't stay in poll wait longer than next hr timeout */ - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, + LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us && us < timeout_us) timeout_us = us; diff --git a/lib/plat/optee/network.c b/lib/plat/optee/network.c index 767c2549..05427df3 100644 --- a/lib/plat/optee/network.c +++ b/lib/plat/optee/network.c @@ -128,7 +128,9 @@ again: lws_pt_lock(pt, __func__); /* don't stay in poll wait longer than next hr timeout */ - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, + LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us && us < timeout_us) timeout_us = us; diff --git a/lib/plat/unix/unix-init.c b/lib/plat/unix/unix-init.c index 6abe4c7b..0f78e1a0 100644 --- a/lib/plat/unix/unix-init.c +++ b/lib/plat/unix/unix-init.c @@ -75,7 +75,8 @@ lws_sul_plat_unix(lws_sorted_usec_list_t *sul) lws_context_unlock(context); #endif - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_plat, 30 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_plat, 30 * LWS_US_PER_SEC); } #endif @@ -141,8 +142,8 @@ lws_plat_init(struct lws_context *context, /* we only need to do this on pt[0] */ context->pt[0].sul_plat.cb = lws_sul_plat_unix; - __lws_sul_insert(&context->pt[0].pt_sul_owner, &context->pt[0].sul_plat, - 30 * LWS_US_PER_SEC); + __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &context->pt[0].sul_plat, 30 * LWS_US_PER_SEC); #endif return 0; diff --git a/lib/plat/unix/unix-service.c b/lib/plat/unix/unix-service.c index c0984b29..c7edfa68 100644 --- a/lib/plat/unix/unix-service.c +++ b/lib/plat/unix/unix-service.c @@ -113,7 +113,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* * service ripe scheduled events, and limit wait to next expected one */ - us = __lws_sul_service_ripe(&pt->pt_sul_owner, us); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, us); if (us && us < timeout_us) timeout_us = us; diff --git a/lib/plat/unix/unix-spawn.c b/lib/plat/unix/unix-spawn.c index 3f6ffbd8..b1960578 100644 --- a/lib/plat/unix/unix-spawn.c +++ b/lib/plat/unix/unix-spawn.c @@ -108,10 +108,8 @@ lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) lws_dll2_remove(&lsp->dll); - lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, - NULL, LWS_SET_TIMER_USEC_CANCEL); - lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul_reap, - NULL, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&lsp->sul); + lws_sul_cancel(&lsp->sul_reap); for (n = 0; n < 3; n++) { #if 0 @@ -188,8 +186,7 @@ lws_spawn_reap(struct lws_spawn_piped *lsp) /* we reached the reap point, no need for timeout wait */ - lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&lsp->sul); /* * All the stdwsi went down, nothing more is coming... it's over diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index ae16d973..51eb2d27 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -133,7 +133,9 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) lws_pt_lock(pt, __func__); /* don't stay in poll wait longer than next hr timeout */ - us = __lws_sul_service_ripe(&pt->pt_sul_owner, lws_now_usecs()); + us = __lws_sul_service_ripe(pt->pt_sul_owner, + LWS_COUNT_PT_SUL_OWNERS, + lws_now_usecs()); if (us && us < timeout_us) timeout_us = us; diff --git a/lib/plat/windows/windows-spawn.c b/lib/plat/windows/windows-spawn.c index fcc11c6b..73487231 100644 --- a/lib/plat/windows/windows-spawn.c +++ b/lib/plat/windows/windows-spawn.c @@ -125,14 +125,9 @@ lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp) lws_dll2_remove(&lsp->dll); - lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, - NULL, LWS_SET_TIMER_USEC_CANCEL); - - lws_sul_schedule(lsp->context, 0, &lsp->sul_reap, NULL, - LWS_SET_TIMER_USEC_CANCEL); - - lws_sul_schedule(lsp->context, 0, &lsp->sul_poll, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&lsp->sul); + lws_sul_cancel(&lsp->sul_reap); + lws_sul_cancel(&lsp->sul_poll); lwsl_warn("%s: deleting lsp\n", __func__); @@ -192,8 +187,7 @@ lws_spawn_reap(struct lws_spawn_piped *lsp) /* we reached the reap point, no need for timeout wait */ - lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&lsp->sul); /* * All the stdwsi went down, nothing more is coming... it's over @@ -517,8 +511,7 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) bail3: - lws_sul_schedule(context, 0, &lsp->sul_poll, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&lsp->sul_poll); while (--n >= 0) __remove_wsi_socket_from_fds(lsp->stdwsi[n]); diff --git a/lib/roles/cgi/ops-cgi.c b/lib/roles/cgi/ops-cgi.c index 4da28ba7..97794197 100644 --- a/lib/roles/cgi/ops-cgi.c +++ b/lib/roles/cgi/ops-cgi.c @@ -92,8 +92,8 @@ lws_cgi_sul_cb(lws_sorted_usec_list_t *sul) lws_cgi_kill_terminated(pt); - __lws_sul_insert_us(&pt->pt_sul_owner, &pt->sul_cgi, - 3 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_cgi, 3 * LWS_US_PER_SEC); } static int @@ -105,8 +105,8 @@ rops_pt_init_destroy_cgi(struct lws_context *context, pt->sul_cgi.cb = lws_cgi_sul_cb; - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_cgi, - 3 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_cgi, 3 * LWS_US_PER_SEC); } else lws_dll2_remove(&pt->sul_cgi.list); diff --git a/lib/roles/dbus/dbus.c b/lib/roles/dbus/dbus.c index 75b65aa6..3662c12e 100644 --- a/lib/roles/dbus/dbus.c +++ b/lib/roles/dbus/dbus.c @@ -491,7 +491,7 @@ lws_dbus_sul_cb(lws_sorted_usec_list_t *sul) } } lws_end_foreach_dll_safe(rdt, nx); - __lws_sul_insert(&pt->pt_sul_owner, &pt->dbus.sul, + lws_sul_schedule(pt->context, pt->tid, &pt->dbus.sul, lws_dbus_sul_cb, 3 * LWS_US_PER_SEC); } @@ -501,13 +501,10 @@ rops_pt_init_destroy_dbus(struct lws_context *context, struct lws_context_per_thread *pt, int destroy) { if (!destroy) { - - pt->dbus.sul.cb = lws_dbus_sul_cb; - - __lws_sul_insert(&pt->pt_sul_owner, &pt->dbus.sul, + lws_sul_schedule(context, pt->tid, &pt->dbus.sul, lws_dbus_sul_cb, 3 * LWS_US_PER_SEC); } else - lws_dll2_remove(&pt->dbus.sul.list); + lws_sul_cancel(&pt->dbus.sul); return 0; } diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 9983bb12..73f0eaea 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -756,8 +756,7 @@ ads_known: } conn_good: - lws_sul_schedule(wsi->context, 0, &wsi->sul_connect_timeout, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&wsi->sul_connect_timeout); lwsl_info("%s: Connection started %p\n", __func__, wsi->dns_results); /* the tcp connection has happend */ @@ -837,8 +836,7 @@ try_next_result_closesock: wsi->desc.sockfd = LWS_SOCK_INVALID; try_next_result: - lws_sul_schedule(wsi->context, 0, &wsi->sul_connect_timeout, - NULL, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&wsi->sul_connect_timeout); if (wsi->dns_results_next) { wsi->dns_results_next = wsi->dns_results_next->ai_next; if (wsi->dns_results_next) diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index 8e2079de..6eeae7cc 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -1111,9 +1111,7 @@ bail1: * no need for ACK timeout wait * any more */ - lws_sul_schedule(lws_get_context(w), 0, - &w->mqtt->sul_qos1_puback_wait, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&w->mqtt->sul_qos1_puback_wait); if (requested_close) { __lws_close_free_wsi(w, @@ -1745,8 +1743,9 @@ do_write: /* For QoS1, if no PUBACK coming after 3s, we must RETRY the publish */ wsi->mqtt->sul_qos1_puback_wait.cb = lws_mqtt_publish_resend; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->mqtt->sul_qos1_puback_wait, - 3 * LWS_USEC_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[wsi->conn_validity_wakesuspend], + &wsi->mqtt->sul_qos1_puback_wait, + 3 * LWS_USEC_PER_SEC); return 0; } diff --git a/lib/roles/mqtt/ops-mqtt.c b/lib/roles/mqtt/ops-mqtt.c index ad498021..22775ad3 100644 --- a/lib/roles/mqtt/ops-mqtt.c +++ b/lib/roles/mqtt/ops-mqtt.c @@ -422,8 +422,7 @@ rops_close_role_mqtt(struct lws_context_per_thread *pt, struct lws *wsi) c = &wsi->mqtt->client; - __lws_sul_insert(&pt->pt_sul_owner, &wsi->mqtt->sul_qos1_puback_wait, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&wsi->mqtt->sul_qos1_puback_wait); lws_mqtt_str_free(&c->username); lws_mqtt_str_free(&c->password); diff --git a/lib/roles/ws/server-ws.c b/lib/roles/ws/server-ws.c index 6fc4d140..15e7d09b 100644 --- a/lib/roles/ws/server-ws.c +++ b/lib/roles/ws/server-ws.c @@ -362,8 +362,7 @@ lws_process_ws_upgrade2(struct lws *wsi) * validity checking */ - __lws_sul_insert(&pt->pt_sul_owner, &wsi->sul_validity, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&wsi->sul_validity); } else #endif { diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index 730d6f8f..98e96bef 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -203,6 +203,14 @@ connection for retry + backoff The name of the trust store described in the `trust_stores` section to apply to validate the remote server cert. +### `swake_validity` + +Set to `true` if this streamtype is important enough for the functioning of the +device that its locally-initiated periodic connection validity checks of the +interval described in the associated retry / backoff selection, are important +enough to wake the whole system from low power suspend so they happen on +schedule. + ## http transport ### `http_method` diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 89170533..253d36ca 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -90,6 +90,7 @@ static const char * const lejp_tokens_policy[] = { "s[].*.mqtt_will_message", "s[].*.mqtt_will_qos", "s[].*.mqtt_will_retain", + "s[].*.swake_validity", "s[].*", }; @@ -155,6 +156,7 @@ typedef enum { LSSPPT_MQTT_WILL_MESSAGE, LSSPPT_MQTT_WILL_QOS, LSSPPT_MQTT_WILL_RETAIN, + LSSPPT_SWAKE_VALIDITY, LSSPPT_STREAMTYPES } policy_token_t; @@ -498,6 +500,11 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED; break; + case LSSPPT_SWAKE_VALIDITY: + if (reason == LEJPCB_VAL_TRUE) + a->curr[LTY_POLICY].p->flags |= + LWSSSPOLF_WAKE_SUSPEND__VALIDITY; + break; case LSSPPT_RETRYPTR: bot = a->heads[LTY_BACKOFF].b; diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index b75c5b87..42124bc7 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -231,8 +231,10 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->retry = 0; h->seqstate = SSSEQ_CONNECTED; - lws_ss_set_timeout_us(h, LWS_SET_TIMER_USEC_CANCEL); - lws_ss_event_helper(h, LWSSSCS_CONNECTED); + lws_sul_cancel(&h->sul); + if (lws_ss_event_helper(h, LWSSSCS_CONNECTED)) { + return -1; + } /* * Since it's an http transaction we initiated... this is diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 1c6d506b..e00ab679 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -72,7 +72,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->wsi = wsi; h->retry = 0; h->seqstate = SSSEQ_CONNECTED; - lws_ss_set_timeout_us(h, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&h->sul); lws_ss_event_helper(h, LWSSSCS_CONNECTED); if (h->policy->u.mqtt.topic) lws_callback_on_writable(wsi); diff --git a/lib/secure-streams/protocols/ss-raw.c b/lib/secure-streams/protocols/ss-raw.c index bad9c257..e37b6710 100644 --- a/lib/secure-streams/protocols/ss-raw.c +++ b/lib/secure-streams/protocols/ss-raw.c @@ -67,7 +67,7 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->retry = 0; h->seqstate = SSSEQ_CONNECTED; - lws_ss_set_timeout_us(h, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&h->sul); lws_ss_event_helper(h, LWSSSCS_CONNECTED); lws_validity_confirmed(wsi); diff --git a/lib/secure-streams/protocols/ss-ws.c b/lib/secure-streams/protocols/ss-ws.c index 086975cb..cdd19f94 100644 --- a/lib/secure-streams/protocols/ss-ws.c +++ b/lib/secure-streams/protocols/ss-ws.c @@ -67,8 +67,9 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_CLIENT_ESTABLISHED: h->retry = 0; h->seqstate = SSSEQ_CONNECTED; - lws_ss_set_timeout_us(h, LWS_SET_TIMER_USEC_CANCEL); - lws_ss_event_helper(h, LWSSSCS_CONNECTED); + lws_sul_cancel(&h->sul); + if (lws_ss_event_helper(h, LWSSSCS_CONNECTED)) + return -1; break; case LWS_CALLBACK_CLIENT_RECEIVE: diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index e9c849ec..ce207757 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -401,8 +401,7 @@ lws_sspc_destroy(lws_sspc_handle_t **ph) h->destroying = 1; - lws_sul_schedule(h->context, 0, &h->sul_retry, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&h->sul_retry); lws_dll2_remove(&h->client_list); if (h->dsh) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index f9b5fc1d..8424fe31 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -150,7 +150,9 @@ lws_ss_set_timeout_us(lws_ss_handle_t *h, lws_usec_t us) struct lws_context_per_thread *pt = &h->context->pt[h->tsi]; h->sul.cb = lws_ss_timeout_sul_check_cb; - __lws_sul_insert(&pt->pt_sul_owner, &h->sul, us); + __lws_sul_insert_us(&pt->pt_sul_owner[ + !!(h->policy->flags & LWSSSPOLF_WAKE_SUSPEND__VALIDITY)], + &h->sul, us); return 0; } @@ -273,6 +275,9 @@ lws_ss_client_connect(lws_ss_handle_t *h) } } + if (h->policy->flags & LWSSSPOLF_WAKE_SUSPEND__VALIDITY) + i.ssl_connection |= LCCSCF_WAKE_SUSPEND__VALIDITY; + i.address = ads; i.port = port; i.host = i.address; @@ -525,7 +530,7 @@ lws_ss_destroy(lws_ss_handle_t **ppss) pmd = pmd->next; } - lws_sul_schedule(h->context, 0, &h->sul, NULL, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&h->sul); lws_free_set_NULL(h); } diff --git a/lib/system/dhcpclient/dhcpclient.c b/lib/system/dhcpclient/dhcpclient.c index cf58b5b4..d10520a9 100644 --- a/lib/system/dhcpclient/dhcpclient.c +++ b/lib/system/dhcpclient/dhcpclient.c @@ -334,8 +334,7 @@ callback_dhcpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!r) break; r->wsi_raw = NULL; - lws_sul_schedule(r->context, 0, &r->sul_write, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&r->sul_write); if (r->state != LDHC_BOUND) { r->state = LDHC_INIT; lws_retry_sul_schedule(r->context, 0, &r->sul_conn, &bo2, @@ -553,10 +552,8 @@ broken: /* clear timeouts related to the broadcast socket */ - lws_sul_schedule(r->context, 0, &r->sul_write, NULL, - LWS_SET_TIMER_USEC_CANCEL); - lws_sul_schedule(r->context, 0, &r->sul_conn, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&r->sul_write); + lws_sul_cancel(&r->sul_conn); lwsl_notice("%s: DHCP configured %s\n", __func__, (const char *)&r[1]); @@ -650,8 +647,7 @@ retry_conn: #if 0 cancel_conn_timer: - lws_sul_schedule(r->context, 0, &r->sul_conn, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&r->sul_conn); return 0; #endif @@ -665,10 +661,8 @@ lws_dhcpc_destroy(lws_dhcpc_req_t **pr) { lws_dhcpc_req_t *r = *pr; - lws_sul_schedule(r->context, 0, &r->sul_conn, NULL, - LWS_SET_TIMER_USEC_CANCEL); - lws_sul_schedule(r->context, 0, &r->sul_write, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&r->sul_conn); + lws_sul_cancel(&r->sul_write); if (r->wsi_raw) lws_set_timeout(r->wsi_raw, 1, LWS_TO_KILL_ASYNC); diff --git a/lib/system/ntpclient/ntpclient.c b/lib/system/ntpclient/ntpclient.c index 8499cd5e..b56efe09 100644 --- a/lib/system/ntpclient/ntpclient.c +++ b/lib/system/ntpclient/ntpclient.c @@ -195,8 +195,7 @@ do_close: v->wsi_udp = NULL; /* cancel any pending write retry */ - lws_sul_schedule(v->context, 0, &v->sul_write, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&v->sul_write); if (v->set_time) goto cancel_conn_timer; @@ -280,8 +279,7 @@ retry_conn: cancel_conn_timer: - lws_sul_schedule(v->context, 0, &v->sul_conn, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&v->sul_conn); return 0; } diff --git a/lib/tls/tls-server.c b/lib/tls/tls-server.c index 9d4ecc99..c18f56a4 100644 --- a/lib/tls/tls-server.c +++ b/lib/tls/tls-server.c @@ -34,8 +34,9 @@ lws_sul_tls_cb(lws_sorted_usec_list_t *sul) lws_tls_check_all_cert_lifetimes(pt->context); - __lws_sul_insert(&pt->pt_sul_owner, &pt->sul_tls, - (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); + __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &pt->sul_tls, + (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); } int @@ -115,8 +116,9 @@ lws_context_init_server_ssl(const struct lws_context_creation_info *info, /* check certs once a day */ context->pt[0].sul_tls.cb = lws_sul_tls_cb; - __lws_sul_insert(&context->pt[0].pt_sul_owner, &context->pt[0].sul_tls, - (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); + __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], + &context->pt[0].sul_tls, + (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); return 0; } diff --git a/lwsws/main.c b/lwsws/main.c index 63a81983..d280f8de 100644 --- a/lwsws/main.c +++ b/lwsws/main.c @@ -335,7 +335,7 @@ int main(int argc, char **argv) } /* cancel the per-minute sul */ - lws_sul_schedule(context, 0, &sul_lwsws, NULL, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&sul_lwsws); lws_context_destroy(context); (void)budget; diff --git a/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c b/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c index 0e72c544..10e525c3 100644 --- a/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c +++ b/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c @@ -41,6 +41,8 @@ struct per_vhost_data__minimal { struct lws_vhost *vhost; const struct lws_protocols *protocol; + lws_sorted_usec_list_t sul; + struct per_session_data__minimal *pss_list; /* linked-list of live pss*/ struct lws_ring *ring; /* ringbuffer holding unsent messages */ @@ -60,9 +62,12 @@ __minimal_destroy_message(void *_msg) msg->len = 0; } -static int -connect_client(struct per_vhost_data__minimal *vhd) +static void +sul_connect_attempt(struct lws_sorted_usec_list *sul) { + struct per_vhost_data__minimal *vhd = + lws_container_of(sul, struct per_vhost_data__minimal, sul); + vhd->i.context = vhd->context; vhd->i.port = 443; vhd->i.address = "libwebsockets.org"; @@ -75,7 +80,9 @@ connect_client(struct per_vhost_data__minimal *vhd) vhd->i.local_protocol_name = "lws-minimal-proxy"; vhd->i.pwsi = &vhd->client_wsi; - return !lws_client_connect_via_info(&vhd->i); + if (!lws_client_connect_via_info(&vhd->i)) + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, 10 * LWS_US_PER_SEC); } static int @@ -109,14 +116,12 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, if (!vhd->ring) return 1; - if (connect_client(vhd)) - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, - LWS_CALLBACK_USER, 1); + sul_connect_attempt(&vhd->sul); break; case LWS_CALLBACK_PROTOCOL_DESTROY: lws_ring_destroy(vhd->ring); + lws_sul_cancel(&vhd->sul); break; /* --- serving callbacks --- */ @@ -169,8 +174,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); vhd->client_wsi = NULL; - lws_timed_callback_vh_protocol(vhd->vhost, vhd->protocol, - LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; case LWS_CALLBACK_CLIENT_ESTABLISHED: @@ -214,18 +219,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_CLOSED: vhd->client_wsi = NULL; - lws_timed_callback_vh_protocol(vhd->vhost, vhd->protocol, - LWS_CALLBACK_USER, 1); - break; - - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); - if (connect_client(vhd)) - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, - LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; default: diff --git a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt index c7443f5d..7b1872fe 100644 --- a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt +++ b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt @@ -1,4 +1,4 @@ -project(lws-minimal-dbus-ws-proxy-testclient) +project(lws-minimal-dbus-ws-proxy-testclient C) cmake_minimum_required(VERSION 2.8) find_package(libwebsockets CONFIG REQUIRED) list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) @@ -11,7 +11,7 @@ require_lws_config(LWS_ROLE_DBUS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) if (NOT MSVC AND NOT WIN32 AND requirements) - add_executable(${SAMP} ${SRCS}) + add_executable(${PROJECT_NAME} minimal-dbus-ws-proxy-testclient.c) if (NOT LWS_PLAT_FREERTOS) find_package(PkgConfig QUIET) @@ -21,11 +21,11 @@ if (NOT MSVC AND NOT WIN32 AND requirements) endif() include_directories("${LWS_DBUS_INCLUDE1}") - + message("project ${PROJECT_NAME}") if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) - add_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB}) + target_link_libraries(${PROJECT_NAME} websockets_shared) + add_dependencies(${PROJECT_NAME} websockets_shared ${LWS_DBUS_LIB}) else() - target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB}) + target_link_libraries(${PROJECT_NAME} websockets ${LWS_DBUS_LIB}) endif() endif() diff --git a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c index d2818fa7..c3d92ee0 100644 --- a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c +++ b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c @@ -43,6 +43,8 @@ enum lws_dbus_client_state { struct lws_dbus_ctx_wsproxy_client { struct lws_dbus_ctx ctx; + lws_sorted_usec_list_t sul; + enum lws_dbus_client_state state; }; @@ -309,83 +311,56 @@ bail: return ret; } -/* - * Stub lws protocol, just so we can get synchronous timers conveniently. - * - * Set up a 1Hz timer and if our connection state is suitable, use that - * to write mirror protocol drawing packets to the proxied ws connection - */ - -static int -callback_just_timer(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) +static void +sul_timer(struct lws_sorted_usec_list *sul) { char payload[64]; const char *ws_pkt = payload; DBusMessage *msg; - switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: - case LWS_CALLBACK_USER: - lwsl_info("%s: LWS_CALLBACK_USER\n", __func__); + if (!dbus_ctx || dbus_ctx->state != LDCS_CONN_ONWARD) + goto again; - if (!dbus_ctx || dbus_ctx->state != LDCS_CONN_ONWARD) - goto again; - - if (autoexit_budget > 0) { - if (!--autoexit_budget) { - lwsl_notice("reached autoexit budget\n"); - interrupted = 1; - break; - } + if (autoexit_budget > 0) { + if (!--autoexit_budget) { + lwsl_notice("reached autoexit budget\n"); + interrupted = 1; + return; } + } - msg = dbus_message_new_method_call(THIS_BUSNAME, THIS_OBJECT, - THIS_INTERFACE, "Send"); - if (!msg) - break; - - lws_snprintf(payload, sizeof(payload), "d #%06X %d %d %d %d;", - rand() & 0xffffff, rand() % 480, rand() % 300, - rand() % 480, rand() % 300); - - if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &ws_pkt, - DBUS_TYPE_INVALID)) { - dbus_message_unref(msg); - break; - } + msg = dbus_message_new_method_call(THIS_BUSNAME, THIS_OBJECT, + THIS_INTERFACE, "Send"); + if (!msg) + goto again; - if (!dbus_connection_send_with_reply(dbus_ctx->ctx.conn, msg, - &dbus_ctx->ctx.pc, - DBUS_TIMEOUT_USE_DEFAULT)) { - lwsl_err("%s: unable to send\n", __func__); - dbus_message_unref(msg); - break; - } + lws_snprintf(payload, sizeof(payload), "d #%06X %d %d %d %d;", + rand() & 0xffffff, rand() % 480, rand() % 300, + rand() % 480, rand() % 300); + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &ws_pkt, + DBUS_TYPE_INVALID)) { dbus_message_unref(msg); - dbus_pending_call_set_notify(dbus_ctx->ctx.pc, - pending_call_notify, - &dbus_ctx->ctx, NULL); - count_tx++; - -again: - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 2); - break; - default: - break; + goto again; } - return 0; -} + if (!dbus_connection_send_with_reply(dbus_ctx->ctx.conn, msg, + &dbus_ctx->ctx.pc, + DBUS_TIMEOUT_USE_DEFAULT)) { + lwsl_err("%s: unable to send\n", __func__); + dbus_message_unref(msg); + goto again; + } -static struct lws_protocols protocols[] = { - { "_just_timer", callback_just_timer, 0, 10, 0, NULL, 0 }, - { } -}; + dbus_message_unref(msg); + dbus_pending_call_set_notify(dbus_ctx->ctx.pc, + pending_call_notify, + &dbus_ctx->ctx, NULL); + count_tx++; +again: + lws_sul_schedule(context, 0, &dbus_ctx->sul, sul_timer, 2 * LWS_US_PER_SEC); +} int main(int argc, const char **argv) { @@ -413,7 +388,6 @@ int main(int argc, const char **argv) memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS; - info.protocols = protocols; context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); @@ -431,6 +405,9 @@ int main(int argc, const char **argv) if (!dbus_ctx) goto bail1; + lws_sul_schedule(context, 0, &dbus_ctx->sul, sul_timer, LWS_US_PER_SEC); + + if (remote_method_call(dbus_ctx)) goto bail2; diff --git a/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c b/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c index b16a0ce4..8e50610a 100644 --- a/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c +++ b/minimal-examples/http-client/minimal-http-client-h2-rxflow/minimal-http-client.c @@ -115,8 +115,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLOSED_CLIENT_HTTP: interrupted = 1; bad = status != 200; - lws_sul_schedule(lws_get_context(wsi), 0, &pss->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&pss->sul); lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ break; diff --git a/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c b/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c index b558dc96..148d4c78 100644 --- a/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c +++ b/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c @@ -79,8 +79,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_CLOSED_HTTP: if (!pss) break; - lws_sul_schedule(lws_get_context(wsi), 0, &pss->sul, sul_cb, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&pss->sul); break; case LWS_CALLBACK_HTTP_WRITEABLE: diff --git a/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c b/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c index 1ee11a86..f4e9d03d 100644 --- a/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c +++ b/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c @@ -153,7 +153,7 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_RAW_CLOSE_FILE: lwsl_notice("LWS_CALLBACK_RAW_CLOSE_FILE\n"); - lws_sul_schedule(lws_get_context(wsi), 0, &vhd->sul, sul_cb, LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&vhd->sul); break; case LWS_CALLBACK_RAW_WRITEABLE_FILE: diff --git a/minimal-examples/secure-streams/minimal-secure-streams-alexa/alexa.c b/minimal-examples/secure-streams/minimal-secure-streams-alexa/alexa.c index ba1fa7e2..fb70f27d 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-alexa/alexa.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-alexa/alexa.c @@ -234,8 +234,7 @@ drain_end_cb(void *v) /* * Put a hold on bringing in any more data */ - lws_sul_schedule(context, 0, &m->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); #endif /* destroy our copy of the handle */ m->mh = NULL; @@ -391,8 +390,7 @@ ss_avs_metadata_rx(void *userobj, const uint8_t *buf, size_t len, int flags) /* * Put a hold on bringing in any more data */ - lws_sul_schedule(context, 0, &m->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); #endif /* destroy our copy of the handle */ m->mh = NULL; @@ -549,8 +547,7 @@ ss_avs_metadata_state(void *userobj, void *sh, lws_ss_request_tx(m->ss); break; case LWSSSCS_DISCONNECTED: - lws_sul_schedule(context, 0, &m->sul, NULL, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); //if (m->mh) { play_mp3(NULL, NULL, NULL); m->mh = NULL; diff --git a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c index ea8f97e2..0121d678 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-avs/avs.c @@ -223,7 +223,7 @@ ss_avs_metadata_state(void *userobj, void *sh, { ss_avs_metadata_t *m = (ss_avs_metadata_t *)userobj; - struct lws_context *context = (struct lws_context *)m->opaque_data; + // struct lws_context *context = (struct lws_context *)m->opaque_data; lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), (unsigned int)ack); @@ -243,13 +243,11 @@ ss_avs_metadata_state(void *userobj, void *sh, /* for this demo app, we want to exit on fail to connect */ case LWSSSCS_DISCONNECTED: /* for this demo app, we want to exit after complete flow */ - lws_sul_schedule(context, 0, &m->sul, use_buffer_50ms, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); interrupted = 1; break; case LWSSSCS_DESTROYING: - lws_sul_schedule(context, 0, &m->sul, use_buffer_50ms, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); break; default: break; diff --git a/minimal-examples/secure-streams/minimal-secure-streams-client-tx/minimal-secure-streams-client-tx.c b/minimal-examples/secure-streams/minimal-secure-streams-client-tx/minimal-secure-streams-client-tx.c index 0eee1e91..0e5e836a 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-client-tx/minimal-secure-streams-client-tx.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-client-tx/minimal-secure-streams-client-tx.c @@ -112,8 +112,7 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, lws_sul_schedule(context, 0, &m->sul, txcb, RATE_US); break; case LWSSSCS_DISCONNECTED: - lws_sul_schedule(context, 0, &m->sul, txcb, - LWS_SET_TIMER_USEC_CANCEL); + lws_sul_cancel(&m->sul); break; case LWSSSCS_ALL_RETRIES_FAILED: /* if we're out of retries, we want to close the app and FAIL */ diff --git a/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c b/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c index 3e895902..2e34b778 100644 --- a/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c +++ b/minimal-examples/ws-client/minimal-ws-client-echo/protocol_lws_minimal_client_echo.c @@ -43,6 +43,8 @@ struct vhd_minimal_client_echo { struct lws_vhost *vhost; struct lws *client_wsi; + lws_sorted_usec_list_t sul; + int *interrupted; int *options; const char **url; @@ -51,9 +53,11 @@ struct vhd_minimal_client_echo { int *port; }; -static int -connect_client(struct vhd_minimal_client_echo *vhd) +static void +sul_connect_attempt(struct lws_sorted_usec_list *sul) { + struct vhd_minimal_client_echo *vhd = + lws_container_of(sul, struct vhd_minimal_client_echo, sul); struct lws_client_connect_info i; char host[128]; @@ -77,7 +81,9 @@ connect_client(struct vhd_minimal_client_echo *vhd) lwsl_user("connecting to %s:%d/%s\n", i.address, i.port, i.path); - return !lws_client_connect_via_info(&i); + if (!lws_client_connect_via_info(&i)) + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, 10 * LWS_US_PER_SEC); } static void @@ -90,13 +96,6 @@ __minimal_destroy_message(void *_msg) msg->len = 0; } -static void -schedule_callback(struct lws *wsi, int reason, int secs) -{ - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), reason, secs); -} - static int callback_minimal_client_echo(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -142,8 +141,11 @@ callback_minimal_client_echo(struct lws *wsi, enum lws_callback_reasons reason, (const struct lws_protocol_vhost_options *)in, "iface")->value; - if (connect_client(vhd)) - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + sul_connect_attempt(&vhd->sul); + break; + + case LWS_CALLBACK_PROTOCOL_DESTROY: + lws_sul_cancel(&vhd->sul); break; case LWS_CALLBACK_CLIENT_ESTABLISHED: @@ -250,32 +252,18 @@ callback_minimal_client_echo(struct lws *wsi, enum lws_callback_reasons reason, lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); vhd->client_wsi = NULL; - //schedule_callback(wsi, LWS_CALLBACK_USER, 1); - //if (*vhd->options & 1) { - if (!*vhd->interrupted) - *vhd->interrupted = 3; - lws_cancel_service(lws_get_context(wsi)); - //} + if (!*vhd->interrupted) + *vhd->interrupted = 3; + lws_cancel_service(lws_get_context(wsi)); break; case LWS_CALLBACK_CLIENT_CLOSED: lwsl_user("LWS_CALLBACK_CLIENT_CLOSED\n"); lws_ring_destroy(pss->ring); vhd->client_wsi = NULL; - // schedule_callback(wsi, LWS_CALLBACK_USER, 1); - //if (*vhd->options & 1) { - if (!*vhd->interrupted) - *vhd->interrupted = 1 + pss->completed; - lws_cancel_service(lws_get_context(wsi)); - // } - break; - - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); - if (connect_client(vhd)) - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + if (!*vhd->interrupted) + *vhd->interrupted = 1 + pss->completed; + lws_cancel_service(lws_get_context(wsi)); break; default: diff --git a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c index 33e224bb..5212c0fd 100644 --- a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c +++ b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/protocol_lws_minimal_pmd_bulk.c @@ -65,6 +65,8 @@ struct vhd_minimal_pmd_bulk { struct lws_vhost *vhost; struct lws *client_wsi; + lws_sorted_usec_list_t sul; + int *interrupted; int *options; }; @@ -78,9 +80,11 @@ static uint64_t rng(uint64_t *r) return *r; } -static int -connect_client(struct vhd_minimal_pmd_bulk *vhd) +static void +sul_connect_attempt(struct lws_sorted_usec_list *sul) { + struct vhd_minimal_pmd_bulk *vhd = + lws_container_of(sul, struct vhd_minimal_pmd_bulk, sul); struct lws_client_connect_info i; memset(&i, 0, sizeof(i)); @@ -96,14 +100,9 @@ connect_client(struct vhd_minimal_pmd_bulk *vhd) i.protocol = "lws-minimal-pmd-bulk"; i.pwsi = &vhd->client_wsi; - return !lws_client_connect_via_info(&i); -} - -static void -schedule_callback(struct lws *wsi, int reason, int secs) -{ - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), reason, secs); + if (!lws_client_connect_via_info(&i)) + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, 10 * LWS_US_PER_SEC); } static int @@ -138,8 +137,11 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, (const struct lws_protocol_vhost_options *)in, "options")->value; - if (connect_client(vhd)) - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + sul_connect_attempt(&vhd->sul); + break; + + case LWS_CALLBACK_PROTOCOL_DESTROY: + lws_sul_cancel(&vhd->sul); break; case LWS_CALLBACK_CLIENT_ESTABLISHED: @@ -253,20 +255,14 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason, lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); vhd->client_wsi = NULL; - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; case LWS_CALLBACK_CLIENT_CLOSED: vhd->client_wsi = NULL; - schedule_callback(wsi, LWS_CALLBACK_USER, 1); - break; - - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); - if (connect_client(vhd)) - schedule_callback(wsi, LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; default: diff --git a/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c b/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c index c83e23e9..2e78a19e 100644 --- a/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c +++ b/minimal-examples/ws-client/minimal-ws-client-tx/minimal-ws-client.c @@ -44,6 +44,8 @@ struct per_vhost_data__minimal { const struct lws_protocols *protocol; pthread_t pthread_spam[2]; + lws_sorted_usec_list_t sul; + pthread_mutex_t lock_ring; /* serialize access to the ring buffer */ struct lws_ring *ring; /* ringbuffer holding unsent messages */ uint32_t tail; @@ -130,9 +132,12 @@ wait: return NULL; } -static int -connect_client(struct per_vhost_data__minimal *vhd) +static void +sul_connect_attempt(struct lws_sorted_usec_list *sul) { + struct per_vhost_data__minimal *vhd = + lws_container_of(sul, struct per_vhost_data__minimal, sul); + vhd->i.context = vhd->context; vhd->i.port = 7681; vhd->i.address = "localhost"; @@ -144,7 +149,9 @@ connect_client(struct per_vhost_data__minimal *vhd) vhd->i.protocol = "lws-minimal-broker"; vhd->i.pwsi = &vhd->client_wsi; - return !lws_client_connect_via_info(&vhd->i); + if (!lws_client_connect_via_info(&vhd->i)) + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, 10 * LWS_US_PER_SEC); } static int @@ -188,9 +195,7 @@ callback_minimal_broker(struct lws *wsi, enum lws_callback_reasons reason, goto init_fail; } - if (connect_client(vhd)) - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, LWS_CALLBACK_USER, 1); + sul_connect_attempt(&vhd->sul); break; case LWS_CALLBACK_PROTOCOL_DESTROY: @@ -202,6 +207,7 @@ init_fail: if (vhd->ring) lws_ring_destroy(vhd->ring); + lws_sul_cancel(&vhd->sul); pthread_mutex_destroy(&vhd->lock_ring); return r; @@ -210,8 +216,8 @@ init_fail: lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)"); vhd->client_wsi = NULL; - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; /* --- client callbacks --- */ @@ -250,8 +256,8 @@ skip: case LWS_CALLBACK_CLIENT_CLOSED: vhd->client_wsi = NULL; vhd->established = 0; - lws_timed_callback_vh_protocol(vhd->vhost, vhd->protocol, - LWS_CALLBACK_USER, 1); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_connect_attempt, LWS_US_PER_SEC); break; case LWS_CALLBACK_EVENT_WAIT_CANCELLED: @@ -267,16 +273,6 @@ skip: lws_callback_on_writable(vhd->client_wsi); break; - /* rate-limited client connect retries */ - - case LWS_CALLBACK_USER: - lwsl_notice("%s: LWS_CALLBACK_USER\n", __func__); - if (connect_client(vhd)) - lws_timed_callback_vh_protocol(vhd->vhost, - vhd->protocol, - LWS_CALLBACK_USER, 1); - break; - default: break; } diff --git a/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c b/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c index 5fd7d873..ba8c2278 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c +++ b/minimal-examples/ws-server/minimal-ws-server-threadpool/protocol_lws_minimal_threadpool.c @@ -34,6 +34,8 @@ struct per_vhost_data__minimal { struct lws_threadpool *tp; + struct lws_context *context; + lws_sorted_usec_list_t sul; const char *config; }; @@ -133,6 +135,22 @@ task_function(void *user, enum lws_threadpool_task_status s) return LWS_TP_RETURN_CHECKING_IN; } + +static void +sul_tp_dump(struct lws_sorted_usec_list *sul) +{ + struct per_vhost_data__minimal *vhd = + lws_container_of(sul, struct per_vhost_data__minimal, sul); + /* + * in debug mode, dump the threadpool stat to the logs once + * a second + */ + lws_threadpool_dump(vhd->tp); + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_tp_dump, LWS_US_PER_SEC); +} + + static int callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -159,6 +177,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, if (!vhd) return 1; + vhd->context = lws_get_context(wsi); + /* recover the pointer to the globals struct */ pvo = lws_pvo_search( (const struct lws_protocol_vhost_options *)in, @@ -179,27 +199,14 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, if (!vhd->tp) return 1; - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); - + lws_sul_schedule(vhd->context, 0, &vhd->sul, + sul_tp_dump, LWS_US_PER_SEC); break; case LWS_CALLBACK_PROTOCOL_DESTROY: lws_threadpool_finish(vhd->tp); lws_threadpool_destroy(vhd->tp); - break; - - case LWS_CALLBACK_USER: - - /* - * in debug mode, dump the threadpool stat to the logs once - * a second - */ - lws_threadpool_dump(vhd->tp); - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); + lws_sul_cancel(&vhd->sul); break; case LWS_CALLBACK_ESTABLISHED: diff --git a/plugins/protocol_lws_server_status.c b/plugins/protocol_lws_server_status.c index d53e857a..3bb57b00 100644 --- a/plugins/protocol_lws_server_status.c +++ b/plugins/protocol_lws_server_status.c @@ -47,6 +47,7 @@ struct vhd { struct lws_context *context; struct lws_vhost *vhost; const struct lws_protocols *protocol; + lws_sorted_usec_list_t sul; int hide_vhosts; int tow_flag; int period_s; @@ -58,8 +59,9 @@ struct vhd { static const struct lws_protocols protocols[1]; static void -update(struct vhd *v) +update(struct lws_sorted_usec_list *sul) { + struct vhd *v = lws_container_of(sul, struct vhd, sul); struct lws_ss_filepath *fp; char contents[256], pure[256], *p = v->d.buf + LWS_PRE, *end = v->d.buf + sizeof(v->d.buf) - LWS_PRE - 1; @@ -97,6 +99,8 @@ update(struct vhd *v) v->d.length = p - (v->d.buf + LWS_PRE); lws_callback_on_writable_all_protocol(v->context, &protocols[0]); + + lws_sul_schedule(v->context, 0, &v->sul, update, v->period_s * LWS_US_PER_SEC); } static int @@ -116,12 +120,9 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_ESTABLISHED: lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__); if (!v->clients++) { - lws_timed_callback_vh_protocol(v->vhost, v->protocol, - LWS_CALLBACK_USER, v->period_s); + lws_sul_schedule(lws_get_context(wsi), 0, &v->sul, update, 1); lwsl_info("%s: starting updates\n", __func__); } - update(v); - break; case LWS_CALLBACK_CLOSED: @@ -130,13 +131,6 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason, break; - case LWS_CALLBACK_USER: - update(v); - if (v->clients) - lws_timed_callback_vh_protocol(v->vhost, v->protocol, - LWS_CALLBACK_USER, v->period_s); - break; - case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ if (v) break; @@ -171,8 +165,7 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason, v->vhost = lws_get_vhost(wsi); v->protocol = lws_get_protocol(wsi); - /* get the initial data */ - update(v); + lws_sul_schedule(lws_get_context(wsi), 0, &v->sul, update, 1); break; case LWS_CALLBACK_PROTOCOL_DESTROY: /* per vhost */ -- Gitee From ca3380fd56bfd0abf58c512f753f32c17a1c3c99 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 31 May 2020 15:02:23 +0100 Subject: [PATCH 0148/1062] deprecation: remove lws_dll1 lws_dll2 has been available for a couple of years and lws_dll1 marked as deprecated since v3.2. Remove it. If it affects you, lws_dll2 has an almost identical api but has more features, such as storing in the lws_dll2_t which owner it is listed by and keeping a count of objects on the list at the owner object. --- include/libwebsockets/lws-dll2.h | 58 -------- lib/core/CMakeLists.txt | 5 - lib/core/lws_dll.c | 248 ------------------------------- 3 files changed, 311 deletions(-) delete mode 100644 lib/core/lws_dll.c diff --git a/include/libwebsockets/lws-dll2.h b/include/libwebsockets/lws-dll2.h index 86561762..367c887d 100644 --- a/include/libwebsockets/lws-dll2.h +++ b/include/libwebsockets/lws-dll2.h @@ -173,64 +173,6 @@ * doubly linked-list */ -#if defined (LWS_WITH_DEPRECATED_LWS_DLL) - -/* - * This is going away in v4.1. You can set the cmake option above to keep it - * around temporarily. Migrate your stuff to the more capable and robust - * lws_dll2 below - */ - -struct lws_dll { - struct lws_dll *prev; - struct lws_dll *next; -}; - -/* - * these all point to the composed list objects... you have to use the - * lws_container_of() helper to recover the start of the containing struct - */ - -#define lws_dll_add_front lws_dll_add_head - -LWS_VISIBLE LWS_EXTERN void -lws_dll_add_head(struct lws_dll *d, struct lws_dll *phead); - -LWS_VISIBLE LWS_EXTERN void -lws_dll_add_tail(struct lws_dll *d, struct lws_dll *phead); - -LWS_VISIBLE LWS_EXTERN void -lws_dll_insert(struct lws_dll *d, struct lws_dll *target, - struct lws_dll *phead, int before); - -static LWS_INLINE struct lws_dll * -lws_dll_get_head(struct lws_dll *phead) { return phead->next; } - -static LWS_INLINE struct lws_dll * -lws_dll_get_tail(struct lws_dll *phead) { return phead->prev; } - -/* - * caution, this doesn't track the tail in the head struct. Use - * lws_dll_remove_track_tail() instead of this if you want tail tracking. Using - * this means you can't use lws_dll_add_tail() amd - */ -LWS_VISIBLE LWS_EXTERN void -lws_dll_remove(struct lws_dll *d) LWS_WARN_DEPRECATED; - -LWS_VISIBLE LWS_EXTERN void -lws_dll_remove_track_tail(struct lws_dll *d, struct lws_dll *phead); - -/* another way to do lws_start_foreach_dll_safe() on a list via a cb */ - -LWS_VISIBLE LWS_EXTERN int -lws_dll_foreach_safe(struct lws_dll *phead, void *user, - int (*cb)(struct lws_dll *d, void *user)); - -#define lws_dll_is_detached(___dll, __head) \ - (!(___dll)->prev && !(___dll)->next && (__head)->prev != (___dll)) - -#endif - /* * lws_dll2_owner / lws_dll2 : more capable version of lws_dll. Differences: * diff --git a/lib/core/CMakeLists.txt b/lib/core/CMakeLists.txt index 6b128ffe..75bec6c3 100644 --- a/lib/core/CMakeLists.txt +++ b/lib/core/CMakeLists.txt @@ -37,10 +37,5 @@ if (LWS_WITH_FILE_OPS) list(APPEND SOURCES core/vfs.c) endif() -if (LWS_WITH_DEPRECATED_LWS_DLL) - list(APPEND SOURCES - core/lws_dll.c) -endif() - exports_to_parent_scope() diff --git a/lib/core/lws_dll.c b/lib/core/lws_dll.c deleted file mode 100644 index 09c3ec82..00000000 --- a/lib/core/lws_dll.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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 "private-lib-core.h" - -#ifdef LWS_HAVE_SYS_TYPES_H -#include -#endif - -void -lws_dll_add_head(struct lws_dll *d, struct lws_dll *phead) -{ - if (!lws_dll_is_detached(d, phead)) { - assert(0); /* only wholly detached things can be added */ - return; - } - - /* our next guy is current first guy, if any */ - if (phead->next != d) - d->next = phead->next; - - /* if there is a next guy, set his prev ptr to our next ptr */ - if (d->next) - d->next->prev = d; - /* there is nobody previous to us, we are the head */ - d->prev = NULL; - - /* set the first guy to be us */ - phead->next = d; - - /* if there was nothing on the list before, we are also now the tail */ - if (!phead->prev) - phead->prev = d; - - assert(d->prev != d); - assert(d->next != d); -} - -void -lws_dll_add_tail(struct lws_dll *d, struct lws_dll *phead) -{ - if (!lws_dll_is_detached(d, phead)) { - assert(0); /* only wholly detached things can be added */ - return; - } - - /* our previous guy is current last guy */ - d->prev = phead->prev; - /* if there is a prev guy, set his next ptr to our prev ptr */ - if (d->prev) - d->prev->next = d; - /* our next ptr is NULL */ - d->next = NULL; - /* set the last guy to be us */ - phead->prev = d; - - /* list head is also us if we're the first */ - if (!phead->next) - phead->next = d; - - assert(d->prev != d); - assert(d->next != d); -} - -void -lws_dll_insert(struct lws_dll *n, struct lws_dll *target, - struct lws_dll *phead, int before) -{ - if (!lws_dll_is_detached(n, phead)) { - assert(0); /* only wholly detached things can be inserted */ - return; - } - if (!target) { - /* - * the case where there's no target identified degenerates to - * a simple add at head or tail - */ - if (before) { - lws_dll_add_head(n, phead); - return; - } - lws_dll_add_tail(n, phead); - return; - } - - /* - * in the case there's a target "cursor", we have to do the work to - * stitch the new guy in appropriately - */ - - if (before) { - /* - * we go before dd - * DDp <-> DD <-> DDn --> DDp <-> us <-> DD <-> DDn - */ - /* we point forward to dd */ - n->next = target; - /* we point back to what dd used to point back to */ - n->prev = target->prev; - /* DDp points forward to us now */ - if (target->prev) - target->prev->next = n; - /* DD points back to us now */ - target->prev = n; - - /* if target was the head, we are now the head */ - if (phead->next == target) - phead->next = n; - - /* since we are before another guy, we cannot become the tail */ - - } else { - /* - * we go after dd - * DDp <-> DD <-> DDn --> DDp <-> DD <-> us <-> DDn - */ - /* we point forward to what dd used to point forward to */ - n->next = target->next; - /* we point back to dd */ - n->prev = target; - /* DDn points back to us */ - if (target->next) - target->next->prev = n; - /* DD points forward to us */ - target->next = n; - - /* if target was the tail, we are now the tail */ - if (phead->prev == target) - phead->prev = n; - - /* since we go after another guy, we cannot become the head */ - } -} - -/* situation is: - * - * HEAD: struct lws_dll * = &entry1 - * - * Entry 1: struct lws_dll .pprev = &HEAD , .next = Entry 2 - * Entry 2: struct lws_dll .pprev = &entry1 , .next = &entry2 - * Entry 3: struct lws_dll .pprev = &entry2 , .next = NULL - * - * Delete Entry1: - * - * - HEAD = &entry2 - * - Entry2: .pprev = &HEAD, .next = &entry3 - * - Entry3: .pprev = &entry2, .next = NULL - * - * Delete Entry2: - * - * - HEAD = &entry1 - * - Entry1: .pprev = &HEAD, .next = &entry3 - * - Entry3: .pprev = &entry1, .next = NULL - * - * Delete Entry3: - * - * - HEAD = &entry1 - * - Entry1: .pprev = &HEAD, .next = &entry2 - * - Entry2: .pprev = &entry1, .next = NULL - * - */ - -void -lws_dll_remove(struct lws_dll *d) -{ - if (!d->prev && !d->next) - return; - - /* - * remove us - * - * USp <-> us <-> USn --> USp <-> USn - */ - - /* if we have a next guy, set his prev to our prev */ - if (d->next) - d->next->prev = d->prev; - - /* set our prev guy to our next guy instead of us */ - if (d->prev) - d->prev->next = d->next; - - /* we're out of the list, we should not point anywhere any more */ - d->prev = NULL; - d->next = NULL; -} - -void -lws_dll_remove_track_tail(struct lws_dll *d, struct lws_dll *phead) -{ - if (lws_dll_is_detached(d, phead)) { - assert(phead->prev != d); - assert(phead->next != d); - return; - } - - /* if we have a next guy, set his prev to our prev */ - if (d->next) - d->next->prev = d->prev; - - /* if we have a previous guy, set his next to our next */ - if (d->prev) - d->prev->next = d->next; - - if (phead->prev == d) - phead->prev = d->prev; - - if (phead->next == d) - phead->next = d->next; - - /* we're out of the list, we should not point anywhere any more */ - d->prev = NULL; - d->next = NULL; -} - - -int -lws_dll_foreach_safe(struct lws_dll *phead, void *user, - int (*cb)(struct lws_dll *d, void *user)) -{ - lws_start_foreach_dll_safe(struct lws_dll *, p, tp, phead->next) { - if (cb(p, user)) - return 1; - } lws_end_foreach_dll_safe(p, tp); - - return 0; -} -- Gitee From e4ab18342a7aed1c187548fab4189cea5f94ee2e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 1 Jun 2020 07:17:48 +0100 Subject: [PATCH 0149/1062] ss: allow NULL cbs Some streamtypes do not pass or receive payload meaningfully. Allow them to just leave their related cb NULL. Ditto for state, although I'm not sure how useful such a streamtype can be. --- lib/secure-streams/protocols/ss-h1.c | 4 ++-- lib/secure-streams/protocols/ss-mqtt.c | 4 ++-- lib/secure-streams/protocols/ss-raw.c | 4 ++-- lib/secure-streams/protocols/ss-ws.c | 4 ++-- lib/secure-streams/secure-streams.c | 8 ++++++-- .../captive-portal-detect.c | 17 ----------------- 6 files changed, 14 insertions(+), 27 deletions(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 42124bc7..2332b698 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -401,7 +401,7 @@ malformed: case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: lwsl_debug("%s: RECEIVE_CLIENT_HTTP_READ: read %d\n", __func__, (int)len); - if (!h) + if (!h || !h->info.rx) return 0; #if defined(LWS_WITH_SS_RIDESHARE) @@ -456,7 +456,7 @@ malformed: case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: lwsl_info("%s: LWS_CALLBACK_CLIENT_HTTP_WRITEABLE\n", __func__); - if (!h) + if (!h || !h->info.tx) return 0; if (!h->rideshare) diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index e00ab679..388f6d62 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -80,7 +80,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_MQTT_CLIENT_RX: // lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE: read %d\n", (int)len); - if (!h) + if (!h || !h->info.rx) return 0; pmqpp = (lws_mqtt_publish_param_t *)in; @@ -109,7 +109,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; case LWS_CALLBACK_MQTT_CLIENT_WRITEABLE: - if (!h) + if (!h || !h->info.tx) return 0; lwsl_notice("%s: ss %p: WRITEABLE\n", __func__, h); diff --git a/lib/secure-streams/protocols/ss-raw.c b/lib/secure-streams/protocols/ss-raw.c index e37b6710..88c9bf98 100644 --- a/lib/secure-streams/protocols/ss-raw.c +++ b/lib/secure-streams/protocols/ss-raw.c @@ -75,7 +75,7 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, /* chunks of chunked content, with header removed */ case LWS_CALLBACK_RAW_RX: - if (!h) + if (!h || !h->info.rx) return 0; if (h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, 0) < 0) @@ -85,7 +85,7 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_RAW_WRITEABLE: lwsl_info("%s: RAW_WRITEABLE\n", __func__); - if (!h) + if (!h || !h->info.tx) return 0; buflen = lws_ptr_diff(end, p); diff --git a/lib/secure-streams/protocols/ss-ws.c b/lib/secure-streams/protocols/ss-ws.c index cdd19f94..ba78f783 100644 --- a/lib/secure-streams/protocols/ss-ws.c +++ b/lib/secure-streams/protocols/ss-ws.c @@ -74,7 +74,7 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_CLIENT_RECEIVE: // lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE: read %d\n", (int)len); - if (!h) + if (!h || !h->info.rx) return 0; if (lws_is_first_fragment(wsi)) f |= LWSSS_FLAG_SOM; @@ -90,7 +90,7 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, return 0; /* don't passthru */ case LWS_CALLBACK_CLIENT_WRITEABLE: - if (!h) + if (!h || !h->info.tx) return 0; // lwsl_notice("%s: ss %p: WRITEABLE\n", __func__, h); diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 8424fe31..12768a3f 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -90,10 +90,14 @@ lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) (void *)h, NULL); #endif - if (h->h_sink &&h->h_sink->info.state(h->sink_obj, h->h_sink, cs, 0)) + if (h->h_sink && h->h_sink->info.state && + h->h_sink->info.state(h->sink_obj, h->h_sink, cs, 0)) return 1; - return h->info.state(ss_to_userobj(h), NULL, cs, 0); + if (h->info.state) + return h->info.state(ss_to_userobj(h), NULL, cs, 0); + + return 0; } static void diff --git a/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c b/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c index 82b74949..02427e39 100644 --- a/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c +++ b/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c @@ -36,21 +36,6 @@ typedef struct ss_cpd { uint8_t partway; } ss_cpd_t; -/* secure streams payload interface */ - -static int -ss_cpd_rx(void *userobj, const uint8_t *buf, size_t len, int flags) -{ - return 0; -} - -static int -ss_cpd_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, - size_t *len, int *flags) -{ - return 1; -} - static int ss_cpd_state(void *userobj, void *sh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack) @@ -95,8 +80,6 @@ lws_ss_sys_cpd(struct lws_context *cx) memset(&ssi, 0, sizeof(ssi)); ssi.handle_offset = offsetof(ss_cpd_t, ss); ssi.opaque_user_data_offset = offsetof(ss_cpd_t, opaque_data); - ssi.rx = ss_cpd_rx; - ssi.tx = ss_cpd_tx; ssi.state = ss_cpd_state; ssi.user_alloc = sizeof(ss_cpd_t); ssi.streamtype = "captive_portal_detect"; -- Gitee From 698eda63d7e72d0c0387ec8e6711f68dcd4173ab Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 1 Jun 2020 07:33:37 +0100 Subject: [PATCH 0150/1062] ss: formalize user cb retcodes It's not safe to destroy objects inside a callback from a parent that still has references to the object. Formalize what the user code can indicate by its return code from the callback functions and provide the implementations at the parents. - LWSSSSRET_OK: no action, OK - LWSSSSRET_DISCONNECT_ME: disconnect the underlying connection - LWSSSSRET_DESTROY_ME: destroy the ss object - LWSSSSRET_TX_DONT_SEND: for tx, give up the tx opportunity since nothing to send --- include/libwebsockets/lws-secure-streams.h | 12 +++++ lib/secure-streams/policy-common.c | 23 ++++++++ lib/secure-streams/protocols/ss-h1.c | 44 +++++++++++----- lib/secure-streams/protocols/ss-mqtt.c | 26 +++++++--- lib/secure-streams/protocols/ss-raw.c | 22 +++++--- lib/secure-streams/protocols/ss-ws.c | 31 +++++++---- lib/secure-streams/secure-streams.c | 52 ++++++++++++++++--- .../captive-portal-detect.c | 6 +-- .../system/fetch-policy/fetch-policy.c | 2 + .../minimal-secure-streams/CMakeLists.txt | 8 +++ 10 files changed, 178 insertions(+), 48 deletions(-) diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index eafdb136..66f0818e 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -232,6 +232,18 @@ typedef enum { } lws_ss_conn_states_t; +/* + * Returns from state() callback can tell the caller what the user code + * wants to do + */ + +enum lws_ss_state_return_t { + LWSSSSRET_TX_DONT_SEND = 1, /* (*tx) only */ + LWSSSSRET_OK = 0, + LWSSSSRET_DISCONNECT_ME = -1, + LWSSSSRET_DESTROY_ME = -2, +}; + /** * lws_ss_info_t: information about stream to be created * diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index 6f83ca0b..6a0d94d5 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -101,6 +101,16 @@ lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index) return NULL; } +static int +fe_lws_ss_destroy(struct lws_dll2 *d, void *user) +{ + lws_ss_handle_t *h = lws_container_of(d, lws_ss_handle_t, list); + + lws_ss_destroy(&h); + + return 0; +} + int lws_ss_policy_set(struct lws_context *context, const char *name) { @@ -123,6 +133,19 @@ lws_ss_policy_set(struct lws_context *context, const char *name) lejp_destruct(&args->jctx); if (context->ac_policy) { + int n; + + /* + * any existing ss created with the old policy have to go away + * now, since they point to the shortly-to-be-destroyed old + * policy + */ + + for (n = 0; n < context->count_threads; n++) { + struct lws_context_per_thread *pt = &context->pt[n]; + + lws_dll2_foreach_safe(&pt->ss_owner, NULL, fe_lws_ss_destroy); + } /* * So this is a bit fun-filled, we already had a policy in diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 2332b698..50aca2ab 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -166,7 +166,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], *end = &buf[sizeof(buf) - 1]; - int f = 0, m, status, txr; + int f = 0, m, status; char conceal_eom = 0; size_t buflen; @@ -177,7 +177,12 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, assert(h->policy); lwsl_info("%s: h: %p, %s CLIENT_CONNECTION_ERROR: %s\n", __func__, h, h->policy->streamtype, in ? (char *)in : "(null)"); - lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + /* already disconnected, no action for DISCONNECT_ME */ + if (lws_ss_event_helper(h, LWSSSCS_UNREACHABLE) == + LWSSSSRET_DESTROY_ME) { + lws_ss_destroy(&h); + break; + } h->wsi = NULL; lws_ss_backoff(h); break; @@ -201,7 +206,9 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && !h->txn_ok && !wsi->context->being_destroyed) lws_ss_backoff(h); - if (lws_ss_event_helper(h, LWSSSCS_DISCONNECTED)) + /* already disconnected, no action for DISCONNECT_ME */ + if (lws_ss_event_helper(h, LWSSSCS_DISCONNECTED) == + LWSSSSRET_DESTROY_ME) lws_ss_destroy(&h); break; @@ -443,13 +450,16 @@ malformed: wsi->http.writeable_len = h->writeable_len = 0; - if (h->u.http.good_respcode) - lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE); - else - lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE); + if (h->u.http.good_respcode) { + if (lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE)) + break; + } else + if (lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE)) + break; h->wsi = NULL; h->txn_ok = 1; + //bad = status != 200; lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ break; @@ -476,15 +486,23 @@ malformed: #endif - txr = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f); - if (txr < 0) { - lwsl_debug("%s: tx handler asked to close\n", __func__); - return -1; - } - if (txr > 0) { + switch(h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f)) { + case LWSSSSRET_DISCONNECT_ME: + lwsl_debug("%s: tx handler asked to close conn\n", __func__); + return -1; /* close connection */ + + case LWSSSSRET_DESTROY_ME: + lws_set_opaque_user_data(wsi, NULL); + h->wsi = NULL; + lws_ss_destroy(&h); + return -1; /* close connection */ + + case LWSSSSRET_TX_DONT_SEND: /* don't want to send anything */ lwsl_debug("%s: dont want to write\n", __func__); return 0; + default: + break; } lwsl_info("%s: WRITEABLE: user tx says len %d fl 0x%x\n", diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 388f6d62..59d5495e 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -31,8 +31,8 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); lws_mqtt_publish_param_t mqpp, *pmqpp; uint8_t buf[LWS_PRE + 1400]; - int f = 0, txr; size_t buflen; + int f = 0; switch (reason) { @@ -144,15 +144,25 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, buflen = sizeof(buf) - LWS_PRE; - txr = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, - &buflen, &f); - if (txr < 0) { - lwsl_debug("%s: tx handler asked to close\n", __func__); - return -1; - } - if (txr > 0) + switch(h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, + &buflen, &f)) { + case LWSSSSRET_DISCONNECT_ME: + lwsl_debug("%s: tx handler asked to close conn\n", __func__); + return -1; /* close connection */ + + case LWSSSSRET_DESTROY_ME: + lws_set_opaque_user_data(wsi, NULL); + h->wsi = NULL; + lws_ss_destroy(&h); + return -1; /* close connection */ + + case LWSSSSRET_TX_DONT_SEND: /* don't want to send anything */ + lwsl_debug("%s: dont want to write\n", __func__); return 0; + default: + break; + } memset(&mqpp, 0, sizeof(mqpp)); mqpp.topic = (char *)h->policy->u.mqtt.topic; diff --git a/lib/secure-streams/protocols/ss-raw.c b/lib/secure-streams/protocols/ss-raw.c index 88c9bf98..05891268 100644 --- a/lib/secure-streams/protocols/ss-raw.c +++ b/lib/secure-streams/protocols/ss-raw.c @@ -33,8 +33,8 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], *end = &buf[sizeof(buf) - 1]; - int f = 0, txr; size_t buflen; + int f = 0; switch (reason) { @@ -89,15 +89,23 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, return 0; buflen = lws_ptr_diff(end, p); - txr = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f); - if (txr < 0) { - lwsl_debug("%s: tx handler asked to close\n", __func__); - return -1; - } - if (txr > 0) { + switch(h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f)) { + case LWSSSSRET_DISCONNECT_ME: + lwsl_debug("%s: tx handler asked to close conn\n", __func__); + return -1; /* close connection */ + + case LWSSSSRET_DESTROY_ME: + lws_set_opaque_user_data(wsi, NULL); + h->wsi = NULL; + lws_ss_destroy(&h); + return -1; /* close connection */ + + case LWSSSSRET_TX_DONT_SEND: /* don't want to send anything */ lwsl_debug("%s: dont want to write\n", __func__); return 0; + default: + break; } /* diff --git a/lib/secure-streams/protocols/ss-ws.c b/lib/secure-streams/protocols/ss-ws.c index ba78f783..08dc9cb9 100644 --- a/lib/secure-streams/protocols/ss-ws.c +++ b/lib/secure-streams/protocols/ss-ws.c @@ -30,7 +30,7 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1400]; - int f = 0, f1, txr; + int f = 0, f1; size_t buflen; switch (reason) { @@ -41,7 +41,10 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, in ? (char *)in : "(null)"); if (!h) break; - lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + if (lws_ss_event_helper(h, LWSSSCS_UNREACHABLE)) { + lws_ss_destroy(&h); + break; + } h->wsi = NULL; lws_ss_backoff(h); break; @@ -100,15 +103,25 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, } buflen = sizeof(buf) - LWS_PRE; - txr = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, - &buflen, &f); - if (txr < 0) { - lwsl_debug("%s: tx handler asked to close\n", __func__); - return -1; - } - if (txr > 0) + switch(h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, + &buflen, &f)) { + case LWSSSSRET_DISCONNECT_ME: + lwsl_debug("%s: tx handler asked to close conn\n", __func__); + return -1; /* close connection */ + + case LWSSSSRET_DESTROY_ME: + lws_set_opaque_user_data(wsi, NULL); + h->wsi = NULL; + lws_ss_destroy(&h); + return -1; /* close connection */ + + case LWSSSSRET_TX_DONT_SEND: /* don't want to send anything */ + lwsl_debug("%s: dont want to write\n", __func__); return 0; + default: + break; + } f1 = lws_write_ws_flags(LWS_WRITE_BINARY, !!(f & LWSSS_FLAG_SOM), diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 12768a3f..1ec9b2b6 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -77,6 +77,8 @@ lws_ss_state_name(int state) int lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) { + int n; + if (!h) return 0; @@ -90,12 +92,38 @@ lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) (void *)h, NULL); #endif - if (h->h_sink && h->h_sink->info.state && - h->h_sink->info.state(h->sink_obj, h->h_sink, cs, 0)) - return 1; + if (h->h_sink && h->h_sink->info.state) { + n = h->h_sink->info.state(h->sink_obj, h->h_sink, cs, 0); + if (n) { + lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); + h->wsi = NULL; /* stop destroy trying to repeat this */ + if (n == LWSSSSRET_DESTROY_ME) { + lws_ss_destroy(&h); + return 1; + } + } + } - if (h->info.state) - return h->info.state(ss_to_userobj(h), NULL, cs, 0); + if (h->info.state) { + n = h->info.state(ss_to_userobj(h), NULL, cs, 0); + if (n) { + if (cs == LWSSSCS_CREATING) + /* just let caller handle it */ + return 1; + if (h->wsi) + lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); + if (n == LWSSSSRET_DESTROY_ME) { + lwsl_info("%s: ss %p asks to be destroyed\n", __func__, h); + /* disconnect ss from the wsi */ + if (h->wsi) + lws_set_opaque_user_data(h->wsi, NULL); + h->wsi = NULL; /* stop destroy trying to repeat this */ + lws_ss_destroy(&h); + return 1; + } + h->wsi = NULL; /* stop destroy trying to repeat this */ + } + } return 0; } @@ -105,7 +133,7 @@ lws_ss_timeout_sul_check_cb(lws_sorted_usec_list_t *sul) { lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, sul); - lwsl_err("%s: retrying ss h %p after backoff\n", __func__, h); + lwsl_err("%s: retrying ss h %p (%s) after backoff\n", __func__, h, h->policy->streamtype); /* we want to retry... */ h->seqstate = SSSEQ_DO_RETRY; @@ -481,7 +509,14 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, */ } - lws_ss_event_helper(h, LWSSSCS_CREATING); + if (lws_ss_event_helper(h, LWSSSCS_CREATING)) { + lws_pt_lock(pt, __func__); + lws_dll2_remove(&h->list); + lws_pt_unlock(pt); + lws_free(h); + + return 1; + } if (!ssi->register_sink && (h->policy->flags & LWSSSPOLF_NAILED_UP)) if (lws_ss_client_connect(h)) @@ -511,7 +546,7 @@ lws_ss_destroy(lws_ss_handle_t **ppss) * Don't let the wsi point to us any more, * we (the ss object bound to the wsi) are going away now */ -// lws_set_opaque_user_data(h->wsi, NULL); + lws_set_opaque_user_data(h->wsi, NULL); lws_set_timeout(h->wsi, 1, LWS_TO_KILL_SYNC); } @@ -521,6 +556,7 @@ lws_ss_destroy(lws_ss_handle_t **ppss) *ppss = NULL; lws_dll2_remove(&h->list); lws_dll2_remove(&h->to_list); + /* no need to worry about return code since we are anyway destroying */ lws_ss_event_helper(h, LWSSSCS_DESTROYING); lws_pt_unlock(pt); diff --git a/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c b/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c index 02427e39..228d65ea 100644 --- a/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c +++ b/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c @@ -52,7 +52,7 @@ ss_cpd_state(void *userobj, void *sh, lws_ss_constate_t state, break; case LWSSSCS_QOS_ACK_REMOTE: lws_system_cpd_set(cx, LWS_CPD_INTERNET_OK); - break; + return LWSSSSRET_DESTROY_ME; case LWSSSCS_ALL_RETRIES_FAILED: case LWSSSCS_DISCONNECTED: @@ -61,13 +61,13 @@ ss_cpd_state(void *userobj, void *sh, lws_ss_constate_t state, * cover the situation we didn't connect to anything */ lws_system_cpd_set(cx, LWS_CPD_NO_INTERNET); - break; + return LWSSSSRET_DESTROY_ME; default: break; } - return 0; + return LWSSSSRET_OK; } int diff --git a/lib/secure-streams/system/fetch-policy/fetch-policy.c b/lib/secure-streams/system/fetch-policy/fetch-policy.c index ace853b3..65444f8b 100644 --- a/lib/secure-streams/system/fetch-policy/fetch-policy.c +++ b/lib/secure-streams/system/fetch-policy/fetch-policy.c @@ -77,6 +77,8 @@ policy_set(lws_sorted_usec_list_t *sul) * ss connection close that was using the vhost from the old policy */ + lws_ss_destroy(&m->ss); + if (lws_ss_policy_set(context, "updated")) lwsl_err("%s: policy set failed\n", __func__); else { diff --git a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt index 257e8f83..8489a756 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt @@ -16,6 +16,14 @@ require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) if (requirements) add_executable(${SAMP} minimal-secure-streams.c) + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME ss-warmcat COMMAND lws-minimal-secure-streams) + set_tests_properties(ss-warmcat + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams + TIMEOUT 20) + endif() + if (websockets_shared) target_link_libraries(${SAMP} websockets_shared) add_dependencies(${SAMP} websockets_shared) -- Gitee From 080d1fc2baeaa40dd80abb53468253829f5f177d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 1 Jun 2020 10:13:50 +0100 Subject: [PATCH 0151/1062] lejp: add api test suite and support empty object Adds api-test-lejp to the CI where LEJP enabled. Supports empty objects like { "a": 123, "b": { } } --- lib/misc/lejp.c | 5 +- .../api-tests/api-test-lejp/CMakeLists.txt | 22 ++ .../api-tests/api-test-lejp/main.c | 198 ++++++++++++++++++ 3 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 minimal-examples/api-tests/api-test-lejp/CMakeLists.txt create mode 100644 minimal-examples/api-tests/api-test-lejp/main.c diff --git a/lib/misc/lejp.c b/lib/misc/lejp.c index 2cda400b..77495288 100644 --- a/lib/misc/lejp.c +++ b/lib/misc/lejp.c @@ -294,6 +294,9 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) break; case LEJP_MEMBERS: if (c == '}') { + if (ctx->sp >= 1) + goto pop_level; + ctx->st[ctx->sp].s = LEJP_IDLE; ret = LEJP_REJECT_MEMBERS_NO_CLOSE; goto reject; @@ -715,7 +718,7 @@ completed: } /* pop */ - +pop_level: ctx->sp--; if (ctx->sp) { ctx->pst[ctx->pst_sp].ppos = ctx->st[ctx->sp].p; diff --git a/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt b/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt new file mode 100644 index 00000000..04835c37 --- /dev/null +++ b/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt @@ -0,0 +1,22 @@ +project(lws-api-test-lejp C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(requirements 1) +require_lws_config(LWS_WITH_LEJP 1 requirements) + +if (requirements) + + add_executable(${PROJECT_NAME} main.c) + add_test(NAME api-test-lejp COMMAND lws-api-test-lejp) + + if (websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared) + add_dependencies(${PROJECT_NAME} websockets_shared) + else() + target_link_libraries(${PROJECT_NAME} websockets) + endif() +endif() diff --git a/minimal-examples/api-tests/api-test-lejp/main.c b/minimal-examples/api-tests/api-test-lejp/main.c new file mode 100644 index 00000000..91cd630f --- /dev/null +++ b/minimal-examples/api-tests/api-test-lejp/main.c @@ -0,0 +1,198 @@ +/* + * lws-api-test-lejp + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * sanity tests for lejp + */ + +#include + +/* + * in this example, the JSON is for one "builder" object, which may specify + * a child list "targets" of zero or more "target" objects. + */ + +static const char * const json_tests[] = { + "{" /* test 1 */ + "\"schema\":\"com-warmcat-sai-builder\"," + + "\"hostname\":\"learn\"," + "\"nspawn_timeout\":1800," + "\"targets\":[" + "{" + "\"name\":\"target1\"," + "\"someflag\":true" + "}," + "{" + "\"name\":\"target2\"," + "\"someflag\":false" + "}" + "]" + "}", + "{" /* test 2 */ + "\"schema\":\"com-warmcat-sai-builder\"," + + "\"hostname\":\"learn\"," + "\"targets\":[" + "{" + "\"name\":\"target1\"" + "}," + "{" + "\"name\":\"target2\"" + "}," + "{" + "\"name\":\"target3\"" + "}" + "]" + "}", "{" /* test 3 */ + "\"schema\":\"com-warmcat-sai-builder\"," + + "\"hostname\":\"learn\"," + "\"nspawn_timeout\":1800," + "\"targets\":[" + "{" + "\"name\":\"target1\"," + "\"unrecognized\":\"xyz\"," + "\"child\": {" + "\"somename\": \"abc\"," + "\"junk\": { \"x\": \"y\" }" + "}" + "}," + "{" + "\"name\":\"target2\"" + "}" + "]" + "}", + "{" /* test 4 */ + "\"schema\":\"com-warmcat-sai-builder\"," + + "\"hostname\":\"learn\"," + "\"nspawn_timeout\":1800" + "}", + "{" /* test 5 */ + "\"schema\":\"com-warmcat-sai-builder\"" + "}", + "{" /* test 6 ... check huge strings into smaller fixed char array */ + "\"schema\":\"com-warmcat-sai-builder\"," + "\"hostname\":\"" + "PYvtan6kqppjnS0KpYTCaiOLsJkc7XecAr1kcE0aCIciewYB+JcLG82mO1Vb1mJtjDwUjBxy2I6A" + "zefzoWUWmqZbsv4MXR55j9bKlyz1liiSX63iO0x6JAwACMtE2MkgcLwR86TSWAD9D1QKIWqg5RJ/" + "CRuVsW0DKAUMD52ql4JmPFuJpJgTq28z6PhYNzN3yI3bmQt6bzhA+A/xAsFzSBnb3MHYWzGMprr5" + "3FAP1ISo5Ec9i+2ehV40sG6Q470sH3PGQZ0YRPO7Sh/SyrSQ/scONmxRc3AcXl7X/CSs417ii+CV" + "8sq3ZgcxKNB7tNfN7idNx3upZ00G2BZy9jSy03cLKKLNaNUt0TQsxXbH55uDHzSEeZWvxJgT6zB1" + "NoMhdC02w+oXim94M6z6COCnqT3rgkGk8PHMry9Bkh4yVpRmzIRfMmln/lEhdZgxky2+g5hhlSIG" + "JYDCrdynD9kCfvfy6KGOpNIi1X+mhbbWn4lnL9ZKihL/RrfOV+oV4R26IDq+KqUiJBENeo8/GXkG" + "LUH/87iPyzXKEMavr6fkrK0vTGto8yEYxmOyaVz8phG5rwf4jJgmYNoMbGo8gWvhqO7UAGy2g7MW" + "v+B/t1eZZ+1euLsNrWAsFJiFbQKgdFfQT3RjB14iU8knlQ8usoy+pXssY2ddGJGVcGC21oZvstK9" + "eu1eRZftda/wP+N5unT1Hw7kCoVzqxHieiYt47EGIOaaQ7XjZDK6qPN6O/grHnvJZm2vBkxuXgsY" + "VkRQ7AuTWIecphqFsq7Wbc1YNbMW47SVU5zMD0WaCqbaaI0t4uIzRvPlD8cpiiTzFTrEHlIBTf8/" + "uZjjEGGLhJR1jPqA9D1Ej3ChV+ye6F9JTUMlozRMsGuF8U4btDzH5xdnmvRS4Ar6LKEtAXGkj2yu" + "yJln+v4RIWj2xOGPJovOqiXwi0FyM61f8U8gj0OiNA2/QlvrqQVDF7sMXgjvaE7iQt5vMETteZlx" + "+z3f+jTFM/aon511W4+ZkRD+6AHwucvM9BEC\"" + "}", + "{" /* test 7 ... check huge strings into char * */ + "\"schema\":\"com-warmcat-sai-builder\"," + "\"targets\":[" + "{" + "\"name\":\"" + "PYvtan6kqppjnS0KpYTCaiOLsJkc7XecAr1kcE0aCIciewYB+JcLG82mO1Vb1mJtjDwUjBxy2I6A" + "zefzoWUWmqZbsv4MXR55j9bKlyz1liiSX63iO0x6JAwACMtE2MkgcLwR86TSWAD9D1QKIWqg5RJ/" + "CRuVsW0DKAUMD52ql4JmPFuJpJgTq28z6PhYNzN3yI3bmQt6bzhA+A/xAsFzSBnb3MHYWzGMprr5" + "3FAP1ISo5Ec9i+2ehV40sG6Q470sH3PGQZ0YRPO7Sh/SyrSQ/scONmxRc3AcXl7X/CSs417ii+CV" + "8sq3ZgcxKNB7tNfN7idNx3upZ00G2BZy9jSy03cLKKLNaNUt0TQsxXbH55uDHzSEeZWvxJgT6zB1" + "NoMhdC02w+oXim94M6z6COCnqT3rgkGk8PHMry9Bkh4yVpRmzIRfMmln/lEhdZgxky2+g5hhlSIG" + "JYDCrdynD9kCfvfy6KGOpNIi1X+mhbbWn4lnL9ZKihL/RrfOV+oV4R26IDq+KqUiJBENeo8/GXkG" + "LUH/87iPyzXKEMavr6fkrK0vTGto8yEYxmOyaVz8phG5rwf4jJgmYNoMbGo8gWvhqO7UAGy2g7MW" + "v+B/t1eZZ+1euLsNrWAsFJiFbQKgdFfQT3RjB14iU8knlQ8usoy+pXssY2ddGJGVcGC21oZvstK9" + "eu1eRZftda/wP+N5unT1Hw7kCoVzqxHieiYt47EGIOaaQ7XjZDK6qPN6O/grHnvJZm2vBkxuXgsY" + "VkRQ7AuTWIecphqFsq7Wbc1YNbMW47SVU5zMD0WaCqbaaI0t4uIzRvPlD8cpiiTzFTrEHlIBTf8/" + "uZjjEGGLhJR1jPqA9D1Ej3ChV+ye6F9JTUMlozRMsGuF8U4btDzH5xdnmvRS4Ar6LKEtAXGkj2yu" + "yJln+v4RIWj2xOGPJovOqiXwi0FyM61f8U8gj0OiNA2/QlvrqQVDF7sMXgjvaE7iQt5vMETteZlx" + "+z3f+jTFM/aon511W4+ZkRD+6AHwucvM9BEC\"}]}" + "}", + "{" /* test 8 the "other" schema */ + "\"schema\":\"com-warmcat-sai-logs\"," + "\"task_uuid\":\"97fc90052506af8b3eb43b87aaa6fb76feab32bc128ede479a8a6b961e801f06\"," + "\"timestamp\": 170366786103,\"channel\":3, \"len\":20, " + "\"log\": \"PnNhaWI+IE5TU1RBVEVfSU5JVAo=\"}\x0a" + "ntu-xenial-amd64\"},{\"name\":\"linux-ubuntu-bionic-amd64\"},{\"name\":\"linux-fedora-32-x86_64\"}]}\",", + + "{" /* test 9, empty object */ + "\"a\":123,\"b\":{}" + "}", + + "{" /* SHOULD_FAIL: test 10, missing open */ + "\"a\":123,\"b\":}" + "}" +}; + +static const char * const tok[] = { + "something", +}; + +static signed char +test_cb(struct lejp_ctx *ctx, char reason) +{ + lwsl_info("%s: ctx->path %s, buf %s\n", __func__, ctx->path, ctx->buf); + return 0; +} + +/* authz JSON parsing */ + + +int main(int argc, const char **argv) +{ + int n, m, e = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + struct lejp_ctx ctx; + const char *p; + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS API selftest: lws_struct JSON\n"); + + for (m = 0; m < (int)LWS_ARRAY_SIZE(json_tests); m++) { + + lwsl_info("%s: ++++++++++++++++ test %d\n", __func__, m + 1); + + lejp_construct(&ctx, test_cb, NULL, tok, LWS_ARRAY_SIZE(tok)); + + lwsl_hexdump_info(json_tests[m], strlen(json_tests[m])); + + if (m == 7) + n = lejp_parse(&ctx, (uint8_t *)json_tests[m], + 0xc8); + else + n = lejp_parse(&ctx, (uint8_t *)json_tests[m], + (int)strlen(json_tests[m])); + + lwsl_info("n = %d\n", n); + if (n < 0 && m != 9) { + lwsl_err("%s: test %d: JSON decode failed '%s'\n", + __func__, m + 1, lejp_error_to_string(n)); + e++; + } + if (n >= 0 && m == 9) { + lwsl_err("%s: test %d: JSON decode should have failed '%s'\n", + __func__, m + 1, lejp_error_to_string(n)); + e++; + } + } + + if (e) + goto bail; + + lwsl_user("Completed: PASS\n"); + + return 0; + +bail: + lwsl_user("Completed: FAIL\n"); + + return 1; +} -- Gitee From d84910da920cf525fe172aaec340bde78defa101 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 1 Jun 2020 20:18:30 +0100 Subject: [PATCH 0152/1062] sai: fedora riscv --- .sai.json | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.sai.json b/.sai.json index b3c4e2ba..7777197e 100644 --- a/.sai.json +++ b/.sai.json @@ -49,13 +49,18 @@ # no obvious way to do that in CI "build": "rm -rf ebuild ; mkdir ebuild; cd ebuild; cp -rp ../minimal-examples/embedded/lws-minimal-esp32 . ; cd lws-minimal-esp32 ; . /opt/esp/esp-idf/export.sh ; ln -sf ../.. libwebsockets ; idf.py set-target esp32 && cp libwebsockets/minimal-examples/embedded/lws-minimal-esp32/sdkconfig . && cp sdkconfig.h build && idf.py build && cd build && /usr/local/bin/sai-device freertos-esp32 ESPPORT=0 ctest --output-on-failure", "default": false + }, + "linux-fedora-32-riscv": { + "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j12 && make -j12 DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}", + "default": false } + }, "configurations": { "default": { "cmake": "", - "platforms": "windows-10, linkit-cross, ubuntu-focal-aarch64, freertos-esp32" + "platforms": "windows-10, linkit-cross, ubuntu-focal-aarch64, freertos-esp32, linux-fedora-32-riscv" }, "default-examples-openssl-v3": { "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1", @@ -67,7 +72,7 @@ }, "default-examples": { "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", - "platforms": "windows-10, ubuntu-focal-aarch64" + "platforms": "windows-10, ubuntu-focal-aarch64, linux-fedora-32-riscv" }, "unix-domain": { "cmake": "-DUNIX_SOCK=1", @@ -79,7 +84,7 @@ }, "secure-streams": { "cmake": "-DLWS_WITH_SECURE_STREAMS=1", - "platforms": "windows-10" + "platforms": "windows-10, linux-fedora-32-riscv" }, "secure-streams-proxy": { "cmake": "-DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1", @@ -87,7 +92,7 @@ }, "distro_recommended": { "cmake": "-DLWS_WITH_DISTRO_RECOMMENDED=1", - "platforms": "not linkit-cross, not windows-10, ubuntu-focal-aarch64", + "platforms": "not linkit-cross, not windows-10, ubuntu-focal-aarch64, linux-fedora-32-riscv", "cpack": "&& cpack $SAI_CPACK", "artifacts": "build/*.rpm, build/*.deb, build/*.zip" }, -- Gitee From c0294c3e10c2867a72c233604c790380b276761d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 3 Jun 2020 06:48:06 +0100 Subject: [PATCH 0153/1062] clean: use lws_intptr_t where needed --- lib/core-net/close.c | 2 +- lib/core-net/dummy-callback.c | 2 +- lib/core-net/output.c | 2 +- lib/event-libs/libuv/libuv.c | 2 +- lib/tls/openssl/openssl-client.c | 2 +- lib/tls/openssl/openssl-server.c | 2 +- plugins/deaddrop/protocol_lws_deaddrop.c | 6 +++--- plugins/protocol_post_demo.c | 6 +++--- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 9f4d0920..f10cea42 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -498,7 +498,7 @@ just_kill_connection: #endif { lwsl_info("%s: shutdown conn: %p (sk %d, state 0x%x)\n", - __func__, wsi, (int)(long)wsi->desc.sockfd, + __func__, wsi, (int)(lws_intptr_t)wsi->desc.sockfd, lwsi_state(wsi)); if (!wsi->socket_is_permanently_unusable && lws_socket_is_valid(wsi->desc.sockfd)) { diff --git a/lib/core-net/dummy-callback.c b/lib/core-net/dummy-callback.c index bfbb6c35..713b96bb 100644 --- a/lib/core-net/dummy-callback.c +++ b/lib/core-net/dummy-callback.c @@ -816,7 +816,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, #if LWS_MAX_SMP > 1 case LWS_CALLBACK_GET_THREAD_ID: - return (int)(unsigned long long)pthread_self(); + return (int)(lws_intptr_t)pthread_self(); #endif default: diff --git a/lib/core-net/output.c b/lib/core-net/output.c index 0865bf1e..7c25ae12 100644 --- a/lib/core-net/output.c +++ b/lib/core-net/output.c @@ -366,7 +366,7 @@ lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len) } else #endif if (wsi->role_ops->file_handle) - n = write((int)(long long)wsi->desc.filefd, buf, len); + n = write((int)(lws_intptr_t)wsi->desc.filefd, buf, len); else n = send(wsi->desc.sockfd, (char *)buf, len, MSG_NOSIGNAL); // lwsl_info("%s: sent len %d result %d", __func__, len, n); diff --git a/lib/event-libs/libuv/libuv.c b/lib/event-libs/libuv/libuv.c index ac116a82..0f0f8016 100644 --- a/lib/event-libs/libuv/libuv.c +++ b/lib/event-libs/libuv/libuv.c @@ -625,7 +625,7 @@ elops_accept_uv(struct lws *wsi) if (wsi->role_ops->file_handle) uv_poll_init(pt->uv.io_loop, wsi->w_read.uv.pwatcher, - (int)(long long)wsi->desc.filefd); + (int)(lws_intptr_t)wsi->desc.filefd); else uv_poll_init_socket(pt->uv.io_loop, wsi->w_read.uv.pwatcher, diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 1fa83b62..9dd0a2c6 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -259,7 +259,7 @@ lws_ssl_client_bio_create(struct lws *wsi) #endif #endif /* USE_WOLFSSL */ - wsi->tls.client_bio = BIO_new_socket((int)(long long)wsi->desc.sockfd, + wsi->tls.client_bio = BIO_new_socket((int)(lws_intptr_t)wsi->desc.sockfd, BIO_NOCLOSE); SSL_set_bio(wsi->tls.ssl, wsi->tls.client_bio, wsi->tls.client_bio); diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index 41bec6f1..c9088463 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -575,7 +575,7 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) } SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index, wsi); - SSL_set_fd(wsi->tls.ssl, (int)(long long)accept_fd); + SSL_set_fd(wsi->tls.ssl, (int)(lws_intptr_t)accept_fd); #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL diff --git a/plugins/deaddrop/protocol_lws_deaddrop.c b/plugins/deaddrop/protocol_lws_deaddrop.c index 9431a0fe..b3653274 100644 --- a/plugins/deaddrop/protocol_lws_deaddrop.c +++ b/plugins/deaddrop/protocol_lws_deaddrop.c @@ -306,7 +306,7 @@ file_upload_cb(void *data, const char *name, const char *filename, if (pss->file_length > pss->vhd->max_size) { pss->response_code = HTTP_STATUS_REQ_ENTITY_TOO_LARGE; - close((int)(long long)pss->fd); + close((int)(lws_intptr_t)pss->fd); pss->fd = LWS_INVALID_FILE; unlink(pss->filename); @@ -314,7 +314,7 @@ file_upload_cb(void *data, const char *name, const char *filename, } if (pss->fd != LWS_INVALID_FILE) { - n = write((int)(long long)pss->fd, buf, len); + n = write((int)(lws_intptr_t)pss->fd, buf, len); lwsl_debug("%s: write %d says %d\n", __func__, len, n); lws_set_timeout(pss->wsi, PENDING_TIMEOUT_HTTP_CONTENT, 30); @@ -324,7 +324,7 @@ file_upload_cb(void *data, const char *name, const char *filename, break; if (pss->fd != LWS_INVALID_FILE) - close((int)(long long)pss->fd); + close((int)(lws_intptr_t)pss->fd); /* the temp filename without the ~ */ lws_strncpy(filename2, pss->filename, sizeof(filename2)); diff --git a/plugins/protocol_post_demo.c b/plugins/protocol_post_demo.c index d918ba4c..86157c29 100644 --- a/plugins/protocol_post_demo.c +++ b/plugins/protocol_post_demo.c @@ -80,7 +80,7 @@ file_upload_cb(void *data, const char *name, const char *filename, * simple demo use a fixed name so we don't have to deal with * attacks */ #if !defined(LWS_WITH_ESP32) - pss->fd = (lws_filefd_type)(long long)lws_open("/tmp/post-file", + pss->fd = (lws_filefd_type)(lws_intptr_t)lws_open("/tmp/post-file", O_CREAT | O_TRUNC | O_RDWR, 0600); #endif break; @@ -94,7 +94,7 @@ file_upload_cb(void *data, const char *name, const char *filename, return 1; #if !defined(LWS_WITH_ESP32) - n = write((int)(long long)pss->fd, buf, len); + n = write((int)(lws_intptr_t)pss->fd, buf, len); lwsl_info("%s: write %d says %d\n", __func__, len, n); #else lwsl_notice("%s: Received chunk size %d\n", __func__, len); @@ -103,7 +103,7 @@ file_upload_cb(void *data, const char *name, const char *filename, if (state == LWS_UFS_CONTENT) break; #if !defined(LWS_WITH_ESP32) - close((int)(long long)pss->fd); + close((int)(lws_intptr_t)pss->fd); pss->fd = LWS_INVALID_FILE; #endif break; -- Gitee From 16cbbe2b40134cc7dd6ee16c4f356c150e3fb52d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 3 Jun 2020 09:29:28 +0100 Subject: [PATCH 0154/1062] mingw: update cross toolchain and add 32 and 64 default builds to sai --- .sai.json | 10 +++++++++- CMakeLists.txt | 10 ++++++++++ contrib/cross-w32.cmake | 10 +++++++--- contrib/cross-w64.cmake | 11 ++++++++--- lib/roles/http/client/client-handshake.c | 2 ++ 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/.sai.json b/.sai.json index 7777197e..8a7a524b 100644 --- a/.sai.json +++ b/.sai.json @@ -44,6 +44,14 @@ "build": "mkdir build && cd build && set SAI_CPACK=\"-G ZIP\" && cmake .. -DLWS_OPENSSL_LIBRARIES=\"C:\\Program Files\\OpenSSL\\lib\\libssl.lib;C:\\Program Files\\OpenSSL\\lib\\libcrypto.lib\" -DLWS_OPENSSL_INCLUDE_DIRS=\"C:\\Program Files\\OpenSSL\\include\" -DLWS_EXT_PTHREAD_INCLUDE_DIR=\"C:\\Program Files (x86)\\pthreads\\include\" -DLWS_EXT_PTHREAD_LIBRARIES=\"C:\\Program Files (x86)\\pthreads\\lib\\x64\\libpthreadGC2.a\" ${cmake} && cmake --build . --config DEBUG && set CTEST_OUTPUT_ON_FAILURE=1 && ctest . -C DEBUG -j4 --output-on-failure", "default": false }, + "mingw32": { + "build": "mkdir build && cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w32.cmake -DLWS_UNIX_SOCK=0 ${cmake} && cmake --build . --config DEBUG", + "default": false + }, + "mingw64": { + "build": "mkdir build && cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w64.cmake -DLWS_UNIX_SOCK=0 ${cmake} && cmake --build . --config DEBUG", + "default": false + }, "freertos-esp32": { # official way to get sdkconfig.h is idf.py menuconfig, but # no obvious way to do that in CI @@ -60,7 +68,7 @@ "configurations": { "default": { "cmake": "", - "platforms": "windows-10, linkit-cross, ubuntu-focal-aarch64, freertos-esp32, linux-fedora-32-riscv" + "platforms": "windows-10, linkit-cross, ubuntu-focal-aarch64, freertos-esp32, linux-fedora-32-riscv, mingw32, mingw64" }, "default-examples-openssl-v3": { "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1", diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bb87145..df913b45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -525,6 +525,16 @@ CHECK_INCLUDE_FILE(malloc.h LWS_HAVE_MALLOC_H) CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H) CHECK_INCLUDE_FILE(inttypes.h LWS_HAVE_INTTYPES_H) +if (WIN32 OR MSVC) + CHECK_C_SOURCE_COMPILES("#include + #include + int main() { return 0; }" LWS_HAVE_WIN32_AFUNIX_H) + + if (LWS_UNIX_SOCK AND NOT LWS_HAVE_WIN32_AFUNIX_H) + message(FATAL_ERROR "No afunix.h in toolchain for LWS_UNIX_SOCK") + endif() +endif() + CHECK_LIBRARY_EXISTS(cap cap_set_flag "" LWS_HAVE_LIBCAP) diff --git a/contrib/cross-w32.cmake b/contrib/cross-w32.cmake index 46a7aa64..cfe563ca 100644 --- a/contrib/cross-w32.cmake +++ b/contrib/cross-w32.cmake @@ -6,7 +6,11 @@ # cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w32.cmake -DLWS_WITH_SSL=0 # -set(CROSS_PATH /opt/mingw32) +# the outermost path to your cross toolchain +#set(CROSS_PATH /opt/mingw32) +set(CROSS_PATH /usr) +# your cross root +set(CROSS_ROOT ${CROSS_PATH}/i686-w64-mingw32/sys-root/) # Target operating system name. set(CMAKE_SYSTEM_NAME Windows) @@ -15,7 +19,6 @@ set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/i686-w64-mingw32-gcc") set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/i686-w64-mingw32-g++") set(CMAKE_RC_COMPILER "${CROSS_PATH}/bin/i686-w64-mingw32-windres") -set(CMAKE_C_FLAGS "-Wno-error") # # Different build system distros set release optimization level to different @@ -34,7 +37,8 @@ if (CMAKE_BUILD_TYPE MATCHES RELEASE OR CMAKE_BUILD_TYPE MATCHES Release OR CMAK endif() # Where to look for the target environment. (More paths can be added here) -set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") +set(CMAKE_FIND_ROOT_PATH "${CROSS_ROOT}/mingw") +set(CMAKE_SYSROOT ${CROSS_ROOT}) # Adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment only. diff --git a/contrib/cross-w64.cmake b/contrib/cross-w64.cmake index ead6da1b..1f1c769c 100644 --- a/contrib/cross-w64.cmake +++ b/contrib/cross-w64.cmake @@ -3,13 +3,18 @@ # # This can be used when running cmake in the following way: # cd build/ -# cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w64.cmake -DLWS_WITH_SSL=0 +# cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w64.cmake # -set(CROSS_PATH /opt/mingw64) +# the outermost path to your cross toolchain +#set(CROSS_PATH /opt/mingw64) +set(CROSS_PATH /usr) +# your cross root +set(CROSS_ROOT ${CROSS_PATH}/x86_64-w64-mingw32/sys-root/) # Target operating system name. set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSROOT ${CROSS_ROOT}) # Name of C compiler. set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/x86_64-w64-mingw32-gcc") @@ -34,7 +39,7 @@ if (CMAKE_BUILD_TYPE MATCHES RELEASE OR CMAKE_BUILD_TYPE MATCHES Release OR CMAK endif() # Where to look for the target environment. (More paths can be added here) -set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") +set(CMAKE_FIND_ROOT_PATH "${CROSS_ROOT}/mingw") # Adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment only. diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 73f0eaea..f1fc266a 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -404,8 +404,10 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, if (lwsi_state(wsi) == LRS_WAITING_CONNECT && lws_socket_is_valid(wsi->desc.sockfd)) { +#if !defined(WIN32) socklen_t sl = sizeof(int); int e = 0; +#endif if (!result && /* no dns results... */ !wsi->sul_connect_timeout.list.owner /* no ongoing connect timeout */) -- Gitee From 425da070e316de6eb1c90dca835b5bfdcf99db03 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 3 Jun 2020 17:14:03 +0100 Subject: [PATCH 0155/1062] cmakelists: clean out pthreads and normalize libmount args --- CMakeLists.txt | 34 +++++++++++++++++++++++----------- lib/plat/unix/CMakeLists.txt | 17 ----------------- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df913b45..0dc5ad1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,11 +31,17 @@ include(CheckLibraryExists) include(CheckTypeSize) include(CheckCSourceCompiles) -if(POLICY CMP0048) +if (POLICY CMP0048) cmake_policy(SET CMP0048 NEW) endif() -#cmake_policy(SET CMP0076 NEW) +#if (POLICY CMP0024) +# cmake_policy(SET CMP0024 NEW) +#endif() + +if (POLICY CMP0075) + cmake_policy(SET CMP0075 NEW) +endif() # General Advice # @@ -577,10 +583,10 @@ if (LWS_HAVE_PTHREAD_H AND NOT LWS_PLAT_FREERTOS) set(LWS_PTHR_FLAGS "-pthread") endif() - set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LWS_PTHR_FLAGS}) - if (NOT WIN32 AND NOT MSVC) - list(APPEND LIB_LIST_AT_END ${LWS_PTHR_FLAGS}) - endif() + # set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LWS_PTHR_FLAGS}) + # if (NOT WIN32 AND NOT MSVC) + # list(APPEND LIB_LIST_AT_END ${LWS_PTHR_FLAGS}) + #endif() endif() CHECK_C_SOURCE_COMPILES("#define _GNU_SOURCE @@ -739,11 +745,16 @@ endif() if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - message("libmount include dir: ${LIBMOUNT_INC_PATH}") - message("libmount libraries: ${LIBMOUNT_LIB_PATH}") - - include_directories("${LIBMOUNT_INC_PATH}") - list(APPEND LIB_LIST ${LIBMOUNT_LIB_PATH}) + if (NOT LWS_LIBMOUNT_INCLUDE_DIRS STREQUAL "") + include_directories(${LWS_LIBMOUNT_INCLUDE_DIRS}) + message("libmount include dir: ${LWS_LIBMOUNT_INCLUDE_DIRS}") + endif() + if (NOT LWS_LIBMOUNT_LIBRARIES STREQUAL "") + message("libmount libraries: ${LWS_LIBMOUNT_LIBRARIES}") + list(APPEND LIB_LIST ${LWS_LIBMOUNT_LIBRARIES}) + else() + list(APPEND LIB_LIST mount) + endif() endif() @@ -767,6 +778,7 @@ if (LWS_WITH_HUBBUB) list(APPEND LIB_LIST ${LIBHUBBUB_LIBRARIES} ) endif() + # # Append the "at end" pieces to the lib list # diff --git a/lib/plat/unix/CMakeLists.txt b/lib/plat/unix/CMakeLists.txt index f52a2407..50340951 100644 --- a/lib/plat/unix/CMakeLists.txt +++ b/lib/plat/unix/CMakeLists.txt @@ -99,23 +99,6 @@ endif() list(APPEND LIB_LIST_AT_END dl) -if (LWS_WITH_FSMOUNT AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - if ("${LWS_LIBMOUNT_LIBRARIES}" STREQUAL "" OR "${LWS_LIBMOUNT_INCLUDE_DIRS}" STREQUAL "") - - # libmount paths (this is only on Linux) - # - find_path( LIBMOUNT_INC_PATH NAMES "libmount/libmount.h") - find_library(LIBMOUNT_LIB_PATH NAMES "mount") - else() - set(LIBMOUNT_INC_PATH ${LWS_LIBMOUNT_INCLUDE_DIRS} PARENT_SCOPE) - set(LIBMOUNT_LIB_PATH ${LWS_LIBMOUNT_LIBRARIES} PARENT_SCOPE) - endif() - - if (NOT LIBMOUNT_INC_PATH OR NOT LIBMOUNT_LIB_PATH) - message(FATAL_ERROR " Unable to find libmount") - endif() -endif() - # # Keep explicit parent scope exports at end # -- Gitee From e9b3898c9952a8957b745e30b9f2ae7d86890273 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 4 Jun 2020 10:12:08 +0100 Subject: [PATCH 0156/1062] spawn: retry when last stdwsi close may not be immediately followed by reapable process --- lib/core-net/private-lib-core-net.h | 1 + lib/plat/unix/unix-spawn.c | 17 +++++++++++++++-- lib/plat/windows/windows-spawn.c | 17 +++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 559d1aca..0f77b091 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -914,6 +914,7 @@ struct lws_spawn_piped { siginfo_t si; #endif + int reap_retry_budget; uint8_t pipes_alive:2; uint8_t we_killed_him_timeout:1; diff --git a/lib/plat/unix/unix-spawn.c b/lib/plat/unix/unix-spawn.c index b1960578..76382070 100644 --- a/lib/plat/unix/unix-spawn.c +++ b/lib/plat/unix/unix-spawn.c @@ -46,8 +46,20 @@ lws_spawn_sul_reap(struct lws_sorted_usec_list *sul) struct lws_spawn_piped *lsp = lws_container_of(sul, struct lws_spawn_piped, sul_reap); - lwsl_warn("%s: reaping spawn after last stdpipe closed\n", __func__); - lws_spawn_reap(lsp); + lwsl_notice("%s: reaping spawn after last stdpipe, tries left %d\n", + __func__, lsp->reap_retry_budget); + if (!lws_spawn_reap(lsp) && !lsp->pipes_alive) { + if (--lsp->reap_retry_budget) { + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul_reap, lws_spawn_sul_reap, + 250 * LWS_US_PER_MS); + } else { + lwsl_err("%s: Unable to reap lsp %p, killing\n", + __func__, lsp); + lsp->reap_retry_budget = 20; + lws_spawn_piped_kill_child_process(lsp); + } + } } static struct lws * @@ -314,6 +326,7 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) /* wholesale take a copy of info */ lsp->info = *i; + lsp->reap_retry_budget = 20; /* * Prepare the stdin / out / err pipes diff --git a/lib/plat/windows/windows-spawn.c b/lib/plat/windows/windows-spawn.c index 73487231..084691c3 100644 --- a/lib/plat/windows/windows-spawn.c +++ b/lib/plat/windows/windows-spawn.c @@ -45,8 +45,20 @@ lws_spawn_sul_reap(struct lws_sorted_usec_list *sul) struct lws_spawn_piped *lsp = lws_container_of(sul, struct lws_spawn_piped, sul_reap); - lwsl_warn("%s: reaping spawn after last stdpipe closed\n", __func__); - lws_spawn_reap(lsp); + lwsl_notice("%s: reaping spawn after last stdpipe, tries left %d\n", + __func__, lsp->reap_retry_budget); + if (!lws_spawn_reap(lsp) && !lsp->pipes_alive) { + if (--lsp->reap_retry_budget) { + lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, + &lsp->sul_reap, lws_spawn_sul_reap, + 250 * LWS_US_PER_MS); + } else { + lwsl_err("%s: Unable to reap lsp %p, killing\n", + __func__, lsp); + lsp->reap_retry_budget = 20; + lws_spawn_piped_kill_child_process(lsp); + } + } } static struct lws * @@ -355,6 +367,7 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) /* wholesale take a copy of info */ lsp->info = *i; lsp->context = context; + lsp->reap_retry_budget = 20; /* * Prepare the stdin / out / err pipes -- Gitee From e3df1eaa74883daf578a8c753932bf14e4def81f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 5 Jun 2020 08:33:51 +0100 Subject: [PATCH 0157/1062] sai: update to new tuple format --- .sai.json | 62 ++++++++++++++++++------------------ lib/misc/lws-struct-sqlite.c | 11 ++++++- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/.sai.json b/.sai.json index 8a7a524b..a117e917 100644 --- a/.sai.json +++ b/.sai.json @@ -5,60 +5,60 @@ # has somewhere to go to find its /usr/share content like certs "platforms": { - "linux-ubuntu-bionic-amd64": { + "linux-ubuntu-18.04/x86_64-amd/gcc": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, - "linux-ubuntu-focal-amd64": { + "linux-ubuntu-20.04/x86_64-amd/gcc": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, - "linux-fedora-32-x86_64": { + "linux-fedora-32/x86_64-amd/gcc": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, - "gentoo-amd64": { + "linux-gentoo/x86_64-amd/gcc": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G ZIP\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, - "linux-centos-8-x8664": { + "linux-centos-8/x86_64-amd/gcc": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, - "ubuntu-focal-aarch64": { + "linux-ubuntu-20.04/aarch64-a72-bcm2711-rpi4/gcc": { "build": "mkdir build;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j3 && make -j DESTDIR=../destdir install && ctest -j3 --output-on-failure ${cpack}", "default": false }, - "android-aarch64": { + "linux-android/aarch64/llvm": { "build": "mkdir build;cd build;cmake .. -DCMAKE_TOOLCHAIN_FILE=../libwebsockets/contrib/cross-aarch64-android.cmake ${cmake} && make -j", "default": false }, - "iOS": { + "netbsd-iOS/aarch64/llvm": { "build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";cmake .. -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DCMAKE_IOS_DEVELOPER_ROOT=/opt/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer -DCMAKE_TOOLCHAIN_FILE=contrib/iOS.cmake -DIOS_PLATFORM=OS ${cmake} && make -j", "default": false }, - "OSX-catalina": { + "netbsd-OSX-catalina/x86_64-intel-i3/llvm": { "build": "mkdir build destdir; cd build; export SAI_CPACK=\"-G ZIP\";export MACOSX_DEPLOYMENT_TARGET=10.14 ; cmake .. -DCMAKE_MAKE_PROGRAM=/usr/bin/make -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/opt/openssl@1.1/include -DLWS_OPENSSL_LIBRARIES=\"/usr/local/opt/openssl/lib/libssl.dylib;/usr/local/opt/openssl/lib/libcrypto.dylib\" ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, - "linkit-cross": { + "freertos-linkit/arm32-m4-mt7697-usi/gcc": { "build": "mkdir build;cd build;export CCACHE_DISABLE=1;cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/tmp -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-linkit.cmake -DLWS_PLAT_FREERTOS=1 -DLWS_WITH_ZLIB=0 -DLWS_WITHOUT_EXTENSIONS=1 -DLWS_WITH_ZIP_FOPS=0 -DLWS_WITH_HTTP_STREAM_COMPRESSION=0 -DLWS_WITH_MBEDTLS=1 -DLWS_WITH_FILE_OPS=0 ${cmake};make -j", "default": false }, - "windows-10": { + "windows-10/x86_64-amd/msvc": { "build": "mkdir build && cd build && set SAI_CPACK=\"-G ZIP\" && cmake .. -DLWS_OPENSSL_LIBRARIES=\"C:\\Program Files\\OpenSSL\\lib\\libssl.lib;C:\\Program Files\\OpenSSL\\lib\\libcrypto.lib\" -DLWS_OPENSSL_INCLUDE_DIRS=\"C:\\Program Files\\OpenSSL\\include\" -DLWS_EXT_PTHREAD_INCLUDE_DIR=\"C:\\Program Files (x86)\\pthreads\\include\" -DLWS_EXT_PTHREAD_LIBRARIES=\"C:\\Program Files (x86)\\pthreads\\lib\\x64\\libpthreadGC2.a\" ${cmake} && cmake --build . --config DEBUG && set CTEST_OUTPUT_ON_FAILURE=1 && ctest . -C DEBUG -j4 --output-on-failure", "default": false }, - "mingw32": { + "windows-10/x86_64-amd/mingw32": { "build": "mkdir build && cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w32.cmake -DLWS_UNIX_SOCK=0 ${cmake} && cmake --build . --config DEBUG", "default": false }, - "mingw64": { + "windows-10/x86_64-amd/mingw64": { "build": "mkdir build && cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=../contrib/cross-w64.cmake -DLWS_UNIX_SOCK=0 ${cmake} && cmake --build . --config DEBUG", "default": false }, - "freertos-esp32": { + "freertos-espidf/xl6-esp32/gcc": { # official way to get sdkconfig.h is idf.py menuconfig, but # no obvious way to do that in CI "build": "rm -rf ebuild ; mkdir ebuild; cd ebuild; cp -rp ../minimal-examples/embedded/lws-minimal-esp32 . ; cd lws-minimal-esp32 ; . /opt/esp/esp-idf/export.sh ; ln -sf ../.. libwebsockets ; idf.py set-target esp32 && cp libwebsockets/minimal-examples/embedded/lws-minimal-esp32/sdkconfig . && cp sdkconfig.h build && idf.py build && cd build && /usr/local/bin/sai-device freertos-esp32 ESPPORT=0 ctest --output-on-failure", "default": false }, - "linux-fedora-32-riscv": { + "linux-fedora-32/riscv64-virt/gcc": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j12 && make -j12 DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}", "default": false } @@ -68,60 +68,60 @@ "configurations": { "default": { "cmake": "", - "platforms": "windows-10, linkit-cross, ubuntu-focal-aarch64, freertos-esp32, linux-fedora-32-riscv, mingw32, mingw64" + "platforms": "windows-10/x86_64-amd/mingw64, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-20.04/aarch64-a72-bcm2711-rpi4/gcc, freertos-espidf/xl6-esp32/gcc, linux-fedora-32/riscv64-virt/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64" }, "default-examples-openssl-v3": { "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1", - "platforms": "none,linux-fedora-32-x86_64" + "platforms": "none,linux-fedora-32/x86_64-amd/gcc" }, "default-examples-boringssl": { "cmake": "cmake .. -DLWS_WITH_BORINGSSL=1 -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/boringssl/include\" -DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/boringssl/build/ssl/libssl.so;/usr/local/src/boringssl/build/crypto/libcrypto.so\" -DLWS_WITH_MINIMAL_EXAMPLES=1", - "platforms": "none,linux-fedora-32-x86_64" + "platforms": "none,linux-fedora-32/x86_64-amd/gcc" }, "default-examples": { "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", - "platforms": "windows-10, ubuntu-focal-aarch64, linux-fedora-32-riscv" + "platforms": "windows-10/x86_64-amd/mingw64, linux-ubuntu-20.04/aarch64-a72-bcm2711-rpi4/gcc, linux-fedora-32/riscv64-virt/gcc" }, "unix-domain": { "cmake": "-DUNIX_SOCK=1", - "platforms": "windows-10" + "platforms": "windows-10/x86_64-amd/mingw64" }, "lws_system": { "cmake": "-DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=RELEASE -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", - "platforms": "windows-10" + "platforms": "windows-10/x86_64-amd/mingw64" }, "secure-streams": { "cmake": "-DLWS_WITH_SECURE_STREAMS=1", - "platforms": "windows-10, linux-fedora-32-riscv" + "platforms": "windows-10/x86_64-amd/mingw64, linux-fedora-32/riscv64-virt/gcc" }, "secure-streams-proxy": { "cmake": "-DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1", - "platforms": "not windows-10" + "platforms": "not windows-10/x86_64-amd/mingw64" }, "distro_recommended": { "cmake": "-DLWS_WITH_DISTRO_RECOMMENDED=1", - "platforms": "not linkit-cross, not windows-10, ubuntu-focal-aarch64, linux-fedora-32-riscv", + "platforms": "not linkit-cross, not windows-10/x86_64-amd/mingw64, linux-ubuntu-20.04/aarch64-a72-bcm2711-rpi4/gcc, linux-fedora-32/riscv64-virt/gcc", "cpack": "&& cpack $SAI_CPACK", "artifacts": "build/*.rpm, build/*.deb, build/*.zip" }, "lwsws": { "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", # no distro -devel package for libuv - "platforms": "not linux-centos-8-x8664" + "platforms": "not linux-centos-8/x86_64-amd/gcc" }, "lwsws2": { "cmake": "-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_LWS_DSH=1", # no distro -devel package for libuv - "platforms": "not linux-centos-8-x8664" + "platforms": "not linux-centos-8/x86_64-amd/gcc" }, "justmbedtls": { "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITHOUT_TESTAPPS=1", - "platforms": "none, android-aarch64" + "platforms": "none, linux-android/aarch64/llvm" }, "mbedtls": { "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG", # no distro -devel package for mbedtls - "platforms": "not linux-centos-8-x8664" + "platforms": "not linux-centos-8/x86_64-amd/gcc" }, "noserver": { "cmake": "-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" @@ -146,11 +146,11 @@ }, "ipv6": { "cmake": "-DLWS_IPV6=ON", - "platforms": "windows-10" + "platforms": "windows-10/x86_64-amd/mingw64" }, "nossl": { "cmake": "-DLWS_WITH_SSL=OFF", - "platforms": "iOS" + "platforms": "netbsd-iOS/aarch64/llvm" }, "daemon": { "cmake": "-DLWS_WITHOUT_DAEMONIZE=OFF" @@ -169,7 +169,7 @@ }, "threadpool": { "cmake": "-DLWS_WITH_THREADPOOL=1 -DLWS_WITH_MINIMAL_EXAMPLES=1", - "platforms": "windows-10" + "platforms": "windows-10/x86_64-amd/mingw64" } } } diff --git a/lib/misc/lws-struct-sqlite.c b/lib/misc/lws-struct-sqlite.c index ef550c12..5e29e445 100644 --- a/lib/misc/lws-struct-sqlite.c +++ b/lib/misc/lws-struct-sqlite.c @@ -537,10 +537,19 @@ lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, int lws_struct_sq3_close(sqlite3 **pdb) { + int n; + if (!*pdb) return 0; - sqlite3_close(*pdb); + n = sqlite3_close(*pdb); + if (n != SQLITE_OK) { + /* + * trouble... + */ + lwsl_err("%s: failed to close: %d\n", __func__, n); + return 1; + } *pdb = NULL; return 0; -- Gitee From 5d514b35fc47c13d4df00ec0c5cda4f0d26c7247 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 4 Jun 2020 19:59:37 -0700 Subject: [PATCH 0158/1062] tls: add read client .pem or .der from memory #1941 and added read private key from mem --- include/libwebsockets/lws-context-vhost.h | 6 ++ lib/tls/mbedtls/mbedtls-client.c | 9 ++- lib/tls/openssl/openssl-client.c | 67 +++++++++++++++++++---- lib/tls/private-network.h | 5 +- lib/tls/tls-client.c | 5 +- 5 files changed, 76 insertions(+), 16 deletions(-) diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index 09c2b126..28abda9e 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -487,6 +487,12 @@ struct lws_context_creation_info { * can handle the LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS * callback of protocols[0] to allow setting of the private key directly * via tls library calls */ + const void *client_ssl_key_mem; + /**< VHOST: Client SSL context init: client key memory buffer or + * NULL... use this to load client key from memory instead of file */ + unsigned int client_ssl_key_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_key_mem in + * bytes */ const char *client_ssl_ca_filepath; /**< VHOST: Client SSL context init: CA certificate filepath or NULL */ const void *client_ssl_ca_mem; diff --git a/lib/tls/mbedtls/mbedtls-client.c b/lib/tls/mbedtls/mbedtls-client.c index 0eac6b5f..f93774aa 100644 --- a/lib/tls/mbedtls/mbedtls-client.c +++ b/lib/tls/mbedtls/mbedtls-client.c @@ -256,7 +256,10 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, const char *cert_filepath, const void *cert_mem, unsigned int cert_mem_len, - const char *private_key_filepath) + const char *private_key_filepath, + const void *key_mem, + unsigned int key_mem_len + ) { X509 *d2i_X509(X509 **cert, const unsigned char *buffer, long len); SSL_METHOD *method = (SSL_METHOD *)TLS_client_method(); @@ -347,13 +350,13 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, lwsl_notice("Loaded client cert %s\n", cert_filepath); #endif } else if (cert_mem && cert_mem_len) { - // lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); + /* lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); */ SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx, cert_mem, cert_mem_len - 1); n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, cert_mem_len, cert_mem); if (n < 1) { - lwsl_err("%s: problem interpreting client cert\n", + lwsl_err("%s: (mbedtls) problem interpreting client cert\n", __func__); lws_tls_err_describe_clear(); return 1; diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 9dd0a2c6..b19523fc 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -531,7 +531,10 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, const char *cert_filepath, const void *cert_mem, unsigned int cert_mem_len, - const char *private_key_filepath) + const char *private_key_filepath, + const void *key_mem, + unsigned int key_mem_len + ) { struct lws_tls_client_reuse *tcr; X509_STORE *x509_store; @@ -752,12 +755,11 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, } else { lws_filepos_t amount = 0; - uint8_t *up1; const uint8_t *up; + uint8_t *up1; if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, ca_mem, - ca_mem_len, &up1, - &amount)) { + ca_mem_len, &up1, &amount)) { lwsl_err("%s: Unable to decode x.509 mem\n", __func__); lwsl_hexdump_notice(ca_mem, ca_mem_len); return 1; @@ -796,6 +798,7 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, */ /* support for client-side certificate authentication */ + if (cert_filepath) { if (lws_tls_use_any_upgrade_check_extant(cert_filepath) != LWS_TLS_EXTANT_YES && @@ -813,18 +816,33 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, return 1; } lwsl_notice("Loaded client cert %s\n", cert_filepath); + } else if (cert_mem && cert_mem_len) { - n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, - cert_mem_len, cert_mem); + lws_filepos_t flen; + uint8_t *p; + + if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, cert_mem, + cert_mem_len, &p, &flen)) { + lwsl_err("%s: couldn't read cert file\n", __func__); + + return 1; + } + + n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, (int)flen, p); + if (n < 1) { - lwsl_err("%s: problem interpreting client cert\n", - __func__); + lwsl_err("%s: problem interpreting client cert\n", __func__); lws_tls_err_describe_clear(); - return 1; } + + lws_free_set_NULL(p); + + if (n != 1) + return 1; + } if (private_key_filepath) { - lwsl_notice("%s: doing private key filepath\n", __func__); + lwsl_info("%s: using private key filepath\n", __func__); lws_ssl_bind_passphrase(vh->tls.ssl_client_ctx, 1, info); /* set the private key from KeyFile */ if (SSL_CTX_use_PrivateKey_file(vh->tls.ssl_client_ctx, @@ -834,7 +852,7 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, lws_tls_err_describe_clear(); return 1; } - lwsl_notice("Loaded client cert private key %s\n", + lwsl_info("Loaded client cert private key %s\n", private_key_filepath); /* verify private key */ @@ -843,6 +861,33 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, return 1; } } + else if (key_mem && key_mem_len) { + + lws_filepos_t flen; + uint8_t *p; + + if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, key_mem, + key_mem_len, &p, &flen)) { + lwsl_err("%s: couldn't use mem cert\n", __func__); + + return 1; + } + + n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vh->tls.ssl_client_ctx, p, + (long)(lws_intptr_t)flen); + if (n != 1) + n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC, + vh->tls.ssl_client_ctx, p, + (long)(lws_intptr_t)flen); + + lws_free_set_NULL(p); + + if (n != 1) { + lwsl_err("%s: unable to use key_mem\n", __func__); + + return 1; + } + } return 0; } diff --git a/lib/tls/private-network.h b/lib/tls/private-network.h index 0cb92321..0dd3a838 100644 --- a/lib/tls/private-network.h +++ b/lib/tls/private-network.h @@ -171,7 +171,10 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, const char *cert_filepath, const void *cert_mem, unsigned int cert_mem_len, - const char *private_key_filepath); + const char *private_key_filepath, + const void *key_mem, + unsigned int key_mem_len); + LWS_EXTERN lws_tls_ctx * lws_tls_ctx_from_wsi(struct lws *wsi); diff --git a/lib/tls/tls-client.c b/lib/tls/tls-client.c index a3d45536..85e64ac6 100644 --- a/lib/tls/tls-client.c +++ b/lib/tls/tls-client.c @@ -134,7 +134,10 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info, cert_filepath, info->client_ssl_cert_mem, info->client_ssl_cert_mem_len, - private_key_filepath)) + private_key_filepath, + info->client_ssl_key_mem, + info->client_ssl_key_mem_len + )) return 1; lwsl_info("created client ssl context for %s\n", vhost->name); -- Gitee From f0c1ea801c99529ce36769a1ca742d1be832d9f3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 5 Jun 2020 10:13:17 +0100 Subject: [PATCH 0159/1062] mingw: fix for different sockfd type in udp example As found by Sai --- .gitignore | 1 + .sai.json | 24 +++++++++---------- lib/core-net/private-lib-core-net.h | 8 ------- lib/core/private-lib-core.h | 10 ++++++++ lib/misc/threadpool/threadpool.c | 2 ++ lib/tls/openssl/openssl-x509.c | 1 + .../minimal-raw-adopt-udp.c | 5 ++++ 7 files changed, 31 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 2919ceaf..fd50d029 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,4 @@ doc /bq/ /cros/ /q/ +/b1/ diff --git a/.sai.json b/.sai.json index a117e917..b490c812 100644 --- a/.sai.json +++ b/.sai.json @@ -5,10 +5,10 @@ # has somewhere to go to find its /usr/share content like certs "platforms": { - "linux-ubuntu-18.04/x86_64-amd/gcc": { + "linux-ubuntu-1804/x86_64-amd/gcc": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, - "linux-ubuntu-20.04/x86_64-amd/gcc": { + "linux-ubuntu-2004/x86_64-amd/gcc": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, "linux-fedora-32/x86_64-amd/gcc": { @@ -20,7 +20,7 @@ "linux-centos-8/x86_64-amd/gcc": { "build": "mkdir build destdir;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G RPM\";cmake .. ${cmake} && make -j && make -j DESTDIR=../destdir install && ctest -j4 --output-on-failure ${cpack}" }, - "linux-ubuntu-20.04/aarch64-a72-bcm2711-rpi4/gcc": { + "linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc": { "build": "mkdir build;cd build;export CCACHE_DISABLE=1;export SAI_CPACK=\"-G DEB\";cmake .. ${cmake} && make -j3 && make -j DESTDIR=../destdir install && ctest -j3 --output-on-failure ${cpack}", "default": false }, @@ -68,7 +68,7 @@ "configurations": { "default": { "cmake": "", - "platforms": "windows-10/x86_64-amd/mingw64, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-20.04/aarch64-a72-bcm2711-rpi4/gcc, freertos-espidf/xl6-esp32/gcc, linux-fedora-32/riscv64-virt/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64" + "platforms": "windows-10/x86_64-amd/msvc, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, freertos-espidf/xl6-esp32/gcc, linux-fedora-32/riscv64-virt/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64" }, "default-examples-openssl-v3": { "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1", @@ -80,27 +80,27 @@ }, "default-examples": { "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", - "platforms": "windows-10/x86_64-amd/mingw64, linux-ubuntu-20.04/aarch64-a72-bcm2711-rpi4/gcc, linux-fedora-32/riscv64-virt/gcc" + "platforms": "windows-10/x86_64-amd/msvc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, linux-fedora-32/riscv64-virt/gcc" }, "unix-domain": { "cmake": "-DUNIX_SOCK=1", - "platforms": "windows-10/x86_64-amd/mingw64" + "platforms": "windows-10/x86_64-amd/msvc" }, "lws_system": { "cmake": "-DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=RELEASE -DLWS_WITH_GENCRYPTO=1 -DLWS_WITH_JOSE=1 -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SYS_NTPCLIENT=1", - "platforms": "windows-10/x86_64-amd/mingw64" + "platforms": "windows-10/x86_64-amd/msvc" }, "secure-streams": { "cmake": "-DLWS_WITH_SECURE_STREAMS=1", - "platforms": "windows-10/x86_64-amd/mingw64, linux-fedora-32/riscv64-virt/gcc" + "platforms": "windows-10/x86_64-amd/msvc, linux-fedora-32/riscv64-virt/gcc" }, "secure-streams-proxy": { "cmake": "-DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1", - "platforms": "not windows-10/x86_64-amd/mingw64" + "platforms": "not windows-10/x86_64-amd/msvc" }, "distro_recommended": { "cmake": "-DLWS_WITH_DISTRO_RECOMMENDED=1", - "platforms": "not linkit-cross, not windows-10/x86_64-amd/mingw64, linux-ubuntu-20.04/aarch64-a72-bcm2711-rpi4/gcc, linux-fedora-32/riscv64-virt/gcc", + "platforms": "not linkit-cross, not windows-10/x86_64-amd/msvc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, linux-fedora-32/riscv64-virt/gcc", "cpack": "&& cpack $SAI_CPACK", "artifacts": "build/*.rpm, build/*.deb, build/*.zip" }, @@ -146,7 +146,7 @@ }, "ipv6": { "cmake": "-DLWS_IPV6=ON", - "platforms": "windows-10/x86_64-amd/mingw64" + "platforms": "windows-10/x86_64-amd/mingw64, windows-10/x86_64-amd/msvc" }, "nossl": { "cmake": "-DLWS_WITH_SSL=OFF", @@ -169,7 +169,7 @@ }, "threadpool": { "cmake": "-DLWS_WITH_THREADPOOL=1 -DLWS_WITH_MINIMAL_EXAMPLES=1", - "platforms": "windows-10/x86_64-amd/mingw64" + "platforms": "windows-10/x86_64-amd/msvc" } } } diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 0f77b091..065b2526 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -48,14 +48,6 @@ struct lws_muxable { #include "private-lib-roles.h" -#ifdef LWS_WITH_IPV6 -#if defined(WIN32) || defined(_WIN32) -#include -#else -#include -#endif -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 85e4ac39..6aac8132 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -148,6 +148,16 @@ struct lws_tx_credit { uint8_t manual; }; +#ifdef LWS_WITH_IPV6 +#if defined(WIN32) || defined(_WIN32) +#include +#else +#include +#endif +#endif + +#undef X509_NAME + #if defined(LWS_WITH_TLS) #include "private-lib-tls.h" #endif diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index b7caf6c5..1f43c0c1 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -482,7 +482,9 @@ done: return 0; } +#if !defined(WIN32) static int dummy; +#endif static void * lws_threadpool_worker(void *d) diff --git a/lib/tls/openssl/openssl-x509.c b/lib/tls/openssl/openssl-x509.c index bf85120a..185a84a8 100644 --- a/lib/tls/openssl/openssl-x509.c +++ b/lib/tls/openssl/openssl-x509.c @@ -22,6 +22,7 @@ * IN THE SOFTWARE. */ +#define WIN32_LEAN_AND_MEAN #include "private-lib-core.h" #include "private-lib-tls-openssl.h" diff --git a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c index 6e23a3c5..415611f5 100644 --- a/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c +++ b/minimal-examples/raw/minimal-raw-adopt-udp/minimal-raw-adopt-udp.c @@ -86,8 +86,13 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, break; fd = lws_get_socket_fd(wsi); +#if defined(WIN32) + if ((int)fd < 0) + break; +#else if (fd < 0) /* keep Coverity happy: actually it cannot be < 0 */ break; +#endif /* * We can write directly on the UDP socket, specifying -- Gitee From 2a772776a92743172191af271345d9d1059d8658 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 7 Jun 2020 07:53:36 +0100 Subject: [PATCH 0160/1062] windows: for data exports use explicit extern LWS_EXTERN needs to be empty for windows when declaring functions in the headers. But for data, it needs the explicit extern otherwise on windows or mingw based builds, it thinks we are redeclaring the data each time. --- .sai.json | 2 +- CMakeLists.txt | 33 +++++++++++++++++++++++--------- include/libwebsockets/lws-misc.h | 6 +++--- lib/CMakeLists.txt | 20 +++++++++++++++---- lib/tls/CMakeLists.txt | 30 +++++++++++++++++++---------- lib/tls/mbedtls/CMakeLists.txt | 29 +++++++++++++++++++++------- plugins/CMakeLists.txt | 2 ++ test-apps/CMakeLists.txt | 6 +++++- 8 files changed, 93 insertions(+), 35 deletions(-) diff --git a/.sai.json b/.sai.json index b490c812..445f22d4 100644 --- a/.sai.json +++ b/.sai.json @@ -55,7 +55,7 @@ "freertos-espidf/xl6-esp32/gcc": { # official way to get sdkconfig.h is idf.py menuconfig, but # no obvious way to do that in CI - "build": "rm -rf ebuild ; mkdir ebuild; cd ebuild; cp -rp ../minimal-examples/embedded/lws-minimal-esp32 . ; cd lws-minimal-esp32 ; . /opt/esp/esp-idf/export.sh ; ln -sf ../.. libwebsockets ; idf.py set-target esp32 && cp libwebsockets/minimal-examples/embedded/lws-minimal-esp32/sdkconfig . && cp sdkconfig.h build && idf.py build && cd build && /usr/local/bin/sai-device freertos-esp32 ESPPORT=0 ctest --output-on-failure", + "build": "rm -rf ebuild ; mkdir ebuild; cd ebuild; cp -rp ../minimal-examples/embedded/lws-minimal-esp32 . ; cd lws-minimal-esp32 ; . /opt/esp/esp-idf/export.sh ; ln -sf ../.. libwebsockets ; idf.py set-target esp32 && cp libwebsockets/minimal-examples/embedded/lws-minimal-esp32/sdkconfig . && cp sdkconfig.h build && idf.py build && cd build && /usr/local/bin/sai-device freertos-espidf ESPPORT=0 ctest --output-on-failure", "default": false }, "linux-fedora-32/riscv64-virt/gcc": { diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dc5ad1e..2ad8250a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -262,17 +262,25 @@ endmacro() macro(exports_to_parent_scope) set(SOURCES ${SOURCES} PARENT_SCOPE) - set(LIB_LIST ${LIB_LIST} PARENT_SCOPE) + if (LIB_LIST) + set(LIB_LIST ${LIB_LIST} PARENT_SCOPE) + endif() get_property(_CURR DIRECTORY PROPERTY INCLUDE_DIRECTORIES) set(_CMAKE_INC_LIST ${_CURR} PARENT_SCOPE) - set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE) + if (LWS_LIB_BUILD_INC_PATHS) + set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE) + endif() endmacro() macro(export_to_parent_intermediate) set(SOURCES ${SOURCES} PARENT_SCOPE) - set(LIB_LIST ${LIB_LIST} PARENT_SCOPE) + if (LIB_LIST) + set(LIB_LIST ${LIB_LIST} PARENT_SCOPE) + endif() set(_CMAKE_INC_LIST ${_CMAKE_INC_LIST} PARENT_SCOPE) - set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE) + if (LWS_LIB_BUILD_INC_PATHS) + set(LWS_LIB_BUILD_INC_PATHS ${LWS_LIB_BUILD_INC_PATHS} PARENT_SCOPE) + endif() endmacro() # @@ -713,9 +721,15 @@ if (MINGW) add_definitions(-DWINVER=0x0601 -D_WIN32_WINNT=0x0601) endif() -source_group("Headers Private" FILES ${HDR_PRIVATE}) -source_group("Headers Public" FILES ${HDR_PUBLIC}) -source_group("Sources" FILES ${SOURCES}) +if (HDR_PRIVATE) + source_group("Headers Private" FILES ${HDR_PRIVATE}) +endif() +if (HDR_PUBLIC) + source_group("Headers Public" FILES ${HDR_PUBLIC}) +endif() +if (SOURCES) + source_group("Sources" FILES ${SOURCES}) +endif() if (RESOURCES) source_group("Resources" FILES ${RESOURCES}) endif() @@ -799,8 +813,9 @@ else() set(DEF_INSTALL_CMAKE_DIR lib${LIB_SUFFIX}/cmake/libwebsockets) endif() -set(LWS__INCLUDE_DIRS - "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}") +if (DEFINED REL_INCLUDE_DIR) + set(LWS__INCLUDE_DIRS "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}") +endif() configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config.cmake.in ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/libwebsockets-config.cmake diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index 47e7ba0e..f71158ab 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -710,9 +710,9 @@ typedef struct lws_humanize_unit { uint64_t factor; } lws_humanize_unit_t; -LWS_VISIBLE LWS_EXTERN const lws_humanize_unit_t humanize_schema_si[7]; -LWS_VISIBLE LWS_EXTERN const lws_humanize_unit_t humanize_schema_si_bytes[7]; -LWS_VISIBLE LWS_EXTERN const lws_humanize_unit_t humanize_schema_us[8]; +LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_si[7]; +LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_si_bytes[7]; +LWS_VISIBLE extern const lws_humanize_unit_t humanize_schema_us[8]; /** * lws_humanize() - Convert possibly large number to human-readable uints diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 9b6001c9..3fba3ebd 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -85,7 +85,9 @@ else() endif() endif() -set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST} ${CMAKE_REQUIRED_LIBRARIES}) +if (LIB_LIST) + set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST} ${CMAKE_REQUIRED_LIBRARIES}) +endif() if (LWS_WITH_ZLIB) if (LWS_WITH_BUNDLED_ZLIB) @@ -296,14 +298,24 @@ endif(UNIX) # export_to_parent_intermediate() -set(LWS_PLAT_UNIX ${LWS_PLAT_UNIX} PARENT_SCOPE) +if (DEFINED LWS_PLAT_UNIX) + set(LWS_PLAT_UNIX ${LWS_PLAT_UNIX} PARENT_SCOPE) +endif() set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) set(LWS_HAVE_PIPE2 ${LWS_HAVE_PIPE2} PARENT_SCOPE) set(LWS_LIBRARIES ${LWS_LIBRARIES} PARENT_SCOPE) -set(WIN32_HELPERS_PATH ${WIN32_HELPERS_PATH} PARENT_SCOPE) +if (DEFINED WIN32_HELPERS_PATH) + set(WIN32_HELPERS_PATH ${WIN32_HELPERS_PATH} PARENT_SCOPE) +endif() +if (DEFINED HDR_PRIVATE) set(HDR_PRIVATE ${HDR_PRIVATE} PARENT_SCOPE) -set(ZLIB_FOUND ${ZLIB_FOUND} PARENT_SCOPE) +endif() +if (DEFINED ZLIB_FOUND) + set(ZLIB_FOUND ${ZLIB_FOUND} PARENT_SCOPE) +endif() +if (DEFINED LIB_LIST_AT_END) set(LIB_LIST_AT_END ${LIB_LIST_AT_END} PARENT_SCOPE) +endif() diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index 44aa0030..3a502d07 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -210,7 +210,7 @@ if (LWS_WITH_SSL) set(chose_ssl 1) endif() - if (LWS_WITH_MBEDTLS) + if (LWS_WITH_MBEDTLS AND DEFINED MBEDTLS_INCLUDE_DIRS AND DEFINED MBEDTLS_LIBRARIES) message("MBEDTLS include dir: ${MBEDTLS_INCLUDE_DIRS}") message("MBEDTLS libraries: ${MBEDTLS_LIBRARIES}") @@ -219,6 +219,9 @@ if (LWS_WITH_SSL) endforeach() list(APPEND LIB_LIST "${MBEDTLS_LIBRARIES}") + endif() + + if (LWS_WITH_MBEDTLS) set(chose_ssl 1) endif() @@ -262,11 +265,15 @@ if (LWS_WITH_SSL) endif(LWS_WITH_SSL) -set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) -set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) - if (UNIX) - set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) - endif() +if (DEFINED OPENSSL_INCLUDE_DIRS) + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS}) +endif() +if (DEFINED LIB_LIST) + set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST}) +endif() +if (UNIX) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) +endif() if (NOT VARIA) set(VARIA "") @@ -334,11 +341,14 @@ endif() if (LWS_WITH_SSL AND NOT LWS_WITH_WOLFSSL) message("Searching for OpenSSL executable and dlls") find_package(OpenSSLbins) - message("OpenSSL executable: ${OPENSSL_EXECUTABLE}") - if (OPENSSL_EXECUTABLE MATCHES "^$") - set(OPENSSL_EXECUTABLE openssl) + if (DEFINED OPENSSL_EXECUTABLE) + message("OpenSSL executable: ${OPENSSL_EXECUTABLE}") + + if (OPENSSL_EXECUTABLE MATCHES "^$") + set(OPENSSL_EXECUTABLE openssl) + endif() endif() - if (NOT OPENSSL_EXECUTABLE) + if (NOT DEFINED OPENSSL_EXECUTABLE) set(OPENSSL_EXECUTABLE openssl) endif() diff --git a/lib/tls/mbedtls/CMakeLists.txt b/lib/tls/mbedtls/CMakeLists.txt index ad3ef327..adfbbbd7 100644 --- a/lib/tls/mbedtls/CMakeLists.txt +++ b/lib/tls/mbedtls/CMakeLists.txt @@ -73,10 +73,17 @@ include_directories(wrapper/include wrapper/include/internal) tls/mbedtls/wrapper/platform/ssl_port.c) endif() + set(_WANT_MBT 0) + if (NOT LWS_PLAT_FREERTOS) + if (NOT DEFINED LWS_MBEDTLS_LIBRARIES) + set(_WANT_MBT 1) + endif() + if (NOT DEFINED LWS_MBEDTLS_INCLUDE_DIRS) + set(_WANT_MBT 1) + endif() + endif() - if ((NOT LWS_MBEDTLS_LIBRARIES OR "${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR - NOT LWS_MBEDTLS_INCLUDE_DIRS OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "") AND - NOT LWS_PLAT_FREERTOS) + if (_WANT_MBT) find_path(LWS_MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) @@ -96,12 +103,20 @@ include_directories(wrapper/include wrapper/include/internal) message(FATAL_ERROR "You must set LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS when LWS_WITH_MBEDTLS is turned on.") endif() endif() - set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES}) - set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS}) + if (LWS_MBEDTLS_LIBRARIES) + set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES}) + endif() + if (LWS_MBEDTLS_INCLUDE_DIRS) + set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS}) + endif() set(USE_MBEDTLS 1 PARENT_SCOPE) - include_directories(${MBEDTLS_INCLUDE_DIRS}) + if (DEFINED MBEDTLS_INCLUDE_DIRS) + include_directories(${MBEDTLS_INCLUDE_DIRS}) + endif() - list(APPEND LIB_LIST ${MBEDTLS_LIBRARIES}) + if (DEFINED MBEDTLS_LIBRARIES) + list(APPEND LIB_LIST ${MBEDTLS_LIBRARIES}) + endif() # old mbedtls has everything in mbedtls/net.h diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 571ab518..0e1560eb 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -24,7 +24,9 @@ include_directories(.) +if (DEFINED LIB_LIST_AT_END) link_libraries(${LIB_LIST_AT_END}) +endif() if (LWS_WITH_PLUGINS AND LWS_WITH_SHARED) macro(create_plugin PLUGIN_NAME PLUGIN_INCLUDE MAIN_SRC S2 S3) diff --git a/test-apps/CMakeLists.txt b/test-apps/CMakeLists.txt index e7b6023f..aff7b68c 100644 --- a/test-apps/CMakeLists.txt +++ b/test-apps/CMakeLists.txt @@ -89,7 +89,11 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2)) endif() endif() - target_include_directories(${TEST_NAME} PRIVATE "${LWS_LIB_INCLUDES}" ${LWS_LIB_BUILD_INC_PATHS}) + if (LWS_LIB_INCLUDES) + target_include_directories(${TEST_NAME} PRIVATE "${LWS_LIB_INCLUDES}" ${LWS_LIB_BUILD_INC_PATHS}) + else() + target_include_directories(${TEST_NAME} PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) + endif() target_compile_options(${TEST_NAME} PRIVATE ${LWS_PTHR_FLAGS}) if (LWS_WITH_HTTP_STREAM_COMPRESSION) -- Gitee From 280584ff8f147832f008b299d0e32fd4273024db Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Jun 2020 05:27:11 +0100 Subject: [PATCH 0161/1062] ipv6: support interface name for scope lookup Currently for ipv6, we look up the scope assuming we were given an interface ip for binding. But with ipv4, we also support giving an interface name. Check it against an interface name first and return that if valid. https://github.com/warmcat/libwebsockets/issues/1944 --- lib/core-net/network.c | 48 +++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/lib/core-net/network.c b/lib/core-net/network.c index 61518acb..49999173 100644 --- a/lib/core-net/network.c +++ b/lib/core-net/network.c @@ -436,14 +436,39 @@ lws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul, #if defined(LWS_WITH_IPV6) unsigned long -lws_get_addr_scope(const char *ipaddr) +lws_get_addr_scope(const char *ifname_or_ipaddr) { - unsigned long scope = 0; - -#ifndef WIN32 - struct ifaddrs *addrs, *addr; + unsigned long scope; char ip[NI_MAXHOST]; unsigned int i; +#if !defined(WIN32) + struct ifaddrs *addrs, *addr; +#else + PIP_ADAPTER_ADDRESSES adapter, addrs = NULL; + PIP_ADAPTER_UNICAST_ADDRESS addr; + struct sockaddr_in6 *sockaddr; + ULONG size = 0; + int found = 0; + DWORD ret; +#endif + + /* + * First see if we can look the string up as a network interface name... + * windows vista+ also has this + */ + + scope = if_nametoindex(ifname_or_ipaddr); + if (scope > 0) + /* we found it from the interface name lookup */ + return scope; + + /* + * if not, try to look it up as an IP -> interface -> interface index + */ + + scope = 0; + +#if !defined(WIN32) getifaddrs(&addrs); for (addr = addrs; addr; addr = addr->ifa_next) { @@ -451,6 +476,7 @@ lws_get_addr_scope(const char *ipaddr) addr->ifa_addr->sa_family != AF_INET6) continue; + ip[0] = '\0'; getnameinfo(addr->ifa_addr, sizeof(struct sockaddr_in6), ip, sizeof(ip), @@ -463,21 +489,13 @@ lws_get_addr_scope(const char *ipaddr) break; } - if (!strcmp(ip, ipaddr)) { + if (!strcmp(ip, ifname_or_ipaddr)) { scope = if_nametoindex(addr->ifa_name); break; } } freeifaddrs(addrs); #else - PIP_ADAPTER_ADDRESSES adapter, addrs = NULL; - PIP_ADAPTER_UNICAST_ADDRESS addr; - ULONG size = 0; - DWORD ret; - struct sockaddr_in6 *sockaddr; - char ip[NI_MAXHOST]; - unsigned int i; - int found = 0; for (i = 0; i < 5; i++) { @@ -516,7 +534,7 @@ lws_get_addr_scope(const char *ipaddr) &sockaddr->sin6_addr, ip, sizeof(ip)); - if (!strcmp(ip, ipaddr)) { + if (!strcmp(ip, ifname_or_ipaddr)) { scope = sockaddr->sin6_scope_id; found = 1; break; -- Gitee From ad5a4f7040615c33fc5ab0903bf66ec0376510b9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 10 Jun 2020 19:07:38 +0100 Subject: [PATCH 0162/1062] clean --- .sai.json | 2 +- lib/secure-streams/secure-streams.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.sai.json b/.sai.json index 445f22d4..7f8d5be6 100644 --- a/.sai.json +++ b/.sai.json @@ -71,7 +71,7 @@ "platforms": "windows-10/x86_64-amd/msvc, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, freertos-espidf/xl6-esp32/gcc, linux-fedora-32/riscv64-virt/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64" }, "default-examples-openssl-v3": { - "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1", + "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_GENCRYPTO=1", "platforms": "none,linux-fedora-32/x86_64-amd/gcc" }, "default-examples-boringssl": { diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 1ec9b2b6..7318b4f1 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -133,7 +133,8 @@ lws_ss_timeout_sul_check_cb(lws_sorted_usec_list_t *sul) { lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, sul); - lwsl_err("%s: retrying ss h %p (%s) after backoff\n", __func__, h, h->policy->streamtype); + lwsl_notice("%s: retrying ss h %p (%s) after backoff\n", __func__, h, + h->policy->streamtype); /* we want to retry... */ h->seqstate = SSSEQ_DO_RETRY; -- Gitee From 15ce46d9716dfeb70ff4f6d25225bf78f1443a5b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 10 Jun 2020 19:17:08 +0100 Subject: [PATCH 0163/1062] drivers: initial generic gpio and i2c plus bitbang Make a start on generic peripheral and bus drivers to provide meta-functionality regardless of platform. On the one hand this simply provides... - bitbang i2c on top of esp-idf gpio apis - ssd1306 oled chip driver as found on Heltec WB32 - modifications to the minimal example test for esp32 to use that ... on the other hand, those capabilities are provided by creating: - an abstract i2c class object - an abstract gpio class object - i2c class implementation using the abstract gpio for bitbang - an abstract display class object - an abstract display state (brightness, animated change, on/off/init tracking, autodim after inactive, auto-off / blanking after inactive) ... with the intention, eg, you only have to add a platform implementation for the gpio to be able to use the i2c-based display drivers and state handling, and i2c bitbang, without any other modifications. --- CMakeLists.txt | 6 + include/libwebsockets.h | 8 + include/libwebsockets/lws-bb-i2c.h | 66 ++++++++ include/libwebsockets/lws-display.h | 140 ++++++++++++++++ include/libwebsockets/lws-esp32.h | 4 + include/libwebsockets/lws-gpio.h | 60 +++++++ include/libwebsockets/lws-i2c.h | 54 +++++++ include/libwebsockets/lws-ssd1306-i2c.h | 64 ++++++++ lib/CMakeLists.txt | 4 + lib/drivers/CMakeLists.txt | 14 ++ lib/drivers/devices/display/ssd1306.h | 66 ++++++++ lib/drivers/display/lws-display.c | 126 +++++++++++++++ lib/drivers/display/ssd1306-i2c.c | 151 ++++++++++++++++++ lib/drivers/i2c/bitbang/lws-bb-i2c.c | 135 ++++++++++++++++ lib/drivers/i2c/lws-i2c.c | 59 +++++++ lib/plat/freertos/esp32/drivers/gpio-esp32.c | 96 +++++++++++ .../freertos/esp32/drivers/lws-plat-gpio.h | 25 +++ lib/plat/freertos/freertos-init.c | 4 + .../embedded/lws-minimal-esp32/CMakeLists.txt | 4 + .../embedded/lws-minimal-esp32/banded-img.h | 64 ++++++++ .../main/lws-minimal-esp32.c | 65 +++++--- .../lws-minimal-esp32/scan/output.bmp | Bin 0 -> 1154 bytes .../embedded/lws-minimal-esp32/scan/pic.h | 64 ++++++++ .../embedded/lws-minimal-esp32/scan/pic.h.1 | 64 ++++++++ .../embedded/lws-minimal-esp32/scan/scan | Bin 0 -> 19568 bytes .../embedded/lws-minimal-esp32/scan/scan.c | 70 ++++++++ .../embedded/lws-minimal-esp32/scan/scan.sh | 8 + 27 files changed, 1401 insertions(+), 20 deletions(-) create mode 100644 include/libwebsockets/lws-bb-i2c.h create mode 100644 include/libwebsockets/lws-display.h create mode 100644 include/libwebsockets/lws-gpio.h create mode 100644 include/libwebsockets/lws-i2c.h create mode 100644 include/libwebsockets/lws-ssd1306-i2c.h create mode 100644 lib/drivers/CMakeLists.txt create mode 100644 lib/drivers/devices/display/ssd1306.h create mode 100644 lib/drivers/display/lws-display.c create mode 100644 lib/drivers/display/ssd1306-i2c.c create mode 100644 lib/drivers/i2c/bitbang/lws-bb-i2c.c create mode 100644 lib/drivers/i2c/lws-i2c.c create mode 100644 lib/plat/freertos/esp32/drivers/gpio-esp32.c create mode 100644 lib/plat/freertos/esp32/drivers/lws-plat-gpio.h create mode 100644 minimal-examples/embedded/lws-minimal-esp32/banded-img.h create mode 100644 minimal-examples/embedded/lws-minimal-esp32/scan/output.bmp create mode 100644 minimal-examples/embedded/lws-minimal-esp32/scan/pic.h create mode 100644 minimal-examples/embedded/lws-minimal-esp32/scan/pic.h.1 create mode 100755 minimal-examples/embedded/lws-minimal-esp32/scan/scan create mode 100644 minimal-examples/embedded/lws-minimal-esp32/scan/scan.c create mode 100755 minimal-examples/embedded/lws-minimal-esp32/scan/scan.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ad8250a..2c040559 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,6 +152,12 @@ option(LWS_WITH_LIBUV "Compile with support for libuv" OFF) option(LWS_WITH_LIBEVENT "Compile with support for libevent" OFF) option(LWS_WITH_GLIB "Compile with support for glib event loop" OFF) +# +# LWS Drivers +# + +option(LWS_WITH_DRIVERS "With generic drivers for gpio, i2c, display etc" OFF) + # # Static / Dynamic build options # diff --git a/include/libwebsockets.h b/include/libwebsockets.h index f0f66c94..af28167c 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -609,6 +609,14 @@ struct lws; #endif +#include +#include +#include + +#include + +#include + #ifdef __cplusplus } #endif diff --git a/include/libwebsockets/lws-bb-i2c.h b/include/libwebsockets/lws-bb-i2c.h new file mode 100644 index 00000000..bd9718e9 --- /dev/null +++ b/include/libwebsockets/lws-bb-i2c.h @@ -0,0 +1,66 @@ +/* + * I2C - bitbanged generic gpio implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ + +typedef struct lws_bb_i2c { + lws_i2c_ops_t bb_ops; /* init to lws_bb_i2c_ops */ + + /* implementation-specific members */ + + _lws_plat_gpio_t scl; + _lws_plat_gpio_t sda; + + const lws_gpio_ops_t *gpio; + void (*delay)(void); +} lws_bb_i2c_t; + +#define lws_bb_i2c_ops \ + { \ + .init = lws_bb_i2c_init, \ + .start = lws_bb_i2c_start, \ + .stop = lws_bb_i2c_stop, \ + .write = lws_bb_i2c_write, \ + .read = lws_bb_i2c_read, \ + .set_ack = lws_bb_i2c_set_ack, \ + } + +int +lws_bb_i2c_init(const lws_i2c_ops_t *octx); + +int +lws_bb_i2c_start(const lws_i2c_ops_t *octx); + +void +lws_bb_i2c_stop(const lws_i2c_ops_t *octx); + +int +lws_bb_i2c_write(const lws_i2c_ops_t *octx, uint8_t data); + +int +lws_bb_i2c_read(const lws_i2c_ops_t *octx); + +void +lws_bb_i2c_set_ack(const lws_i2c_ops_t *octx, int ack); diff --git a/include/libwebsockets/lws-display.h b/include/libwebsockets/lws-display.h new file mode 100644 index 00000000..ff750aed --- /dev/null +++ b/include/libwebsockets/lws-display.h @@ -0,0 +1,140 @@ +/* + * lws abstract display + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +#if !defined(__LWS_DISPLAY_H__) +#define __LWS_DISPLAY_H__ + +#include + +typedef uint16_t lws_display_scalar; +typedef uint8_t lws_display_brightness; + +/* + * This is embedded in the actual display implementation object at the top, + * so a pointer to this can be cast to a pointer to the implementation object + * by any code that is specific to how it was implemented. + */ + +typedef struct lws_display { + int (*init)(const struct lws_display *disp); + int (*brightness)(const struct lws_display *disp, lws_display_brightness b); + int (*blit)(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h); + int (*power)(const struct lws_display *disp, int state); + void *variant; + lws_display_scalar w; + lws_display_scalar h; +} lws_display_t; + +/* + * This contains dynamic data related to display state + */ + +enum lws_display_state { + LWSDISPS_OFF, /* managed in display_state */ + LWSDISPS_AUTODIMMED, + LWSDISPS_ACTIVE, +}; + +typedef struct lws_diplay_state { + + lws_sorted_usec_list_t sul; + lws_sorted_usec_list_t sul_autodim; + const lws_display_t *disp; + struct lws_context *ctx; + + int autodim_ms; + int off_ms; + + lws_display_brightness bl_current; + lws_display_brightness bl_target; + lws_display_brightness bl_step; + lws_display_brightness bl_active; + lws_display_brightness bl_dim; + enum lws_display_state state; + +} lws_display_state_t; + +/** + * lws_display_state_init() - initialize display states + * + * \param lds: the display state object + * \param ctx: the lws context + * \param autodim_ms: ms since last active report to dim display (<0 = never) + * \param off_ms: ms since dim to turn display off (<0 = never) + * \param active: brightness level to use when active (0-255) + * \param dim: brightness level to use when dim (0-255) + * \param disp: generic display object we belong to + * + * This initializes a display's state, and sets up the optional screen auto-dim + * and blanking on inactive, and gradual brightness change timer. + * + * - auto-dim then off: set autodim to some ms and off_ms to some ms + * - auto-dim only: set autodim to some ms and off_ms to -1 + * - off-only: set autodim to some ms and off_ms to 0 + * - neither: set both autodim and off_ms to -1 + */ +void +lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx, + int autodim_ms, int off_ms, lws_display_brightness active, + lws_display_brightness dim, const lws_display_t *disp); + +/** + * lws_display_state_set_brightness() - gradually change the brightness + * + * \param lds: the display state we are changing + * \param target: the target brightness + * \param step: the step change for each gradual brightness change + * + * Adjusts the brightness gradually twoards the target at 20Hz + */ +void +lws_display_state_set_brightness(lws_display_state_t *lds, + lws_display_brightness target, + lws_display_brightness step); + +/* + * lws_display_state_active() - inform the system the display is active + * + * \param lds: the display state we are marking as active + * + * Resets the auto-dim and auto-off timers and makes sure the display is on and + * at the active brightness level + */ +void +lws_display_state_active(lws_display_state_t *lds); + +/* + * lws_display_state_off() - turns off the related display + * + * \param lds: the display state we are turning off + * + * Turns the display to least power mode or completely off if possible. + * Disables the timers related to dimming and blanking. + */ +void +lws_display_state_off(lws_display_state_t *lds); + +#endif diff --git a/include/libwebsockets/lws-esp32.h b/include/libwebsockets/lws-esp32.h index 49cb6377..5105b3b2 100644 --- a/include/libwebsockets/lws-esp32.h +++ b/include/libwebsockets/lws-esp32.h @@ -150,3 +150,7 @@ extern uint16_t lws_esp32_sine_interp(int n); /* required in external code by esp32 plat (may just return if no leds) */ extern void lws_esp32_leds_timer_cb(TimerHandle_t th); + +#include "libwebsockets/lws-gpio.h" +extern const lws_gpio_ops_t lws_gpio_plat; + diff --git a/include/libwebsockets/lws-gpio.h b/include/libwebsockets/lws-gpio.h new file mode 100644 index 00000000..f86620ad --- /dev/null +++ b/include/libwebsockets/lws-gpio.h @@ -0,0 +1,60 @@ +/* + * Generic GPIO ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ + +#if !defined(__LWS_GPIO_H__) +#define __LWS_GPIO_H__ + +typedef int _lws_plat_gpio_t; + +typedef enum { + LWSGGPIO_IRQ_NONE, + LWSGGPIO_IRQ_RISING, + LWSGGPIO_IRQ_FALLING, + LWSGGPIO_IRQ_CHANGE, + LWSGGPIO_IRQ_LOW, + LWSGGPIO_IRQ_HIGH +} lws_gpio_irq_t; + +enum { + LWSGGPIO_FL_READ = (1 << 0), + LWSGGPIO_FL_WRITE = (1 << 1), + LWSGGPIO_FL_PULLUP = (1 << 2), + LWSGGPIO_FL_PULLDOWN = (1 << 3), + LWSGGPIO_FL_START_LOW = (1 << 4), +}; + +typedef void (*lws_gpio_irq_cb_t)(void *arg); + +typedef struct lws_gpio_ops { + void (*mode)(_lws_plat_gpio_t gpio, int flags); + int (*read)(_lws_plat_gpio_t gpio); + void (*set)(_lws_plat_gpio_t gpio, int val); + int (*irq_mode)(_lws_plat_gpio_t gpio, lws_gpio_irq_t irq, + lws_gpio_irq_cb_t cb, void *arg); +} lws_gpio_ops_t; + +#endif diff --git a/include/libwebsockets/lws-i2c.h b/include/libwebsockets/lws-i2c.h new file mode 100644 index 00000000..5f8b6341 --- /dev/null +++ b/include/libwebsockets/lws-i2c.h @@ -0,0 +1,54 @@ +/* + * Generic I2C ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for i2c, a real implementation provides + * functions for the ops that use the underlying OS arrangements. + */ + +#if !defined(__LWS_I2C_H__) +#define __LWS_I2C_H__ + +#include +#include + +typedef struct lws_i2c_ops { + int (*init)(const struct lws_i2c_ops *ctx); + int (*start)(const struct lws_i2c_ops *ctx); + void (*stop)(const struct lws_i2c_ops *ctx); + int (*write)(const struct lws_i2c_ops *ctx, uint8_t data); + int (*read)(const struct lws_i2c_ops *ctx); + void (*set_ack)(const struct lws_i2c_ops *octx, int ack); +} lws_i2c_ops_t; + +/* + * These are implemented by calling the ops above, and so are generic + */ + +int +lws_i2c_command(const lws_i2c_ops_t *ctx, uint8_t ads7, uint8_t c); + +int +lws_i2c_command_list(const lws_i2c_ops_t *ctx, uint8_t ads7, const uint8_t *buf, + size_t len); + +#endif diff --git a/include/libwebsockets/lws-ssd1306-i2c.h b/include/libwebsockets/lws-ssd1306-i2c.h new file mode 100644 index 00000000..bd50551a --- /dev/null +++ b/include/libwebsockets/lws-ssd1306-i2c.h @@ -0,0 +1,64 @@ +/* + * lws abstract display implementation for ssd1306 on i2c + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +#if !defined(__LWS_DISPLAY_SSD1306_I2C_H__) +#define __LWS_DISPLAY_SSD1306_I2C_H__ + +/* + * D/C# pin on SSD1306 sets the I2C slave ads + * from these two options (7-bit address) + */ + +#define SSD1306_I2C7_ADS1 0x3c +#define SSD1306_I2C7_ADS2 0x3d + +typedef struct lws_display_ssd1306 { + + lws_display_t disp; /* use lws_display_ssd1306_ops to set ops */ + const lws_i2c_ops_t *i2c; /* i2c ops */ + + const lws_gpio_ops_t *gpio; /* NULL or gpio ops */ + _lws_plat_gpio_t reset_gpio; /* if gpio ops, nReset gpio # */ + + uint8_t i2c7_address; /* one of SSD1306_I2C7_ADS... */ + +} lws_display_ssd1306_t; + +int +lws_display_ssd1306_i2c_init(const struct lws_display *disp); +int +lws_display_ssd1306_i2c_brightness(const struct lws_display *disp, uint8_t b); +int +lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h); +int +lws_display_ssd1306_i2c_power(const struct lws_display *disp, int state); + +#define lws_display_ssd1306_ops \ + .init = lws_display_ssd1306_i2c_init, \ + .brightness = lws_display_ssd1306_i2c_brightness, \ + .blit = lws_display_ssd1306_i2c_blit, \ + .power = lws_display_ssd1306_i2c_power +#endif diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 3fba3ebd..6ed6b50e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -122,6 +122,10 @@ add_subdir_include_dirs(misc) add_subdir_include_dirs(system) add_subdir_include_dirs(event-libs) +if (LWS_WITH_DRIVERS) + add_subdir_include_dirs(drivers) +endif() + if (LWS_WITH_NETWORK) add_subdir_include_dirs(core-net) if (LWS_WITH_ABSTRACT) diff --git a/lib/drivers/CMakeLists.txt b/lib/drivers/CMakeLists.txt new file mode 100644 index 00000000..33a6b193 --- /dev/null +++ b/lib/drivers/CMakeLists.txt @@ -0,0 +1,14 @@ +list(APPEND SOURCES + drivers/display/lws-display.c + drivers/display/ssd1306-i2c.c + drivers/i2c/lws-i2c.c + drivers/i2c/bitbang/lws-bb-i2c.c +) + +if (LWS_ESP_PLATFORM) + list(APPEND SOURCES + plat/freertos/esp32/drivers/gpio-esp32.c) +endif() + +exports_to_parent_scope() + diff --git a/lib/drivers/devices/display/ssd1306.h b/lib/drivers/devices/display/ssd1306.h new file mode 100644 index 00000000..0d8fb459 --- /dev/null +++ b/lib/drivers/devices/display/ssd1306.h @@ -0,0 +1,66 @@ +/* + * Private register map for SSD1306 + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + */ + +#if !defined(__LWS_SSD1306_H__) +#define __LWS_SSD1306_H__ + +enum { + SSD1306_SETLOWCOLUMN = 0x00, + SSD1306_SETHIGHCOLUMN = 0x10, + + SSD1306_MEMORYMODE = 0x20, + SSD1306_COLUMNADDR = 0x21, + SSD1306_PAGEADDR = 0x22, + SSD1306_DEACTIVATE_SCROLL = 0x2e, + + SSD1306_SETSTARTLINE = 0x40, + + SSD1306_SETCONTRAST = 0x81, + SSD1306_CHARGEPUMP = 0x8d, + + SSD1306_SEGREMAP = 0xa0, + SSD1306_SETSEGMENTREMAP = 0xa1, + SSD1306_DISPLAYALLON_RESUME = 0xa4, + SSD1306_DISPLAYALLON = 0xa5, + SSD1306_NORMALDISPLAY = 0xa6, + SSD1306_INVERTDISPLAY = 0xa7, + SSD1306_SETMULTIPLEX = 0xa8, + SSD1306_DISPLAYOFF = 0xae, + SSD1306_DISPLAYON = 0xaf, + + SSD1306_COMSCANINC = 0xc0, + SSD1306_COMSCANDEC = 0xc8, + + SSD1306_SETDISPLAYOFFSET = 0xd3, + SSD1306_SETDISPLAYCLOCKDIV = 0xd5, + SSD1306_SETPRECHARGE = 0xd9, + SSD1306_SETCOMPINS = 0xda, + SSD1306_SETVCOMDESELECT = 0xdb, + + SSD1306_NOP = 0xe3, +}; + +#endif + diff --git a/lib/drivers/display/lws-display.c b/lib/drivers/display/lws-display.c new file mode 100644 index 00000000..32e85368 --- /dev/null +++ b/lib/drivers/display/lws-display.c @@ -0,0 +1,126 @@ +/* + * lws abstract display + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +static void +sul_cb(lws_sorted_usec_list_t *sul) +{ + lws_display_state_t *lds = lws_container_of(sul, lws_display_state_t, + sul); + + if (lds->bl_target > lds->bl_current) { + if (lds->bl_target - lds->bl_current < lds->bl_step) + lds->bl_current = lds->bl_target; + else + lds->bl_current += lds->bl_step; + } else { + if (lds->bl_current - lds->bl_target < lds->bl_step) + lds->bl_current = lds->bl_target; + else + lds->bl_current -= lds->bl_step; + } + + lds->disp->brightness(lds->disp, lds->bl_current); + + if (lds->bl_current != lds->bl_target) + /* + * Come back and move towards the target again in 50ms + */ + lws_sul_schedule(lds->ctx, 0, &lds->sul, + sul_cb, 50 * LWS_US_PER_MS); +} + +static void +sul_autodim_cb(lws_sorted_usec_list_t *sul) +{ + lws_display_state_t *lds = lws_container_of(sul, lws_display_state_t, + sul_autodim); + + /* we fire both to dim and to blank... if already in dim state, blank */ + + if (lds->state == LWSDISPS_AUTODIMMED) { + lws_display_state_off(lds); + return; + } + + lds->state = LWSDISPS_AUTODIMMED; + lws_display_state_set_brightness(lds, lds->bl_dim, lds->bl_step); + + if (lds->off_ms >= 0) + lws_sul_schedule(lds->ctx, 0, &lds->sul_autodim, sul_autodim_cb, + lds->off_ms * LWS_US_PER_MS); +} + +void +lws_display_state_init(lws_display_state_t *ds, struct lws_context *ctx, + int dim_ms, int off_ms, lws_display_brightness active, + lws_display_brightness dim, const lws_display_t *disp) +{ + memset(ds, 0, sizeof(*ds)); + ds->disp = disp; + ds->ctx = ctx; + ds->autodim_ms = dim_ms; + ds->off_ms = off_ms; + ds->bl_active = active; + ds->bl_dim = dim; +} + +void +lws_display_state_set_brightness(lws_display_state_t *lds, + lws_display_brightness target, + lws_display_brightness step) +{ + lds->bl_target = target; + lds->bl_step = step; + + lws_sul_schedule(lds->ctx, 0, &lds->sul, sul_cb, 1); +} + +void +lws_display_state_active(lws_display_state_t *lds) +{ + if (lds->state == LWSDISPS_OFF) + lds->disp->power(lds->disp, 1); + + if (lds->bl_current != lds->bl_active) + lws_display_state_set_brightness(lds, lds->bl_active, 2); + + /* reset the autodim timer */ + if (lds->autodim_ms >= 0) + lws_sul_schedule(lds->ctx, 0, &lds->sul_autodim, sul_autodim_cb, + lds->autodim_ms * LWS_US_PER_MS); + + lds->state = LWSDISPS_ACTIVE; +} + +void +lws_display_state_off(lws_display_state_t *lds) +{ + lds->disp->power(lds->disp, 0); + lws_sul_cancel(&lds->sul); + lws_sul_cancel(&lds->sul_autodim); + lds->bl_current = 0; + lds->state = LWSDISPS_OFF; +} diff --git a/lib/drivers/display/ssd1306-i2c.c b/lib/drivers/display/ssd1306-i2c.c new file mode 100644 index 00000000..a050271f --- /dev/null +++ b/lib/drivers/display/ssd1306-i2c.c @@ -0,0 +1,151 @@ +/* + * lws abstract display implementation for ssd1306 on i2c + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 +#include + + +static uint8_t ssd1306_128x64_init[] = { + SSD1306_DISPLAYOFF, + SSD1306_SETDISPLAYCLOCKDIV, 0xf0, + SSD1306_SETMULTIPLEX, 64 - 1, + SSD1306_SETDISPLAYOFFSET, 0, + SSD1306_CHARGEPUMP, 0x14, + SSD1306_MEMORYMODE, 0, + SSD1306_SEGREMAP | (0 << 0), + SSD1306_COMSCANDEC, + SSD1306_SETCOMPINS, (1 << 4) | 0x02, + SSD1306_SETCONTRAST, 0, /* start at lowest */ + SSD1306_SETPRECHARGE, (0xf << 4) | (1 << 0), + SSD1306_SETVCOMDESELECT, (4 << 4), + SSD1306_DEACTIVATE_SCROLL, + SSD1306_DISPLAYALLON_RESUME, + SSD1306_NORMALDISPLAY, + SSD1306_DISPLAYON +}; + +int +lws_display_ssd1306_i2c_init(const struct lws_display *disp) +{ + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + + si->i2c->init(si->i2c); + + if (si->gpio) { + si->gpio->mode(si->reset_gpio, LWSGGPIO_FL_WRITE | + LWSGGPIO_FL_PULLUP); + si->gpio->set(si->reset_gpio, 0); + +#if defined(LWS_PLAT_FREERTOS) + vTaskDelay(10); +#else + usleep(10000); +#endif + si->gpio->set(si->reset_gpio, 1); +#if defined(LWS_PLAT_FREERTOS) + vTaskDelay(1); +#else + usleep(1000); +#endif + } + + if (lws_i2c_command_list(si->i2c, si->i2c7_address, + ssd1306_128x64_init, + LWS_ARRAY_SIZE(ssd1306_128x64_init))) { + lwsl_err("%s: fail\n", __func__); + return 1; + } + + return 0; +} + +int +lws_display_ssd1306_i2c_brightness(const struct lws_display *disp, uint8_t b) +{ + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + uint8_t ba[2]; + + ba[0] = SSD1306_SETCONTRAST; + ba[1] = b; + + return lws_i2c_command_list(si->i2c, si->i2c7_address, + ba, LWS_ARRAY_SIZE(ba)); +} + +int +lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h) +{ + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + uint8_t ba[6]; + int n, m; + + /* + * The display is arranged in 128x8 bands, with one byte containing + * the 8 vertical pixels of the band. + */ + + if (h < 8) + h = 8; + + ba[0] = SSD1306_COLUMNADDR; + ba[1] = x; + ba[2] = x + w - 1; + ba[3] = SSD1306_PAGEADDR; + ba[4] = y / 8; + ba[5] = ba[4] + (h / 8) - 1; + + if (lws_i2c_command_list(si->i2c, si->i2c7_address, + ba, LWS_ARRAY_SIZE(ba))) { + lwsl_err("%s: fail\n", __func__); + return 1; + } + + for (n = 0; n < (w * h) / 8;) { + lws_bb_i2c_start(si->i2c); + lws_bb_i2c_write(si->i2c, si->i2c7_address << 1); + lws_bb_i2c_write(si->i2c, SSD1306_SETSTARTLINE | y); + + for (m = 0; m < w; m++) + lws_bb_i2c_write(si->i2c, src[n++]); + + lws_bb_i2c_stop(si->i2c); + y += 8; + } + + return 0; +} + +int +lws_display_ssd1306_i2c_power(const struct lws_display *disp, int state) +{ + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + + if (!state) + return lws_i2c_command(si->i2c, si->i2c7_address, + SSD1306_DISPLAYOFF | !!state); + + return lws_display_ssd1306_i2c_init(disp); +} diff --git a/lib/drivers/i2c/bitbang/lws-bb-i2c.c b/lib/drivers/i2c/bitbang/lws-bb-i2c.c new file mode 100644 index 00000000..99e92a55 --- /dev/null +++ b/lib/drivers/i2c/bitbang/lws-bb-i2c.c @@ -0,0 +1,135 @@ +/* + * I2C bitbang implementation using generic gpio + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ +#include + +int +lws_bb_i2c_init(const lws_i2c_ops_t *octx) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + + ctx->gpio->mode(ctx->scl, LWSGGPIO_FL_WRITE | LWSGGPIO_FL_READ | LWSGGPIO_FL_PULLUP); + ctx->gpio->mode(ctx->sda, LWSGGPIO_FL_WRITE | LWSGGPIO_FL_READ | LWSGGPIO_FL_PULLUP); + + return 0; +} + +int +lws_bb_i2c_start(const lws_i2c_ops_t *octx) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + + ctx->gpio->set(ctx->sda, 1); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + + if (!ctx->gpio->read(ctx->sda)) + return 1; + + ctx->gpio->set(ctx->sda, 0); + ctx->delay(); + ctx->gpio->set(ctx->scl, 0); + + return 0; +} + +void +lws_bb_i2c_stop(const lws_i2c_ops_t *octx) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + + ctx->gpio->set(ctx->sda, 0); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + + while (!ctx->gpio->read(ctx->scl)) + ; + + ctx->gpio->set(ctx->sda, 1); + ctx->delay(); +} + +int +lws_bb_i2c_write(const lws_i2c_ops_t *octx, uint8_t data) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + int n; + + for (n = 0; n < 8; n++) { + ctx->gpio->set(ctx->sda, !!(data & (1 << 7))); + ctx->delay(); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + data <<= 1; + ctx->gpio->set(ctx->scl, 0); + } + + ctx->gpio->set(ctx->sda, 1); + ctx->delay(); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + n = ctx->gpio->read(ctx->sda); + ctx->gpio->set(ctx->scl, 0); + ctx->delay(); + + return !!n; /* 0 = ACKED = OK */ +} + +int +lws_bb_i2c_read(const lws_i2c_ops_t *octx) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + int n, r = 0; + + ctx->gpio->set(ctx->sda, 1); + + for (n = 7; n <= 0; n--) { + ctx->gpio->set(ctx->scl, 0); + ctx->delay(); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + if (ctx->gpio->read(ctx->sda)) + r |= 1 << n; + } + ctx->gpio->set(ctx->scl, 0); + + return r; +} + +void +lws_bb_i2c_set_ack(const lws_i2c_ops_t *octx, int ack) +{ + lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; + + ctx->gpio->set(ctx->scl, 0); + ctx->gpio->set(ctx->sda, !!ack); + ctx->delay(); + ctx->gpio->set(ctx->scl, 1); + ctx->delay(); + ctx->gpio->set(ctx->scl, 0); + ctx->delay(); + ctx->gpio->set(ctx->sda, 1); +} diff --git a/lib/drivers/i2c/lws-i2c.c b/lib/drivers/i2c/lws-i2c.c new file mode 100644 index 00000000..fa00008f --- /dev/null +++ b/lib/drivers/i2c/lws-i2c.c @@ -0,0 +1,59 @@ +/* + * Generic I2C + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * These are generic helpers made up of calls to the i2c driver ops, so they + * just need implementing once like this and are usable for any i2c underlying + * implementation via the ops. + */ + +#include + +int +lws_i2c_command(const lws_i2c_ops_t *ctx, uint8_t ads7, uint8_t c) +{ + if (ctx->start(ctx)) + return 1; + + if (ctx->write(ctx, ads7 << 1)) { + ctx->stop(ctx); + + return 1; + } + + ctx->write(ctx, 0); + ctx->write(ctx, c); + ctx->stop(ctx); + + return 0; +} + +int +lws_i2c_command_list(const lws_i2c_ops_t *ctx, uint8_t ads7, const uint8_t *buf, + size_t len) +{ + while (len--) + if (lws_i2c_command(ctx, ads7, *buf++)) + return 1; + + return 0; +} diff --git a/lib/plat/freertos/esp32/drivers/gpio-esp32.c b/lib/plat/freertos/esp32/drivers/gpio-esp32.c new file mode 100644 index 00000000..163a1409 --- /dev/null +++ b/lib/plat/freertos/esp32/drivers/gpio-esp32.c @@ -0,0 +1,96 @@ +/* + * esp32 / esp-idf gpio + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +static void +lws_gpio_esp32_mode(_lws_plat_gpio_t gpio, int flags) +{ + int mode, pup = GPIO_FLOATING; + + switch (flags & (LWSGGPIO_FL_READ | LWSGGPIO_FL_WRITE)) { + default: + lwsl_err("%s: neither read nor write\n", __func__); + return; + case LWSGGPIO_FL_READ: + mode = GPIO_MODE_INPUT; + break; + case LWSGGPIO_FL_WRITE: + mode = GPIO_MODE_OUTPUT; + break; + case LWSGGPIO_FL_READ | LWSGGPIO_FL_WRITE: + mode = GPIO_MODE_INPUT_OUTPUT; + break; + } + + switch (flags & (LWSGGPIO_FL_PULLUP | LWSGGPIO_FL_PULLDOWN)) { + default: + break; + case LWSGGPIO_FL_PULLUP: + pup = GPIO_PULLUP_ONLY; + break; + case LWSGGPIO_FL_PULLDOWN: + pup = GPIO_PULLDOWN_ONLY; + break; + case LWSGGPIO_FL_PULLUP | LWSGGPIO_FL_PULLDOWN: + pup = GPIO_PULLUP_PULLDOWN; + break; + } + + gpio_reset_pin(gpio); + gpio_set_direction(gpio, mode); + gpio_set_pull_mode(gpio, pup); + gpio_set_level(gpio, flags & LWSGGPIO_FL_START_LOW ? 0 : 1); +} + +static int +lws_gpio_esp32_read(_lws_plat_gpio_t gpio) +{ + return gpio_get_level(gpio); +} +static void +lws_gpio_esp32_set(_lws_plat_gpio_t gpio, int val) +{ + gpio_set_level(gpio, val); +} + +static int +lws_gpio_esp32_irq_mode(_lws_plat_gpio_t gpio, lws_gpio_irq_t irq_type, + lws_gpio_irq_cb_t cb, void *arg) +{ + if (gpio_set_intr_type(gpio, irq_type)) + return 1; + + if (cb) + return gpio_isr_handler_add(gpio, cb, arg); + + return gpio_isr_handler_remove(gpio); +} + +const lws_gpio_ops_t lws_gpio_plat = { + .mode = lws_gpio_esp32_mode, + .read = lws_gpio_esp32_read, + .set = lws_gpio_esp32_set, + .irq_mode = lws_gpio_esp32_irq_mode, +}; diff --git a/lib/plat/freertos/esp32/drivers/lws-plat-gpio.h b/lib/plat/freertos/esp32/drivers/lws-plat-gpio.h new file mode 100644 index 00000000..257d13d8 --- /dev/null +++ b/lib/plat/freertos/esp32/drivers/lws-plat-gpio.h @@ -0,0 +1,25 @@ +/* + * lws generic gpio - esp32 platform wrapper + * + * Written in 2010-2020 by Andy Green + * + * 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. + */ + +extern const lws_gpio_ops_t lws_gpio_plat; diff --git a/lib/plat/freertos/freertos-init.c b/lib/plat/freertos/freertos-init.c index d9996623..9addd761 100644 --- a/lib/plat/freertos/freertos-init.c +++ b/lib/plat/freertos/freertos-init.c @@ -111,5 +111,9 @@ lws_plat_init(struct lws_context *context, context->set = lws_h2_defaults_esp32; #endif +#if defined(LWS_ESP_PLATFORM) + gpio_install_isr_service(0); +#endif + return 0; } diff --git a/minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt b/minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt index 6cf7e915..e17a99ca 100644 --- a/minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt +++ b/minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt @@ -6,6 +6,10 @@ if (ESP_PLATFORM) enable_testing() target_link_libraries(lws-minimal-esp32.elf websockets) + + option(LWS_WITH_DRIVERS "With generic drivers for gpio, i2c, display etc" ON) + set(LWS_WITH_DRIVERS ON) + add_subdirectory(libwebsockets) add_test(NAME flashing COMMAND idf.py flash) diff --git a/minimal-examples/embedded/lws-minimal-esp32/banded-img.h b/minimal-examples/embedded/lws-minimal-esp32/banded-img.h new file mode 100644 index 00000000..7fbe218f --- /dev/null +++ b/minimal-examples/embedded/lws-minimal-esp32/banded-img.h @@ -0,0 +1,64 @@ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xE0, 0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x40, 0xE0, 0x00, 0x80, 0xE0, 0x20, 0x20, +0x20, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0x80, 0x40, 0x20, +0x20, 0x20, 0x60, 0x80, 0x00, 0xE0, 0x40, 0x20, 0x20, 0x60, 0xC0, 0x00, 0x80, 0x40, 0x20, 0x20, +0x20, 0x60, 0x80, 0x00, 0xC0, 0x60, 0x20, 0x20, 0x20, 0xC0, 0x00, 0x80, 0xC0, 0x20, 0x20, 0x20, +0x40, 0xC0, 0x00, 0xE0, 0x00, 0x80, 0x80, 0x60, 0x00, 0x80, 0xC0, 0x20, 0x20, 0x20, 0x60, 0x80, +0x00, 0x00, 0x40, 0x60, 0x20, 0x00, 0xC0, 0x40, 0x20, 0x20, 0x20, 0xC0, 0x40, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7F, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x34, 0x2F, 0x08, 0x08, +0x08, 0x0D, 0x07, 0x00, 0x0F, 0x00, 0x01, 0x0E, 0x0E, 0x01, 0x00, 0x0F, 0x08, 0x02, 0x0F, 0x09, +0x09, 0x19, 0x0F, 0x02, 0x00, 0x7F, 0x19, 0x08, 0x18, 0x08, 0x07, 0x01, 0x00, 0x0E, 0x09, 0x0B, +0x09, 0x0D, 0x04, 0x00, 0x07, 0x08, 0x08, 0x08, 0x08, 0x0F, 0x00, 0x03, 0x0E, 0x08, 0x18, 0x08, +0x0C, 0x04, 0x00, 0x7F, 0x02, 0x07, 0x08, 0x08, 0x00, 0x05, 0x0F, 0x0A, 0x11, 0x09, 0x0D, 0x06, +0x00, 0x08, 0x3F, 0x19, 0x08, 0x00, 0x06, 0x0A, 0x09, 0x09, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xC0, 0x80, 0x00, +0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0xC0, +0xE0, 0xE0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xE0, +0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC1, 0x87, 0x8F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x00, 0x00, +0x00, 0x80, 0x80, 0xC0, 0x83, 0x87, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x83, 0x80, 0x80, 0x80, 0x83, +0x07, 0x0F, 0x1F, 0x0F, 0x0F, 0x0F, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, +0x0F, 0x0F, 0x0F, 0x8F, 0x87, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x00, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xF8, 0x00, 0x28, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, +0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, +0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x00, 0x00, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0x7F, 0x7F, +0x3F, 0x0E, 0x00, 0x05, 0x3F, 0x7F, 0x7F, 0xFF, 0x7F, 0x7F, 0x7F, 0x1F, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0E, 0x3F, 0x7F, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c index 608238e8..da6a672e 100644 --- a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c @@ -21,16 +21,50 @@ #include "esp_wifi.h" #include #include +#include #include +struct lws_context *context; lws_sorted_usec_list_t sul; +lws_display_state_t lds; int interrupted; +static void +esp32_i2c_delay(void) +{ + ets_delay_us(1); +} + +static const lws_bb_i2c_t li2c = { + .bb_ops = lws_bb_i2c_ops, + .scl = GPIO_NUM_15, + .sda = GPIO_NUM_4, + .gpio = &lws_gpio_plat, + .delay = esp32_i2c_delay +}; + +static const lws_display_ssd1306_t disp = { + .disp = { + lws_display_ssd1306_ops, + .w = 128, + .h = 64 + }, + .i2c = (lws_i2c_ops_t *)&li2c, + .gpio = &lws_gpio_plat, + .reset_gpio = GPIO_NUM_16, + .i2c7_address = SSD1306_I2C7_ADS1 +}; + +static const uint8_t img[] = { +#include "../banded-img.h" +}; + static void sul_cb(lws_sorted_usec_list_t *sul) { - interrupted = 1; + //interrupted = 1; + lwsl_notice("Completed: PASS\n"); } void @@ -38,8 +72,6 @@ app_main(void) { wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); struct lws_context_creation_info info; - struct lws_context *context; - esp_chip_info_t chip_info; int n = 0; lws_set_log_level(15, NULL); @@ -54,20 +86,7 @@ app_main(void) memset(&info, 0, sizeof(info)); - lwsl_notice("LWS minimal build test\n"); - - esp_chip_info(&chip_info); - lwsl_notice("chip: %s (%d CPU cores) WiFi%s%s\n", - CONFIG_IDF_TARGET, chip_info.cores, - (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", - (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); - - lwsl_notice("silicon revision %d\n", chip_info.revision); - - lwsl_notice("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024), - (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); - - lwsl_notice("Free heap: %d\n", esp_get_free_heap_size()); + lwsl_notice("LWS test for Heltec WB32 ESP32 board\n"); info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.port = CONTEXT_PORT_NO_LISTEN; @@ -78,7 +97,15 @@ app_main(void) } /* - * We just exit the event loop after 3s + * Show the lws logo on the display + */ + + lws_display_state_init(&lds, context, 10000, 20000, 200, 10, &disp.disp); + lws_display_state_active(&lds); + disp.disp.blit(lds.disp, img, 0, 0, 128, 64); + + /* + * We say the test succeeded if we survive 3s around the event loop */ lws_sul_schedule(context, 0, &sul, sul_cb, 3 * LWS_USEC_PER_SEC); @@ -90,7 +117,6 @@ app_main(void) lws_context_destroy(context); - lwsl_notice("Completed: PASS\n"); // fflush(stdout); // esp_restart(); @@ -99,4 +125,3 @@ spin: taskYIELD(); goto spin; } - diff --git a/minimal-examples/embedded/lws-minimal-esp32/scan/output.bmp b/minimal-examples/embedded/lws-minimal-esp32/scan/output.bmp new file mode 100644 index 0000000000000000000000000000000000000000..bab071c83ebadf9d33f2e48f2b8eb05d01506ef5 GIT binary patch literal 1154 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 z +#include +#include +#include +/* + * The bitmap mapping for the framebuffer is from top left to right, a strip of 8 vertical + * bits from each byte, so there is a block of 128 x 8 px on a stride of 128 bytes. + * + * The 8 bits from the first byte in the fb are the leftmost vertical strip of 8, then the + * next byte is the 8 pixels one to the right, until the 127th byte if the vertical strip + * of 8 on the rhs. + * + * +----------------------------------+ + * |0 | + * |1 | + * |2 | + * |3 | + * |4 | + * |5 | + * |6 | + * |7 | + * + * In this way the fb is more like (8 x vertical (128 x 8)) + * + */ + + +static const uint8_t scan[] = { + +#include "pic.h" +}; + +/* + * input byte 0 is like ABCDEFGH, one bit per horizontal pixel for one line + * on an hstride of 16 bytes + * + * output byte 0 = b0 = byte 0 b0, b1 = byte16 b0, b2 = byte24 b0 etc + * + * px(0,0) --> byte0 b0 + * px(0,1) --> byte0 b1 + */ + +int +main(void) +{ + const uint8_t *p = scan; + uint8_t r[1024]; + int x, y, t = 0; + + memset(&r, 0, sizeof(r)); + + while (t < 1024) { + + for (x = 0; x < 128; x++) { + for (y = 0; y < 8; y++) { + if (p[t + (16 * y) + (x / 8)] & (1 << (7 - (x & 7)))) + r[t + x] |= 1 << y; + } + } + + t += 128; + } + + for (x = 0; x < 1024; x++) { + printf("0x%02X, ", r[x]); + if ((x & 0xf) == 0xf) + printf("\n"); + } +} + diff --git a/minimal-examples/embedded/lws-minimal-esp32/scan/scan.sh b/minimal-examples/embedded/lws-minimal-esp32/scan/scan.sh new file mode 100755 index 00000000..be090a84 --- /dev/null +++ b/minimal-examples/embedded/lws-minimal-esp32/scan/scan.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +convert -size 128x64 /tmp/128x64.png -monochrome output.bmp +dd if=output.bmp bs=1 skip=130 | hexdump -Cv | tr -s ' ' | cut -d' ' -f2-17 | grep ' ' | sed "s/^/0x/g" | sed "s/\ /,\ 0x/g" > pic.h.1 +cat pic.h.1 | sed "s/\$/,/g" > pic.h + +gcc -o scan scan.c && ./scan > ../banded-img.h + -- Gitee From 4948291b8b4d071ddeab8282d4dff795f6fa688c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 12 Jun 2020 07:22:59 +0100 Subject: [PATCH 0164/1062] multipart: quote boundary https://github.com/warmcat/libwebsockets/issues/1948 --- lib/roles/http/client/client-http.c | 2 +- lib/roles/http/server/lws-spa.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 6651e371..cf6ffa8e 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -1027,7 +1027,7 @@ lws_http_multipart_headers(struct lws *wsi, uint8_t *p) wsi->http.multipart_boundary, sizeof(wsi->http.multipart_boundary)); - n = lws_snprintf(arg, sizeof(arg), "multipart/form-data; boundary=%s", + n = lws_snprintf(arg, sizeof(arg), "multipart/form-data; boundary=\"%s\"", wsi->http.multipart_boundary); if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, diff --git a/lib/roles/http/server/lws-spa.c b/lib/roles/http/server/lws-spa.c index 1bbf77a6..fdf146de 100644 --- a/lib/roles/http/server/lws-spa.c +++ b/lib/roles/http/server/lws-spa.c @@ -138,8 +138,10 @@ lws_urldecode_s_create(struct lws_spa *spa, struct lws *wsi, char *out, s->mime_boundary[m++] = '\x0a'; s->mime_boundary[m++] = '-'; s->mime_boundary[m++] = '-'; + if (*p == '\"') + p++; while (m < (int)sizeof(s->mime_boundary) - 1 && - *p && *p != ' ' && *p != ';') + *p && *p != ' ' && *p != ';' && *p != '\"') s->mime_boundary[m++] = *p++; s->mime_boundary[m] = '\0'; -- Gitee From 30e6c22e141d79fdb86e8f46fc66ce6c82cfd821 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 11 Jun 2020 16:09:51 +0100 Subject: [PATCH 0165/1062] openssl3: migrate genhmac to EVP The low level apis for HMAC (including those only introduced at 1.1.0...) are all deprecated in OpenSSL v3. Let's bite the bullet and migrate to EVP, it's already existing in modern OpenSSL and we already use it for genhash. EVP needs a PKEY, sort that out and keep it around until the hmac is destroyed. --- cmake/lws_config.h.in | 1 + include/libwebsockets/lws-genhash.h | 7 +++ lib/tls/CMakeLists.txt | 1 + lib/tls/openssl/lws-genhash.c | 74 +++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+) diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index 9136a8a0..a33f55dc 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -46,6 +46,7 @@ #cmakedefine LWS_HAVE_EVP_aes_256_cfb8 #cmakedefine LWS_HAVE_EVP_aes_256_cfb128 #cmakedefine LWS_HAVE_EVP_aes_128_xts +#cmakedefine LWS_HAVE_EVP_PKEY_new_raw_private_key #cmakedefine LWS_HAVE_EXECVPE #cmakedefine LWS_HAVE_LIBCAP #cmakedefine LWS_HAVE_HMAC_CTX_new diff --git a/include/libwebsockets/lws-genhash.h b/include/libwebsockets/lws-genhash.h index 292a1ff6..8407d2f0 100644 --- a/include/libwebsockets/lws-genhash.h +++ b/include/libwebsockets/lws-genhash.h @@ -74,11 +74,18 @@ struct lws_genhmac_ctx { mbedtls_md_context_t ctx; #else const EVP_MD *evp_type; + +#if defined(LWS_HAVE_EVP_PKEY_new_raw_private_key) + EVP_MD_CTX *ctx; + EVP_PKEY *key; +#else #if defined(LWS_HAVE_HMAC_CTX_new) HMAC_CTX *ctx; #else HMAC_CTX ctx; #endif +#endif + #endif }; diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index 3a502d07..0c48f5d4 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -298,6 +298,7 @@ CHECK_FUNCTION_EXISTS(${VARIA}EVP_aes_128_xts LWS_HAVE_EVP_aes_128_xts PARENT_SC CHECK_FUNCTION_EXISTS(${VARIA}RSA_verify_pss_mgf1 LWS_HAVE_RSA_verify_pss_mgf1 PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}HMAC_CTX_new LWS_HAVE_HMAC_CTX_new PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}SSL_CTX_set_ciphersuites LWS_HAVE_SSL_CTX_set_ciphersuites PARENT_SCOPE) +CHECK_FUNCTION_EXISTS(${VARIA}EVP_PKEY_new_raw_private_key LWS_HAVE_EVP_PKEY_new_raw_private_key PARENT_SCOPE) if (LWS_WITH_SSL AND NOT LWS_WITH_MBEDTLS) # we don't want to confuse what's in or out of the wrapper with diff --git a/lib/tls/openssl/lws-genhash.c b/lib/tls/openssl/lws-genhash.c index 04d881fd..7ff52186 100644 --- a/lib/tls/openssl/lws-genhash.c +++ b/lib/tls/openssl/lws-genhash.c @@ -93,6 +93,78 @@ lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result) return ret; } +#if defined(LWS_HAVE_EVP_PKEY_new_raw_private_key) + +int +lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, + const uint8_t *key, size_t key_len) +{ + ctx->ctx = EVP_MD_CTX_create(); + if (!ctx->ctx) + return -1; + + ctx->evp_type = 0; + ctx->type = type; + + switch (type) { + case LWS_GENHMAC_TYPE_SHA256: + ctx->evp_type = EVP_sha256(); + break; + case LWS_GENHMAC_TYPE_SHA384: + ctx->evp_type = EVP_sha384(); + break; + case LWS_GENHMAC_TYPE_SHA512: + ctx->evp_type = EVP_sha512(); + break; + default: + lwsl_err("%s: unknown HMAC type %d\n", __func__, type); + goto bail; + } + + ctx->key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, key_len); + if (!ctx->key) + goto bail; + + if (EVP_DigestSignInit(ctx->ctx, NULL, ctx->evp_type, NULL, ctx->key) != 1) + goto bail1; + + return 0; + +bail1: + EVP_PKEY_free(ctx->key); +bail: + EVP_MD_CTX_free(ctx->ctx); + + return -1; +} + +int +lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len) +{ + + if (EVP_DigestSignUpdate(ctx->ctx, in, len) != 1) + return -1; + + return 0; +} + +int +lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result) +{ + size_t size = (size_t)lws_genhmac_size(ctx->type); + int n; + + n = EVP_DigestSignFinal(ctx->ctx, result, &size); + EVP_MD_CTX_free(ctx->ctx); + EVP_PKEY_free(ctx->key); + + if (n != 1) + return -1; + + return 0; +} + +#else int lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type, @@ -172,3 +244,5 @@ lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result) return 0; } + +#endif -- Gitee From ac6edaf19970554ac5380f7d41057a05aed1a187 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 15 Jun 2020 15:01:35 +0100 Subject: [PATCH 0166/1062] lws_strexp: add ability to find output length without write Sometimes we need to find out the substituted length before we can allocate and actually store it. Teach strexp that if we set the output buffer to NULL (and the output length to something big) we are asking for the substituted length and to not produce output. --- include/libwebsockets/lws-tokenize.h | 14 ++++++++++++-- lib/core/libwebsockets.c | 14 ++++++++++---- lib/secure-streams/secure-streams.c | 3 ++- .../api-tests/api-test-lws_tokenize/main.c | 14 +++++++++++++- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/include/libwebsockets/lws-tokenize.h b/include/libwebsockets/lws-tokenize.h index e9e6851f..70379de0 100644 --- a/include/libwebsockets/lws-tokenize.h +++ b/include/libwebsockets/lws-tokenize.h @@ -192,10 +192,15 @@ enum { * \p exp: the exp object to init * \p priv: the user's object pointer to pass to callback * \p cb: the callback to expand named objects - * \p out: the start of the output buffer + * \p out: the start of the output buffer, or NULL just to get the length * \p olen: the length of the output buffer in bytes * * Prepares an lws_strexp_t for use and sets the initial output buffer + * + * If \p out is NULL, substitution proceeds normally, but no output is produced, + * only the length is returned. olen should be set to the largest feasible + * overall length. To use this mode, the substitution callback must also check + * for NULL \p out and avoid producing the output. */ LWS_VISIBLE LWS_EXTERN void lws_strexp_init(lws_strexp_t *exp, void *priv, lws_strexp_expand_cb cb, @@ -205,12 +210,17 @@ lws_strexp_init(lws_strexp_t *exp, void *priv, lws_strexp_expand_cb cb, * lws_strexp_reset_out() - reset the output buffer on an existing strexp * * \p exp: the exp object to init - * \p out: the start of the output buffer + * \p out: the start of the output buffer, or NULL to just get length * \p olen: the length of the output buffer in bytes * * Provides a new output buffer for lws_strexp_expand() to continue to write * into. It can be the same as the old one if it has been copied out or used. * The position of the next write will be reset to the start of the given buf. + * + * If \p out is NULL, substitution proceeds normally, but no output is produced, + * only the length is returned. \p olen should be set to the largest feasible + * overall length. To use this mode, the substitution callback must also check + * for NULL \p out and avoid producing the output. */ LWS_VISIBLE LWS_EXTERN void lws_strexp_reset_out(lws_strexp_t *exp, char *out, size_t olen); diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index 4688b3e2..0ad9330d 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -936,7 +936,9 @@ lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len, break; } - exp->out[exp->pos++] = *in; + if (exp->out) + exp->out[exp->pos] = *in; + exp->pos++; if (exp->olen - exp->pos < 1) { *pused_in = used + 1; *pused_out = exp->pos; @@ -955,8 +957,11 @@ lws_strexp_expand(lws_strexp_t *exp, const char *in, size_t len, if (exp->olen - exp->pos < 3) return -1; - exp->out[exp->pos++] = '$'; - exp->out[exp->pos++] = *in; + if (exp->out) { + exp->out[exp->pos++] = '$'; + exp->out[exp->pos++] = *in; + } else + exp->pos += 2; if (*in != '$') exp->state = LWS_EXPS_LITERAL; break; @@ -991,7 +996,8 @@ drain: in++; } - exp->out[exp->pos] = '\0'; + if (exp->out) + exp->out[exp->pos] = '\0'; *pused_in = used; *pused_out = exp->pos; diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 7318b4f1..a8f4ed84 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -167,7 +167,8 @@ lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, if (total < budget) budget = total; - memcpy(out + *pos, replace + (*exp_ofs), budget); + if (out) + memcpy(out + *pos, replace + (*exp_ofs), budget); *exp_ofs += budget; *pos += budget; diff --git a/minimal-examples/api-tests/api-test-lws_tokenize/main.c b/minimal-examples/api-tests/api-test-lws_tokenize/main.c index 9cbc2e3c..7682ede1 100644 --- a/minimal-examples/api-tests/api-test-lws_tokenize/main.c +++ b/minimal-examples/api-tests/api-test-lws_tokenize/main.c @@ -299,7 +299,8 @@ expand: if (total < budget) budget = total; - memcpy(out + *pos, replace + (*exp_ofs), budget); + if (out) + memcpy(out + *pos, replace + (*exp_ofs), budget); *exp_ofs += budget; *pos += budget; @@ -354,6 +355,17 @@ int main(int argc, const char **argv) return 1; } + /* as above, but don't generate output, just find the length */ + + lws_strexp_init(&exp, NULL, exp_cb1, NULL, (size_t)-1); + n = lws_strexp_expand(&exp, exp_inp1, 28, &used_in, &used_out); + if (n != LSTRX_DONE || used_in != 28 || used_out != 39) { + lwsl_err("%s: lws_strexp test 2 failed: %d, used_out: %d\n", + __func__, n, (int)used_out); + + return 1; + } + p = exp_inp1; in_len = strlen(p); memset(obuf, 0, sizeof(obuf)); -- Gitee From c9f31bdcebe023fcfd648a0b487cabd9aa0fce4f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 15 Jun 2020 15:02:52 +0100 Subject: [PATCH 0167/1062] ss-mqtt: additional strexp in MQTT policy elements Allow usage of ${metadata} string substitution in more policy elements for MQTT: - associated subscription topic in policy - associated publish topic in policy - associated will topic in policy - associated will message in policy Tested against lws-minimal-mqtt-client-multi / mosquitto --- .../private-lib-secure-streams.h | 4 + lib/secure-streams/protocols/ss-mqtt.c | 129 ++++++++++++++---- 2 files changed, 109 insertions(+), 24 deletions(-) diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 02e607f6..48e5efe6 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -115,6 +115,10 @@ typedef struct lws_ss_handle { lws_mqtt_topic_elem_t topic_qos; lws_mqtt_topic_elem_t sub_top; lws_mqtt_subscribe_param_t sub_info; + /* allocation that must be destroyed with conn */ + void *heap_baggage; + const char *subscribe_to; + size_t subscribe_to_len; } mqtt; #endif } u; diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 59d5495e..eb2e4bf6 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -44,6 +44,11 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); h->wsi = NULL; + if (h->u.mqtt.heap_baggage) { + lws_free(h->u.mqtt.heap_baggage); + h->u.mqtt.heap_baggage = NULL; + } + lws_ss_backoff(h); break; @@ -54,6 +59,12 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (h->wsi) lws_set_opaque_user_data(h->wsi, NULL); h->wsi = NULL; + + if (h->u.mqtt.heap_baggage) { + lws_free(h->u.mqtt.heap_baggage); + h->u.mqtt.heap_baggage = NULL; + } + if (f) { lws_ss_destroy(&h); break; @@ -118,17 +129,20 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; } - if (h->policy->u.mqtt.subscribe && !wsi->mqtt->done_subscribe) { + if (h->policy->u.mqtt.subscribe && + !wsi->mqtt->done_subscribe) { /* * The policy says to subscribe to something, and we - * haven't done it yet + * haven't done it yet. Do it using the pre-prepared + * string-substituted version of the policy string. */ - lwsl_warn("%s: subscribing %s\n", __func__, h->policy->u.mqtt.subscribe); + lwsl_notice("%s: subscribing %s\n", __func__, + h->u.mqtt.subscribe_to); memset(&h->u.mqtt.sub_top, 0, sizeof(h->u.mqtt.sub_top)); - h->u.mqtt.sub_top.name = h->policy->u.mqtt.subscribe; + h->u.mqtt.sub_top.name = h->u.mqtt.subscribe_to; h->u.mqtt.sub_top.qos = h->policy->u.mqtt.qos; memset(&h->u.mqtt.sub_info, 0, sizeof(h->u.mqtt.sub_info)); h->u.mqtt.sub_info.num_topics = 1; @@ -165,7 +179,8 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, } memset(&mqpp, 0, sizeof(mqpp)); - mqpp.topic = (char *)h->policy->u.mqtt.topic; + /* this is the string-substituted h->policy->u.mqtt.topic */ + mqpp.topic = (char *)h->u.mqtt.topic_qos.name; mqpp.topic_len = strlen(mqpp.topic); mqpp.packet_id = h->txord - 1; mqpp.payload = buf + LWS_PRE; @@ -174,7 +189,8 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, else mqpp.payload_len = buflen; - lwsl_notice("%s: payload len %d\n", __func__, (int)mqpp.payload_len); + lwsl_notice("%s: payload len %d\n", __func__, + (int)mqpp.payload_len); mqpp.qos = h->policy->u.mqtt.qos; @@ -212,25 +228,103 @@ const struct lws_protocols protocol_secstream_mqtt = { * For ws, protocol aux is ; */ +enum { + SSCMM_STRSUB_WILL_TOPIC, + SSCMM_STRSUB_WILL_MESSAGE, + SSCMM_STRSUB_SUBSCRIBE, + SSCMM_STRSUB_TOPIC +}; + static int secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *sources[4] = { + /* we're going to string-substitute these before use */ + h->policy->u.mqtt.will_topic, + h->policy->u.mqtt.will_message, + h->policy->u.mqtt.subscribe, + h->policy->u.mqtt.topic + }; + size_t used_in, olen[4] = { 0, 0, 0, 0 }, tot = 0; + lws_strexp_t exp; + char *p, *ps[4]; + int n; + memset(&ct->ccp, 0, sizeof(ct->ccp)); ct->ccp.client_id = "lwsMqttClient"; ct->ccp.keep_alive = h->policy->u.mqtt.keep_alive; ct->ccp.clean_start = h->policy->u.mqtt.clean_start; - ct->ccp.will_param.topic = h->policy->u.mqtt.will_topic; - ct->ccp.will_param.message = h->policy->u.mqtt.will_message; ct->ccp.will_param.qos = h->policy->u.mqtt.will_qos; ct->ccp.will_param.retain = h->policy->u.mqtt.will_retain; + h->u.mqtt.topic_qos.qos = h->policy->u.mqtt.qos; + + /* + * We're going to string-substitute several of these parameters, which + * have unknown, possibly large size. And, as their usage is deferred + * inside the asynchronous lifetime of the MQTT connection, they need + * to live on the heap. + * + * Notice these allocations at h->u.mqtt.heap_baggage belong to the + * underlying MQTT stream lifetime, not the logical SS lifetime, and + * are destroyed if present at connection error or close of the + * underlying connection. + * + * + * First, compute the length of each without producing strsubst output, + * and keep a running total. + */ + + for (n = 0; n < (int)LWS_ARRAY_SIZE(sources); n++) { + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, + NULL, (size_t)-1); + if (lws_strexp_expand(&exp, sources[n], strlen(sources[n]), + &used_in, &olen[n]) != LSTRX_DONE) { + lwsl_err("%s: failed to subsitute %s\n", __func__, + sources[n]); + return 1; + } + tot += olen[n] + 1; + } + + /* + * Then, allocate enough space on the heap for the total of the + * substituted results + */ + + h->u.mqtt.heap_baggage = lws_malloc(tot, __func__); + if (!h->u.mqtt.heap_baggage) + return 1; + + /* + * Finally, issue the subsitutions one after the other into the single + * allocated result buffer and prepare pointers into them + */ + + p = h->u.mqtt.heap_baggage; + for (n = 0; n < (int)LWS_ARRAY_SIZE(sources); n++) { + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, + p, (size_t)-1); + ps[n] = p; + if (lws_strexp_expand(&exp, sources[n], strlen(sources[n]), + &used_in, &olen[n]) != LSTRX_DONE) + return 1; + + p += olen[n] + 1; + } - lwsl_notice("%s\n", __func__); + /* + * Point the guys who want the substituted content at the substituted + * strings + */ - h->u.mqtt.topic_qos.name = h->policy->u.mqtt.subscribe; - h->u.mqtt.topic_qos.qos = h->policy->u.mqtt.qos; + ct->ccp.will_param.topic = ps[SSCMM_STRSUB_WILL_TOPIC]; + ct->ccp.will_param.message = ps[SSCMM_STRSUB_WILL_MESSAGE]; + h->u.mqtt.subscribe_to = ps[SSCMM_STRSUB_SUBSCRIBE]; + h->u.mqtt.subscribe_to_len = olen[SSCMM_STRSUB_SUBSCRIBE]; + h->u.mqtt.topic_qos.name = ps[SSCMM_STRSUB_TOPIC]; i->method = "MQTT"; i->mqtt_cp = &ct->ccp; @@ -240,19 +334,6 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, /* share connections where possible */ i->ssl_connection |= LCCSCF_PIPELINE; -/* - if (!h->policy->u.http.url) - return 0; - - // protocol aux is the path part ; ws subprotocol name - - i->path = NULL; - lws_snprintf(buf, len, "/%s", h->policy->u.mqtt.topic); - -// i->protocol = h->policy->u.mqtt.u.ws.subprotocol; - - lwsl_notice("%s: url %s, ws subprotocol %s\n", __func__, buf, i->protocol); -*/ return 0; } -- Gitee From b324f0e43b668c8be3b8642c48053cb2dd251263 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 15 Jun 2020 19:49:35 +0100 Subject: [PATCH 0168/1062] cmake: provide LIBWEBSOCKETS_DEP_LIBS in CONFIG --- cmake/libwebsockets-config.cmake.in | 10 +++++++++- .../abstract/protocols/smtp-client/CMakeLists.txt | 4 ++-- .../api-tests/api-test-async-dns/CMakeLists.txt | 4 ++-- .../api-tests/api-test-dhcpc/CMakeLists.txt | 4 ++-- minimal-examples/api-tests/api-test-fts/CMakeLists.txt | 4 ++-- .../api-tests/api-test-gencrypto/CMakeLists.txt | 4 ++-- .../api-tests/api-test-jose/CMakeLists.txt | 4 ++-- .../api-tests/api-test-lejp/CMakeLists.txt | 4 ++-- .../api-tests/api-test-lws_dsh/CMakeLists.txt | 4 ++-- .../api-tests/api-test-lws_sequencer/CMakeLists.txt | 4 ++-- .../api-tests/api-test-lws_struct-json/CMakeLists.txt | 4 ++-- .../api-test-lws_struct_sqlite/CMakeLists.txt | 4 ++-- .../api-tests/api-test-lws_tokenize/CMakeLists.txt | 4 ++-- .../api-tests/api-test-lwsac/CMakeLists.txt | 4 ++-- .../api-tests/api-test-secure-streams/CMakeLists.txt | 4 ++-- .../api-tests/api-test-smtp_client/CMakeLists.txt | 4 ++-- .../client-server/minimal-ws-proxy/CMakeLists.txt | 4 ++-- .../crypto/minimal-crypto-jwe/CMakeLists.txt | 4 ++-- .../crypto/minimal-crypto-jwk/CMakeLists.txt | 4 ++-- .../crypto/minimal-crypto-jws/CMakeLists.txt | 4 ++-- .../crypto/minimal-crypto-x509/CMakeLists.txt | 4 ++-- .../dbus-client/minimal-dbus-client/CMakeLists.txt | 4 ++-- .../minimal-dbus-ws-proxy-testclient/CMakeLists.txt | 4 ++-- .../dbus-server/minimal-dbus-server/CMakeLists.txt | 4 ++-- .../dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt | 4 ++-- minimal-examples/gtk/minimal-gtk/CMakeLists.txt | 4 ++-- .../minimal-http-client-attach/CMakeLists.txt | 4 ++-- .../minimal-http-client-captive-portal/CMakeLists.txt | 4 ++-- .../minimal-http-client-certinfo/CMakeLists.txt | 4 ++-- .../minimal-http-client-custom-headers/CMakeLists.txt | 4 ++-- .../minimal-http-client-h2-rxflow/CMakeLists.txt | 4 ++-- .../minimal-http-client-hugeurl/CMakeLists.txt | 4 ++-- .../minimal-http-client-multi/CMakeLists.txt | 4 ++-- .../minimal-http-client-post/CMakeLists.txt | 4 ++-- .../http-client/minimal-http-client/CMakeLists.txt | 4 ++-- .../minimal-http-server-basicauth/CMakeLists.txt | 4 ++-- .../http-server/minimal-http-server-cgi/CMakeLists.txt | 4 ++-- .../minimal-http-server-custom-headers/CMakeLists.txt | 4 ++-- .../minimal-http-server-deaddrop/CMakeLists.txt | 4 ++-- .../minimal-http-server-dynamic/CMakeLists.txt | 4 ++-- .../minimal-http-server-eventlib-demos/CMakeLists.txt | 4 ++-- .../CMakeLists.txt | 4 ++-- .../minimal-http-server-eventlib-smp/CMakeLists.txt | 4 ++-- .../minimal-http-server-eventlib/CMakeLists.txt | 4 ++-- .../minimal-http-server-form-get/CMakeLists.txt | 4 ++-- .../minimal-http-server-form-post-file/CMakeLists.txt | 4 ++-- .../minimal-http-server-form-post-lwsac/CMakeLists.txt | 4 ++-- .../minimal-http-server-form-post/CMakeLists.txt | 4 ++-- .../minimal-http-server-fulltext-search/CMakeLists.txt | 4 ++-- .../CMakeLists.txt | 4 ++-- .../minimal-http-server-h2-long-poll/CMakeLists.txt | 4 ++-- .../minimal-http-server-mimetypes/CMakeLists.txt | 4 ++-- .../minimal-http-server-multivhost/CMakeLists.txt | 4 ++-- .../minimal-http-server-proxy/CMakeLists.txt | 4 ++-- .../http-server/minimal-http-server-smp/CMakeLists.txt | 4 ++-- .../minimal-http-server-sse-ring/CMakeLists.txt | 5 +++-- .../http-server/minimal-http-server-sse/CMakeLists.txt | 4 ++-- .../minimal-http-server-tls-80/CMakeLists.txt | 4 ++-- .../minimal-http-server-tls-mem/CMakeLists.txt | 4 ++-- .../http-server/minimal-http-server-tls/CMakeLists.txt | 4 ++-- .../http-server/minimal-http-server/CMakeLists.txt | 4 ++-- .../minimal-mqtt-client-multi/CMakeLists.txt | 4 ++-- .../mqtt-client/minimal-mqtt-client/CMakeLists.txt | 4 ++-- .../raw/minimal-raw-adopt-tcp/CMakeLists.txt | 4 ++-- .../raw/minimal-raw-adopt-udp/CMakeLists.txt | 4 ++-- minimal-examples/raw/minimal-raw-audio/CMakeLists.txt | 4 ++-- .../minimal-raw-fallback-http-server/CMakeLists.txt | 4 ++-- minimal-examples/raw/minimal-raw-file/CMakeLists.txt | 4 ++-- minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt | 4 ++-- .../raw/minimal-raw-proxy-fallback/CMakeLists.txt | 4 ++-- minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt | 4 ++-- minimal-examples/raw/minimal-raw-serial/CMakeLists.txt | 4 ++-- minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt | 4 ++-- .../minimal-secure-streams-alexa/CMakeLists.txt | 8 ++++---- .../minimal-secure-streams-avs/CMakeLists.txt | 8 ++++---- .../minimal-secure-streams-client-tx/CMakeLists.txt | 4 ++-- .../minimal-secure-streams-metadata/CMakeLists.txt | 8 ++++---- .../minimal-secure-streams-policy2c/CMakeLists.txt | 4 ++-- .../minimal-secure-streams-proxy/CMakeLists.txt | 4 ++-- .../minimal-secure-streams-seq/CMakeLists.txt | 4 ++-- .../minimal-secure-streams-sink/CMakeLists.txt | 4 ++-- .../minimal-secure-streams-staticpolicy/CMakeLists.txt | 4 ++-- .../minimal-secure-streams/CMakeLists.txt | 8 ++++---- .../ws-client/minimal-ws-client-echo/CMakeLists.txt | 4 ++-- .../ws-client/minimal-ws-client-ping/CMakeLists.txt | 4 ++-- .../minimal-ws-client-pmd-bulk/CMakeLists.txt | 4 ++-- .../ws-client/minimal-ws-client-rx/CMakeLists.txt | 4 ++-- .../ws-client/minimal-ws-client-spam/CMakeLists.txt | 4 ++-- .../ws-client/minimal-ws-client-tx/CMakeLists.txt | 4 ++-- .../ws-client/minimal-ws-client/CMakeLists.txt | 4 ++-- .../ws-server/minimal-ws-broker/CMakeLists.txt | 4 ++-- .../ws-server/minimal-ws-server-echo/CMakeLists.txt | 4 ++-- .../minimal-ws-server-pmd-bulk/CMakeLists.txt | 4 ++-- .../minimal-ws-server-pmd-corner/CMakeLists.txt | 4 ++-- .../ws-server/minimal-ws-server-pmd/CMakeLists.txt | 4 ++-- .../ws-server/minimal-ws-server-ring/CMakeLists.txt | 4 ++-- .../minimal-ws-server-threadpool/CMakeLists.txt | 4 ++-- .../minimal-ws-server-threads-smp/CMakeLists.txt | 4 ++-- .../ws-server/minimal-ws-server-threads/CMakeLists.txt | 4 ++-- .../ws-server/minimal-ws-server-timer/CMakeLists.txt | 4 ++-- .../ws-server/minimal-ws-server/CMakeLists.txt | 4 ++-- plugin-standalone/CMakeLists.txt | 3 ++- 102 files changed, 220 insertions(+), 210 deletions(-) diff --git a/cmake/libwebsockets-config.cmake.in b/cmake/libwebsockets-config.cmake.in index bea82b58..c683335c 100644 --- a/cmake/libwebsockets-config.cmake.in +++ b/cmake/libwebsockets-config.cmake.in @@ -1,4 +1,5 @@ -# - Config file for the Libevent package +# - Config file for lws + # It defines the following variables # LIBWEBSOCKETS_INCLUDE_DIRS - include directories for FooBar # LIBWEBSOCKETS_LIBRARIES - libraries to link against @@ -15,3 +16,10 @@ include(${LWS_CMAKE_DIR}/LibwebsocketsTargets.cmake) # IMPORTED targets from LibwebsocketsTargets.cmake set(LIBWEBSOCKETS_LIBRARIES websockets websockets_shared) +# These are additional libs that lws wants your app to also link to +if (NOT WIN32 AND NOT MSVC) + set(LIBWEBSOCKETS_DEP_LIBS @LIB_LIST_AT_END@) +else() + set(LIBWEBSOCKETS_DEP_LIBS) +endif() + diff --git a/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt b/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt index 60ad5e48..bcff88d8 100644 --- a/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt +++ b/minimal-examples/abstract/protocols/smtp-client/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt b/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt index 6a29ebc6..56168861 100644 --- a/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt @@ -22,9 +22,9 @@ if (requirements) TIMEOUT 60) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt b/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt index 27887a22..8faf9c53 100644 --- a/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-dhcpc/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-fts/CMakeLists.txt b/minimal-examples/api-tests/api-test-fts/CMakeLists.txt index 53256709..15db9566 100644 --- a/minimal-examples/api-tests/api-test-fts/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-fts/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt index 4344bb57..f9a20f32 100644 --- a/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-gencrypto/CMakeLists.txt @@ -19,10 +19,10 @@ if (requirements) add_test(NAME api-test-gencrypto COMMAND lws-api-test-gencrypto) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-jose/CMakeLists.txt b/minimal-examples/api-tests/api-test-jose/CMakeLists.txt index 32a9dcf6..27ab3a17 100644 --- a/minimal-examples/api-tests/api-test-jose/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-jose/CMakeLists.txt @@ -20,9 +20,9 @@ if (requirements) endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt b/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt index 04835c37..d9575dbd 100644 --- a/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lejp/CMakeLists.txt @@ -14,9 +14,9 @@ if (requirements) add_test(NAME api-test-lejp COMMAND lws-api-test-lejp) if (websockets_shared) - target_link_libraries(${PROJECT_NAME} websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${PROJECT_NAME} websockets_shared) else() - target_link_libraries(${PROJECT_NAME} websockets) + target_link_libraries(${PROJECT_NAME} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt index 6eb7e030..0c9134cb 100644 --- a/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_dsh/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_test(NAME api-test-lws_dsh COMMAND lws-api-test-lws_dsh) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt index 6e5101eb..72e7af17 100644 --- a/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_sequencer/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt index a752480c..a5a60bee 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_struct-json/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_test(NAME api-test-lws_struct-json COMMAND lws-api-test-lws_struct-json) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt index e30388e1..38bbbf47 100644 --- a/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_struct_sqlite/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_test(NAME api-test-lws_struct_sqlite COMMAND lws-api-test-lws_struct-sqlite) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared sqlite3) + target_link_libraries(${SAMP} websockets_shared sqlite3 ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets sqlite3) + target_link_libraries(${SAMP} websockets sqlite3 ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt index 0ab7308a..9a46db0a 100644 --- a/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lws_tokenize/CMakeLists.txt @@ -12,8 +12,8 @@ set(SRCS main.c) add_test(NAME api-test-lws_tokenize COMMAND lws-api-test-lws_tokenize) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() diff --git a/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt b/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt index ed394e95..1ba2ef27 100644 --- a/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-lwsac/CMakeLists.txt @@ -12,8 +12,8 @@ add_executable(${SAMP} ${SRCS}) add_test(NAME api-test-lwsac COMMAND lws-api-test-lwsac) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() diff --git a/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt b/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt index 998c2c49..98015b42 100644 --- a/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt @@ -19,10 +19,10 @@ if (requirements) endif() if (websockets_shared) - target_link_libraries(${PROJECT_NAME} websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${PROJECT_NAME} websockets_shared) else() - target_link_libraries(${PROJECT_NAME} websockets) + target_link_libraries(${PROJECT_NAME} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt b/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt index 07715d0d..eccf2738 100644 --- a/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-smtp_client/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt b/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt index eaaa3068..85c74449 100644 --- a/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt +++ b/minimal-examples/client-server/minimal-ws-proxy/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff --git a/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt b/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt index f43e1f9b..67f19e16 100644 --- a/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt +++ b/minimal-examples/crypto/minimal-crypto-jwe/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt b/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt index 8649dc02..0c5924ca 100644 --- a/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt +++ b/minimal-examples/crypto/minimal-crypto-jwk/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt b/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt index 7fc01c99..ad73a324 100644 --- a/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt +++ b/minimal-examples/crypto/minimal-crypto-jws/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt b/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt index e5b348bb..90720c81 100644 --- a/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt +++ b/minimal-examples/crypto/minimal-crypto-x509/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt b/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt index ee42b478..468ecd46 100644 --- a/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt +++ b/minimal-examples/dbus-client/minimal-dbus-client/CMakeLists.txt @@ -26,9 +26,9 @@ if (NOT MSVC AND NOT WIN32 AND requirements) include_directories("${LWS_DBUS_INCLUDE1}") if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB}) else() - target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB}) + target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt index 7b1872fe..bd318287 100644 --- a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt +++ b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt @@ -23,9 +23,9 @@ if (NOT MSVC AND NOT WIN32 AND requirements) include_directories("${LWS_DBUS_INCLUDE1}") message("project ${PROJECT_NAME}") if (websockets_shared) - target_link_libraries(${PROJECT_NAME} websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${PROJECT_NAME} websockets_shared ${LWS_DBUS_LIB}) else() - target_link_libraries(${PROJECT_NAME} websockets ${LWS_DBUS_LIB}) + target_link_libraries(${PROJECT_NAME} websockets ${LWS_DBUS_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt b/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt index e809cc8c..cf479f32 100644 --- a/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt +++ b/minimal-examples/dbus-server/minimal-dbus-server/CMakeLists.txt @@ -26,9 +26,9 @@ if (NOT MSVC AND NOT WIN32 AND requirements) include_directories("${LWS_DBUS_INCLUDE1}") if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB}) else() - target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB}) + target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt index 04844be7..3802d5a4 100644 --- a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt +++ b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt @@ -28,9 +28,9 @@ if (NOT MSVC AND NOT WIN32 AND requirements) include_directories("${LWS_DBUS_INCLUDE1}") if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB}) else() - target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB}) + target_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/gtk/minimal-gtk/CMakeLists.txt b/minimal-examples/gtk/minimal-gtk/CMakeLists.txt index 6b33e25b..c0a1ba5c 100644 --- a/minimal-examples/gtk/minimal-gtk/CMakeLists.txt +++ b/minimal-examples/gtk/minimal-gtk/CMakeLists.txt @@ -39,9 +39,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${extralibs}) + target_link_libraries(${SAMP} websockets_shared ${extralibs} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${extralibs}) + target_link_libraries(${SAMP} websockets ${extralibs} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt index a7938d1f..0dd9dfc7 100644 --- a/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-attach/CMakeLists.txt @@ -19,9 +19,9 @@ if (requirements AND NOT WIN32) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt index e3616903..e369b1b8 100644 --- a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt @@ -17,9 +17,9 @@ if (NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread) + target_link_libraries(${SAMP} websockets_shared pthread ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread) + target_link_libraries(${SAMP} websockets pthread ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt index 70773824..7995ae2a 100644 --- a/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-certinfo/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt index 948d10d9..faf6454b 100644 --- a/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-custom-headers/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt index 1dcbdb99..f3ae1a79 100644 --- a/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt @@ -25,9 +25,9 @@ if (requirements) endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt index 0805bc6d..947d7a00 100644 --- a/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-hugeurl/CMakeLists.txt @@ -27,9 +27,9 @@ if (requirements) endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt index 7ccc6d83..47717552 100644 --- a/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt @@ -164,9 +164,9 @@ endif() endif(NOT WIN32 AND LWS_WITH_SERVER) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt index 37d27967..b4ed0b32 100644 --- a/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-post/CMakeLists.txt @@ -82,9 +82,9 @@ endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt index 49e11b83..7405e74f 100644 --- a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt @@ -27,9 +27,9 @@ if (requirements) #endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt index 5faf9746..c348226d 100644 --- a/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-basicauth/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt index 3bb6def6..0e0b1719 100644 --- a/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-cgi/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt index 7c0ad4be..af6e43d0 100644 --- a/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-custom-headers/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt index ee150551..d048c97d 100644 --- a/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-deaddrop/CMakeLists.txt @@ -26,9 +26,9 @@ if (requirements AND UNIX) endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt index 0d579d68..9793b3c5 100644 --- a/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-dynamic/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt index ff379de3..20cc980e 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt index ebcfe8fd..ddeb8c48 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/CMakeLists.txt @@ -76,9 +76,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${extralibs}) + target_link_libraries(${SAMP} websockets_shared ${extralibs} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${extralibs}) + target_link_libraries(${SAMP} websockets ${extralibs} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt index 4243d76f..1a51e54c 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib-smp/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared ${PTHREAD_LIB}) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt index 5d89fcfd..87472050 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-eventlib/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt index 2dec8623..58138ee9 100644 --- a/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-form-get/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt index 664ed06f..d92699b0 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-form-post-file/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt index d7872d83..874e1709 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-form-post-lwsac/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt index 9c17a794..91964526 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-form-post/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt index b80bcbcb..2bbdb4e6 100644 --- a/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-fulltext-search/CMakeLists.txt @@ -19,9 +19,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt index c298dd7c..6a24a7be 100644 --- a/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-generic-sessions/CMakeLists.txt @@ -20,9 +20,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt index 4321f6d3..e555b25a 100644 --- a/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-h2-long-poll/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt index 1e4a756e..2f94229a 100644 --- a/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-mimetypes/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt index 9db33227..ba35291c 100644 --- a/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-multivhost/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff --git a/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt index 082507e7..ddac1153 100644 --- a/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-proxy/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt index ea0d4771..fa96c134 100644 --- a/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-smp/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff --git a/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt index 604ef00b..72085768 100644 --- a/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-sse-ring/CMakeLists.txt @@ -1,5 +1,6 @@ project(lws-minimal-http-server-sse-ring) cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) include(CheckIncludeFile) include(CheckCSourceCompiles) @@ -15,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt index 9970d3ca..ce4f6077 100644 --- a/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-sse/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt index 44082ffc..2434de7b 100644 --- a/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-tls-80/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt index ab88835e..dec8d79c 100644 --- a/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-tls-mem/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt index 73a07211..5044310f 100644 --- a/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server-tls/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/http-server/minimal-http-server/CMakeLists.txt b/minimal-examples/http-server/minimal-http-server/CMakeLists.txt index 54b412ef..0fca5bad 100644 --- a/minimal-examples/http-server/minimal-http-server/CMakeLists.txt +++ b/minimal-examples/http-server/minimal-http-server/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt index 2e91b417..7e878efe 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt +++ b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt b/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt index 3d729068..a0d05db4 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt +++ b/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt @@ -14,9 +14,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt b/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt index 38ced079..24adc568 100644 --- a/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-adopt-tcp/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt b/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt index b41ec507..2c7eb9db 100644 --- a/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-adopt-udp/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt b/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt index ca007d4c..43342812 100644 --- a/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-audio/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared asound) + target_link_libraries(${SAMP} websockets_shared asound ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets asound) + target_link_libraries(${SAMP} websockets asound ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt b/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt index 45361e92..88d879ed 100644 --- a/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-fallback-http-server/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-file/CMakeLists.txt b/minimal-examples/raw/minimal-raw-file/CMakeLists.txt index 60e2f755..ecb632ee 100644 --- a/minimal-examples/raw/minimal-raw-file/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-file/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff --git a/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt b/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt index c848c731..e47cf0c0 100644 --- a/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-netcat/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt b/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt index c83e5f66..e1ab2765 100644 --- a/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-proxy-fallback/CMakeLists.txt @@ -23,9 +23,9 @@ if (requirements) endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt b/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt index 27aa5ee2..457946f4 100644 --- a/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-proxy/CMakeLists.txt @@ -23,9 +23,9 @@ if (requirements) endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt b/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt index b7061782..31e51795 100644 --- a/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-serial/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements AND UNIX) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt b/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt index 9e1f1993..8cb05a8a 100644 --- a/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt +++ b/minimal-examples/raw/minimal-raw-vhost/CMakeLists.txt @@ -15,9 +15,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt index 1a7b6b49..077440a1 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt @@ -19,10 +19,10 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared asound pv_porcupine mpg123) + target_link_libraries(${SAMP} websockets_shared asound pv_porcupine mpg123 ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets asound pv_porcupine mpg123) + target_link_libraries(${SAMP} websockets asound pv_porcupine mpg123 ${LIBWEBSOCKETS_DEP_LIBS}) endif() if (LWS_WITH_SECURE_STREAMS_PROXY_API) @@ -30,10 +30,10 @@ if (requirements) add_executable(${SAMP}-client ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP}-client websockets_shared asound pv_porcupine mpg123) + target_link_libraries(${SAMP}-client websockets_shared asound pv_porcupine mpg123 ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP}-client websockets_shared) else() - target_link_libraries(${SAMP}-client websockets asound pv_porcupine mpg123) + target_link_libraries(${SAMP}-client websockets asound pv_porcupine mpg123 ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt index 0c4d91d8..edb410de 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt @@ -17,10 +17,10 @@ if (requirements) add_executable(${SAMP} main.c avs.c) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() if (LWS_WITH_SECURE_STREAMS_PROXY_API) @@ -28,10 +28,10 @@ if (requirements) add_executable(${SAMP}-client main-client.c avs.c) if (websockets_shared) - target_link_libraries(${SAMP}-client websockets_shared) + target_link_libraries(${SAMP}-client websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP}-client websockets_shared) else() - target_link_libraries(${SAMP}-client websockets) + target_link_libraries(${SAMP}-client websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt index c18fec9f..36908aad 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-client-tx/CMakeLists.txt @@ -19,9 +19,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt index 1fd06ea7..267568d4 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt @@ -17,10 +17,10 @@ if (requirements) add_executable(${SAMP} minimal-secure-streams.c) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() if (LWS_WITH_SECURE_STREAMS_PROXY_API) @@ -28,10 +28,10 @@ if (requirements) add_executable(${SAMP}-client minimal-secure-streams.c) if (websockets_shared) - target_link_libraries(${SAMP}-client websockets_shared) + target_link_libraries(${SAMP}-client websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP}-client websockets_shared) else() - target_link_libraries(${SAMP}-client websockets) + target_link_libraries(${SAMP}-client websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt index 0ed47004..5bbb4b94 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/CMakeLists.txt @@ -19,10 +19,10 @@ if (requirements) add_executable(${SAMP} minimal-secure-streams.c) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt index e27cbd7d..485205fc 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt @@ -19,9 +19,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt index 093fda6f..673c6294 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-seq/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt index 1cbfe002..0725d601 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-sink/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt index a54f7387..3e2b33b0 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/CMakeLists.txt @@ -17,10 +17,10 @@ if (requirements) add_executable(${SAMP} minimal-secure-streams.c) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt index 8489a756..8428f9db 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt @@ -25,10 +25,10 @@ if (requirements) endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() if (LWS_WITH_SECURE_STREAMS_PROXY_API) @@ -36,10 +36,10 @@ if (requirements) add_executable(${SAMP}-client minimal-secure-streams.c) if (websockets_shared) - target_link_libraries(${SAMP}-client websockets_shared) + target_link_libraries(${SAMP}-client websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP}-client websockets_shared) else() - target_link_libraries(${SAMP}-client websockets) + target_link_libraries(${SAMP}-client websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt index eae57afb..2795831c 100644 --- a/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-echo/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt index 887dc21e..f5234b1c 100644 --- a/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-ping/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt index 08a00c9c..eba3611c 100644 --- a/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-pmd-bulk/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt index 7f5fe2fb..1122e167 100644 --- a/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-rx/CMakeLists.txt @@ -24,9 +24,9 @@ if (requirements) endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt index d8efb1d1..9aa2dad6 100644 --- a/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-spam/CMakeLists.txt @@ -65,9 +65,9 @@ endif() endif() if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt index 274a28e7..2de3dd9d 100644 --- a/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client-tx/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff --git a/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt b/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt index e936d1eb..782af5b8 100644 --- a/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt +++ b/minimal-examples/ws-client/minimal-ws-client/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt index 70082d1d..2c262d52 100644 --- a/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-broker/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff --git a/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt index 523d823c..cb764386 100644 --- a/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-echo/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt index b9cfaa6e..8e09d5e0 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-bulk/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt index 6d0347f2..87f4e5fa 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-pmd-corner/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt index 2651af7f..88d64453 100644 --- a/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-pmd/CMakeLists.txt @@ -17,9 +17,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt index b235a6b0..22b95ee0 100644 --- a/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-ring/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt index 96f2aee6..8d22126c 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threadpool/CMakeLists.txt @@ -19,9 +19,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt index 8a5b92ab..c3721e46 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threads-smp/CMakeLists.txt @@ -18,9 +18,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt index f359ab5b..e4eb00e8 100644 --- a/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-threads/CMakeLists.txt @@ -21,9 +21,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets ${PTHREAD_LIB}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt index ee6dc79f..6cabd11d 100644 --- a/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server-timer/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt b/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt index 1f2e6f8a..e590cea8 100644 --- a/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt +++ b/minimal-examples/ws-server/minimal-ws-server/CMakeLists.txt @@ -16,9 +16,9 @@ if (requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets) + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() \ No newline at end of file diff --git a/plugin-standalone/CMakeLists.txt b/plugin-standalone/CMakeLists.txt index 2d213e99..39e8e566 100644 --- a/plugin-standalone/CMakeLists.txt +++ b/plugin-standalone/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) if(NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type") @@ -57,7 +58,7 @@ source_group("Headers Private" FILES ${PLUGIN_HDR}) source_group("Sources" FILES ${PLUGIN_SRCS}) add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SRCS} ${PLUGIN_HDR}) -target_link_libraries(${PLUGIN_NAME} -lwebsockets) +target_link_libraries(${PLUGIN_NAME} -lwebsockets ${LIBWEBSOCKETS_DEP_LIBS}) # Set test app specific defines. set_property(TARGET ${PLUGIN_NAME} -- Gitee From fdf8a5f9311423836cf2b36891aa98292ad10fdf Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 16 Jun 2020 09:28:06 +0100 Subject: [PATCH 0169/1062] lws_mutex Add a simple platform wrapper around OS mutexes. *nix and windows == pthreads freertos = SemaphoreHandle --- lib/plat/freertos/private-lib-plat-freertos.h | 6 ++++++ lib/plat/unix/private-lib-plat-unix.h | 9 +++++++++ lib/plat/windows/private-lib-plat-windows.h | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/lib/plat/freertos/private-lib-plat-freertos.h b/lib/plat/freertos/private-lib-plat-freertos.h index 052f43ad..f8d61499 100644 --- a/lib/plat/freertos/private-lib-plat-freertos.h +++ b/lib/plat/freertos/private-lib-plat-freertos.h @@ -72,6 +72,12 @@ gai_strerror(int); #include #endif +typedef SemaphoreHandle_t lws_mutex_t; +#define lws_mutex_init(x) x = xSemaphoreCreateMutex() +#define lws_mutex_destroy(x) vSemaphoreDelete(x) +#define lws_mutex_lock(x) xSemaphoreTake(x, portMAX_DELAY) +#define lws_mutex_unlock(x) xSemaphoreGive(x) + #include #if defined(LWS_BUILTIN_GETIFADDRS) diff --git a/lib/plat/unix/private-lib-plat-unix.h b/lib/plat/unix/private-lib-plat-unix.h index d64f8988..feb22273 100644 --- a/lib/plat/unix/private-lib-plat-unix.h +++ b/lib/plat/unix/private-lib-plat-unix.h @@ -75,6 +75,15 @@ #endif #endif +#if defined(LWS_HAVE_PTHREAD_H) +#include +typedef pthread_mutex_t lws_mutex_t; +#define lws_mutex_init(x) pthread_mutex_init(&(x), NULL) +#define lws_mutex_destroy(x) pthread_mutex_destroy(&(x)) +#define lws_mutex_lock(x) pthread_mutex_lock(&(x)) +#define lws_mutex_unlock(x) pthread_mutex_unlock(&(x)) +#endif + #if defined(__sun) && defined(__GNUC__) #include diff --git a/lib/plat/windows/private-lib-plat-windows.h b/lib/plat/windows/private-lib-plat-windows.h index 03cffd17..56bfc3c0 100644 --- a/lib/plat/windows/private-lib-plat-windows.h +++ b/lib/plat/windows/private-lib-plat-windows.h @@ -66,6 +66,15 @@ #if defined(LWS_WITH_UNIX_SOCK) #include +#endif + +#if defined(LWS_HAVE_PTHREAD_H) +#include +typedef pthread_mutex_t lws_mutex_t; +#define lws_mutex_init(x) pthread_mutex_init(&(x), NULL) +#define lws_mutex_destroy(x) pthread_mutex_destroy(&(x)) +#define lws_mutex_lock(x) pthread_mutex_lock(&(x)) +#define lws_mutex_unlock(x) pthread_mutex_unlock(&(x)) #endif #if !defined(LWS_HAVE_ATOLL) -- Gitee From 6747ab830e23c0a8ba2aab4c84f575e890d7d76f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 17 Jun 2020 11:13:01 +0100 Subject: [PATCH 0170/1062] content_info: make members conditional --- CMakeLists-implied-options.txt | 1 + include/libwebsockets/lws-context-vhost.h | 517 ++++++++++-------- lib/core/context.c | 19 +- lib/core/libwebsockets.c | 6 + lib/roles/http/server/lejp-conf.c | 38 +- lib/secure-streams/CMakeLists.txt | 2 + lib/secure-streams/policy-common.c | 2 + lib/tls/openssl/openssl-ssl.c | 36 +- lib/tls/tls-client.c | 2 + .../minimal-http-server-custom-headers.c | 2 + .../minimal-http-server-deaddrop.c | 2 + .../minimal-http-server-dynamic.c | 2 + .../minimal-http-server-eventlib-demos.c | 2 + .../minimal-http-server-eventlib-smp.c | 2 + .../minimal-http-server-eventlib.c | 2 + .../minimal-http-server-form-post.c | 2 + .../minimal-http-server-form-post.c | 3 +- .../minimal-http-server.c | 2 + .../minimal-http-server-smp.c | 2 + .../minimal-http-server-sse.c | 3 + .../minimal-raw-fallback-http-server.c | 2 + .../raw/minimal-raw-vhost/minimal-raw-vhost.c | 2 + .../minimal-ws-server.c | 2 + .../minimal-ws-server/minimal-ws-server.c | 2 + test-apps/test-client.c | 9 +- test-apps/test-server.c | 14 +- 26 files changed, 415 insertions(+), 263 deletions(-) diff --git a/CMakeLists-implied-options.txt b/CMakeLists-implied-options.txt index 94fe5991..4ec90bc5 100644 --- a/CMakeLists-implied-options.txt +++ b/CMakeLists-implied-options.txt @@ -348,6 +348,7 @@ endif() set(LWS_WITH_CLIENT 1) if (LWS_WITHOUT_CLIENT) set(LWS_WITH_CLIENT) + set(LWS_WITH_SECURE_STREAMS 0) endif() set(LWS_WITH_SERVER 1) if (LWS_WITHOUT_SERVER) diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index 28abda9e..ef03c410 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -251,15 +251,7 @@ typedef int (*lws_peer_limits_notify_t)(struct lws_context *ctx, * at the same time as the context, they are expected to be created afterwards. */ struct lws_context_creation_info { - int port; - /**< VHOST: Port to listen on. Use CONTEXT_PORT_NO_LISTEN to suppress - * listening for a client. Use CONTEXT_PORT_NO_LISTEN_SERVER if you are - * writing a server but you are using \ref sock-adopt instead of the - * built-in listener. - * - * You can also set port to 0, in which case the kernel will pick - * a random port that is not already in use. You can find out what - * port the vhost is listening on using lws_get_vhost_listen_port() */ +#if defined(LWS_WITH_NETWORK) const char *iface; /**< VHOST: NULL to bind the listen socket to all interfaces, or the * interface name, eg, "eth2" @@ -273,12 +265,94 @@ struct lws_context_creation_info { * entry that has a NULL callback pointer. SEE ALSO .pprotocols below, * which gives an alternative way to provide an array of pointers to * protocol structs. */ +#if defined(LWS_ROLE_WS) const struct lws_extension *extensions; /**< VHOST: NULL or array of lws_extension structs listing the * extensions this context supports. */ +#endif +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) const struct lws_token_limits *token_limits; /**< CONTEXT: NULL or struct lws_token_limits pointer which is * initialized with a token length limit for each possible WSI_TOKEN_ */ + const char *http_proxy_address; + /**< VHOST: If non-NULL, attempts to proxy via the given address. + * If proxy auth is required, use format + * "username:password\@server:port" */ + const struct lws_protocol_vhost_options *headers; + /**< VHOST: pointer to optional linked list of per-vhost + * canned headers that are added to server responses */ + + const struct lws_protocol_vhost_options *reject_service_keywords; + /**< CONTEXT: Optional list of keywords and rejection codes + text. + * + * The keywords are checked for existing in the user agent string. + * + * Eg, "badrobot" "404 Not Found" + */ + const struct lws_protocol_vhost_options *pvo; + /**< VHOST: pointer to optional linked list of per-vhost + * options made accessible to protocols */ + const char *log_filepath; + /**< VHOST: filepath to append logs to... this is opened before + * any dropping of initial privileges */ + const struct lws_http_mount *mounts; + /**< VHOST: optional linked list of mounts for this vhost */ + const char *server_string; + /**< CONTEXT: string used in HTTP headers to identify server + * software, if NULL, "libwebsockets". */ + + const char *error_document_404; + /**< VHOST: If non-NULL, when asked to serve a non-existent file, + * lws attempts to server this url path instead. Eg, + * "/404.html" */ + int port; + /**< VHOST: Port to listen on. Use CONTEXT_PORT_NO_LISTEN to suppress + * listening for a client. Use CONTEXT_PORT_NO_LISTEN_SERVER if you are + * writing a server but you are using \ref sock-adopt instead of the + * built-in listener. + * + * You can also set port to 0, in which case the kernel will pick + * a random port that is not already in use. You can find out what + * port the vhost is listening on using lws_get_vhost_listen_port() */ + + unsigned int http_proxy_port; + /**< VHOST: If http_proxy_address was non-NULL, uses this port */ + unsigned int max_http_header_data2; + /**< CONTEXT: if max_http_header_data is 0 and this + * is nonzero, this will be used in place of the default. It's + * like this for compatibility with the original short version, + * this is unsigned int length. */ + unsigned int max_http_header_pool2; + /**< CONTEXT: if max_http_header_pool is 0 and this + * is nonzero, this will be used in place of the default. It's + * like this for compatibility with the original short version: + * this is unsigned int length. */ + + int keepalive_timeout; + /**< VHOST: (default = 0 = 5s, 31s for http/2) seconds to allow remote + * client to hold on to an idle HTTP/1.1 connection. Timeout lifetime + * applied to idle h2 network connections */ + uint32_t http2_settings[7]; + /**< VHOST: if http2_settings[0] is nonzero, the values given in + * http2_settings[1]..[6] are used instead of the lws + * platform default values. + * Just leave all at 0 if you don't care. + */ + + unsigned short max_http_header_data; + /**< CONTEXT: The max amount of header payload that can be handled + * in an http request (unrecognized header payload is dropped) */ + unsigned short max_http_header_pool; + /**< CONTEXT: The max number of connections with http headers that + * can be processed simultaneously (the corresponding memory is + * allocated and deallocated dynamically as needed). If the pool is + * fully busy new incoming connections must wait for accept until one + * becomes free. 0 = allow as many ah as number of availble fds for + * the process */ + +#endif + +#if defined(LWS_WITH_TLS) const char *ssl_private_key_password; /**< VHOST: NULL or the passphrase needed for the private key. (For * backwards compatibility, this can also be used to pass the client @@ -329,12 +403,159 @@ struct lws_context_creation_info { * SEE .tls1_3_plus_cipher_list and .client_tls_1_3_plus_cipher_list * for the equivalent for tls1.3. */ - const char *http_proxy_address; - /**< VHOST: If non-NULL, attempts to proxy via the given address. - * If proxy auth is required, use format - * "username:password\@server:port" */ - unsigned int http_proxy_port; - /**< VHOST: If http_proxy_address was non-NULL, uses this port */ + const char *ecdh_curve; + /**< VHOST: if NULL, defaults to initializing server with + * "prime256v1" */ + const char *tls1_3_plus_cipher_list; + /**< VHOST: List of valid ciphers to use for incoming server connections + * ON TLS1.3 AND ABOVE (eg, "TLS_CHACHA20_POLY1305_SHA256" on this vhost + * or you can leave it as NULL to get "DEFAULT". + * SEE .client_tls_1_3_plus_cipher_list to do the same on the vhost + * client SSL_CTX. + */ + + const void *server_ssl_cert_mem; + /**< VHOST: Alternative for \p ssl_cert_filepath that allows setting + * from memory instead of from a file. At most one of + * \p ssl_cert_filepath or \p server_ssl_cert_mem should be non-NULL. */ + const void *server_ssl_private_key_mem; + /**< VHOST: Alternative for \p ssl_private_key_filepath allowing + * init from a private key in memory instead of a file. At most one + * of \p ssl_private_key_filepath or \p server_ssl_private_key_mem + * should be non-NULL. */ + const void *server_ssl_ca_mem; + /**< VHOST: Alternative for \p ssl_ca_filepath allowing + * init from a CA cert in memory instead of a file. At most one + * of \p ssl_ca_filepath or \p server_ssl_ca_mem should be non-NULL. */ + + long ssl_options_set; + /**< VHOST: Any bits set here will be set as server SSL options */ + long ssl_options_clear; + /**< VHOST: Any bits set here will be cleared as server SSL options */ + int simultaneous_ssl_restriction; + /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions + * possible.*/ + int ssl_info_event_mask; + /**< VHOST: mask of ssl events to be reported on LWS_CALLBACK_SSL_INFO + * callback for connections on this vhost. The mask values are of + * the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of + * 0 means no info events will be reported. + */ + unsigned int server_ssl_cert_mem_len; + /**< VHOST: Server SSL context init: length of server_ssl_cert_mem in + * bytes */ + unsigned int server_ssl_private_key_mem_len; + /**< VHOST: length of \p server_ssl_private_key_mem in memory */ + unsigned int server_ssl_ca_mem_len; + /**< VHOST: length of \p server_ssl_ca_mem in memory */ + + const char *alpn; + /**< CONTEXT: If non-NULL, default list of advertised alpn, comma- + * separated + * + * VHOST: If non-NULL, per-vhost list of advertised alpn, comma- + * separated + */ + + +#if defined(LWS_WITH_CLIENT) + const char *client_ssl_private_key_password; + /**< VHOST: Client SSL context init: NULL or the passphrase needed + * for the private key */ + const char *client_ssl_cert_filepath; + /**< VHOST: Client SSL context init: The certificate the client + * should present to the peer on connection */ + const void *client_ssl_cert_mem; + /**< VHOST: Client SSL context init: client certificate memory buffer or + * NULL... use this to load client cert from memory instead of file */ + unsigned int client_ssl_cert_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_cert_mem in + * bytes */ + const char *client_ssl_private_key_filepath; + /**< VHOST: Client SSL context init: filepath to client private key + * if this is set to NULL but client_ssl_cert_filepath is set, you + * can handle the LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS + * callback of protocols[0] to allow setting of the private key directly + * via tls library calls */ + const void *client_ssl_key_mem; + /**< VHOST: Client SSL context init: client key memory buffer or + * NULL... use this to load client key from memory instead of file */ + const char *client_ssl_ca_filepath; + /**< VHOST: Client SSL context init: CA certificate filepath or NULL */ + const void *client_ssl_ca_mem; + /**< VHOST: Client SSL context init: CA certificate memory buffer or + * NULL... use this to load CA cert from memory instead of file */ + + const char *client_ssl_cipher_list; + /**< VHOST: Client SSL context init: List of valid ciphers to use (eg, + * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL" + * or you can leave it as NULL to get "DEFAULT" */ + const char *client_tls_1_3_plus_cipher_list; + /**< VHOST: List of valid ciphers to use for outgoing client connections + * ON TLS1.3 AND ABOVE on this vhost (eg, + * "TLS_CHACHA20_POLY1305_SHA256") or you can leave it as NULL to get + * "DEFAULT". + */ + + long ssl_client_options_set; + /**< VHOST: Any bits set here will be set as CLIENT SSL options */ + long ssl_client_options_clear; + /**< VHOST: Any bits set here will be cleared as CLIENT SSL options */ + + + unsigned int client_ssl_ca_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_ca_mem in + * bytes */ + unsigned int client_ssl_key_mem_len; + /**< VHOST: Client SSL context init: length of client_ssl_key_mem in + * bytes */ + +#endif + +#if !defined(LWS_WITH_MBEDTLS) + SSL_CTX *provided_client_ssl_ctx; + /**< CONTEXT: If non-null, swap out libwebsockets ssl + * implementation for the one provided by provided_ssl_ctx. + * Libwebsockets no longer is responsible for freeing the context + * if this option is selected. */ +#endif +#endif + + int ka_time; + /**< CONTEXT: 0 for no TCP keepalive, otherwise apply this keepalive + * timeout to all libwebsocket sockets, client or server */ + int ka_probes; + /**< CONTEXT: if ka_time was nonzero, after the timeout expires how many + * times to try to get a response from the peer before giving up + * and killing the connection */ + int ka_interval; + /**< CONTEXT: if ka_time was nonzero, how long to wait before each ka_probes + * attempt */ + unsigned int timeout_secs; + /**< VHOST: various processes involving network roundtrips in the + * library are protected from hanging forever by timeouts. If + * nonzero, this member lets you set the timeout used in seconds. + * Otherwise a default timeout is used. */ + unsigned int connect_timeout_secs; + /**< VHOST: client connections have this long to find a working server + * from the DNS results, or the whole connection times out. If zero, + * a default timeout is used */ + int bind_iface; + /**< VHOST: nonzero to strictly bind sockets to the interface name in + * .iface (eg, "eth2"), using SO_BIND_TO_DEVICE. + * + * Requires SO_BINDTODEVICE support from your OS and CAP_NET_RAW + * capability. + * + * Notice that common things like access network interface IP from + * your local machine use your lo / loopback interface and will be + * disallowed by this. + */ + unsigned int timeout_secs_ah_idle; + /**< VHOST: seconds to allow a client to hold an ah without using it. + * 0 defaults to 10s. */ +#endif /* WITH_NETWORK */ + int gid; /**< CONTEXT: group id to change to after setting listen socket, * or -1. See also .username below. */ @@ -352,37 +573,6 @@ struct lws_context_creation_info { * if you care about giving the context and vhost different user pointer * values. */ - int ka_time; - /**< CONTEXT: 0 for no TCP keepalive, otherwise apply this keepalive - * timeout to all libwebsocket sockets, client or server */ - int ka_probes; - /**< CONTEXT: if ka_time was nonzero, after the timeout expires how many - * times to try to get a response from the peer before giving up - * and killing the connection */ - int ka_interval; - /**< CONTEXT: if ka_time was nonzero, how long to wait before each ka_probes - * attempt */ -#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS) - SSL_CTX *provided_client_ssl_ctx; - /**< CONTEXT: If non-null, swap out libwebsockets ssl - * implementation for the one provided by provided_ssl_ctx. - * Libwebsockets no longer is responsible for freeing the context - * if this option is selected. */ -#else /* maintain structure layout either way */ - void *provided_client_ssl_ctx; /**< dummy if ssl disabled */ -#endif - - unsigned short max_http_header_data; - /**< CONTEXT: The max amount of header payload that can be handled - * in an http request (unrecognized header payload is dropped) */ - unsigned short max_http_header_pool; - /**< CONTEXT: The max number of connections with http headers that - * can be processed simultaneously (the corresponding memory is - * allocated and deallocated dynamically as needed). If the pool is - * fully busy new incoming connections must wait for accept until one - * becomes free. 0 = allow as many ah as number of availble fds for - * the process */ - unsigned int count_threads; /**< CONTEXT: how many contexts to create in an array, 0 = 1 */ unsigned int fd_limit_per_thread; @@ -401,66 +591,15 @@ struct lws_context_creation_info { * cancel pipe, so you may need to allow for some extras for normal * operation. */ - unsigned int timeout_secs; - /**< VHOST: various processes involving network roundtrips in the - * library are protected from hanging forever by timeouts. If - * nonzero, this member lets you set the timeout used in seconds. - * Otherwise a default timeout is used. */ - unsigned int connect_timeout_secs; - /**< VHOST: client connections have this long to find a working server - * from the DNS results, or the whole connection times out. If zero, - * a default timeout is used */ - const char *ecdh_curve; - /**< VHOST: if NULL, defaults to initializing server with - * "prime256v1" */ const char *vhost_name; /**< VHOST: name of vhost, must match external DNS name used to * access the site, like "warmcat.com" as it's used to match * Host: header and / or SNI name for SSL. */ +#if defined(LWS_WITH_PLUGINS) const char * const *plugin_dirs; /**< CONTEXT: NULL, or NULL-terminated array of directories to * scan for lws protocol plugins at context creation time */ - const struct lws_protocol_vhost_options *pvo; - /**< VHOST: pointer to optional linked list of per-vhost - * options made accessible to protocols */ - int keepalive_timeout; - /**< VHOST: (default = 0 = 5s, 31s for http/2) seconds to allow remote - * client to hold on to an idle HTTP/1.1 connection. Timeout lifetime - * applied to idle h2 network connections */ - const char *log_filepath; - /**< VHOST: filepath to append logs to... this is opened before - * any dropping of initial privileges */ - const struct lws_http_mount *mounts; - /**< VHOST: optional linked list of mounts for this vhost */ - const char *server_string; - /**< CONTEXT: string used in HTTP headers to identify server - * software, if NULL, "libwebsockets". */ - unsigned int pt_serv_buf_size; - /**< CONTEXT: 0 = default of 4096. This buffer is used by - * various service related features including file serving, it - * defines the max chunk of file that can be sent at once. - * At the risk of lws having to buffer failed large sends, it - * can be increased to, eg, 128KiB to improve throughput. */ - unsigned int max_http_header_data2; - /**< CONTEXT: if max_http_header_data is 0 and this - * is nonzero, this will be used in place of the default. It's - * like this for compatibility with the original short version, - * this is unsigned int length. */ - long ssl_options_set; - /**< VHOST: Any bits set here will be set as server SSL options */ - long ssl_options_clear; - /**< VHOST: Any bits set here will be cleared as server SSL options */ - const struct lws_protocol_vhost_options *headers; - /**< VHOST: pointer to optional linked list of per-vhost - * canned headers that are added to server responses */ - - const struct lws_protocol_vhost_options *reject_service_keywords; - /**< CONTEXT: Optional list of keywords and rejection codes + text. - * - * The keywords are checked for existing in the user agent string. - * - * Eg, "badrobot" "404 Not Found" - */ +#endif void *external_baggage_free_on_destroy; /**< CONTEXT: NULL, or pointer to something externally malloc'd, that * should be freed when the context is destroyed. This allows you to @@ -469,44 +608,14 @@ struct lws_context_creation_info { * succeeded to create. */ - const char *client_ssl_private_key_password; - /**< VHOST: Client SSL context init: NULL or the passphrase needed - * for the private key */ - const char *client_ssl_cert_filepath; - /**< VHOST: Client SSL context init: The certificate the client - * should present to the peer on connection */ - const void *client_ssl_cert_mem; - /**< VHOST: Client SSL context init: client certificate memory buffer or - * NULL... use this to load client cert from memory instead of file */ - unsigned int client_ssl_cert_mem_len; - /**< VHOST: Client SSL context init: length of client_ssl_cert_mem in - * bytes */ - const char *client_ssl_private_key_filepath; - /**< VHOST: Client SSL context init: filepath to client private key - * if this is set to NULL but client_ssl_cert_filepath is set, you - * can handle the LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS - * callback of protocols[0] to allow setting of the private key directly - * via tls library calls */ - const void *client_ssl_key_mem; - /**< VHOST: Client SSL context init: client key memory buffer or - * NULL... use this to load client key from memory instead of file */ - unsigned int client_ssl_key_mem_len; - /**< VHOST: Client SSL context init: length of client_ssl_key_mem in - * bytes */ - const char *client_ssl_ca_filepath; - /**< VHOST: Client SSL context init: CA certificate filepath or NULL */ - const void *client_ssl_ca_mem; - /**< VHOST: Client SSL context init: CA certificate memory buffer or - * NULL... use this to load CA cert from memory instead of file */ - unsigned int client_ssl_ca_mem_len; - /**< VHOST: Client SSL context init: length of client_ssl_ca_mem in - * bytes */ - - const char *client_ssl_cipher_list; - /**< VHOST: Client SSL context init: List of valid ciphers to use (eg, - * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL" - * or you can leave it as NULL to get "DEFAULT" */ + unsigned int pt_serv_buf_size; + /**< CONTEXT: 0 = default of 4096. This buffer is used by + * various service related features including file serving, it + * defines the max chunk of file that can be sent at once. + * At the risk of lws having to buffer failed large sends, it + * can be increased to, eg, 128KiB to improve throughput. */ +#if defined(LWS_WITH_FILE_OPS) const struct lws_plat_file_ops *fops; /**< CONTEXT: NULL, or pointer to an array of fops structs, terminated * by a sentinel with NULL .open. @@ -514,9 +623,9 @@ struct lws_context_creation_info { * If NULL, lws provides just the platform file operations struct for * backwards compatibility. */ - int simultaneous_ssl_restriction; - /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions - * possible.*/ +#endif + +#if defined(LWS_WITH_SOCKS5) const char *socks_proxy_address; /**< VHOST: If non-NULL, attempts to proxy via the given address. * If proxy auth is required, use format @@ -525,6 +634,8 @@ struct lws_context_creation_info { /**< VHOST: If socks_proxy_address was non-NULL, uses this port * if nonzero, otherwise requires "server:port" in .socks_proxy_address */ +#endif + #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) cap_value_t caps[4]; /**< CONTEXT: array holding Linux capabilities you want to @@ -537,58 +648,6 @@ struct lws_context_creation_info { /**< CONTEXT: count of Linux capabilities in .caps[]. 0 means * no capabilities will be inherited from root (the default) */ #endif - int bind_iface; - /**< VHOST: nonzero to strictly bind sockets to the interface name in - * .iface (eg, "eth2"), using SO_BIND_TO_DEVICE. - * - * Requires SO_BINDTODEVICE support from your OS and CAP_NET_RAW - * capability. - * - * Notice that common things like access network interface IP from - * your local machine use your lo / loopback interface and will be - * disallowed by this. - */ - int ssl_info_event_mask; - /**< VHOST: mask of ssl events to be reported on LWS_CALLBACK_SSL_INFO - * callback for connections on this vhost. The mask values are of - * the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of - * 0 means no info events will be reported. - */ - unsigned int timeout_secs_ah_idle; - /**< VHOST: seconds to allow a client to hold an ah without using it. - * 0 defaults to 10s. */ - unsigned short ip_limit_ah; - /**< CONTEXT: max number of ah a single IP may use simultaneously - * 0 is no limit. This is a soft limit: if the limit is - * reached, connections from that IP will wait in the ah - * waiting list and not be able to acquire an ah until - * a connection belonging to the IP relinquishes one it - * already has. - */ - unsigned short ip_limit_wsi; - /**< CONTEXT: max number of wsi a single IP may use simultaneously. - * 0 is no limit. This is a hard limit, connections from - * the same IP will simply be dropped once it acquires the - * amount of simultaneous wsi / accepted connections - * given here. - */ - uint32_t http2_settings[7]; - /**< VHOST: if http2_settings[0] is nonzero, the values given in - * http2_settings[1]..[6] are used instead of the lws - * platform default values. - * Just leave all at 0 if you don't care. - */ - const char *error_document_404; - /**< VHOST: If non-NULL, when asked to serve a non-existent file, - * lws attempts to server this url path instead. Eg, - * "/404.html" */ - const char *alpn; - /**< CONTEXT: If non-NULL, default list of advertised alpn, comma- - * separated - * - * VHOST: If non-NULL, per-vhost list of advertised alpn, comma- - * separated - */ void **foreign_loops; /**< CONTEXT: This is ignored if the context is not being started with * an event loop, ie, .options has a flag like @@ -624,30 +683,6 @@ struct lws_context_creation_info { /**< VHOST: opaque pointer lws ignores but passes to the finalize * callback. If you don't care, leave it NULL. */ - unsigned int max_http_header_pool2; - /**< CONTEXT: if max_http_header_pool is 0 and this - * is nonzero, this will be used in place of the default. It's - * like this for compatibility with the original short version: - * this is unsigned int length. */ - - long ssl_client_options_set; - /**< VHOST: Any bits set here will be set as CLIENT SSL options */ - long ssl_client_options_clear; - /**< VHOST: Any bits set here will be cleared as CLIENT SSL options */ - - const char *tls1_3_plus_cipher_list; - /**< VHOST: List of valid ciphers to use for incoming server connections - * ON TLS1.3 AND ABOVE (eg, "TLS_CHACHA20_POLY1305_SHA256" on this vhost - * or you can leave it as NULL to get "DEFAULT". - * SEE .client_tls_1_3_plus_cipher_list to do the same on the vhost - * client SSL_CTX. - */ - const char *client_tls_1_3_plus_cipher_list; - /**< VHOST: List of valid ciphers to use for outgoing client connections - * ON TLS1.3 AND ABOVE on this vhost (eg, - * "TLS_CHACHA20_POLY1305_SHA256") or you can leave it as NULL to get - * "DEFAULT". - */ const char *listen_accept_role; /**< VHOST: NULL for default, or force accepted incoming connections to * bind to this role. Uses the role names from their ops struct, eg, @@ -668,26 +703,6 @@ struct lws_context_creation_info { * the type of the user data to be known so its size can be given. */ - const void *server_ssl_cert_mem; - /**< VHOST: Alternative for \p ssl_cert_filepath that allows setting - * from memory instead of from a file. At most one of - * \p ssl_cert_filepath or \p server_ssl_cert_mem should be non-NULL. */ - unsigned int server_ssl_cert_mem_len; - /**< VHOST: Server SSL context init: length of server_ssl_cert_mem in - * bytes */ - const void *server_ssl_private_key_mem; - /**< VHOST: Alternative for \p ssl_private_key_filepath allowing - * init from a private key in memory instead of a file. At most one - * of \p ssl_private_key_filepath or \p server_ssl_private_key_mem - * should be non-NULL. */ - unsigned int server_ssl_private_key_mem_len; - /**< VHOST: length of \p server_ssl_private_key_mem in memory */ - const void *server_ssl_ca_mem; - /**< VHOST: Alternative for \p ssl_ca_filepath allowing - * init from a CA cert in memory instead of a file. At most one - * of \p ssl_ca_filepath or \p server_ssl_ca_mem should be non-NULL. */ - unsigned int server_ssl_ca_mem_len; - /**< VHOST: length of \p server_ssl_ca_mem in memory */ const char *username; /**< CONTEXT: string username for post-init * permissions. Like .uid but takes a string username. */ const char *groupname; /**< CONTEXT: string groupname for post-init @@ -699,11 +714,13 @@ struct lws_context_creation_info { const lws_system_ops_t *system_ops; /**< CONTEXT: hook up lws_system_ apis to system-specific * implementations */ +#if defined(LWS_WITH_DETAILED_LATENCY) det_lat_buf_cb_t detailed_latency_cb; /**< CONTEXT: NULL, or callback to receive detailed latency information * collected for each read and write */ const char *detailed_latency_filepath; /**< CONTEXT: NULL, or filepath to put latency data into */ +#endif const lws_retry_bo_t *retry_and_idle_policy; /**< VHOST: optional retry and idle policy to apply to this vhost. * Currently only the idle parts are applied to the connections. @@ -712,12 +729,6 @@ struct lws_context_creation_info { /**< CONTEXT: NULL, or pointer to an array of notifiers that should * be registered during context creation, so they can see state change * events from very early on. The array should end with a NULL. */ - uint8_t udp_loss_sim_tx_pc; - /**< CONTEXT: percentage of udp writes we could have performed - * to instead not do, in order to simulate and test udp retry flow */ - uint8_t udp_loss_sim_rx_pc; - /**< CONTEXT: percentage of udp reads we actually received - * to make disappear, in order to simulate and test udp retry flow */ #if defined(LWS_WITH_SECURE_STREAMS) #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) const struct lws_ss_policy *pss_policies; /**< CONTEXT: point to first @@ -756,6 +767,30 @@ struct lws_context_creation_info { * The callback provides the context, and an lws_sockaddr46 with the * peer address and port. */ + unsigned short ip_limit_ah; + /**< CONTEXT: max number of ah a single IP may use simultaneously + * 0 is no limit. This is a soft limit: if the limit is + * reached, connections from that IP will wait in the ah + * waiting list and not be able to acquire an ah until + * a connection belonging to the IP relinquishes one it + * already has. + */ + unsigned short ip_limit_wsi; + /**< CONTEXT: max number of wsi a single IP may use simultaneously. + * 0 is no limit. This is a hard limit, connections from + * the same IP will simply be dropped once it acquires the + * amount of simultaneous wsi / accepted connections + * given here. + */ + +#endif /* PEER_LIMITS */ +#if defined(LWS_WITH_UDP) + uint8_t udp_loss_sim_tx_pc; + /**< CONTEXT: percentage of udp writes we could have performed + * to instead not do, in order to simulate and test udp retry flow */ + uint8_t udp_loss_sim_rx_pc; + /**< CONTEXT: percentage of udp reads we actually received + * to make disappear, in order to simulate and test udp retry flow */ #endif /* Add new things just above here ---^ diff --git a/lib/core/context.c b/lib/core/context.c index 425acc0e..196ea67e 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -134,7 +134,7 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, } #endif -#if defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) +#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) /* * Skip this if we are running something without the policy for it * @@ -301,6 +301,8 @@ lws_create_context(const struct lws_context_creation_info *info) context->groupname = info->groupname; context->system_ops = info->system_ops; context->pt_serv_buf_size = (unsigned int)s1; + +#if defined(LWS_WITH_UDP) context->udp_loss_sim_tx_pc = info->udp_loss_sim_tx_pc; context->udp_loss_sim_rx_pc = info->udp_loss_sim_rx_pc; @@ -308,6 +310,7 @@ lws_create_context(const struct lws_context_creation_info *info) lwsl_warn("%s: simulating udp loss tx: %d%%, rx: %d%%\n", __func__, context->udp_loss_sim_tx_pc, context->udp_loss_sim_rx_pc); +#endif #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) /* directly use the user-provided policy object list */ @@ -331,7 +334,7 @@ lws_create_context(const struct lws_context_creation_info *info) context->detailed_latency_filepath = info->detailed_latency_filepath; context->latencies_fd = -1; #endif -#if defined(LWS_WITHOUT_EXTENSIONS) +#if defined(LWS_ROLE_WS) && defined(LWS_WITHOUT_EXTENSIONS) if (info->extensions) lwsl_warn("%s: LWS_WITHOUT_EXTENSIONS but extensions ptr set\n", __func__); #endif @@ -413,8 +416,10 @@ lws_create_context(const struct lws_context_creation_info *info) #endif context->pcontext_finalize = info->pcontext; +#if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK) context->simultaneous_ssl_restriction = info->simultaneous_ssl_restriction; +#endif context->options = info->options; @@ -474,10 +479,10 @@ lws_create_context(const struct lws_context_creation_info *info) } } - context->token_limits = info->token_limits; - #if defined(LWS_WITH_NETWORK) + context->token_limits = info->token_limits; + /* * set the context event loops ops struct * @@ -546,14 +551,16 @@ lws_create_context(const struct lws_context_creation_info *info) lwsl_info("Default ALPN advertisment: %s\n", context->tls.alpn_default); #endif - +#if defined(LWS_WITH_NETWORK) if (info->timeout_secs) context->timeout_secs = info->timeout_secs; else +#endif context->timeout_secs = 5; lwsl_info(" default timeout (secs): %u\n", context->timeout_secs); +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) if (info->max_http_header_data) context->max_http_header_data = info->max_http_header_data; else @@ -571,7 +578,7 @@ lws_create_context(const struct lws_context_creation_info *info) info->max_http_header_pool2; else context->max_http_header_pool = context->max_fds; - +#endif if (info->fd_limit_per_thread) context->fd_limit_per_thread = lpf; diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index 0ad9330d..adecc1c3 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -1092,8 +1092,10 @@ lws_cmdline_option(int argc, const char **argv, const char *val) static const char * const builtins[] = { "-d", +#if defined(LWS_WITH_UDP) "--udp-tx-loss", "--udp-rx-loss", +#endif "--ignore-sigterm" }; @@ -1122,6 +1124,7 @@ lws_cmdline_option_handle_builtin(int argc, const char **argv, case 0: logs = m; break; +#if defined(LWS_WITH_UDP) case 1: info->udp_loss_sim_tx_pc = m; break; @@ -1129,6 +1132,9 @@ lws_cmdline_option_handle_builtin(int argc, const char **argv, info->udp_loss_sim_rx_pc = m; break; case 3: +#else + case 1: +#endif #if !defined(LWS_PLAT_FREERTOS) signal(SIGTERM, lws_sigterm_catch); #endif diff --git a/lib/roles/http/server/lejp-conf.c b/lib/roles/http/server/lejp-conf.c index 86b25508..6db7afc1 100644 --- a/lib/roles/http/server/lejp-conf.c +++ b/lib/roles/http/server/lejp-conf.c @@ -335,10 +335,13 @@ lejp_globals_cb(struct lejp_ctx *ctx, char reason) a->info->timeout_secs = atoi(ctx->buf); return 0; +#if defined(LWS_WITH_TLS) case LWJPGP_DEFAULT_ALPN: a->info->alpn = a->p; break; +#endif +#if defined(LWS_WITH_PEER_LIMITS) case LWJPGP_IP_LIMIT_AH: a->info->ip_limit_ah = atoi(ctx->buf); return 0; @@ -346,6 +349,7 @@ lejp_globals_cb(struct lejp_ctx *ctx, char reason) case LWJPGP_IP_LIMIT_WSI: a->info->ip_limit_wsi = atoi(ctx->buf); return 0; +#endif case LWJPGP_FD_LIMIT_PT: a->info->rlimit_nofile = atoi(ctx->buf); @@ -415,8 +419,11 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) a->info->protocols = a->protocols; a->info->pprotocols = a->pprotocols; +#if defined(LWS_ROLE_WS) a->info->extensions = a->extensions; +#endif #if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_CLIENT) a->info->client_ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:" "ECDHE-RSA-AES256-GCM-SHA384:" "DHE-RSA-AES256-GCM-SHA384:" @@ -431,6 +438,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) "!AES256-GCM-SHA384:" "!AES256-SHA256"; #endif +#if defined(LWS_WITH_SERVER) a->info->ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:" "ECDHE-RSA-AES256-GCM-SHA384:" "DHE-RSA-AES256-GCM-SHA384:" @@ -444,6 +452,8 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) "!DHE-RSA-AES256-SHA256:" "!AES256-GCM-SHA384:" "!AES256-SHA256"; +#endif +#endif a->info->keepalive_timeout = 5; } @@ -529,7 +539,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) vhost->default_protocol_index = 255; } -#if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT) if (a->enable_client_ssl) { const char *cert_filepath = a->info->client_ssl_cert_filepath; @@ -632,6 +642,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) else a->info->options &= ~(LWS_SERVER_OPTION_STS); return 0; +#if defined(LWS_WITH_TLS) case LEJPVP_HOST_SSL_KEY: a->info->ssl_private_key_filepath = a->p; break; @@ -641,6 +652,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) case LEJPVP_HOST_SSL_CA: a->info->ssl_ca_filepath = a->p; break; +#endif case LEJPVP_ACCESS_LOG: a->info->log_filepath = a->p; break; @@ -685,23 +697,25 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) a->info->keepalive_timeout = atoi(ctx->buf); return 0; #if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_CLIENT) case LEJPVP_CLIENT_CIPHERS: a->info->client_ssl_cipher_list = a->p; break; + case LEJPVP_CLIENT_TLS13_CIPHERS: + a->info->client_tls_1_3_plus_cipher_list = a->p; + break; #endif + case LEJPVP_CIPHERS: a->info->ssl_cipher_list = a->p; break; case LEJPVP_TLS13_CIPHERS: a->info->tls1_3_plus_cipher_list = a->p; break; - case LEJPVP_CLIENT_TLS13_CIPHERS: - a->info->client_tls_1_3_plus_cipher_list = a->p; - break; - case LEJPVP_ECDH_CURVE: a->info->ecdh_curve = a->p; break; +#endif case LEJPVP_PMO: case LEJPVP_CGI_ENV: mp_cgienv = lwsws_align(a); @@ -771,7 +785,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) case LEJPVP_ENABLE_CLIENT_SSL: a->enable_client_ssl = arg_to_bool(ctx->buf); return 0; -#if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT) case LEJPVP_CLIENT_SSL_KEY: a->info->client_ssl_private_key_filepath = a->p; break; @@ -819,6 +833,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) a->info->error_document_404 = a->p; break; +#if defined(LWS_WITH_TLS) case LEJPVP_SSL_OPTION_SET: a->info->ssl_options_set |= atol(ctx->buf); return 0; @@ -826,16 +841,19 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) a->info->ssl_options_clear |= atol(ctx->buf); return 0; +#if defined(LWS_WITH_CLIENT) case LEJPVP_SSL_CLIENT_OPTION_SET: a->info->ssl_client_options_set |= atol(ctx->buf); return 0; case LEJPVP_SSL_CLIENT_OPTION_CLEAR: a->info->ssl_client_options_clear |= atol(ctx->buf); return 0; +#endif case LEJPVP_ALPN: a->info->alpn = a->p; break; +#endif case LEJPVP_LISTEN_ACCEPT_ROLE: a->info->listen_accept_role = a->p; @@ -972,7 +990,9 @@ lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d, { struct lws_dir_args da; struct jpargs a; +#if defined(LWS_WITH_PLUGINS) const char * const *old = info->plugin_dirs; +#endif char dd[128]; memset(&a, 0, sizeof(a)); @@ -983,16 +1003,20 @@ lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d, a.valid = 0; lwsws_align(&a); +#if defined(LWS_WITH_PLUGINS) info->plugin_dirs = (void *)a.p; +#endif a.plugin_dirs = (void *)a.p; /* writeable version */ a.p += MAX_PLUGIN_DIRS * sizeof(void *); +#if defined(LWS_WITH_PLUGINS) /* copy any default paths */ while (old && *old) { a.plugin_dirs[a.count_plugin_dirs++] = *old; old++; } +#endif lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d); if (lwsws_get_config(&a, dd, paths_global, @@ -1034,7 +1058,9 @@ lwsws_get_config_vhosts(struct lws_context *context, a.context = context; a.protocols = info->protocols; a.pprotocols = info->pprotocols; +#if defined(LWS_ROLE_WS) a.extensions = info->extensions; +#endif lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d); if (lwsws_get_config(&a, dd, paths_vhosts, diff --git a/lib/secure-streams/CMakeLists.txt b/lib/secure-streams/CMakeLists.txt index d75f701d..1d46849d 100644 --- a/lib/secure-streams/CMakeLists.txt +++ b/lib/secure-streams/CMakeLists.txt @@ -26,6 +26,7 @@ include_directories(.) +if (LWS_WITH_CLIENT) list(APPEND SOURCES secure-streams/secure-streams.c secure-streams/policy-common.c @@ -121,6 +122,7 @@ include_directories(.) endmacro() create_ss_plugin(ssp-h1url "h1url.c" "" "" "" "") +endif() # # Keep explicit parent scope exports at end diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index 6a0d94d5..ae862f38 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -234,9 +234,11 @@ lws_ss_policy_set(struct lws_context *context, const char *name) i.options = context->options; i.vhost_name = pol->trust_store->name; lwsl_debug("%s: %s\n", __func__, i.vhost_name); +#if defined(LWS_WITH_TLS) && defined(LWS_WITH_CLIENT) i.client_ssl_ca_mem = pol->trust_store->ssx509[0]->ca_der; i.client_ssl_ca_mem_len = (unsigned int) pol->trust_store->ssx509[0]->ca_der_len; +#endif i.port = CONTEXT_PORT_NO_LISTEN; lwsl_info("%s: %s trust store initial '%s'\n", __func__, i.vhost_name, pol->trust_store->ssx509[0]->vhost_name); diff --git a/lib/tls/openssl/openssl-ssl.c b/lib/tls/openssl/openssl-ssl.c index 57e298f9..a5e27cca 100644 --- a/lib/tls/openssl/openssl-ssl.c +++ b/lib/tls/openssl/openssl-ssl.c @@ -65,6 +65,7 @@ int lws_ssl_get_error(struct lws *wsi, int n) return m; } +#if defined(LWS_WITH_SERVER) static int lws_context_init_ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) @@ -77,7 +78,9 @@ lws_context_init_ssl_pem_passwd_cb(char *buf, int size, int rwflag, return (int)strlen(buf); } +#endif +#if defined(LWS_WITH_CLIENT) static int lws_context_init_ssl_pem_passwd_client_cb(char *buf, int size, int rwflag, void *userdata) @@ -94,13 +97,23 @@ lws_context_init_ssl_pem_passwd_client_cb(char *buf, int size, int rwflag, return (int)strlen(buf); } +#endif void lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, int is_client, const struct lws_context_creation_info *info) { - if (!info->ssl_private_key_password && - !info->client_ssl_private_key_password) + if ( +#if defined(LWS_WITH_SERVER) + !info->ssl_private_key_password +#endif +#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_CLIENT) + && +#endif +#if defined(LWS_WITH_CLIENT) + !info->client_ssl_private_key_password +#endif + ) return; /* * password provided, set ssl callback and user data @@ -109,10 +122,20 @@ lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, int is_client, */ SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)info); SSL_CTX_set_default_passwd_cb(ssl_ctx, is_client ? +#if defined(LWS_WITH_CLIENT) lws_context_init_ssl_pem_passwd_client_cb: - lws_context_init_ssl_pem_passwd_cb); +#else + NULL: +#endif +#if defined(LWS_WITH_SERVER) + lws_context_init_ssl_pem_passwd_cb +#else + NULL +#endif + ); } +#if defined(LWS_WITH_CLIENT) static void lws_ssl_destroy_client_ctx(struct lws_vhost *vhost) { @@ -135,7 +158,7 @@ lws_ssl_destroy_client_ctx(struct lws_vhost *vhost) lws_dll2_remove(&tcr->cc_list); lws_free(tcr); } - +#endif void lws_ssl_destroy(struct lws_vhost *vhost) { @@ -145,8 +168,9 @@ lws_ssl_destroy(struct lws_vhost *vhost) if (vhost->tls.ssl_ctx) SSL_CTX_free(vhost->tls.ssl_ctx); - +#if defined(LWS_WITH_CLIENT) lws_ssl_destroy_client_ctx(vhost); +#endif // after 1.1.0 no need #if (OPENSSL_VERSION_NUMBER < 0x10100000) @@ -441,7 +465,9 @@ lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost) if (vhost->tls.ssl_ctx) SSL_CTX_free(vhost->tls.ssl_ctx); +#if defined(LWS_WITH_CLIENT) lws_ssl_destroy_client_ctx(vhost); +#endif #if defined(LWS_WITH_ACME) lws_tls_acme_sni_cert_destroy(vhost); diff --git a/lib/tls/tls-client.c b/lib/tls/tls-client.c index 85e64ac6..dc0e74ab 100644 --- a/lib/tls/tls-client.c +++ b/lib/tls/tls-client.c @@ -118,6 +118,7 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info, if (vhost->tls.ssl_client_ctx) return 0; +#if !defined(LWS_WITH_MBEDTLS) if (info->provided_client_ssl_ctx) { /* use the provided OpenSSL context if given one */ vhost->tls.ssl_client_ctx = info->provided_client_ssl_ctx; @@ -126,6 +127,7 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info, return 0; } +#endif if (lws_tls_client_create_vhost_context(vhost, info, cipher_list, ca_filepath, diff --git a/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c b/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c index dcdb0b8f..6e4c9ad6 100644 --- a/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c +++ b/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c @@ -201,8 +201,10 @@ int main(int argc, const char **argv) info.port = 7682; info.error_document_404 = "/404.html"; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif info.vhost_name = "https"; if (!lws_create_vhost(context, &info)) { diff --git a/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c b/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c index fe064122..7d40abd2 100644 --- a/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c +++ b/minimal-examples/http-server/minimal-http-server-deaddrop/minimal-http-server-deaddrop.c @@ -153,8 +153,10 @@ int main(int argc, const char **argv) info.error_document_404 = "/404.html"; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif context = lws_create_context(&info); if (!context) { diff --git a/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c b/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c index 14c363dd..77ca6947 100644 --- a/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c +++ b/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c @@ -284,8 +284,10 @@ int main(int argc, const char **argv) info.port = 7682; info.error_document_404 = "/404.html"; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif info.vhost_name = "localhost"; if (!lws_create_vhost(context, &info)) { diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c b/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c index abbe00da..f079972b 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c +++ b/minimal-examples/http-server/minimal-http-server-eventlib-demos/minimal-http-server-eventlib-demos.c @@ -157,8 +157,10 @@ int main(int argc, const char **argv) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif } if (lws_cmdline_option(argc, argv, "--uv")) diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c b/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c index f82fa048..4a371700 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c +++ b/minimal-examples/http-server/minimal-http-server-eventlib-smp/minimal-http-server-eventlib-smp.c @@ -122,11 +122,13 @@ int main(int argc, const char **argv) } else info.count_threads = COUNT_THREADS; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif if (lws_cmdline_option(argc, argv, "--uv")) info.options |= LWS_SERVER_OPTION_LIBUV; diff --git a/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c b/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c index c3147f79..a1fed6d4 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c +++ b/minimal-examples/http-server/minimal-http-server-eventlib/minimal-http-server-eventlib.c @@ -86,11 +86,13 @@ int main(int argc, const char **argv) info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif if (lws_cmdline_option(argc, argv, "--uv")) info.options |= LWS_SERVER_OPTION_LIBUV; diff --git a/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c b/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c index 5acc2556..59d2bc37 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c +++ b/minimal-examples/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c @@ -198,8 +198,10 @@ int main(int argc, const char **argv) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif } context = lws_create_context(&info); diff --git a/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c b/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c index edc55bcc..1859cb83 100644 --- a/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c +++ b/minimal-examples/http-server/minimal-http-server-form-post/minimal-http-server-form-post.c @@ -195,12 +195,13 @@ int main(int argc, const char **argv) info.mounts = &mount; info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; - +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif if ((p = lws_cmdline_option(argc, argv, "--port"))) info.port = atoi(p); diff --git a/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c b/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c index 148d4c78..0d1e1d0d 100644 --- a/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c +++ b/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c @@ -128,8 +128,10 @@ int main(int argc, const char **argv) memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ info.port = 7681; +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; +#endif info.protocols = protocols; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | diff --git a/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c b/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c index b6a34415..b7d2e693 100644 --- a/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c +++ b/minimal-examples/http-server/minimal-http-server-smp/minimal-http-server-smp.c @@ -106,11 +106,13 @@ int main(int argc, const char **argv) } else info.count_threads = COUNT_THREADS; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif context = lws_create_context(&info); if (!context) { diff --git a/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c b/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c index c7f8e7d3..adae1c05 100644 --- a/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c +++ b/minimal-examples/http-server/minimal-http-server-sse/minimal-http-server-sse.c @@ -208,12 +208,15 @@ int main(int argc, const char **argv) info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; info.port = 7681; + +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.port = 443; info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif context = lws_create_context(&info); if (!context) { diff --git a/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c b/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c index 5cb133ba..9a98277d 100644 --- a/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c +++ b/minimal-examples/raw/minimal-raw-fallback-http-server/minimal-raw-fallback-http-server.c @@ -119,6 +119,7 @@ int main(int argc, const char **argv) info.listen_accept_role = "raw-skt"; info.listen_accept_protocol = "raw-echo"; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT; @@ -131,6 +132,7 @@ int main(int argc, const char **argv) if (lws_cmdline_option(argc, argv, "-h")) info.options |= LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER; } +#endif context = lws_create_context(&info); if (!context) { diff --git a/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c b/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c index e2fe529d..ddf0a835 100644 --- a/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c +++ b/minimal-examples/raw/minimal-raw-vhost/minimal-raw-vhost.c @@ -137,11 +137,13 @@ int main(int argc, const char **argv) info.protocols = protocols; info.options = LWS_SERVER_OPTION_ONLY_RAW; /* vhost accepts RAW */ +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif context = lws_create_context(&info); if (!context) { diff --git a/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c index 0fe5391c..de97e6c7 100644 --- a/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c +++ b/minimal-examples/ws-server/minimal-ws-server-timer/minimal-ws-server.c @@ -114,12 +114,14 @@ int main(int argc, const char **argv) info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { lwsl_user("Server using TLS\n"); info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif if (lws_cmdline_option(argc, argv, "-h")) info.options |= LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK; diff --git a/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c index 9e911ad4..741d1741 100644 --- a/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c +++ b/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c @@ -88,12 +88,14 @@ int main(int argc, const char **argv) info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; +#if defined(LWS_WITH_TLS) if (lws_cmdline_option(argc, argv, "-s")) { lwsl_user("Server using TLS\n"); info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.ssl_cert_filepath = "localhost-100y.cert"; info.ssl_private_key_filepath = "localhost-100y.key"; } +#endif if (lws_cmdline_option(argc, argv, "-h")) info.options |= LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK; diff --git a/test-apps/test-client.c b/test-apps/test-client.c index 52478523..3eae37e3 100644 --- a/test-apps/test-client.c +++ b/test-apps/test-client.c @@ -510,6 +510,7 @@ static const struct lws_protocols protocols[] = { { NULL, NULL, 0, 0 } /* end */ }; +#if defined(LWS_ROLE_WS) static const struct lws_extension exts[] = { { "permessage-deflate", @@ -523,7 +524,7 @@ static const struct lws_extension exts[] = { }, { NULL, NULL, NULL /* terminator */ } }; - +#endif void sighandler(int sig) @@ -703,7 +704,9 @@ int main(int argc, char **argv) info.protocols = protocols; info.gid = -1; info.uid = -1; +#if defined(LWS_ROLE_WS) info.extensions = exts; +#endif /* * since we know this lws context is only ever going to be used with @@ -718,7 +721,7 @@ int main(int argc, char **argv) #endif info.options |= LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW; - +#if defined(LWS_WITH_TLS) if (use_ssl) { /* * If the server wants us to present a valid SSL client certificate @@ -759,7 +762,7 @@ int main(int argc, char **argv) lwsl_notice(" Skipping peer cert hostname check\n"); else lwsl_notice(" Requiring peer cert hostname matches\n"); - +#endif context = lws_create_context(&info); if (context == NULL) { fprintf(stderr, "Creating libwebsocket context failed\n"); diff --git a/test-apps/test-server.c b/test-apps/test-server.c index ddec2007..837136c0 100644 --- a/test-apps/test-server.c +++ b/test-apps/test-server.c @@ -206,6 +206,7 @@ void sighandler(int sig) lws_cancel_service(context); } +#if defined(LWS_ROLE_WS) static const struct lws_extension exts[] = { { "permessage-deflate", @@ -214,6 +215,7 @@ static const struct lws_extension exts[] = { }, { NULL, NULL, NULL /* terminator */ } }; +#endif /* * mount handlers for sections of the URL space @@ -503,6 +505,8 @@ int main(int argc, char **argv) info.iface = iface; info.protocols = protocols; + +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = NULL; info.ssl_private_key_filepath = NULL; @@ -521,17 +525,22 @@ int main(int argc, char **argv) if (!key_path[0]) sprintf(key_path, "%s/libwebsockets-test-server.key.pem", resource_path); - +#if defined(LWS_WITH_TLS) info.ssl_cert_filepath = cert_path; info.ssl_private_key_filepath = key_path; if (ca_path[0]) info.ssl_ca_filepath = ca_path; +#endif } +#endif info.gid = gid; info.uid = uid; info.options = opts | LWS_SERVER_OPTION_VALIDATE_UTF8 | LWS_SERVER_OPTION_EXPLICIT_VHOSTS; +#if defined(LWS_ROLE_WS) info.extensions = exts; +#endif info.timeout_secs = 5; +#if defined(LWS_WITH_TLS) info.ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:" "ECDHE-RSA-AES256-GCM-SHA384:" "DHE-RSA-AES256-GCM-SHA384:" @@ -545,9 +554,12 @@ int main(int argc, char **argv) "!DHE-RSA-AES256-SHA256:" "!AES256-GCM-SHA384:" "!AES256-SHA256"; +#endif info.mounts = &mount; +#if defined(LWS_WITH_PEER_LIMITS) info.ip_limit_ah = 128; /* for testing */ info.ip_limit_wsi = 800; /* for testing */ +#endif if (use_ssl) /* redirect guys coming on http */ -- Gitee From a0535d010c72691d706014fadcd1b59eaf1e5dc5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 18 Jun 2020 08:32:22 +0100 Subject: [PATCH 0171/1062] sai.json: reduce riscv qemu builds These are really slow since the processor itself is emulated... if it's broken, it will break on the most complex configurations, configuration conflicts will be flushed out by building on native arch anyway. So just build the complex configuration on Risc-V. --- .sai.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.sai.json b/.sai.json index 7f8d5be6..1cf7a153 100644 --- a/.sai.json +++ b/.sai.json @@ -68,7 +68,7 @@ "configurations": { "default": { "cmake": "", - "platforms": "windows-10/x86_64-amd/msvc, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, freertos-espidf/xl6-esp32/gcc, linux-fedora-32/riscv64-virt/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64" + "platforms": "windows-10/x86_64-amd/msvc, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, freertos-espidf/xl6-esp32/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64" }, "default-examples-openssl-v3": { "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_GENCRYPTO=1", @@ -80,7 +80,7 @@ }, "default-examples": { "cmake": "-DLWS_WITH_MINIMAL_EXAMPLES=1", - "platforms": "windows-10/x86_64-amd/msvc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, linux-fedora-32/riscv64-virt/gcc" + "platforms": "windows-10/x86_64-amd/msvc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc" }, "unix-domain": { "cmake": "-DUNIX_SOCK=1", @@ -92,7 +92,7 @@ }, "secure-streams": { "cmake": "-DLWS_WITH_SECURE_STREAMS=1", - "platforms": "windows-10/x86_64-amd/msvc, linux-fedora-32/riscv64-virt/gcc" + "platforms": "windows-10/x86_64-amd/msvc" }, "secure-streams-proxy": { "cmake": "-DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1", -- Gitee From 34de22b648a83b283daac0a3557dd5ceaa4f75bf Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 18 Jun 2020 08:53:09 +0100 Subject: [PATCH 0172/1062] cmake: cleanups --- cmake/libwebsockets-config.cmake.in | 8 +++----- .../api-tests/api-test-secure-streams/CMakeLists.txt | 2 ++ .../minimal-http-client-captive-portal/CMakeLists.txt | 1 + .../http-client/minimal-http-client-multi/CMakeLists.txt | 2 ++ .../minimal-secure-streams.c | 1 + 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/cmake/libwebsockets-config.cmake.in b/cmake/libwebsockets-config.cmake.in index c683335c..e12464f8 100644 --- a/cmake/libwebsockets-config.cmake.in +++ b/cmake/libwebsockets-config.cmake.in @@ -17,9 +17,7 @@ include(${LWS_CMAKE_DIR}/LibwebsocketsTargets.cmake) set(LIBWEBSOCKETS_LIBRARIES websockets websockets_shared) # These are additional libs that lws wants your app to also link to -if (NOT WIN32 AND NOT MSVC) - set(LIBWEBSOCKETS_DEP_LIBS @LIB_LIST_AT_END@) -else() - set(LIBWEBSOCKETS_DEP_LIBS) -endif() +foreach(item "@LIB_LIST_AT_END@") + list(APPEND LIBWEBSOCKETS_DEP_LIBS ${item}) +endforeach() diff --git a/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt b/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt index 98015b42..6396f98d 100644 --- a/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt @@ -5,6 +5,8 @@ include(LwsCheckRequirements) set(requirements 1) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) + if (requirements) diff --git a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt index e369b1b8..dcfc9832 100644 --- a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt @@ -11,6 +11,7 @@ set(SRCS minimal-http-client-captive-portal.c) set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) if (NOT WIN32 AND requirements) diff --git a/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt index 47717552..b71e0916 100644 --- a/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-multi/CMakeLists.txt @@ -11,6 +11,8 @@ set(SRCS minimal-http-client-multi.c) set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_TLS 1 requirements) + if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c index 0dfa5fa1..4f0c0a46 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c @@ -20,6 +20,7 @@ #include #include #include +#include #include static int interrupted, bad = 1; -- Gitee From d4a7c7134af7db1bdec8360e2f8d6f9b61abd313 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 17 Jun 2020 07:54:26 +0100 Subject: [PATCH 0173/1062] lws_button and lws_led Generic drivers for buttons and leds --- include/libwebsockets.h | 4 +- include/libwebsockets/lws-button.h | 95 ++++++++++ include/libwebsockets/lws-display.h | 8 +- include/libwebsockets/lws-i2c.h | 4 +- include/libwebsockets/lws-led.h | 96 ++++++++++ lib/drivers/CMakeLists.txt | 2 + lib/drivers/button/lws-button.c | 168 ++++++++++++++++++ lib/drivers/led/led-gpio.c | 150 ++++++++++++++++ .../main/lws-minimal-esp32.c | 105 +++++++++-- .../embedded/lws-minimal-esp32/sdkconfig | 39 ++-- 10 files changed, 636 insertions(+), 35 deletions(-) create mode 100644 include/libwebsockets/lws-button.h create mode 100644 include/libwebsockets/lws-led.h create mode 100644 lib/drivers/button/lws-button.c create mode 100644 lib/drivers/led/led-gpio.c diff --git a/include/libwebsockets.h b/include/libwebsockets.h index af28167c..462658d0 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -612,10 +612,10 @@ struct lws; #include #include #include - #include - #include +#include +#include #ifdef __cplusplus } diff --git a/include/libwebsockets/lws-button.h b/include/libwebsockets/lws-button.h new file mode 100644 index 00000000..a1972c2a --- /dev/null +++ b/include/libwebsockets/lws-button.h @@ -0,0 +1,95 @@ +/* + * Generic button ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * Leverages the lws generic gpio pieces to bind gpio buttons to smd events + */ + +#if !defined(__LWS_BUTTON_H__) +#define __LWS_BUTTON_H__ + +typedef uint16_t lws_button_idx_t; + +typedef void (*lws_button_cb_t)(void *opaque, lws_button_idx_t idx, int state); + +/* + * This is the const part of the button controller, describing the static + * bindings to gpio, and lws_smd event name information + */ + +typedef struct lws_button_map { + _lws_plat_gpio_t gpio; + const char *smd_interaction_name; +} lws_button_map_t; + +typedef struct lws_button_controller { + const char *smd_bc_name; + const lws_gpio_ops_t *gpio_ops; + const lws_button_map_t *button_map; + lws_button_idx_t active_state_bitmap; + lws_button_idx_t message_on_down_bitmap; + lws_button_idx_t message_on_up_bitmap; + uint8_t count_buttons; +} lws_button_controller_t; + +struct lws_button_state; /* opaque */ + +/** + * lws_button_controller_create() - instantiate a button controller + * + * \param ctx: the lws_context + * \param controller: the static controller definition + * + * Instantiates a button controller from a static definition of the buttons + * and their smd names, and active levels, and binds it to a gpio implementation + */ + +LWS_VISIBLE LWS_EXTERN struct lws_button_state * +lws_button_controller_create(struct lws_context *ctx, + const lws_button_controller_t *controller); + +/** + * lws_button_controller_destroy() - destroys a button controller + * + * \param bcs: button controller state previously created + * + * Disables all buttons and then destroys and frees a previously created + * button controller. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_button_controller_destroy(struct lws_button_state *bcs); + + +LWS_VISIBLE LWS_EXTERN lws_button_idx_t +lws_button_get_bit(struct lws_button_state *bcs, const char *name); + +/* + * lws_button_enable() - enable and disable buttons + */ + +LWS_VISIBLE LWS_EXTERN void +lws_button_enable(struct lws_button_state *bcs, + lws_button_idx_t _reset, lws_button_idx_t _set); + +#endif + diff --git a/include/libwebsockets/lws-display.h b/include/libwebsockets/lws-display.h index ff750aed..8ac9e289 100644 --- a/include/libwebsockets/lws-display.h +++ b/include/libwebsockets/lws-display.h @@ -96,7 +96,7 @@ typedef struct lws_diplay_state { * - off-only: set autodim to some ms and off_ms to 0 * - neither: set both autodim and off_ms to -1 */ -void +LWS_VISIBLE LWS_EXTERN void lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx, int autodim_ms, int off_ms, lws_display_brightness active, lws_display_brightness dim, const lws_display_t *disp); @@ -110,7 +110,7 @@ lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx, * * Adjusts the brightness gradually twoards the target at 20Hz */ -void +LWS_VISIBLE LWS_EXTERN void lws_display_state_set_brightness(lws_display_state_t *lds, lws_display_brightness target, lws_display_brightness step); @@ -123,7 +123,7 @@ lws_display_state_set_brightness(lws_display_state_t *lds, * Resets the auto-dim and auto-off timers and makes sure the display is on and * at the active brightness level */ -void +LWS_VISIBLE LWS_EXTERN void lws_display_state_active(lws_display_state_t *lds); /* @@ -134,7 +134,7 @@ lws_display_state_active(lws_display_state_t *lds); * Turns the display to least power mode or completely off if possible. * Disables the timers related to dimming and blanking. */ -void +LWS_VISIBLE LWS_EXTERN void lws_display_state_off(lws_display_state_t *lds); #endif diff --git a/include/libwebsockets/lws-i2c.h b/include/libwebsockets/lws-i2c.h index 5f8b6341..3bd81ed3 100644 --- a/include/libwebsockets/lws-i2c.h +++ b/include/libwebsockets/lws-i2c.h @@ -44,10 +44,10 @@ typedef struct lws_i2c_ops { * These are implemented by calling the ops above, and so are generic */ -int +LWS_VISIBLE LWS_EXTERN int lws_i2c_command(const lws_i2c_ops_t *ctx, uint8_t ads7, uint8_t c); -int +LWS_VISIBLE LWS_EXTERN int lws_i2c_command_list(const lws_i2c_ops_t *ctx, uint8_t ads7, const uint8_t *buf, size_t len); diff --git a/include/libwebsockets/lws-led.h b/include/libwebsockets/lws-led.h new file mode 100644 index 00000000..015760f0 --- /dev/null +++ b/include/libwebsockets/lws-led.h @@ -0,0 +1,96 @@ +/* + * Generic LED controller ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for leds, a real implementation provides + * functions for the ops that use the underlying, eg, OS gpio arrangements. + */ + +#if !defined(__LWS_LED_H__) +#define __LWS_LED_H__ + +/* 0 is always OFF, for gpio, anything else is ON */ +typedef uint16_t lws_led_intensity_t; +typedef uint16_t lws_led_seq_phase_t; +#define LWS_LED_MAX_INTENSITY (0xffff) +#define LWS_LED_FRAME_RATE 20 +#define LWS_LED_FUNC_PHASE 1024 + +struct lws_led_state; /* opaque */ + +typedef lws_led_intensity_t (*lws_led_lookup_t)(int idx); + +typedef struct lws_led_sequence_def_t { + lws_led_lookup_t func; + lws_led_seq_phase_t ledphase_offset; + int ledphase_total; + int ms_full_phase; /* to compute rate */ +} lws_led_sequence_def_t; + +/* this should always be first in the subclassed implementation types */ + +typedef struct lws_led_ops { + void (*intensity)(const struct lws_led_ops *lo, int index, + lws_led_intensity_t inten); + int (*lookup)(const struct lws_led_ops *lo, const char *name); + struct lws_led_state * (*create)(const struct lws_led_ops *led_ops); + void (*destroy)(struct lws_led_state *); +} lws_led_ops_t; + +typedef struct lws_led_gpio_map { + const char *name; + _lws_plat_gpio_t gpio; + uint8_t active_level; +} lws_led_gpio_map_t; + +typedef struct lws_led_gpio_controller { + const lws_led_ops_t led_ops; + + const lws_gpio_ops_t *gpio_ops; + const lws_led_gpio_map_t *led_map; + uint8_t count_leds; +} lws_led_gpio_controller_t; + +/* ops */ + +LWS_VISIBLE LWS_EXTERN struct lws_led_state * +lws_led_gpio_create(const lws_led_ops_t *led_ops); + +LWS_VISIBLE LWS_EXTERN void +lws_led_gpio_destroy(struct lws_led_state *lcs); + +LWS_VISIBLE LWS_EXTERN void +lws_led_gpio_intensity(const struct lws_led_ops *lo, int index, lws_led_intensity_t inten); + +LWS_VISIBLE LWS_EXTERN int +lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name); + +#define lws_led_gpio_ops \ + { \ + .create = lws_led_gpio_create, \ + .destroy = lws_led_gpio_destroy, \ + .intensity = lws_led_gpio_intensity, \ + .lookup = lws_led_gpio_lookup, \ + } + +#endif + diff --git a/lib/drivers/CMakeLists.txt b/lib/drivers/CMakeLists.txt index 33a6b193..192ca450 100644 --- a/lib/drivers/CMakeLists.txt +++ b/lib/drivers/CMakeLists.txt @@ -3,6 +3,8 @@ list(APPEND SOURCES drivers/display/ssd1306-i2c.c drivers/i2c/lws-i2c.c drivers/i2c/bitbang/lws-bb-i2c.c + drivers/button/lws-button.c + drivers/led/led-gpio.c ) if (LWS_ESP_PLATFORM) diff --git a/lib/drivers/button/lws-button.c b/lib/drivers/button/lws-button.c new file mode 100644 index 00000000..ab194149 --- /dev/null +++ b/lib/drivers/button/lws-button.c @@ -0,0 +1,168 @@ +/* + * Generic GPIO / irq buttons + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 "private-lib-core.h" + +#if defined(LWS_PLAT_FREERTOS) +#include +#endif + +/* + * This is the opaque, allocated, non-const, dynamic footprint of the + * button controller + */ + +typedef struct lws_button_state { +#if defined(LWS_PLAT_FREERTOS) + TimerHandle_t timer; +#endif + const lws_button_controller_t *controller; + struct lws_context *ctx; + lws_button_idx_t enable_bitmap; + lws_button_idx_t state_bitmap; +} lws_button_state_t; + +/* + * This is the bottom-half scheduled via a timer set in the ISR. From here + * we are allowed to hold mutexes etc. We are coming here because any button + * interrupt arrived, we have to try to figure out which events have happened. + */ + +#if defined(LWS_PLAT_FREERTOS) +static void +lws_button_bh(TimerHandle_t th) +{ + lws_button_state_t *bcs = pvTimerGetTimerID(th); + + lws_smd_msg_printf(bcs->ctx, LWSSMDCL_INTERACTION, + "{\"btn\":\"%s/%s\", \"s\":\"click\"}", + bcs->controller->smd_bc_name, + bcs->controller->button_map[0].smd_interaction_name); + +#if 0 + if (lws_esp32.button_is_down) + gpio_set_intr_type(GPIO_SW, GPIO_INTR_POSEDGE); + else + gpio_set_intr_type(GPIO_SW, GPIO_INTR_NEGEDGE); + + lws_esp32.button_is_down = gpio_get_level(GPIO_SW); + + lws_esp32_button(lws_esp32.button_is_down); +#endif +} +#endif + +struct lws_button_state * +lws_button_controller_create(struct lws_context *ctx, + const lws_button_controller_t *controller) +{ + lws_button_state_t *bcs = lws_zalloc(sizeof(lws_button_state_t), __func__); + + if (!bcs) + return NULL; + + bcs->controller = controller; + bcs->ctx = ctx; + +#if defined(LWS_PLAT_FREERTOS) + bcs->timer = xTimerCreate("bcst", 1, 0, bcs, + (TimerCallbackFunction_t)lws_button_bh); +#endif + + return bcs; +} + +void +lws_button_controller_destroy(struct lws_button_state *bcs) +{ + /* disable them all */ + lws_button_enable(bcs, 0, 0); + +#if defined(LWS_PLAT_FREERTOS) + xTimerDelete(&bcs->timer, 0); +#endif + + lws_free(bcs); +} + +/* + * This is happening in interrupt context, we have to schedule a bottom half to + * do the foreground lws_smd queueing, using, eg, a platform timer. + * + * All the buttons point here and use one timer per button controller. An + * interrupt here means, "something happened to one or more buttons" + */ + +void +lws_button_irq_cb_t(void *arg) +{ +#if defined(LWS_PLAT_FREERTOS) + lws_button_state_t *bcs = (lws_button_state_t *)arg; + + xTimerStart(bcs->timer, 0); +#endif +} + +lws_button_idx_t +lws_button_get_bit(struct lws_button_state *bcs, const char *name) +{ + const lws_button_controller_t *bc = bcs->controller; + int n; + + for (n = 0; n < bc->count_buttons; n++) + if (!strcmp(name, bc->button_map[n].smd_interaction_name)) + return 1 << n; + + return 0; /* not found */ +} + +void +lws_button_enable(lws_button_state_t *bcs, + lws_button_idx_t _reset, lws_button_idx_t _set) +{ + lws_button_idx_t u = (bcs->enable_bitmap & (~_reset)) | _set; + const lws_button_controller_t *bc = bcs->controller; + int n; + + for (n = 0; n < bcs->controller->count_buttons; n++) { + if (!(bcs->enable_bitmap & (1 << n)) && (u & (1 << n))) { + /* set as input with pullup or pulldown appropriately */ + bc->gpio_ops->mode(bc->button_map[n].gpio, + LWSGGPIO_FL_READ | + ((bc->active_state_bitmap & (1 << n)) ? + LWSGGPIO_FL_PULLDOWN : LWSGGPIO_FL_PULLUP)); + /* this one is becoming enabled */ + bc->gpio_ops->irq_mode(bc->button_map[n].gpio, + bc->active_state_bitmap & (1 << n) ? + LWSGGPIO_IRQ_RISING : + LWSGGPIO_IRQ_FALLING, + lws_button_irq_cb_t, bcs); + } + if ((bcs->enable_bitmap & (1 << n)) && !(u & (1 << n))) + /* this one is becoming disabled */ + bc->gpio_ops->irq_mode(bc->button_map[n].gpio, + LWSGGPIO_IRQ_NONE, NULL, NULL); + } + + bcs->enable_bitmap = u; +} diff --git a/lib/drivers/led/led-gpio.c b/lib/drivers/led/led-gpio.c new file mode 100644 index 00000000..11267f61 --- /dev/null +++ b/lib/drivers/led/led-gpio.c @@ -0,0 +1,150 @@ +/* + * Generic GPIO led + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 "private-lib-core.h" + +typedef struct lws_led_state +{ +#if defined(LWS_PLAT_FREERTOS) + TimerHandle_t timer; +#endif + lws_led_gpio_controller_t *controller; +} lws_led_state_t; + +#if defined(LWS_PLAT_FREERTOS) +static void +lws_led_timer_cb(TimerHandle_t th) +{ +// lws_led_state_t *lcs = pvTimerGetTimerID(th); +} +#endif + +struct lws_led_state * +lws_led_gpio_create(const lws_led_ops_t *led_ops) +{ + lws_led_state_t *lcs = lws_zalloc(sizeof(lws_led_state_t), __func__); + lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)led_ops; + int n; + + if (!lcs) + return NULL; + + lcs->controller = lgc; + +#if defined(LWS_PLAT_FREERTOS) + lcs->timer = xTimerCreate("leds", 1, 0, lcs, + (TimerCallbackFunction_t)lws_led_timer_cb); +#endif + + for (n = 0; n < lgc->count_leds; n++) { + lgc->gpio_ops->mode(lgc->led_map[n].gpio, LWSGGPIO_FL_WRITE); + lgc->gpio_ops->set(lgc->led_map[n].gpio, + !lgc->led_map[n].active_level); + } + + return lcs; +} + +void +lws_led_gpio_destroy(struct lws_led_state *lcs) +{ +#if defined(LWS_PLAT_FREERTOS) + xTimerDelete(&lcs->timer, 0); +#endif + lws_free(lcs); +} + +void +lws_led_gpio_intensity(const struct lws_led_ops *lo, int idx, lws_led_intensity_t inten) +{ + const lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)lo; + const lws_led_gpio_map_t *map = &lgc->led_map[idx]; + + lgc->gpio_ops->set(map->gpio, (!!map->active_level) ^ !inten); + +// ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, inten); +// ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0); +} + + +int +lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name) +{ + const lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)lo; + int n; + + for (n = 0; n < lgc->count_leds; n++) + if (!strcmp(name, lgc->led_map[n].name)) + return n; + + return -1; +} + +static const lws_led_intensity_t sineq16[] = { + 0x0000, 0x0191, 0x031e, 0x04a4, 0x061e, 0x0789, 0x08e2, 0x0a24, + 0x0b4e, 0x0c5c, 0x0d4b, 0x0e1a, 0x0ec6, 0x0f4d, 0x0faf, 0x0fea, +}; + +static lws_led_intensity_t sine_lu(int n) +{ + switch ((n >> 4) & 3) { + case 1: + return 4096 + sineq16[n & 15]; + case 2: + return 4096 + sineq16[15 - (n & 15)]; + case 3: + return 4096 - sineq16[n & 15]; + default: + return 4096 - sineq16[15 - (n & 15)]; + } +} + +/* useful for sine led fade patterns */ + +lws_led_intensity_t lws_led_func_sine(int n) +{ + /* + * 2: quadrant + * 4: table entry in quadrant + * 4: interp (LSB) + * + * total 10 bits / 1024 steps per cycle + * + * + 0: 0 + * + 256: 4096 + * + 512: 8192 + * + 768: 4096 + * +1023: 0 + */ + + return (sine_lu(n >> 4) * (15 - (n & 15)) + + sine_lu((n >> 4) + 1) * (n & 15)) / 15; +} + +const lws_led_sequence_def_t lws_ledseq_sine_wipe = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = 512, /* 180 degree phase ./^ */ + .ms_full_phase = 1000, /* ie, 500ms for 180 degree */ +}; + diff --git a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c index da6a672e..7dd42596 100644 --- a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c @@ -28,8 +28,13 @@ struct lws_context *context; lws_sorted_usec_list_t sul; lws_display_state_t lds; +struct lws_led_state *lls; int interrupted; +/* + * Hook up bitbang i2c, display driver and display + */ + static void esp32_i2c_delay(void) { @@ -37,29 +42,90 @@ esp32_i2c_delay(void) } static const lws_bb_i2c_t li2c = { - .bb_ops = lws_bb_i2c_ops, - .scl = GPIO_NUM_15, - .sda = GPIO_NUM_4, - .gpio = &lws_gpio_plat, - .delay = esp32_i2c_delay + .bb_ops = lws_bb_i2c_ops, + .scl = GPIO_NUM_15, + .sda = GPIO_NUM_4, + .gpio = &lws_gpio_plat, + .delay = esp32_i2c_delay }; static const lws_display_ssd1306_t disp = { .disp = { lws_display_ssd1306_ops, - .w = 128, - .h = 64 + .w = 128, + .h = 64 + }, + .i2c = (lws_i2c_ops_t *)&li2c, + .gpio = &lws_gpio_plat, + .reset_gpio = GPIO_NUM_16, + .i2c7_address = SSD1306_I2C7_ADS1 +}; + +/* + * Button controller + */ + +static const lws_button_map_t bcm[] = { + { + .gpio = GPIO_NUM_0, + .smd_interaction_name = "user" }, - .i2c = (lws_i2c_ops_t *)&li2c, - .gpio = &lws_gpio_plat, - .reset_gpio = GPIO_NUM_16, - .i2c7_address = SSD1306_I2C7_ADS1 +}; + +static const lws_button_controller_t bc = { + .smd_bc_name = "bc", + .gpio_ops = &lws_gpio_plat, + .button_map = &bcm[0], + .active_state_bitmap = 0, + .message_on_down_bitmap = (1 << 0), + .message_on_up_bitmap = 0, + .count_buttons = LWS_ARRAY_SIZE(bcm) +}; + +/* + * led controller + */ + +static const lws_led_gpio_map_t lgm[] = { + { + .name = "alert", + .gpio = GPIO_NUM_25, + .active_level = 1, + }, +}; + +static const lws_led_gpio_controller_t lgc = { + .led_ops = lws_led_gpio_ops, + .gpio_ops = &lws_gpio_plat, + .led_map = &lgm[0], + .count_leds = LWS_ARRAY_SIZE(lgm) }; static const uint8_t img[] = { #include "../banded-img.h" }; +static uint8_t flip; + +static int +smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf, + size_t len) +{ + flip = flip ^ 1; + lgc.led_ops.intensity(&lgc.led_ops, + lgc.led_ops.lookup(&lgc.led_ops, "alert"), flip); + + lwsl_hexdump_notice(buf, len); + + /* + * Any kind of user interaction brings the display back up and resets + * the dimming and blanking timers + */ + lws_display_state_active(&lds); + + return 0; +} + static void sul_cb(lws_sorted_usec_list_t *sul) { @@ -72,6 +138,7 @@ app_main(void) { wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); struct lws_context_creation_info info; + struct lws_button_state *bcs; int n = 0; lws_set_log_level(15, NULL); @@ -90,12 +157,26 @@ app_main(void) info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; info.port = CONTEXT_PORT_NO_LISTEN; + info.early_smd_cb = smd_cb; + info.early_smd_class_filter = LWSSMDCL_INTERACTION; context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); return; } + lls = lgc.led_ops.create(&lgc.led_ops); + if (!lls) { + lwsl_err("%s: could not create led\n", __func__); + goto spin; + } + + bcs = lws_button_controller_create(context, &bc); + if (!bcs) { + lwsl_err("%s: could not create buttons\n", __func__); + goto spin; + } + /* * Show the lws logo on the display */ @@ -104,6 +185,8 @@ app_main(void) lws_display_state_active(&lds); disp.disp.blit(lds.disp, img, 0, 0, 128, 64); + lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); + /* * We say the test succeeded if we survive 3s around the event loop */ diff --git a/minimal-examples/embedded/lws-minimal-esp32/sdkconfig b/minimal-examples/embedded/lws-minimal-esp32/sdkconfig index a90f41ca..6ed73d93 100644 --- a/minimal-examples/embedded/lws-minimal-esp32/sdkconfig +++ b/minimal-examples/embedded/lws-minimal-esp32/sdkconfig @@ -221,6 +221,7 @@ CONFIG_EFUSE_MAX_BLK_LEN=192 # ESP-TLS # CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set # CONFIG_ESP_TLS_SERVER is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set # end of ESP-TLS @@ -298,9 +299,9 @@ CONFIG_ADC_CAL_LUT_ENABLE=y # CONFIG_ESP_ERR_TO_NAME_LOOKUP=y CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 -CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 -CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 -CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=6584 +CONFIG_ESP_IPC_TASK_STACK_SIZE=3024 CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 CONFIG_ESP_CONSOLE_UART_DEFAULT=y @@ -408,7 +409,7 @@ CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y # High resolution timer (esp_timer) # # CONFIG_ESP_TIMER_PROFILING is not set -CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_TASK_STACK_SIZE=6584 # CONFIG_ESP_TIMER_IMPL_FRC2 is not set CONFIG_ESP_TIMER_IMPL_TG0_LAC=y # end of High resolution timer (esp_timer) @@ -537,7 +538,7 @@ CONFIG_FREERTOS_ISR_STACKSIZE=1536 CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 # CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION is not set CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 -CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5048 CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 # CONFIG_FREERTOS_USE_TRACE_FACILITY is not set @@ -692,6 +693,7 @@ CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set # CONFIG_MBEDTLS_DEBUG is not set # @@ -709,8 +711,12 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y CONFIG_MBEDTLS_HARDWARE_AES=y CONFIG_MBEDTLS_HARDWARE_MPI=y CONFIG_MBEDTLS_HARDWARE_SHA=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set CONFIG_MBEDTLS_HAVE_TIME=y # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y # CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set # CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set @@ -722,11 +728,7 @@ CONFIG_MBEDTLS_TLS_ENABLED=y # # TLS Key Exchange Methods # -CONFIG_MBEDTLS_PSK_MODES=y -CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y -CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y +# CONFIG_MBEDTLS_PSK_MODES is not set CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y @@ -741,7 +743,7 @@ CONFIG_MBEDTLS_SSL_RENEGOTIATION=y CONFIG_MBEDTLS_SSL_PROTO_TLS1=y CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y -CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set CONFIG_MBEDTLS_SSL_ALPN=y CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y @@ -791,6 +793,8 @@ CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y CONFIG_MBEDTLS_ECP_NIST_OPTIM=y # CONFIG_MBEDTLS_POLY1305_C is not set # CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set # CONFIG_MBEDTLS_SECURITY_RISKS is not set # end of mbedTLS @@ -799,6 +803,7 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y # CONFIG_MDNS_MAX_SERVICES=10 CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 # CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set CONFIG_MDNS_TASK_AFFINITY_CPU0=y # CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set @@ -980,6 +985,7 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # CONFIG_WPA_DEBUG_PRINT is not set # CONFIG_WPA_TESTING_OPTIONS is not set # CONFIG_WPA_TLS_V12 is not set +# CONFIG_WPA_WPS_WARS is not set # end of Supplicant # end of Component config @@ -1059,9 +1065,9 @@ CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y # CONFIG_NO_BLOBS is not set # CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 -CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 -CONFIG_MAIN_TASK_STACK_SIZE=3584 -CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4304 +CONFIG_MAIN_TASK_STACK_SIZE=6584 +CONFIG_IPC_TASK_STACK_SIZE=3024 CONFIG_CONSOLE_UART_DEFAULT=y # CONFIG_CONSOLE_UART_CUSTOM is not set # CONFIG_CONSOLE_UART_NONE is not set @@ -1084,7 +1090,7 @@ CONFIG_POST_EVENTS_FROM_IRAM_ISR=y CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y # CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set # CONFIG_ESP32S2_PANIC_GDBSTUB is not set -CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_TIMER_TASK_STACK_SIZE=6584 CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 CONFIG_MB_QUEUE_LENGTH=20 @@ -1101,7 +1107,7 @@ CONFIG_MB_TIMER_GROUP=0 CONFIG_MB_TIMER_INDEX=0 # CONFIG_SUPPORT_STATIC_ALLOCATION is not set CONFIG_TIMER_TASK_PRIORITY=1 -CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_TASK_STACK_DEPTH=5048 CONFIG_TIMER_QUEUE_LENGTH=10 # CONFIG_L2_TO_L3_COPY is not set # CONFIG_USE_ONLY_LWIP_SELECT is not set @@ -1143,3 +1149,4 @@ CONFIG_SUPPORT_TERMIOS=y CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 # End of deprecated options + -- Gitee From 5a937fa830c536f52f2d8a6292190457e65a8dbd Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 19 Jun 2020 11:10:56 +0100 Subject: [PATCH 0174/1062] lws_json_simple_find and lws_nstrstr String helpers for scanning non-NUL-delimited strings safely, and very cheap simple string match based JSON parse for cases that make sense for it... for more complex cases, do a full JSON parse. --- include/libwebsockets/lws-misc.h | 62 ++++++++++ lib/core/libwebsockets.c | 111 ++++++++++++++++++ .../api-tests/api-test-lws_tokenize/main.c | 67 +++++++++++ 3 files changed, 240 insertions(+) diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index f71158ab..e9185504 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -180,6 +180,68 @@ lws_strncpy(char *dest, const char *src, size_t size); lws_strncpy(dest, src, (size_t)(size1 + 1) < (size_t)(destsize) ? \ (size_t)(size1 + 1) : (size_t)(destsize)) +/** + * lws_nstrstr(): like strstr for length-based strings without terminating NUL + * + * \param buf: the string to search + * \param len: the length of the string to search + * \param name: the substring to search for + * \param nl: the length of name + * + * Returns NULL if \p name is not present in \p buf. Otherwise returns the + * address of the first instance of \p name in \p buf. + * + * Neither buf nor name need to be NUL-terminated. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_nstrstr(const char *buf, size_t len, const char *name, size_t nl); + +/** + * lws_json_simple_find(): dumb JSON string parser + * + * \param buf: the JSON to search + * \param len: the length of the JSON to search + * \param name: the name field to search the JSON for, eg, "\"myname\":" + * \param alen: set to the length of the argument part if non-NULL return + * + * Either returns NULL if \p name is not present in buf, or returns a pointer + * to the argument body of the first instance of \p name, and sets *alen to the + * length of the argument body. + * + * This can cheaply handle fishing out, eg, myarg from {"myname": "myarg"} by + * searching for "\"myname\":". It will return a pointer to myarg and set *alen + * to 5. It equally handles args like "myname": true, or "myname":false, and + * null or numbers are all returned as delimited strings. + * + * Anything more complicated like the value is a subobject or array, you should + * parse it using a full parser like lejp. This is suitable is the JSON is + * and will remain short and simple, and contains well-known names amongst other + * extensible JSON members. + */ +LWS_VISIBLE LWS_EXTERN const char * +lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen); + +/** + * lws_json_simple_strcmp(): dumb JSON string comparison + * + * \param buf: the JSON to search + * \param len: the length of the JSON to search + * \param name: the name field to search the JSON for, eg, "\"myname\":" + * \param comp: return a strcmp of this and the discovered argument + * + * Helper that combines lws_json_simple_find() with strcmp() if it was found. + * If the \p name was not found, returns -1. Otherwise returns a strcmp() + * between what was found and \p comp, ie, return 0 if they match or something + * else if they don't. + * + * If the JSON is relatively simple and you want to target constrained + * devices, this can be a good choice. If the JSON may be complex, you + * should use a full JSON parser. + */ +LWS_VISIBLE LWS_EXTERN int +lws_json_simple_strcmp(const char *buf, size_t len, const char *name, const char *comp); + + /** * lws_hex_to_byte_array(): convert hex string like 0123456789ab into byte data * diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index adecc1c3..d034fe79 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -345,6 +345,117 @@ lws_strdup(const char *s) return d; } +const char * +lws_nstrstr(const char *buf, size_t len, const char *name, size_t nl) +{ + const char *end = buf + len - nl + 1; + size_t n; + + if (nl > len) + /* it cannot be found if the needle is longer than the haystack */ + return NULL; + + while (buf < end) { + if (*buf != name[0]) { + buf++; + continue; + } + + if (nl == 1) + /* single char match, we are done */ + return buf; + + if (buf[nl - 1] == name[nl - 1]) { + /* + * This is looking interesting then... the first + * and last chars match, let's check the insides + */ + n = 1; + while (n < nl && buf[n] == name[n]) + n++; + + if (n == nl) + /* it's a hit */ + return buf; + } + + buf++; + } + + return NULL; +} + +/* + * name wants to be something like "\"myname\":" + */ + +const char * +lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen) +{ + size_t nl = strlen(name); + const char *np = lws_nstrstr(buf, len, name, nl), + *end = buf + len, *as; + int qu = 0; + + if (!np) + return NULL; + + np += nl; + + while (np < end && (*np == ' ' || *np == '\t')) + np++; + + if (np >= end - 1) + return NULL; + + /* + * The arg could be lots of things after "name": with JSON, commonly a + * string like "mystring", true, false, null, [...] or {...} ... we want + * to handle common, simple cases cheaply with this; the user can choose + * a full JSON parser like lejp if it's complicated. So if no opening + * quote, return until a terminator like , ] }. If there's an opening + * quote, return until closing quote, handling escaped quotes. + */ + + if (*np == '\"') { + qu = 1; + np++; + } + + as = np; + while (np < end && + (!qu || *np != '\"') && /* end quote is EOT if quoted */ + (qu || (*np != '}' && *np != ']' && *np != ',')) /* delimiters */ + ) { + if (qu && *np == '\\') /* skip next char if quoted escape */ + np++; + np++; + } + + if (np == end) + return NULL; + + *alen = lws_ptr_diff(np, as); + + return as; +} + +int +lws_json_simple_strcmp(const char *buf, size_t len, const char *name, + const char *comp) +{ + size_t al; + const char *hit = lws_json_simple_find(buf, len, name, &al); + + if (!hit) + return -1; + + if (al != strlen(comp)) + return -1; + + return strncmp(hit, comp, al); +} + static const char *hex = "0123456789ABCDEF"; const char * diff --git a/minimal-examples/api-tests/api-test-lws_tokenize/main.c b/minimal-examples/api-tests/api-test-lws_tokenize/main.c index 7682ede1..e6d26d63 100644 --- a/minimal-examples/api-tests/api-test-lws_tokenize/main.c +++ b/minimal-examples/api-tests/api-test-lws_tokenize/main.c @@ -417,6 +417,73 @@ int main(int argc, const char **argv) return 1; } + /* sanity check lws_nstrstr() */ + + { + static const char *t1 = "abc123456"; + const char *mcp; + + mcp = lws_nstrstr(t1, strlen(t1), "abc", 3); + if (mcp != t1) { + lwsl_err("%s: lws_nstrstr 1 failed\n", __func__); + return 1; + } + mcp = lws_nstrstr(t1, strlen(t1), "def", 3); + if (mcp != NULL) { + lwsl_err("%s: lws_nstrstr 2 failed\n", __func__); + return 1; + } + mcp = lws_nstrstr(t1, strlen(t1), "456", 3); + if (mcp != t1 + 6) { + lwsl_err("%s: lws_nstrstr 3 failed: %p\n", __func__, mcp); + return 1; + } + mcp = lws_nstrstr(t1, strlen(t1), "1", 1); + if (mcp != t1 + 3) { + lwsl_err("%s: lws_nstrstr 4 failed\n", __func__); + return 1; + } + mcp = lws_nstrstr(t1, strlen(t1), "abc1234567", 10); + if (mcp != NULL) { + lwsl_err("%s: lws_nstrstr 5 failed\n", __func__); + return 1; + } + } + + /* sanity check lws_json_simple_find() */ + + { + static const char *t1 = "{\"myname1\":true," + "\"myname2\":\"string\", " + "\"myname3\": 123}"; + size_t alen; + const char *mcp; + + mcp = lws_json_simple_find(t1, strlen(t1), "\"myname1\":", &alen); + if (mcp != t1 + 11 || alen != 4) { + lwsl_err("%s: lws_json_simple_find 1 failed: (%d) %s\n", __func__, (int)alen, mcp); + return 1; + } + + mcp = lws_json_simple_find(t1, strlen(t1), "\"myname2\":", &alen); + if (mcp != t1 + 27 || alen != 6) { + lwsl_err("%s: lws_json_simple_find 2 failed\n", __func__); + return 1; + } + + mcp = lws_json_simple_find(t1, strlen(t1), "\"myname3\":", &alen); + if (mcp != t1 + 47 || alen != 3) { + lwsl_err("%s: lws_json_simple_find 3 failed\n", __func__); + return 1; + } + + mcp = lws_json_simple_find(t1, strlen(t1), "\"nope\":", &alen); + if (mcp != NULL) { + lwsl_err("%s: lws_json_simple_find 4 failed\n", __func__); + return 1; + } + } + p = lws_cmdline_option(argc, argv, "-s"); for (n = 0; n < (int)LWS_ARRAY_SIZE(tests); n++) { -- Gitee From c2609f6d7b0d04f97b3e3f6b789d678e32cb1a0b Mon Sep 17 00:00:00 2001 From: Jed Lu Date: Fri, 19 Jun 2020 18:25:56 +0100 Subject: [PATCH 0175/1062] ss: http: if not retrying move to idle state --- lib/secure-streams/protocols/ss-h1.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 50aca2ab..a97c9f73 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -206,6 +206,8 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && !h->txn_ok && !wsi->context->being_destroyed) lws_ss_backoff(h); + else + h->seqstate = SSSEQ_IDLE; /* already disconnected, no action for DISCONNECT_ME */ if (lws_ss_event_helper(h, LWSSSCS_DISCONNECTED) == LWSSSSRET_DESTROY_ME) -- Gitee From 43ba4e4ef5155cc242ae0f1dda5c8a8054027cc5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 19 Jun 2020 19:54:17 +0100 Subject: [PATCH 0176/1062] libevent: enforce no event state duplication https://github.com/warmcat/libwebsockets/issues/1956 --- lib/event-libs/libevent/libevent.c | 17 +++++++++++++---- .../libevent/private-lib-event-libs-libevent.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/event-libs/libevent/libevent.c b/lib/event-libs/libevent/libevent.c index bd59d30f..7805fc10 100644 --- a/lib/event-libs/libevent/libevent.c +++ b/lib/event-libs/libevent/libevent.c @@ -200,6 +200,7 @@ elops_init_pt_event(struct lws_context *context, void *_loop, int tsi) (EV_READ | EV_PERSIST), lws_event_cb, &vh->lserv_wsi->w_read); event_add(vh->lserv_wsi->w_read.event.watcher, NULL); + vh->lserv_wsi->w_read.event.set = 1; } vh = vh->vhost_next; } @@ -277,17 +278,25 @@ elops_io_event(struct lws *wsi, int flags) (flags & (LWS_EV_READ | LWS_EV_WRITE))); if (flags & LWS_EV_START) { - if (flags & LWS_EV_WRITE) + if ((flags & LWS_EV_WRITE) && !wsi->w_write.event.set) { event_add(wsi->w_write.event.watcher, NULL); + wsi->w_write.event.set = 1; + } - if (flags & LWS_EV_READ) + if ((flags & LWS_EV_READ) && !wsi->w_read.event.set) { event_add(wsi->w_read.event.watcher, NULL); + wsi->w_read.event.set = 1; + } } else { - if (flags & LWS_EV_WRITE) + if ((flags & LWS_EV_WRITE) && wsi->w_write.event.set) { event_del(wsi->w_write.event.watcher); + wsi->w_write.event.set = 0; + } - if (flags & LWS_EV_READ) + if ((flags & LWS_EV_READ) && wsi->w_read.event.set) { event_del(wsi->w_read.event.watcher); + wsi->w_read.event.set = 0; + } } } diff --git a/lib/event-libs/libevent/private-lib-event-libs-libevent.h b/lib/event-libs/libevent/private-lib-event-libs-libevent.h index 6d002954..9bc8e684 100644 --- a/lib/event-libs/libevent/private-lib-event-libs-libevent.h +++ b/lib/event-libs/libevent/private-lib-event-libs-libevent.h @@ -32,6 +32,7 @@ struct lws_pt_eventlibs_libevent { struct lws_io_watcher_libevent { struct event *watcher; + char set; }; struct lws_signal_watcher_libevent { -- Gitee From 81bff78c86fc5292658b3cba487bababdcbafe31 Mon Sep 17 00:00:00 2001 From: dev31337 Date: Sat, 20 Jun 2020 17:22:04 +0100 Subject: [PATCH 0177/1062] lejp: enable negative integers https://github.com/warmcat/libwebsockets/issues/1957 --- lib/misc/lejp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/misc/lejp.c b/lib/misc/lejp.c index 77495288..8f7a0c09 100644 --- a/lib/misc/lejp.c +++ b/lib/misc/lejp.c @@ -434,7 +434,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) break; case LEJP_MP_VALUE: - if (c >= '0' && c <= '9') { + if (c == '-' || (c >= '0' && c <= '9')) { ctx->npos = 0; ctx->dcount = 0; ctx->f = 0; -- Gitee From 366333adba202e6c2925c8c90747689be88a95af Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 20 Jun 2020 17:49:40 +0100 Subject: [PATCH 0178/1062] lejp: docs: clarify LEJPCB_VAL_STR_CHUNK --- include/libwebsockets/lws-lejp.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/libwebsockets/lws-lejp.h b/include/libwebsockets/lws-lejp.h index b8837bbf..cd90777b 100644 --- a/include/libwebsockets/lws-lejp.h +++ b/include/libwebsockets/lws-lejp.h @@ -153,11 +153,12 @@ enum lejp_callbacks { * * LEJPCB_VAL_STR_START: We are starting to parse a string, no data yet * - * LEJPCB_VAL_STR_CHUNK: We parsed LEJP_STRING_CHUNK -1 bytes of string data in - * ctx->buf, which is as much as we can buffer, so we are - * spilling it. If all your strings are less than - * LEJP_STRING_CHUNK - 1 bytes, you will never see this - * callback. + * LEJPCB_VAL_STR_CHUNK: We filled the string buffer in the ctx, but it's not + * the end of the string. We produce this to spill the + * intermediate buffer to the user code, so we can handle + * huge JSON strings using only the small buffer in the + * ctx. If the whole JSON string fits in the ctx buffer, + * you won't get these callbacks. * * LEJPCB_VAL_STR_END: String parsing has completed, the last chunk of the * string is in ctx->buf. -- Gitee From 33f1003305b98a3f5523fb2705ff33a5a62e9005 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 18 Jun 2020 07:53:07 +0100 Subject: [PATCH 0179/1062] lws_pwm --- include/libwebsockets.h | 1 + include/libwebsockets/lws-led.h | 61 ++++-- include/libwebsockets/lws-pwm.h | 64 ++++++ lib/drivers/CMakeLists.txt | 6 +- lib/drivers/led/README.md | 154 ++++++++++++++ lib/drivers/led/led-gpio.c | 122 ++++------- lib/drivers/led/led-seq.c | 198 ++++++++++++++++++ lib/drivers/led/private-lib-drivers-led.h | 58 +++++ lib/drivers/pwm/pwm.c | 149 +++++++++++++ lib/plat/freertos/esp32/drivers/pwm-esp32.c | 78 +++++++ lib/plat/freertos/private-lib-plat-freertos.h | 11 + .../main/lws-minimal-esp32.c | 35 +++- 12 files changed, 841 insertions(+), 96 deletions(-) create mode 100644 include/libwebsockets/lws-pwm.h create mode 100644 lib/drivers/led/README.md create mode 100644 lib/drivers/led/led-seq.c create mode 100644 lib/drivers/led/private-lib-drivers-led.h create mode 100644 lib/drivers/pwm/pwm.c create mode 100644 lib/plat/freertos/esp32/drivers/pwm-esp32.c diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 462658d0..ac226bb1 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -616,6 +616,7 @@ struct lws; #include #include #include +#include #ifdef __cplusplus } diff --git a/include/libwebsockets/lws-led.h b/include/libwebsockets/lws-led.h index 015760f0..7f131b89 100644 --- a/include/libwebsockets/lws-led.h +++ b/include/libwebsockets/lws-led.h @@ -28,30 +28,39 @@ #if !defined(__LWS_LED_H__) #define __LWS_LED_H__ -/* 0 is always OFF, for gpio, anything else is ON */ +/* only b15 significant for GPIO */ typedef uint16_t lws_led_intensity_t; typedef uint16_t lws_led_seq_phase_t; -#define LWS_LED_MAX_INTENSITY (0xffff) -#define LWS_LED_FRAME_RATE 20 -#define LWS_LED_FUNC_PHASE 1024 + +/* the normalized max intensity */ +#define LWS_LED_MAX_INTENSITY (0xffff) + +/* the normalized 360 degree phase count for intensity functions */ +#define LWS_LED_FUNC_PHASE 65536 +/* used when the sequence doesn't stop by itself and goes around forever */ +#define LWS_SEQ_LEDPHASE_TOTAL_ENDLESS (-1) + +#define LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS 33 struct lws_led_state; /* opaque */ +struct lws_pwm_ops; /* forward ref */ -typedef lws_led_intensity_t (*lws_led_lookup_t)(int idx); +typedef lws_led_intensity_t (*lws_led_lookup_t)(lws_led_seq_phase_t ph); typedef struct lws_led_sequence_def_t { - lws_led_lookup_t func; - lws_led_seq_phase_t ledphase_offset; - int ledphase_total; - int ms_full_phase; /* to compute rate */ + lws_led_lookup_t func; + lws_led_seq_phase_t ledphase_offset; + int ledphase_total; /* 65536= one cycle */ + uint16_t ms; + uint8_t flags; } lws_led_sequence_def_t; /* this should always be first in the subclassed implementation types */ typedef struct lws_led_ops { - void (*intensity)(const struct lws_led_ops *lo, int index, + void (*intensity)(const struct lws_led_ops *lo, const char *name, lws_led_intensity_t inten); - int (*lookup)(const struct lws_led_ops *lo, const char *name); + /**< for BOOL led control like GPIO, only inten b15 is significant */ struct lws_led_state * (*create)(const struct lws_led_ops *led_ops); void (*destroy)(struct lws_led_state *); } lws_led_ops_t; @@ -59,6 +68,15 @@ typedef struct lws_led_ops { typedef struct lws_led_gpio_map { const char *name; _lws_plat_gpio_t gpio; + lws_led_lookup_t intensity_correction; + /**< May be NULL. If GPIO-based LED, ignored. If pwm_ops provided, + * NULL means use default CIE 100% correction function. If non-NULL, + * use the pointed-to correction function. This is useful to provide + * LED-specific intensity correction / scaling so different types of + * LED can "look the same". */ + const struct lws_pwm_ops *pwm_ops; + /**< if NULL, gpio controls the led directly. If set to a pwm_ops, + * the led control is outsourced to the pwm controller. */ uint8_t active_level; } lws_led_gpio_map_t; @@ -78,19 +96,32 @@ lws_led_gpio_create(const lws_led_ops_t *led_ops); LWS_VISIBLE LWS_EXTERN void lws_led_gpio_destroy(struct lws_led_state *lcs); +/** + * lws_led_gpio_intensity() - set the static intensity of an led + * + * \param lo: the base class of the led controller + * \param index: which led in the controller set + * \param inten: 16-bit unsigned intensity + * + * For LEDs controlled by a BOOL like GPIO, only inten b15 is significant. + * For PWM type LED control, as many bits as the hardware can support from b15 + * down are significant. + */ LWS_VISIBLE LWS_EXTERN void -lws_led_gpio_intensity(const struct lws_led_ops *lo, int index, lws_led_intensity_t inten); +lws_led_gpio_intensity(const struct lws_led_ops *lo, const char *name, + lws_led_intensity_t inten); LWS_VISIBLE LWS_EXTERN int -lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name); +lws_led_transition(struct lws_led_state *lcs, const char *name, + const lws_led_sequence_def_t *next, + const lws_led_sequence_def_t *trans); + #define lws_led_gpio_ops \ { \ .create = lws_led_gpio_create, \ .destroy = lws_led_gpio_destroy, \ .intensity = lws_led_gpio_intensity, \ - .lookup = lws_led_gpio_lookup, \ } #endif - diff --git a/include/libwebsockets/lws-pwm.h b/include/libwebsockets/lws-pwm.h new file mode 100644 index 00000000..ed3d558f --- /dev/null +++ b/include/libwebsockets/lws-pwm.h @@ -0,0 +1,64 @@ +/* + * Generic PWM controller ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +typedef struct lws_pwm_map { + _lws_plat_gpio_t gpio; + uint8_t index; +} lws_pwm_map_t; + +typedef struct lws_pwm_ops { + int (*init)(const struct lws_pwm_ops *lo); + void (*intensity)(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, + lws_led_intensity_t inten); + const lws_pwm_map_t *pwm_map; + uint8_t count_pwm_map; +} lws_pwm_ops_t; + +LWS_VISIBLE LWS_EXTERN int +lws_pwm_plat_init(const struct lws_pwm_ops *lo); + +LWS_VISIBLE LWS_EXTERN void +lws_pwm_plat_intensity(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, + lws_led_intensity_t inten); + +#define lws_pwm_plat_ops \ + .init = lws_pwm_plat_init, \ + .intensity = lws_pwm_plat_intensity + +/* + * May be useful for making your own transitions or sequences + */ + +LWS_VISIBLE LWS_EXTERN lws_led_intensity_t +lws_led_func_linear(lws_led_seq_phase_t n); +LWS_VISIBLE LWS_EXTERN lws_led_intensity_t +lws_led_func_sine(lws_led_seq_phase_t n); + +/* canned sequences that can work out of the box */ + +extern const lws_led_sequence_def_t lws_pwmseq_sine_endless_slow, + lws_pwmseq_sine_endless_fast, + lws_pwmseq_linear_wipe, + lws_pwmseq_sine_up, lws_pwmseq_sine_down, + lws_pwmseq_static_on, lws_pwmseq_static_off; diff --git a/lib/drivers/CMakeLists.txt b/lib/drivers/CMakeLists.txt index 192ca450..b15a7c38 100644 --- a/lib/drivers/CMakeLists.txt +++ b/lib/drivers/CMakeLists.txt @@ -5,11 +5,15 @@ list(APPEND SOURCES drivers/i2c/bitbang/lws-bb-i2c.c drivers/button/lws-button.c drivers/led/led-gpio.c + drivers/led/led-seq.c + drivers/pwm/pwm.c ) if (LWS_ESP_PLATFORM) list(APPEND SOURCES - plat/freertos/esp32/drivers/gpio-esp32.c) + plat/freertos/esp32/drivers/gpio-esp32.c + plat/freertos/esp32/drivers/pwm-esp32.c + ) endif() exports_to_parent_scope() diff --git a/lib/drivers/led/README.md b/lib/drivers/led/README.md new file mode 100644 index 00000000..1fef8558 --- /dev/null +++ b/lib/drivers/led/README.md @@ -0,0 +1,154 @@ +# lws_led gpio and pwm class drivers + +Lws provides an abstract led controller class that can bind an array of LEDs +to gpio and pwm controllers, and automatically handled pwm sequencers. + +Lumience intensity is corrected for IEC curves to match perceptual intensity, +and the correction can be overridden per led for curve adaptation matching. + +Intensity is normalized to a 16-bit scale, when controlled by a GPIO b15 is +significant and the rest ignored. When controlled by PWM, as many bits from +b15 down are significant as the PWM arrangements can represent. + +The PWM sequencers use arbitrary function generation callbacks on a normalized +16-bit phase space, they can choose how much to interpolate and how much to put +in a table, a 64-sample, 16-bit sine function is provided along with 16-bit +linear sawtooth. + +Changing the sequencer is subject to a third transition function sequencer, this +can for example mix the transition linearly over, eg, 500ms so the leds look +very smooth. + +## Defining an led controller + +An array of inidividual LED information is provided first, and referenced by +the LED controller definintion. Leds are named so code does not introduce +dependencies on specific implementations. + +``` +static const lws_led_gpio_map_t lgm[] = { + { + .name = "alert", + .gpio = GPIO_NUM_25, + .pwm_ops = &pwm_ops, + .active_level = 1, + }, +}; + +static const lws_led_gpio_controller_t lgc = { + .led_ops = lws_led_gpio_ops, + .gpio_ops = &lws_gpio_plat, + .led_map = &lgm[0], + .count_leds = LWS_ARRAY_SIZE(lgm) +}; + + struct lws_led_state *lls; + + lls = lgc.led_ops.create(&lgc.led_ops); + if (!lls) { + lwsl_err("%s: could not create led\n", __func__); + goto spin; + } + +``` + +For GPIO control, the active level of the GPIO to light the LED may be set. + +Each LED may bind to a pwm controller, in which case setting the intensity +programs the pwm controller corresponding to the GPIO. + +## Setting the intensity directly + +``` + lgc.led_ops.intensity(&lgc.led_ops, "alert", 0); +``` + +## Defining Sequencer + +Some common sequencers are provided out of the box, you can also define your +own arbitrary ones. + +The main point is sequencers have a function that returns an intensity for each +of 65536 phase steps in its cycle. For example, this is the linear function +that is included + +``` +lws_led_intensity_t +lws_led_func_linear(lws_led_seq_phase_t n) +{ + return (lws_led_intensity_t)n; +} +``` + +It simply returns an intensity between 0 - 65535 matching the phase angle of +0 - 65535 that it was given, so it's a sawtooth ramp. + +An interpolated sine function is also provided that returns an intensity +between 0 - 65535 reflecting one cycle of sine wave for the phase angle of 0 - +65535. + +These functions are packaged into sequencer structures like this + +``` +const lws_led_sequence_def_t lws_pwmseq_sine_endless_fast = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_SEQ_LEDPHASE_TOTAL_ENDLESS, + .ms = 750 +}; +``` + +This "endless" sequencer cycles through the sine function at 750ms per cycle. +Non-endless sequencers have a specific start and end in the phase space, eg + +``` +const lws_led_sequence_def_t lws_pwmseq_sine_up = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_LED_FUNC_PHASE / 2, /* 180 degree ./^ */ + .ms = 300 +}; +``` + +... this one traverses 180 degrees of the sine wave starting from 0 and ending +at full intensity, over 300ms. + +A commonly-used, provided one is like this, as used in the next section + +``` +const lws_led_sequence_def_t lws_pwmseq_linear_wipe = { + .func = lws_led_func_linear, + .ledphase_offset = 0, + .ledphase_total = LWS_LED_FUNC_PHASE - 1, + .ms = 300 +}; +``` + +## Setting the intensity using sequencer transitions + +The main api for high level sequenced control is + +``` +int +lws_led_transition(struct lws_led_state *lcs, const char *name, + const lws_led_sequence_def_t *next, + const lws_led_sequence_def_t *trans); +``` + +This fades from the current sequence to a new sequence, using `trans` sequencer +intensity as the mix factor. `trans` is typically `lws_pwmseq_linear_wipe`, +fading between the current and new linearly over 300ms. At the end of the +`trans` sequence, the new sequence simply replaces the current one and the +transition is completed. + +Sequencers use a single 30Hz OS timer while any sequence is active. + +exported sequencer symbol|description +---|--- +lws_pwmseq_sine_endless_slow|continuous 100% sine, 1.5s cycle +lws_pwmseq_sine_endless_fast|continuous 100% sine, 0.75s cycle +lws_pwmseq_linear_wipe|single 0 - 100% ramp over 0.3s +lws_pwmseq_sine_up|single 0 - 100% using sine curve over 0.3s +lws_pwmseq_sine_down|single 100% - 0 using sine curve over 0.3s +lws_pwmseq_static_on|100% static +lws_pwmseq_static_off|0% static diff --git a/lib/drivers/led/led-gpio.c b/lib/drivers/led/led-gpio.c index 11267f61..664a120c 100644 --- a/lib/drivers/led/led-gpio.c +++ b/lib/drivers/led/led-gpio.c @@ -22,28 +22,30 @@ * IN THE SOFTWARE. */ #include "private-lib-core.h" +#include "drivers/led/private-lib-drivers-led.h" -typedef struct lws_led_state +#if defined(LWS_PLAT_TIMER_CB) +static LWS_PLAT_TIMER_CB(lws_led_timer_cb, th) { -#if defined(LWS_PLAT_FREERTOS) - TimerHandle_t timer; -#endif - lws_led_gpio_controller_t *controller; -} lws_led_state_t; + lws_led_state_t *lcs = LWS_PLAT_TIMER_CB_GET_OPAQUE(th); -#if defined(LWS_PLAT_FREERTOS) -static void -lws_led_timer_cb(TimerHandle_t th) -{ -// lws_led_state_t *lcs = pvTimerGetTimerID(th); + lws_seq_timer_handle(lcs); } #endif struct lws_led_state * lws_led_gpio_create(const lws_led_ops_t *led_ops) { - lws_led_state_t *lcs = lws_zalloc(sizeof(lws_led_state_t), __func__); lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)led_ops; + /* + * We allocate the main state object, and a 3 x seq dynamic footprint + * for each led, since it may be sequencing the transition between two + * other sequences. + */ + + lws_led_state_t *lcs = lws_zalloc(sizeof(lws_led_state_t) + + (lgc->count_leds * sizeof(lws_led_state_chs_t)), + __func__); int n; if (!lcs) @@ -51,15 +53,25 @@ lws_led_gpio_create(const lws_led_ops_t *led_ops) lcs->controller = lgc; -#if defined(LWS_PLAT_FREERTOS) - lcs->timer = xTimerCreate("leds", 1, 0, lcs, +#if defined(LWS_PLAT_TIMER_CREATE) + lcs->timer = LWS_PLAT_TIMER_CREATE("leds", + LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS, 1, lcs, (TimerCallbackFunction_t)lws_led_timer_cb); + if (!lcs->timer) + return NULL; #endif for (n = 0; n < lgc->count_leds; n++) { - lgc->gpio_ops->mode(lgc->led_map[n].gpio, LWSGGPIO_FL_WRITE); - lgc->gpio_ops->set(lgc->led_map[n].gpio, - !lgc->led_map[n].active_level); + const lws_led_gpio_map_t *map = &lgc->led_map[n]; + + if (map->pwm_ops) { + lgc->gpio_ops->mode(map->gpio, LWSGGPIO_FL_READ); + lgc->gpio_ops->set(map->gpio, 0); + } else { + lgc->gpio_ops->mode(map->gpio, LWSGGPIO_FL_WRITE); + lgc->gpio_ops->set(map->gpio, + !lgc->led_map[n].active_level); + } } return lcs; @@ -68,25 +80,12 @@ lws_led_gpio_create(const lws_led_ops_t *led_ops) void lws_led_gpio_destroy(struct lws_led_state *lcs) { -#if defined(LWS_PLAT_FREERTOS) - xTimerDelete(&lcs->timer, 0); +#if defined(LWS_PLAT_TIMER_DELETE) + LWS_PLAT_TIMER_DELETE(&lcs->timer); #endif lws_free(lcs); } -void -lws_led_gpio_intensity(const struct lws_led_ops *lo, int idx, lws_led_intensity_t inten) -{ - const lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)lo; - const lws_led_gpio_map_t *map = &lgc->led_map[idx]; - - lgc->gpio_ops->set(map->gpio, (!!map->active_level) ^ !inten); - -// ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, inten); -// ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0); -} - - int lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name) { @@ -100,51 +99,22 @@ lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name) return -1; } -static const lws_led_intensity_t sineq16[] = { - 0x0000, 0x0191, 0x031e, 0x04a4, 0x061e, 0x0789, 0x08e2, 0x0a24, - 0x0b4e, 0x0c5c, 0x0d4b, 0x0e1a, 0x0ec6, 0x0f4d, 0x0faf, 0x0fea, -}; - -static lws_led_intensity_t sine_lu(int n) +void +lws_led_gpio_intensity(const struct lws_led_ops *lo, const char *name, + lws_led_intensity_t inten) { - switch ((n >> 4) & 3) { - case 1: - return 4096 + sineq16[n & 15]; - case 2: - return 4096 + sineq16[15 - (n & 15)]; - case 3: - return 4096 - sineq16[n & 15]; - default: - return 4096 - sineq16[15 - (n & 15)]; - } -} - -/* useful for sine led fade patterns */ + const lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)lo; + int idx = lws_led_gpio_lookup(lo, name); + const lws_led_gpio_map_t *map; -lws_led_intensity_t lws_led_func_sine(int n) -{ - /* - * 2: quadrant - * 4: table entry in quadrant - * 4: interp (LSB) - * - * total 10 bits / 1024 steps per cycle - * - * + 0: 0 - * + 256: 4096 - * + 512: 8192 - * + 768: 4096 - * +1023: 0 - */ - - return (sine_lu(n >> 4) * (15 - (n & 15)) + - sine_lu((n >> 4) + 1) * (n & 15)) / 15; -} + if (idx < 0) + return; -const lws_led_sequence_def_t lws_ledseq_sine_wipe = { - .func = lws_led_func_sine, - .ledphase_offset = 0, /* already at 0 amp at 0 phase */ - .ledphase_total = 512, /* 180 degree phase ./^ */ - .ms_full_phase = 1000, /* ie, 500ms for 180 degree */ -}; + map = &lgc->led_map[idx]; + if (map->pwm_ops) + map->pwm_ops->intensity(map->pwm_ops, map->gpio, inten); + else + lgc->gpio_ops->set(map->gpio, + (!!map->active_level) ^ !(inten & 0x8000)); +} diff --git a/lib/drivers/led/led-seq.c b/lib/drivers/led/led-seq.c new file mode 100644 index 00000000..49381d39 --- /dev/null +++ b/lib/drivers/led/led-seq.c @@ -0,0 +1,198 @@ +/* + * Generic GPIO led + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 "private-lib-core.h" + +#include "drivers/led/private-lib-drivers-led.h" + +/* + * 64 entry interpolated CIE correction + * https://en.wikipedia.org/wiki/Lightness + */ + +uint16_t cie[] = { + 0, 113, 227, 340, 454, 568, 688, 824, 976, 1146, + 1335, 1543, 1772, 2023, 2296, 2592, 2914, 3260, 3633, 4034, + 4463, 4921, 5409, 5929, 6482, 7067, 7687, 8341, 9032, 9761, + 10527, 11332, 12178, 13064, 13993, 14964, 15980, 17040, 18146, 19299, + 20500, 21750, 23049, 24400, 25802, 27256, 28765, 30328, 31946, 33622, + 35354, 37146, 38996, 40908, 42881, 44916, 47014, 49177, 51406, 53700, + 56062, 58492, 60992, 63561, + 65535 /* for interpolation */ +}; + +/* + * This is the default intensity correction function, it can be overridden + * per-led to eg, normalize intensity of different leds + */ + +static lws_led_intensity_t +cie_antilog(lws_led_intensity_t lin) +{ + return (cie[lin >> 10] * (0x3ff - (lin & 0x3ff)) + + cie[(lin >> 10) + 1] * (lin & 0x3ff)) / 0x3ff; +} + +static void +lws_seq_advance(lws_led_state_t *lcs, lws_led_state_ch_t *ch) +{ + if (!ch->seq) + return; + + if (ch->phase_budget != -1 && + ch->phase_budget < ch->step) { + + /* we are done */ + + ch->seq = NULL; + if (!(--lcs->timer_refcount)) { +#if defined(LWS_PLAT_TIMER_STOP) + LWS_PLAT_TIMER_STOP(lcs->timer); +#endif + } + + return; + } + + ch->ph += ch->step; + if (ch->phase_budget != -1) + ch->phase_budget -= ch->step; +} + +static lws_led_intensity_t +lws_seq_sample(const lws_led_gpio_map_t *map, lws_led_state_chs_t *chs) +{ + unsigned int i = 0, mix, nx; + + if (chs->seqs[LWS_LED_SEQ_IDX_CURR].seq) + i = chs->seqs[LWS_LED_SEQ_IDX_CURR].seq-> + func(chs->seqs[LWS_LED_SEQ_IDX_CURR].ph); + + if (chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].seq) { + /* + * If a transition is ongoing, we need to use the transition + * intensity as the mixing factor between the still-live current + * and newly-live next sequences + */ + mix = chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].seq-> + func(chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].ph); + nx = 0; + if (chs->seqs[LWS_LED_SEQ_IDX_NEXT].seq) + nx = chs->seqs[LWS_LED_SEQ_IDX_NEXT].seq-> + func(chs->seqs[LWS_LED_SEQ_IDX_NEXT].ph); + + i = (lws_led_intensity_t)( + ((i * (65535 - mix) / 65536) + + ((nx * mix) / 65536))); + } + + return map->intensity_correction ? + map->intensity_correction(i) : + cie_antilog((lws_led_intensity_t)i); +} + +void +lws_seq_timer_handle(lws_led_state_t *lcs) +{ + lws_led_gpio_controller_t *lgc = lcs->controller; + lws_led_state_chs_t *chs = (lws_led_state_chs_t *)&lcs[1]; + const lws_led_gpio_map_t *map = &lgc->led_map[0]; + unsigned int n; + + for (n = 0; n < lgc->count_leds; n++) { + + lws_seq_advance(lcs, &chs->seqs[LWS_LED_SEQ_IDX_CURR]); + + if (chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].seq) { + lws_seq_advance(lcs, &chs->seqs[LWS_LED_SEQ_IDX_NEXT]); + lws_seq_advance(lcs, &chs->seqs[LWS_LED_SEQ_IDX_TRANSITION]); + if (!chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].seq) { + chs->seqs[LWS_LED_SEQ_IDX_CURR] = + chs->seqs[LWS_LED_SEQ_IDX_NEXT]; + chs->seqs[LWS_LED_SEQ_IDX_NEXT].seq = NULL; + } + } + + lgc->led_ops.intensity(&lgc->led_ops, map->name, + lws_seq_sample(map, chs)); + + map++; + chs++; + } +} + +static int +lws_led_set_chs_seq(struct lws_led_state *lcs, lws_led_state_ch_t *dest, + const lws_led_sequence_def_t *def) +{ + int steps; + + dest->seq = def; + dest->ph = def->ledphase_offset; + dest->phase_budget = def->ledphase_total; + + /* + * We need to compute the incremental phase angle step to cover the + * total number of phases in the indicated ms, incrementing at the + * timer rate of LWS_LED_SEQUENCER_UPDATE_RATE_HZ. Eg, + * + * 65536 phase steps (one cycle) in 2000ms at 30Hz timer rate means we + * will update 2000ms / 33ms = 60 times, so we must step at at + * 65536 / 60 = 1092 phase angle resolution + */ + + steps = def->ms / LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS; + dest->step = (def->ledphase_total != -1 ? + def->ledphase_total : LWS_LED_FUNC_PHASE) / (steps ? steps : 1); + + if (steps && !lcs->timer_refcount++) { +#if defined(LWS_PLAT_TIMER_START) + LWS_PLAT_TIMER_START(lcs->timer); +#endif + } + + return steps; +} + +int +lws_led_transition(struct lws_led_state *lcs, const char *name, + const lws_led_sequence_def_t *next, + const lws_led_sequence_def_t *trans) +{ + lws_led_state_chs_t *chs = (lws_led_state_chs_t *)&lcs[1]; + int index = lws_led_gpio_lookup(&lcs->controller->led_ops, name); + const lws_led_gpio_map_t *map; + + if (index < 0) + return 1; + + map = &lcs->controller->led_map[index]; + + lws_led_set_chs_seq(lcs, &chs[index].seqs[LWS_LED_SEQ_IDX_TRANSITION], trans); + lws_led_set_chs_seq(lcs, &chs[index].seqs[LWS_LED_SEQ_IDX_NEXT], next); + + lcs->controller->led_ops.intensity(&lcs->controller->led_ops, map->name, + lws_seq_sample(map, chs)); + + return 0; +} diff --git a/lib/drivers/led/private-lib-drivers-led.h b/lib/drivers/led/private-lib-drivers-led.h new file mode 100644 index 00000000..43cfd738 --- /dev/null +++ b/lib/drivers/led/private-lib-drivers-led.h @@ -0,0 +1,58 @@ +/* + * Generic GPIO led + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +typedef struct lws_led_state +{ +#if defined(LWS_PLAT_TIMER_TYPE) + LWS_PLAT_TIMER_TYPE timer; +#endif + + lws_led_gpio_controller_t *controller; + int timer_refcount; +} lws_led_state_t; + +enum { + LWS_LED_SEQ_IDX_CURR, + LWS_LED_SEQ_IDX_NEXT, + LWS_LED_SEQ_IDX_TRANSITION +}; + +typedef struct lws_led_state_ch +{ + const lws_led_sequence_def_t *seq; /* NULL = inactive */ + lws_led_seq_phase_t ph; + lws_led_seq_phase_t step; + int phase_budget; +} lws_led_state_ch_t; + +typedef struct lws_led_state_chs +{ + lws_led_state_ch_t seqs[3]; +} lws_led_state_chs_t; + +void +lws_seq_timer_handle(lws_led_state_t *lcs); + +int +lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name); diff --git a/lib/drivers/pwm/pwm.c b/lib/drivers/pwm/pwm.c new file mode 100644 index 00000000..20f95e15 --- /dev/null +++ b/lib/drivers/pwm/pwm.c @@ -0,0 +1,149 @@ +/* + * Generic GPIO led + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 "private-lib-core.h" + +static const lws_led_intensity_t sineq16[] = { + + /* + * Quadrant at sin(270) in 16 samples, normalized so + * -1 == 0 and 0 == 32767 + */ + + 0, 158, 630, 1411, 2494, 3869, 5522, 7437, + 9597, 11980, 14562, 17321, 20228, 23225, 26374, 29555, + 32767 /* to interpolate against */ +}; + +/* + * Elaborate the 90 degree phase table to 360 degrees and offset to +32768, + * notice for the last sample we have to interpolate against a 17th sample + * reflecting full scale to avoid clipping due to interpolation against the + * 16th sample again + */ + +static lws_led_intensity_t +sine_lu(int n, int next) +{ + switch ((n >> 4) & 3) { + case 1: + /* forwards */ + return 32768 + sineq16[(n & 15) + next]; + case 2: + /* scan it backwards */ + return 32768 + sineq16[15 - (n & 15) + (!next)]; + case 3: + /* forwards */ + return 32768 - sineq16[(n & 15) + next]; + default: + /* scan it backwards */ + return 32768 - sineq16[15 - (n & 15) + (!next)]; + } +} + +/* + * The normalized phase resolution is 16-bit, however much table you decide to + * have needs interpolating or indexing in a reduced number of significant + * phase bits if it doesn't have the same phase resolution. + * + * In this sine table we have a 16 x 15-bit sample quadrant reflected 4 times + * to make 360 degrees, so 64 accurate sample points, with the rest of the + * intermediate phases generated by linear interpolation. That probably would + * sound a bit funky, but for modulating light dynamically it's more than + * enough. + */ + +lws_led_intensity_t +lws_led_func_sine(lws_led_seq_phase_t n) +{ + /* + * 2: quadrant + * 4: table entry in quadrant + * 10: interp (LSB) + */ + + return (sine_lu(n >> 10, 0) * (0x3ff - (n & 0x3ff)) + + sine_lu(n >> 10, 1) * (n & 0x3ff)) / 0x3ff; +} + +lws_led_intensity_t +lws_led_func_linear(lws_led_seq_phase_t n) +{ + return (lws_led_intensity_t)n; +} + + +static lws_led_intensity_t +lws_led_func_static(lws_led_seq_phase_t n) +{ + return n ? LWS_LED_MAX_INTENSITY : 0; +} + +const lws_led_sequence_def_t lws_pwmseq_static_off = { + .func = lws_led_func_static, + .ledphase_offset = 0, + .ledphase_total = 0, + .ms = 0 +}; + +const lws_led_sequence_def_t lws_pwmseq_static_on = { + .func = lws_led_func_static, + .ledphase_offset = 1, + .ledphase_total = 0, + .ms = 0 +}; + +const lws_led_sequence_def_t lws_pwmseq_sine_up = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_LED_FUNC_PHASE / 2, /* 180 degree ./^ */ + .ms = 300 +}; + +const lws_led_sequence_def_t lws_pwmseq_sine_down = { + .func = lws_led_func_sine, + .ledphase_offset = LWS_LED_FUNC_PHASE / 2, /* start at peak */ + .ledphase_total = LWS_LED_FUNC_PHASE / 2, /* 180 degree ./^ */ + .ms = 300 +}; + +const lws_led_sequence_def_t lws_pwmseq_linear_wipe = { + .func = lws_led_func_linear, + .ledphase_offset = 0, + .ledphase_total = LWS_LED_FUNC_PHASE - 1, + .ms = 300 +}; + +const lws_led_sequence_def_t lws_pwmseq_sine_endless_slow = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_SEQ_LEDPHASE_TOTAL_ENDLESS, + .ms = 1500 +}; + +const lws_led_sequence_def_t lws_pwmseq_sine_endless_fast = { + .func = lws_led_func_sine, + .ledphase_offset = 0, /* already at 0 amp at 0 phase */ + .ledphase_total = LWS_SEQ_LEDPHASE_TOTAL_ENDLESS, + .ms = 750 +}; diff --git a/lib/plat/freertos/esp32/drivers/pwm-esp32.c b/lib/plat/freertos/esp32/drivers/pwm-esp32.c new file mode 100644 index 00000000..e65d1520 --- /dev/null +++ b/lib/plat/freertos/esp32/drivers/pwm-esp32.c @@ -0,0 +1,78 @@ +/* + * esp32 / esp-idf pwm + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 "private-lib-core.h" +#include "soc/ledc_reg.h" +#include "driver/ledc.h" + +static const ledc_timer_config_t tc = { + .speed_mode = LEDC_HIGH_SPEED_MODE, + .duty_resolution = LEDC_TIMER_13_BIT, + .timer_num = LEDC_TIMER_0, + .freq_hz = 5000, + .clk_cfg = LEDC_AUTO_CLK +}; + +int +lws_pwm_plat_init(const struct lws_pwm_ops *lo) +{ + ledc_channel_config_t lc = { + .duty = 8191, + .intr_type = LEDC_INTR_FADE_END, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_sel = LEDC_TIMER_0, + }; + size_t n; + + ledc_timer_config(&tc); + + for (n = 0; n < lo->count_pwm_map; n++) { + lc.channel = LEDC_CHANNEL_0 + lo->pwm_map[n].index; + lc.gpio_num = lo->pwm_map[n].gpio; + ledc_channel_config(&lc); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, lc.channel, 0); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, lc.channel); + } + + return 0; +} + +void +lws_pwm_plat_intensity(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, + lws_led_intensity_t inten) +{ + size_t n; + + for (n = 0; n < lo->count_pwm_map; n++) { + if (lo->pwm_map[n].gpio == gpio) { + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0 + + lo->pwm_map[n].index, inten >> 3); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0 + + lo->pwm_map[n].index); + return; + } + } + + lwsl_err("%s: unknown gpio for pwm\n", __func__); +} diff --git a/lib/plat/freertos/private-lib-plat-freertos.h b/lib/plat/freertos/private-lib-plat-freertos.h index f8d61499..36fd7dea 100644 --- a/lib/plat/freertos/private-lib-plat-freertos.h +++ b/lib/plat/freertos/private-lib-plat-freertos.h @@ -118,3 +118,14 @@ insert_wsi(const struct lws_context *context, struct lws *wsi); #define delete_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()] = 0 +#define LWS_PLAT_TIMER_TYPE TimerHandle_t +#define LWS_PLAT_TIMER_CB(name, var) void name(TimerHandle_t var) +#define LWS_PLAT_TIMER_CB_GET_OPAQUE(x) pvTimerGetTimerID(x) +#define LWS_PLAT_TIMER_CREATE(name, interval, repeat, opaque, cb) \ + xTimerCreate(name, pdMS_TO_TICKS(interval), repeat ? pdTRUE : 0, \ + opaque, cb) +#define LWS_PLAT_TIMER_DELETE(ptr) xTimerDelete(ptr, 0) +#define LWS_PLAT_TIMER_START(ptr) xTimerStart(ptr, 0) +#define LWS_PLAT_TIMER_STOP(ptr) xTimerStop(ptr, 0) + + diff --git a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c index 7dd42596..e8e7ed87 100644 --- a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c @@ -27,8 +27,8 @@ struct lws_context *context; lws_sorted_usec_list_t sul; -lws_display_state_t lds; struct lws_led_state *lls; +lws_display_state_t lds; int interrupted; /* @@ -82,6 +82,20 @@ static const lws_button_controller_t bc = { .count_buttons = LWS_ARRAY_SIZE(bcm) }; +/* + * pwm controller + */ + +static const lws_pwm_map_t pwm_map[] = { + { .gpio = GPIO_NUM_25, .index = 0 } +}; + +static const lws_pwm_ops_t pwm_ops = { + lws_pwm_plat_ops, + .pwm_map = &pwm_map[0], + .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) +}; + /* * led controller */ @@ -90,6 +104,7 @@ static const lws_led_gpio_map_t lgm[] = { { .name = "alert", .gpio = GPIO_NUM_25, + .pwm_ops = &pwm_ops, /* managed by pwm */ .active_level = 1, }, }; @@ -107,13 +122,19 @@ static const uint8_t img[] = { static uint8_t flip; +static const lws_led_sequence_def_t *seqs[] = { + &lws_pwmseq_static_on, + &lws_pwmseq_static_off, + &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_sine_endless_fast, +}; + static int smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf, size_t len) { - flip = flip ^ 1; - lgc.led_ops.intensity(&lgc.led_ops, - lgc.led_ops.lookup(&lgc.led_ops, "alert"), flip); + lws_led_transition(lls, 0, seqs[flip & 3], &lws_pwmseq_linear_wipe); + flip++; lwsl_hexdump_notice(buf, len); @@ -171,6 +192,12 @@ app_main(void) goto spin; } + /* pwm init must go after the led controller init */ + + pwm_ops.init(&pwm_ops); + lgc.led_ops.intensity(&lgc.led_ops, "alert", 0); +// lws_led_transition(lls, 0, &lws_pwmseq_sine_endless, NULL); + bcs = lws_button_controller_create(context, &bc); if (!bcs) { lwsl_err("%s: could not create buttons\n", __func__); -- Gitee From ceb4e5317429ad029ef2e394e6820d412ef22736 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 21 Jun 2020 07:39:12 +0100 Subject: [PATCH 0180/1062] lws_button: classification Now there's an abstract button class regardless of the underlying connection, we can add more sophicsticated analysis on top of it for processing its usually noisy events and classifying them into smd-ready click, long-click or double-click events. A "regime" defines the timing limits for different press recognition and can be specified per-button, if not given a default regime is applied. --- include/libwebsockets/lws-button.h | 29 +- lib/drivers/README.md | 44 ++ lib/drivers/button/README.md | 151 ++++++ lib/drivers/button/lws-button.c | 462 ++++++++++++++++-- lib/plat/freertos/private-lib-plat-freertos.h | 4 +- .../main/lws-minimal-esp32.c | 15 +- 6 files changed, 647 insertions(+), 58 deletions(-) create mode 100644 lib/drivers/README.md create mode 100644 lib/drivers/button/README.md diff --git a/include/libwebsockets/lws-button.h b/include/libwebsockets/lws-button.h index a1972c2a..e1981423 100644 --- a/include/libwebsockets/lws-button.h +++ b/include/libwebsockets/lws-button.h @@ -29,8 +29,33 @@ typedef uint16_t lws_button_idx_t; +/* actual minimum may be 1 x RTOS tick depending on platform */ +#define LWS_BUTTON_MON_TIMER_MS 5 + typedef void (*lws_button_cb_t)(void *opaque, lws_button_idx_t idx, int state); +/* These are specified in ms but the granularity is LWS_BUTTON_MON_TIMER_MS, + * which may have been rounded up to an RTOS tick depending on platform */ + +enum { + LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK = (1 << 0) +}; + +typedef struct lws_button_regime { + uint16_t ms_min_down; + uint16_t ms_min_down_longpress; + uint16_t ms_up_settle; + uint16_t ms_doubleclick_grace; + uint16_t ms_repeat_down; + uint8_t flags; + /**< when double-click classification is enabled, clicks are delayed + * by ms_min_down + ms_doubleclick_grace to wait and see if it will + * become a double-click. Set LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK to + * enable it or leave that bit at 0 to get faster single-click + * classification. + */ +} lws_button_regime_t; + /* * This is the const part of the button controller, describing the static * bindings to gpio, and lws_smd event name information @@ -39,6 +64,8 @@ typedef void (*lws_button_cb_t)(void *opaque, lws_button_idx_t idx, int state); typedef struct lws_button_map { _lws_plat_gpio_t gpio; const char *smd_interaction_name; + const lws_button_regime_t *regime; + /**< a default regime is applied if this is left NULL */ } lws_button_map_t; typedef struct lws_button_controller { @@ -46,8 +73,6 @@ typedef struct lws_button_controller { const lws_gpio_ops_t *gpio_ops; const lws_button_map_t *button_map; lws_button_idx_t active_state_bitmap; - lws_button_idx_t message_on_down_bitmap; - lws_button_idx_t message_on_up_bitmap; uint8_t count_buttons; } lws_button_controller_t; diff --git a/lib/drivers/README.md b/lib/drivers/README.md new file mode 100644 index 00000000..a18dfdaa --- /dev/null +++ b/lib/drivers/README.md @@ -0,0 +1,44 @@ +# lws meta-drivers + +Although drivers in lws (enabled in cmake by `LWS_WITH_DRIVERS`) provide +actual drivers for some devices like I2C OLED controllers, their main job is +to conceal from user code the underlying OS APIs being used to interface +to the SoC hardware assets. + +CMake already allows lws to be platform-agnostic for build, the plat adaptations +allow lws to be platform-agnostic within itself for runtime. The lws +drivers intend to extend that agnosticism to user code. + +Using this technique on supported OSes frees the user code from dependencies +on the underlying OS choice... for example, although ESP32 is very good, it +comes with a highly specific set of apis in esp-idf that mean your code is +locked in to esp-idf if you follow them. Esp-idf uses freertos apis for things +like OS timers, again if you follow those you are locked into freertos, the +end result is your work is non-portable to other platforms and completely +dependent on esp. + +LWS drivers provide a thin wrapper to eliminate the OS dependencies while +still taking advantage of the work, drivers and maintenance of the underlying +OS layer without duplicating them, but bringing the flexibility to retarget +your work to other scenarios... for example, there is a generic gpio object +subclassed for specific implementations, an i2c object which may be subclassed +to use OS drivers or bitbang using the generic gpio object, buttons on top of +generic gpio, led class that can use generic gpio or pwm interchangeably, +platform-specific gpio, i2c, pwm implementations that can be used at the generic +level are defined to use underlying OS native apis and drivers. + +## Building on the next layer up + +At these generic objects like buttons or led controllers, there is a stable +codebase used by multiple implementations and the intention is to provide +best-of-breed features there generically, like + + - sophisticated button press debounce and classification + + - high quality transitions and log-response compensation and mixing for led pwm + + - display dimming timers, blanking timers, generic interaction detection to unblank + +which are automatically available on top of any implementation that is ported to +lws drivers. + diff --git a/lib/drivers/button/README.md b/lib/drivers/button/README.md new file mode 100644 index 00000000..6c7b9ce8 --- /dev/null +++ b/lib/drivers/button/README.md @@ -0,0 +1,151 @@ +# LWS GPIO Button class drivers + +Lws provides an GPIO button controller class, this centralizes handling a set of +up to 31 buttons for resource efficiency. Each controller has two OS timers, +one for interrupt to bottom-half event triggering and another that runs at 5ms +intervals only when one or more button is down. + +Each button has its own active level control and sophisticated state tracking; +each button can apply its own classification regime, to allow for different +physical button characteristics, if not overridden a default one is provided. + +Both the controller and individual buttons specify names that are used in the +JSON events produced when the buttons perform actions. + +## Button electronic to logical event processing + +Buttons are monitored using GPIO interrupts since this is very cheap in the +usual case no interaction is ongoing. There is assumed to be one interrupt +per GPIO, but they are pointed at the same ISR, with an opaque pointer to an +internal struct passed per-interrupt to differentiate them and bind them to a +particular button. + +The interrupt is set for notification of the active-going edge, usually if +the button is pulled-up, that's the downgoing edge only. This avoids any +ambiguity about the interrupt meaning, although oscillation is common around +the transition region when the signal is becoming inactive too. + +An OS timer is used to schedule a bottom-half handler outside of interrupt +context. + +To combat commonly-seen partial charging of the actual and parasitic network +around the button causing drift and oscillation, the bottom-half briefly drives +the button signal to the active level, forcing a more deterministic charge level +if it reached the point the interrupt was triggered. This removes much of the +unpredictable behaviour in the us range. It would be better done in the ISR +but many OS apis cannot perform GPIO operations in interrupt context. + +The bottom-half makes sure a monitoring timer is enabled, by refcount. This +is the engine of the rest of the classification while any button is down. The +monitoring timer happens per OS tick or 5ms, whichever is longer. + +## Declaring button controllers + +An array of button map elements if provided first mapping at least GPIOs to +button names, and also optionally the classification regime for that button. + +Then the button controller definition which points back to the button map. + +``` +static const lws_button_map_t bcm[] = { + { + .gpio = GPIO_NUM_0, + .smd_interaction_name = "user" + }, +}; + +static const lws_button_controller_t bc = { + .smd_bc_name = "bc", + .gpio_ops = &lws_gpio_plat, + .button_map = &bcm[0], + .active_state_bitmap = 0, + .count_buttons = LWS_ARRAY_SIZE(bcm), +}; + + struct lws_button_state *bcs; + + bcs = lws_button_controller_create(context, &bc); + if (!bcs) { + lwsl_err("%s: could not create buttons\n", __func__); + goto spin; + } +``` + +That is all that is needed for init, button events will be issued on lws_smd +when buttons are pressed. + +### Regime settings + +The classification regime is designed to reflect both the user interaction +style and the characteristics of a particular type of button. + +Member|Default|Meaning +---|---|--- +ms_min_down|20ms|Down events shorter than this are ignored +ms_min_down_longpress|300ms|Down events longer than this are reported as a long-click +ms_up_settle|20ms|After the first indication a button is no longer down, the button is ignored for this interval +ms_doubleclick_grace|120ms|The time allowed after a click to see if a second, double-click, is forthcoming +flags|LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK|Control which classifications can apply + +### lws_smd System Message Distribution Events + +The button controller emits system messages of class `LWSSMDCL_INTERACTION`, +using a JSON formatted payload + +``` +{ + "type": "button", + "src": "controller-name/button-name", + "event": "event-name" +} +``` + +For example, `{"type":"button","src":"bc/user","event":"doubleclick"}` + +JSON is used because it is maintainable, extensible, self-documenting and does +not require a central, fragile-against-versioning specification of mappings. +Using button names allows the same code to adapt to different hardware or +button mappings. Button events may be synthesized for test or other purposes +cleanly and clearly. + +All the events are somewhat filtered, too short glitches from EMI or whatever +are not reported. "up" and "down" events are reported for the buttons in case +the intention is the duration of the press is meaningful to the user code, but +more typically the user code wants to consume a higher-level classification of +the interaction, eg, that it can be understood as a single "double-click" event. + +Event name|Meaning +---|--- +down|The button passes a filter for being down, useful for duration-based response +up|The button has come up, useful for duration-based response +click|The button activity resulted in a classification as a single-click +longclick|The button activity resulted in a classification as a long-click +doubleclick|The button activity resulted in a classification as a double-click + +Since double-click detection requires delaying click reporting until it becomes +clear a second click isn't coming, it is enabled as a possible classification in +the regime structure and the regime structure chosen per-button. + +Typically user code is interested in, eg, a high level classification of what +the button is doing, eg, a "click" event on a specific button. Rather than +perform a JSON parse, these events can be processed as strings cheaply using +`lws_json_simple_strcmp()`, it's dumb enough to be cheap but smart enough to +understand enough JSON semantics to be accurate, while retaining the ability to +change and extend the JSON, eg + +``` + if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user")) { + if (!lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { + ... + } + ... + } +``` + +### Relationship between up / down and classification + +Classification|Sequencing +---|--- +click|down-up-click (it's classified when it went up and cannot be a longclick) +longclick|down-longclick-up (it's classified while still down) +doubleclick|down-up-down-doubleclick-up (classified as soon as second click down long enough) diff --git a/lib/drivers/button/lws-button.c b/lib/drivers/button/lws-button.c index ab194149..e937db6f 100644 --- a/lib/drivers/button/lws-button.c +++ b/lib/drivers/button/lws-button.c @@ -23,9 +23,18 @@ */ #include "private-lib-core.h" -#if defined(LWS_PLAT_FREERTOS) -#include -#endif +typedef enum lws_button_classify_states { + LBCS_IDLE, /* nothing happening */ + LBCS_MIN_DOWN_QUALIFY, + + LBCS_ASSESS_DOWN_HOLD, + LBCS_UP_SETTLE1, + LBCS_WAIT_DOUBLECLICK, + LBCS_MIN_DOWN_QUALIFY2, + + LBCS_WAIT_UP, + LBCS_UP_SETTLE2, +} lws_button_classify_states_t; /* * This is the opaque, allocated, non-const, dynamic footprint of the @@ -33,42 +42,388 @@ */ typedef struct lws_button_state { -#if defined(LWS_PLAT_FREERTOS) - TimerHandle_t timer; +#if defined(LWS_PLAT_TIMER_TYPE) + LWS_PLAT_TIMER_TYPE timer; /* bh timer */ + LWS_PLAT_TIMER_TYPE timer_mon; /* monitor timer */ #endif const lws_button_controller_t *controller; struct lws_context *ctx; + short mon_refcount; lws_button_idx_t enable_bitmap; lws_button_idx_t state_bitmap; + + uint16_t mon_timer_count; + /* incremented each time the mon timer cb happens */ + + /* lws_button_each_t per button overallocated after this */ } lws_button_state_t; +typedef struct lws_button_each { + lws_button_state_t *bcs; + uint16_t mon_timer_comp; + uint16_t mon_timer_repeat; + uint8_t state; + /**^ lws_button_classify_states_t */ + uint8_t isr_pending; +} lws_button_each_t; + +#if defined(LWS_PLAT_TIMER_START) +static const lws_button_regime_t default_regime = { + .ms_min_down = 20, + .ms_min_down_longpress = 300, + .ms_up_settle = 20, + .ms_doubleclick_grace = 120, + .flags = LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK +}; +#endif + + /* - * This is the bottom-half scheduled via a timer set in the ISR. From here - * we are allowed to hold mutexes etc. We are coming here because any button - * interrupt arrived, we have to try to figure out which events have happened. + * This is happening in interrupt context, we have to schedule a bottom half to + * do the foreground lws_smd queueing, using, eg, a platform timer. + * + * All the buttons point here and use one timer per button controller. An + * interrupt here means, "something happened to one or more buttons" + */ +#if defined(LWS_PLAT_TIMER_START) +void +lws_button_irq_cb_t(void *arg) +{ + lws_button_each_t *each = (lws_button_each_t *)arg; + + each->isr_pending = 1; + LWS_PLAT_TIMER_START(each->bcs->timer); +} +#endif + +/* + * This is the bottom-half scheduled via a timer set in the ISR. From here we + * are allowed to hold mutexes etc. We are coming here because any button + * interrupt arrived, we have to run another timer that tries to put whatever is + * observed on any active button into context and either discard it or arrive at + * a definitive event classification. */ -#if defined(LWS_PLAT_FREERTOS) -static void -lws_button_bh(TimerHandle_t th) +#if defined(LWS_PLAT_TIMER_CB) +static LWS_PLAT_TIMER_CB(lws_button_bh, th) { - lws_button_state_t *bcs = pvTimerGetTimerID(th); + lws_button_state_t *bcs = LWS_PLAT_TIMER_CB_GET_OPAQUE(th); + lws_button_each_t *each = (lws_button_each_t *)&bcs[1]; + const lws_button_controller_t *bc = bcs->controller; + size_t n; + + /* + * The ISR and bottom-half is shared by all the buttons. Each gpio + * IRQ has an individual opaque ptr pointing to the corresponding + * button's dynamic lws_button_each_t, the ISR marks the button's + * each->isr_pending and schedules this bottom half. + * + * So now the bh timer has fired and something to do, we need to go + * through all the buttons that have isr_pending set and service their + * state. Intermediate states should start / bump the refcount on the + * mon timer. That's refcounted so it only runs when a button down. + */ - lws_smd_msg_printf(bcs->ctx, LWSSMDCL_INTERACTION, - "{\"btn\":\"%s/%s\", \"s\":\"click\"}", - bcs->controller->smd_bc_name, - bcs->controller->button_map[0].smd_interaction_name); + for (n = 0; n < bc->count_buttons; n++) { -#if 0 - if (lws_esp32.button_is_down) - gpio_set_intr_type(GPIO_SW, GPIO_INTR_POSEDGE); - else - gpio_set_intr_type(GPIO_SW, GPIO_INTR_NEGEDGE); + if (!each[n].isr_pending) + continue; - lws_esp32.button_is_down = gpio_get_level(GPIO_SW); + /* + * Hide what we're about to do from the delicate eyes of the + * IRQ controller... + */ - lws_esp32_button(lws_esp32.button_is_down); + bc->gpio_ops->irq_mode(bc->button_map[n].gpio, + LWSGGPIO_IRQ_NONE, NULL, NULL); + + each[n].isr_pending = 0; + + /* + * Force the network around the switch to the + * active level briefly + */ + + bc->gpio_ops->set(bc->button_map[n].gpio, + !!(bc->active_state_bitmap & (1 << n))); + bc->gpio_ops->mode(bc->button_map[n].gpio, LWSGGPIO_FL_WRITE); + + if (each[n].state == LBCS_IDLE) { + /* + * If this is the first sign something happening on this + * button, make sure the monitor timer is running to + * classify its response over time + */ + + each[n].state = LBCS_MIN_DOWN_QUALIFY; + each[n].mon_timer_comp = bcs->mon_timer_count; + + if (!bcs->mon_refcount++) { +#if defined(LWS_PLAT_TIMER_START) + LWS_PLAT_TIMER_START(bcs->timer_mon); #endif + } + } + + /* + * Just for a us or two inbetween here, we're driving it to the + * level we were informed by the interrupt it had enetered, to + * force to charge on the actual and parasitic network around + * the switch to a deterministic-ish state. + * + * If the switch remains in that state, well, it makes no + * difference; if it was a pre-contact and the charge on the + * network was left indeterminate, this will dispose it to act + * consistently in the short term until the pullup / pulldown + * has time to act on it or the switch comes and forces the + * network charge state itself. + */ + bc->gpio_ops->mode(bc->button_map[n].gpio, LWSGGPIO_FL_READ); + + /* + * We could do a better job manipulating the irq mode according + * to the switch state. But if an interrupt comes and we have + * done that, we can't tell if it's from before or after the + * mode change... ie, we don't know what the interrupt was + * telling us. We can't trust the gpio state if we read it now + * to be related to what the irq from some time before was + * trying to tell us. So always set it back to the same mode + * and accept the limitation. + */ + + bc->gpio_ops->irq_mode(bc->button_map[n].gpio, + bc->active_state_bitmap & (1 << n) ? + LWSGGPIO_IRQ_RISING : + LWSGGPIO_IRQ_FALLING, + lws_button_irq_cb_t, &each[n]); + } +} +#endif + +#if defined(LWS_PLAT_TIMER_CB) +static LWS_PLAT_TIMER_CB(lws_button_mon, th) +{ + lws_button_state_t *bcs = LWS_PLAT_TIMER_CB_GET_OPAQUE(th); + lws_button_each_t *each = (lws_button_each_t *)&bcs[1]; + const lws_button_controller_t *bc = bcs->controller; + const lws_button_regime_t *regime; + const char *event_name; + int comp_age_ms; + char active; + size_t n; + + bcs->mon_timer_count++; + + for (n = 0; n < bc->count_buttons; n++) { + + if (each->state == LBCS_IDLE) { + each++; + continue; + } + + if (bc->button_map[n].regime) + regime = bc->button_map[n].regime; + else + regime = &default_regime; + + comp_age_ms = (bcs->mon_timer_count - each->mon_timer_comp) * + LWS_BUTTON_MON_TIMER_MS; + + active = bc->gpio_ops->read(bc->button_map[n].gpio) ^ + (!(bc->active_state_bitmap & (1 << n))); + + // lwsl_notice("%d\n", each->state); + + switch (each->state) { + case LBCS_MIN_DOWN_QUALIFY: + /* + * We're trying to figure out if the initial down event + * is a glitch, or if it meets the criteria for being + * treated as the definitive start of some kind of click + * action. To get past this, he has to be solidly down + * for the time mentioned in the applied regime (at + * least when we sample it). + * + * Significant bounce at the start will abort this try, + * but if it's really down there will be a subsequent + * solid down period... it will simply restart this flow + * from a new interrupt and pass the filter then. + * + * The "brief drive on edge" strategy considerably + * reduces inconsistencies here. But physical bounce + * will continue to be observed. + */ + + if (!active) { + /* We ignore stuff for a bit after discard */ + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_UP_SETTLE2; + break; + } + + if (comp_age_ms >= regime->ms_min_down) { + + /* We made it through the initial regime filter, + * the next step is wait and see if this down + * event evolves into a single/double click or + * we can call it as a long-click + */ + + each->mon_timer_repeat = bcs->mon_timer_count; + each->state = LBCS_ASSESS_DOWN_HOLD; + event_name = "down"; + goto emit; + } + break; + + case LBCS_ASSESS_DOWN_HOLD: + + /* + * How long is he going to hold it? If he holds it + * past the long-click threshold, we can call it as a + * long-click and do the up processing afterwards. + */ + if (comp_age_ms >= regime->ms_min_down_longpress) { + /* call it as a longclick */ + event_name = "longclick"; + each->state = LBCS_WAIT_UP; + goto emit; + } + + if (!active) { + /* + * He didn't hold it past the long-click + * threshold... we could end up classifying it + * as either a click or a double-click then. + * + * If double-clicks are not allowed to be + * classified, then we can already classify it + * as a single-click. + */ + if (!(regime->flags & + LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK)) + goto classify_single; + + /* + * Just wait for the up settle time then start + * looking for a second down. + */ + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_UP_SETTLE1; + event_name = "up"; + goto emit; + } + + goto stilldown; + + case LBCS_UP_SETTLE1: + if (comp_age_ms > regime->ms_up_settle) + /* + * Just block anything for the up settle time + */ + each->state = LBCS_WAIT_DOUBLECLICK; + break; + + case LBCS_WAIT_DOUBLECLICK: + if (active) { + /* + * He has gone down again inside the regime's + * doubleclick grace period... he's going down + * the double-click path + */ + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_MIN_DOWN_QUALIFY2; + break; + } + + if (comp_age_ms >= regime->ms_doubleclick_grace) { + /* + * The grace period expired, the second click + * was either not forthcoming at all, or coming + * quick enough to count: we classify it as a + * single-click + */ + + goto classify_single; + } + break; + + case LBCS_MIN_DOWN_QUALIFY2: + if (!active) { + + /* + * He went up again too quickly, classify it + * as a single-click. It could be bounce in + * which case you might want to increase the + * ms_up_settle in the regime + */ +classify_single: + event_name = "click"; + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_UP_SETTLE2; + goto emit; + } + + if (comp_age_ms == regime->ms_min_down) { + event_name = "down"; + goto emit; + } + + if (comp_age_ms > regime->ms_min_down) { + /* + * It's a double-click + */ + event_name = "doubleclick"; + each->state = LBCS_WAIT_UP; + goto emit; + } + break; + + case LBCS_WAIT_UP: + if (!active) { + /* + * He has stopped pressing it + */ + each->mon_timer_comp = bcs->mon_timer_count; + each->state = LBCS_UP_SETTLE2; + event_name = "up"; + goto emit; + } +stilldown: + if (regime->ms_repeat_down && + (bcs->mon_timer_count - each->mon_timer_repeat) * + LWS_BUTTON_MON_TIMER_MS > regime->ms_repeat_down) { + each->mon_timer_repeat = bcs->mon_timer_count; + event_name = "stilldown"; + goto emit; + } + break; + + case LBCS_UP_SETTLE2: + if (comp_age_ms < regime->ms_up_settle) + break; + + each->state = LBCS_IDLE; + if (!(--bcs->mon_refcount)) { +#if defined(LWS_PLAT_TIMER_STOP) + LWS_PLAT_TIMER_STOP(bcs->timer_mon); +#endif + } + } + + each++; + continue; + +emit: + lws_smd_msg_printf(bcs->ctx, LWSSMDCL_INTERACTION, + "{\"type\":\"button\"," + "\"src\":\"%s/%s\",\"event\":\"%s\"}", + bc->smd_bc_name, + bc->button_map[n].smd_interaction_name, + event_name); + + each++; + } } #endif @@ -76,7 +431,11 @@ struct lws_button_state * lws_button_controller_create(struct lws_context *ctx, const lws_button_controller_t *controller) { - lws_button_state_t *bcs = lws_zalloc(sizeof(lws_button_state_t), __func__); + lws_button_state_t *bcs = lws_zalloc(sizeof(lws_button_state_t) + + (controller->count_buttons * sizeof(lws_button_each_t)), + __func__); + lws_button_each_t *each = (lws_button_each_t *)&bcs[1]; + size_t n; if (!bcs) return NULL; @@ -84,9 +443,22 @@ lws_button_controller_create(struct lws_context *ctx, bcs->controller = controller; bcs->ctx = ctx; -#if defined(LWS_PLAT_FREERTOS) - bcs->timer = xTimerCreate("bcst", 1, 0, bcs, - (TimerCallbackFunction_t)lws_button_bh); + for (n = 0; n < controller->count_buttons; n++) + each[n].bcs = bcs; + +#if defined(LWS_PLAT_TIMER_CREATE) + /* this only runs inbetween a gpio ISR and the bottom half */ + bcs->timer = LWS_PLAT_TIMER_CREATE("bcst", + 1, 0, bcs, (TimerCallbackFunction_t)lws_button_bh); + if (!bcs->timer) + return NULL; + + /* this only runs when a button activity is being classified */ + bcs->timer_mon = LWS_PLAT_TIMER_CREATE("bcmon", LWS_BUTTON_MON_TIMER_MS, + 1, bcs, (TimerCallbackFunction_t) + lws_button_mon); + if (!bcs->timer_mon) + return NULL; #endif return bcs; @@ -98,31 +470,14 @@ lws_button_controller_destroy(struct lws_button_state *bcs) /* disable them all */ lws_button_enable(bcs, 0, 0); -#if defined(LWS_PLAT_FREERTOS) - xTimerDelete(&bcs->timer, 0); +#if defined(LWS_PLAT_TIMER_DELETE) + LWS_PLAT_TIMER_DELETE(&bcs->timer); + LWS_PLAT_TIMER_DELETE(&bcs->timer_mon); #endif lws_free(bcs); } -/* - * This is happening in interrupt context, we have to schedule a bottom half to - * do the foreground lws_smd queueing, using, eg, a platform timer. - * - * All the buttons point here and use one timer per button controller. An - * interrupt here means, "something happened to one or more buttons" - */ - -void -lws_button_irq_cb_t(void *arg) -{ -#if defined(LWS_PLAT_FREERTOS) - lws_button_state_t *bcs = (lws_button_state_t *)arg; - - xTimerStart(bcs->timer, 0); -#endif -} - lws_button_idx_t lws_button_get_bit(struct lws_button_state *bcs, const char *name) { @@ -142,6 +497,9 @@ lws_button_enable(lws_button_state_t *bcs, { lws_button_idx_t u = (bcs->enable_bitmap & (~_reset)) | _set; const lws_button_controller_t *bc = bcs->controller; +#if defined(LWS_PLAT_TIMER_START) + lws_button_each_t *each = (lws_button_each_t *)&bcs[1]; +#endif int n; for (n = 0; n < bcs->controller->count_buttons; n++) { @@ -151,12 +509,18 @@ lws_button_enable(lws_button_state_t *bcs, LWSGGPIO_FL_READ | ((bc->active_state_bitmap & (1 << n)) ? LWSGGPIO_FL_PULLDOWN : LWSGGPIO_FL_PULLUP)); - /* this one is becoming enabled */ +#if defined(LWS_PLAT_TIMER_START) + /* + * This one is becoming enabled... the opaque for the + * ISR is the indvidual lws_button_each_t, they all + * point to the same ISR + */ bc->gpio_ops->irq_mode(bc->button_map[n].gpio, bc->active_state_bitmap & (1 << n) ? LWSGGPIO_IRQ_RISING : LWSGGPIO_IRQ_FALLING, - lws_button_irq_cb_t, bcs); + lws_button_irq_cb_t, &each[n]); +#endif } if ((bcs->enable_bitmap & (1 << n)) && !(u & (1 << n))) /* this one is becoming disabled */ diff --git a/lib/plat/freertos/private-lib-plat-freertos.h b/lib/plat/freertos/private-lib-plat-freertos.h index 36fd7dea..a81bbc05 100644 --- a/lib/plat/freertos/private-lib-plat-freertos.h +++ b/lib/plat/freertos/private-lib-plat-freertos.h @@ -122,8 +122,8 @@ insert_wsi(const struct lws_context *context, struct lws *wsi); #define LWS_PLAT_TIMER_CB(name, var) void name(TimerHandle_t var) #define LWS_PLAT_TIMER_CB_GET_OPAQUE(x) pvTimerGetTimerID(x) #define LWS_PLAT_TIMER_CREATE(name, interval, repeat, opaque, cb) \ - xTimerCreate(name, pdMS_TO_TICKS(interval), repeat ? pdTRUE : 0, \ - opaque, cb) + xTimerCreate(name, pdMS_TO_TICKS(interval) ? pdMS_TO_TICKS(interval) : 1, \ + repeat ? pdTRUE : 0, opaque, cb) #define LWS_PLAT_TIMER_DELETE(ptr) xTimerDelete(ptr, 0) #define LWS_PLAT_TIMER_START(ptr) xTimerStart(ptr, 0) #define LWS_PLAT_TIMER_STOP(ptr) xTimerStop(ptr, 0) diff --git a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c index e8e7ed87..4cc8f864 100644 --- a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c @@ -77,9 +77,7 @@ static const lws_button_controller_t bc = { .gpio_ops = &lws_gpio_plat, .button_map = &bcm[0], .active_state_bitmap = 0, - .message_on_down_bitmap = (1 << 0), - .message_on_up_bitmap = 0, - .count_buttons = LWS_ARRAY_SIZE(bcm) + .count_buttons = LWS_ARRAY_SIZE(bcm), }; /* @@ -133,8 +131,14 @@ static int smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf, size_t len) { - lws_led_transition(lls, 0, seqs[flip & 3], &lws_pwmseq_linear_wipe); - flip++; + + if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user")) { + if (!lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { + lws_led_transition(lls, "alert", seqs[flip & 3], + &lws_pwmseq_linear_wipe); + flip++; + } + } lwsl_hexdump_notice(buf, len); @@ -213,6 +217,7 @@ app_main(void) disp.disp.blit(lds.disp, img, 0, 0, 128, 64); lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); + lgc.led_ops.intensity(&lgc.led_ops, "alert", 0); /* * We say the test succeeded if we survive 3s around the event loop -- Gitee From 30f3606b0eb9883e2f82271ada518d3147ee258c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 23 Jun 2020 13:19:30 +0100 Subject: [PATCH 0181/1062] context: option to disable system state management --- CMakeLists.txt | 1 + cmake/lws_config.h.in | 1 + include/libwebsockets/lws-context-vhost.h | 8 ++++++- include/libwebsockets/lws-state.h | 6 +++++ include/libwebsockets/lws-system.h | 7 +++++- lib/core-net/CMakeLists.txt | 7 +++++- lib/core-net/network.c | 2 ++ lib/core-net/state.c | 2 +- lib/core/context.c | 15 ++++++++++++- lib/core/private-lib-core.h | 2 ++ lib/secure-streams/CMakeLists.txt | 3 ++- lib/secure-streams/secure-streams-process.c | 20 +++++++++-------- .../system/fetch-policy/fetch-policy.c | 2 ++ lib/system/system.c | 2 ++ .../api-test-secure-streams/CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../minimal-http-client/CMakeLists.txt | 1 + .../minimal-mqtt-client-multi/CMakeLists.txt | 1 + .../minimal-mqtt-client/CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../minimal-secure-streams-avs/CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../minimal-secure-streams/CMakeLists.txt | 1 + .../minimal-secure-streams.c | 22 +++++++++++++++++++ 26 files changed, 96 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c040559..311e9f9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,7 @@ option(LWS_WITH_SYS_NTPCLIENT "Build in tiny ntpclient good for tls date validat option(LWS_WITH_SYS_DHCP_CLIENT "Build in tiny DHCP client" OFF) option(LWS_WITH_HTTP_BASIC_AUTH "Support Basic Auth" ON) option(LWS_WITH_HTTP_UNCOMMON_HEADERS "Include less common http header support" ON) +option(LWS_WITH_SYS_STATE "lws_system state support" ON) # # Secure Streams diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index a33f55dc..c24af00f 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -179,6 +179,7 @@ #cmakedefine LWS_WITH_SQLITE3 #cmakedefine LWS_WITH_SYS_NTPCLIENT #cmakedefine LWS_WITH_SYS_DHCP_CLIENT +#cmakedefine LWS_WITH_SYS_STATE #cmakedefine LWS_WITH_THREADPOOL #cmakedefine LWS_WITH_TLS #cmakedefine LWS_WITH_UDP diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index ef03c410..14ca4c98 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -221,11 +221,15 @@ #define LWS_SERVER_OPTION_GLIB (1ll << 33) /**< (CTX) Use glib event loop */ -#define LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE (1ll << 34) +#define LWS_SERVER_OPTION_H2_PRIOR_KNOWLEDGE (1ll << 34) /**< (VH) Tell the vhost to treat plain text http connections as * H2 with prior knowledge (no upgrade request involved) */ +#define LWS_SERVER_OPTION_NO_LWS_SYSTEM_STATES (1ll << 35) + /**< (CTX) Disable lws_system state, eg, because we are a secure streams + * proxy client that is not trying to track system state by itself. */ + /****** add new things just above ---^ ******/ @@ -725,10 +729,12 @@ struct lws_context_creation_info { /**< VHOST: optional retry and idle policy to apply to this vhost. * Currently only the idle parts are applied to the connections. */ +#if defined(LWS_WITH_SYS_STATE) lws_state_notify_link_t * const *register_notifier_list; /**< CONTEXT: NULL, or pointer to an array of notifiers that should * be registered during context creation, so they can see state change * events from very early on. The array should end with a NULL. */ +#endif #if defined(LWS_WITH_SECURE_STREAMS) #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) const struct lws_ss_policy *pss_policies; /**< CONTEXT: point to first diff --git a/include/libwebsockets/lws-state.h b/include/libwebsockets/lws-state.h index e5adabc4..dfa688f1 100644 --- a/include/libwebsockets/lws-state.h +++ b/include/libwebsockets/lws-state.h @@ -25,6 +25,8 @@ struct lws_state_notify_link; struct lws_state_manager; +#if defined(LWS_WITH_SYS_STATE) + typedef int (*lws_state_notify_t)(struct lws_state_manager *mgr, struct lws_state_notify_link *link, int current, int target); @@ -107,3 +109,7 @@ lws_state_transition_steps(lws_state_manager_t *mgr, int target); */ LWS_EXTERN LWS_VISIBLE int lws_state_transition(lws_state_manager_t *mgr, int target); + +#else + +#endif diff --git a/include/libwebsockets/lws-system.h b/include/libwebsockets/lws-system.h index bf946e47..6167a953 100644 --- a/include/libwebsockets/lws-system.h +++ b/include/libwebsockets/lws-system.h @@ -175,6 +175,8 @@ typedef struct lws_system_ops { */ } lws_system_ops_t; +#if defined(LWS_WITH_SYS_STATE) + /** * lws_system_get_state_manager() - return the state mgr object for system state * @@ -186,7 +188,7 @@ typedef struct lws_system_ops { LWS_EXTERN LWS_VISIBLE lws_state_manager_t * lws_system_get_state_manager(struct lws_context *context); - +#endif /* wrappers handle NULL members or no ops struct set at all cleanly */ @@ -203,6 +205,8 @@ lws_system_get_state_manager(struct lws_context *context); LWS_EXTERN LWS_VISIBLE const lws_system_ops_t * lws_system_get_ops(struct lws_context *context); +#if defined(LWS_WITH_SYS_STATE) + /** * lws_system_context_from_system_mgr() - return context from system state mgr * @@ -214,6 +218,7 @@ lws_system_get_ops(struct lws_context *context); LWS_EXTERN LWS_VISIBLE struct lws_context * lws_system_context_from_system_mgr(lws_state_manager_t *mgr); +#endif /** * __lws_system_attach() - get and set items on context attach list diff --git a/lib/core-net/CMakeLists.txt b/lib/core-net/CMakeLists.txt index 671b99fe..5bbc24ae 100644 --- a/lib/core-net/CMakeLists.txt +++ b/lib/core-net/CMakeLists.txt @@ -33,13 +33,18 @@ list(APPEND SOURCES core-net/pollfd.c core-net/service.c core-net/sorted-usec-list.c - core-net/state.c core-net/wsi.c core-net/wsi-timeout.c core-net/adopt.c roles/pipe/ops-pipe.c ) +if (LWS_WITH_SYS_STATE) + list(APPEND SOURCES + core-net/state.c + ) +endif() + if (LWS_WITH_DETAILED_LATENCY) list(APPEND SOURCES core-net/detailed-latency.c) diff --git a/lib/core-net/network.c b/lib/core-net/network.c index 49999173..af44a397 100644 --- a/lib/core-net/network.c +++ b/lib/core-net/network.c @@ -851,8 +851,10 @@ lws_sa46_compare_ads(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46b) return sa46a->sa4.sin_addr.s_addr != sa46b->sa4.sin_addr.s_addr; } +#if defined(LWS_WITH_SYS_STATE) lws_state_manager_t * lws_system_get_state_manager(struct lws_context *context) { return &context->mgr_system; } +#endif diff --git a/lib/core-net/state.c b/lib/core-net/state.c index 8fe830bf..660cf917 100644 --- a/lib/core-net/state.c +++ b/lib/core-net/state.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to diff --git a/lib/core/context.c b/lib/core/context.c index 196ea67e..adf43e0f 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -82,6 +82,8 @@ lws_sul_peer_limits_cb(lws_sorted_usec_list_t *sul) #if defined(LWS_WITH_NETWORK) +#if defined(LWS_WITH_SYS_STATE) + #if defined(_DEBUG) static const char * system_state_names[] = { "undef", @@ -101,6 +103,7 @@ static const char * system_state_names[] = { }; #endif + /* * Handle provoking protocol init when we pass through the right system state */ @@ -213,6 +216,7 @@ lws_context_creation_completion_cb(lws_sorted_usec_list_t *sul) lws_state_transition_steps(&context->mgr_system, LWS_SYSTATE_OPERATIONAL); } +#endif /* WITH_SYS_STATE */ #endif struct lws_context * @@ -824,6 +828,7 @@ lws_create_context(const struct lws_context_creation_info *info) } #endif +#if defined(LWS_WITH_SYS_STATE) /* * init the lws_state mgr for the system state */ @@ -847,6 +852,7 @@ lws_create_context(const struct lws_context_creation_info *info) lws_state_reg_notifier_list(&context->mgr_system, info->register_notifier_list); +#endif /* * if he's not saying he'll make his own vhosts later then act @@ -914,6 +920,7 @@ lws_create_context(const struct lws_context_creation_info *info) if (lws_plat_drop_app_privileges(context, 1)) goto bail; +#if defined(LWS_WITH_SYS_STATE) /* * We want to move on the syste, state as far as it can go towards * OPERATIONAL now. But we have to return from here first so the user @@ -925,6 +932,7 @@ lws_create_context(const struct lws_context_creation_info *info) lws_sul_schedule(context, 0, &context->sul_system_state, lws_context_creation_completion_cb, 1); +#endif /* expedite post-context init (eg, protocols) */ lws_cancel_service(context); @@ -1002,11 +1010,12 @@ lws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result) lwsl_notice("%s: setting CPD result %s\n", __func__, cname[result]); cx->captive_portal_detect = (uint8_t)result; - +#if defined(LWS_WITH_SYS_STATE) /* if nothing is there to intercept anything, go all the way */ if (cx->mgr_system.state != LWS_SYSTATE_POLICY_INVALID) lws_state_transition_steps(&cx->mgr_system, LWS_SYSTATE_OPERATIONAL); +#endif } lws_cpd_result_t @@ -1345,7 +1354,9 @@ lws_context_destroy(struct lws_context *context) context->being_destroyed = 1; #if defined(LWS_WITH_NETWORK) +#if defined(LWS_WITH_SYS_STATE) lws_state_transition(&context->mgr_system, LWS_SYSTATE_POLICY_INVALID); +#endif m = context->count_threads; while (m--) { @@ -1434,6 +1445,7 @@ out: #endif } +#if defined(LWS_WITH_SYS_STATE) struct lws_context * lws_system_context_from_system_mgr(lws_state_manager_t *mgr) { @@ -1443,3 +1455,4 @@ lws_system_context_from_system_mgr(lws_state_manager_t *mgr) return NULL; #endif } +#endif diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 6aac8132..9fcddb0d 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -375,8 +375,10 @@ struct lws_context { lws_sorted_usec_list_t sul_api_amazon_com_kick; #endif +#if defined(LWS_WITH_SYS_STATE) lws_state_manager_t mgr_system; lws_state_notify_link_t protocols_notify; +#endif #if defined (LWS_WITH_SYS_DHCP_CLIENT) lws_dll2_owner_t dhcpc_owner; /**< list of ifaces with dhcpc */ diff --git a/lib/secure-streams/CMakeLists.txt b/lib/secure-streams/CMakeLists.txt index 1d46849d..ead679d0 100644 --- a/lib/secure-streams/CMakeLists.txt +++ b/lib/secure-streams/CMakeLists.txt @@ -73,7 +73,8 @@ if (LWS_WITH_CLIENT) ) endif() - if (LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) + if (LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM AND + LWS_WITH_SYS_STATE) list(APPEND SOURCES secure-streams/system/auth-api.amazon.com/auth.c ) diff --git a/lib/secure-streams/secure-streams-process.c b/lib/secure-streams/secure-streams-process.c index 8ee0d11b..65362cb6 100644 --- a/lib/secure-streams/secure-streams-process.c +++ b/lib/secure-streams/secure-streams-process.c @@ -385,15 +385,17 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, * first 4 bytes or the create result, comma-separated */ - rsp = conn->ss->policy; - - while (rsp) { - if (n != 4 && n < (int)sizeof(s) - 2) - s[n++] = ','; - n += lws_snprintf(&s[n], sizeof(s) - n, - "%s", rsp->streamtype); - rsp = lws_ss_policy_lookup(wsi->context, - rsp->rideshare_streamtype); + if (conn->ss) { + rsp = conn->ss->policy; + + while (rsp) { + if (n != 4 && n < (int)sizeof(s) - 2) + s[n++] = ','; + n += lws_snprintf(&s[n], sizeof(s) - n, + "%s", rsp->streamtype); + rsp = lws_ss_policy_lookup(wsi->context, + rsp->rideshare_streamtype); + } } s[2] = n - 3; conn->state = LPCS_OPERATIONAL; diff --git a/lib/secure-streams/system/fetch-policy/fetch-policy.c b/lib/secure-streams/system/fetch-policy/fetch-policy.c index 65444f8b..cbf54f0b 100644 --- a/lib/secure-streams/system/fetch-policy/fetch-policy.c +++ b/lib/secure-streams/system/fetch-policy/fetch-policy.c @@ -83,8 +83,10 @@ policy_set(lws_sorted_usec_list_t *sul) lwsl_err("%s: policy set failed\n", __func__); else { context->policy_updated = 1; +#if defined(LWS_WITH_SYS_STATE) lws_state_transition_steps(&context->mgr_system, LWS_SYSTATE_OPERATIONAL); +#endif } } diff --git a/lib/system/system.c b/lib/system/system.c index e5c8723d..af7c3341 100644 --- a/lib/system/system.c +++ b/lib/system/system.c @@ -179,6 +179,7 @@ __lws_system_attach(struct lws_context *context, int tsi, lws_attach_cb_t cb, } *get = NULL; +#if defined(LWS_WITH_SYS_STATE) if (!pt->attach_owner.count) return 0; @@ -202,6 +203,7 @@ __lws_system_attach(struct lws_context *context, int tsi, lws_attach_cb_t cb, return 0; } } lws_end_foreach_dll(d); +#endif /* nobody ready to go... leave *get as NULL and return cleanly */ diff --git a/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt b/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt index 6396f98d..0640e811 100644 --- a/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-secure-streams/CMakeLists.txt @@ -6,6 +6,7 @@ include(LwsCheckRequirements) set(requirements 1) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) require_lws_config(LWS_WITH_TLS 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) diff --git a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt index dcfc9832..09c81330 100644 --- a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt @@ -13,6 +13,7 @@ set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_TLS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt index f3ae1a79..f755f005 100644 --- a/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-h2-rxflow/CMakeLists.txt @@ -11,6 +11,7 @@ set(SRCS minimal-http-client.c) set(requirements 1) require_lws_config(LWS_ROLE_H2 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt index 7405e74f..f4c2e991 100644 --- a/minimal-examples/http-client/minimal-http-client/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client/CMakeLists.txt @@ -11,6 +11,7 @@ set(SRCS minimal-http-client.c) set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt index 7e878efe..aced3844 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt +++ b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/CMakeLists.txt @@ -11,6 +11,7 @@ set(SRCS minimal-mqtt-client-multi.c) set(requirements 1) require_lws_config(LWS_ROLE_MQTT 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt b/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt index a0d05db4..ce1a67f1 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt +++ b/minimal-examples/mqtt-client/minimal-mqtt-client/CMakeLists.txt @@ -9,6 +9,7 @@ set(SRCS minimal-mqtt-client.c) set(requirements 1) require_lws_config(LWS_ROLE_MQTT 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt index 077440a1..bad2498f 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-alexa/CMakeLists.txt @@ -14,6 +14,7 @@ require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) require_lws_config(LWS_WITH_ALSA 1 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt index edb410de..1d4d4ba4 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-avs/CMakeLists.txt @@ -12,6 +12,7 @@ require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} main.c avs.c) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt index 267568d4..63cfea8a 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-metadata/CMakeLists.txt @@ -12,6 +12,7 @@ require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} minimal-secure-streams.c) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt index 485205fc..3068dca1 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-proxy/CMakeLists.txt @@ -14,6 +14,7 @@ require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS_PROXY_API 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} ${SRCS}) diff --git a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt index 8428f9db..1f97b9cd 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams/CMakeLists.txt @@ -12,6 +12,7 @@ require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) if (requirements) add_executable(${SAMP} minimal-secure-streams.c) diff --git a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c index bdd42974..6ee06309 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c @@ -206,6 +206,8 @@ typedef struct myss { lws_sorted_usec_list_t sul; } myss_t; +#if !defined(LWS_SS_USE_SSPC) + static const char *canned_root_token_payload = "grant_type=refresh_token" "&refresh_token=Atzr|IwEBIJedGXjDqsU_vMxykqOMg" @@ -220,6 +222,8 @@ static const char *canned_root_token_payload = "&client_id=" "amzn1.application-oa2-client.4823334c434b4190a2b5a42c07938a2d"; +#endif + /* secure streams payload interface */ static int @@ -285,9 +289,12 @@ app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, int current, int target) { struct lws_context *context = lws_system_context_from_system_mgr(mgr); +#if !defined(LWS_SS_USE_SSPC) + lws_system_blob_t *ab = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, 1 /* AUTH_IDX_ROOT */); size_t size; +#endif /* * For the things we care about, let's notice if we are trying to get @@ -296,6 +303,13 @@ app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, */ switch (target) { +#if !defined(LWS_SS_USE_SSPC) + + /* + * The proxy takes responsibility for this stuff if we get things + * done through that + */ + case LWS_SYSTATE_INITIALIZED: /* overlay on the hardcoded policy */ case LWS_SYSTATE_POLICY_VALID: /* overlay on the loaded policy */ @@ -338,6 +352,8 @@ app_system_state_nf(lws_state_manager_t *mgr, lws_state_notify_link_t *link, strlen(canned_root_token_payload)); break; +#endif + case LWS_SYSTATE_OPERATIONAL: if (current == LWS_SYSTATE_OPERATIONAL) { lws_ss_info_t ssi; @@ -444,6 +460,11 @@ int main(int argc, const char **argv) return 1; } +#if !defined(LWS_SS_USE_SSPC) + /* + * If we're being a proxied client, the proxy does all this + */ + /* * Set the related lws_system blobs * @@ -472,6 +493,7 @@ int main(int argc, const char **argv) lws_system_blob_heap_append(lws_system_get_blob(context, LWS_SYSBLOB_TYPE_DEVICE_TYPE, 0), (const uint8_t *)"spacerocket", 11); +#endif /* the event loop */ -- Gitee From 8eca7e17f27c8588170c5fa5fa3e6b14eb90e35d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 24 Jun 2020 20:15:46 +0100 Subject: [PATCH 0182/1062] lws_smd: system message distribution - Add low level system message distibution framework - Add support for local Secure Streams to participate using _lws_smd streamtype - Add apit test and minimal example - Add SS proxy support for _lws_smd See minimal-secure-streams-smd README.md --- CMakeLists-implied-options.txt | 3 +- CMakeLists.txt | 1 + cmake/lws_config.h.in | 1 + include/libwebsockets.h | 9 +- include/libwebsockets/lws-context-vhost.h | 12 + include/libwebsockets/lws-secure-streams.h | 31 +- include/libwebsockets/lws-smd.h | 175 ++++++ include/libwebsockets/lws-state.h | 6 +- lib/core-net/connect.c | 2 +- lib/core-net/service.c | 8 + lib/core-net/state.c | 7 + lib/core/context.c | 82 ++- lib/core/private-lib-core.h | 17 +- lib/plat/freertos/freertos-service.c | 4 +- lib/plat/optee/network.c | 4 +- lib/plat/unix/unix-service.c | 4 +- lib/plat/windows/private-lib-plat-windows.h | 3 +- lib/plat/windows/windows-service.c | 4 +- lib/secure-streams/policy-common.c | 15 +- .../private-lib-secure-streams.h | 12 + lib/secure-streams/secure-streams-client.c | 15 +- lib/secure-streams/secure-streams-process.c | 2 + lib/secure-streams/secure-streams-serialize.c | 28 +- lib/secure-streams/secure-streams.c | 173 +++++- .../captive-portal-detect.c | 23 +- lib/system/CMakeLists.txt | 6 +- lib/system/smd/CMakeLists.txt | 8 + lib/system/smd/README.md | 223 ++++++++ lib/system/smd/private-lib-system-smd.h | 114 ++++ lib/system/smd/smd.c | 524 ++++++++++++++++++ lib/system/system.c | 2 +- .../api-tests/api-test-lws_smd/CMakeLists.txt | 27 + .../api-tests/api-test-lws_smd/main.c | 202 +++++++ .../api-tests/api-test-lws_tokenize/main.c | 3 +- .../minimal-secure-streams-proxy/main.c | 14 +- .../minimal-secure-streams-smd/CMakeLists.txt | 46 ++ .../minimal-secure-streams-smd/README.md | 126 +++++ .../minimal-secure-streams-smd.c | 319 +++++++++++ 38 files changed, 2179 insertions(+), 76 deletions(-) create mode 100644 include/libwebsockets/lws-smd.h create mode 100644 lib/system/smd/CMakeLists.txt create mode 100644 lib/system/smd/README.md create mode 100644 lib/system/smd/private-lib-system-smd.h create mode 100644 lib/system/smd/smd.c create mode 100644 minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt create mode 100644 minimal-examples/api-tests/api-test-lws_smd/main.c create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-smd/README.md create mode 100644 minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c diff --git a/CMakeLists-implied-options.txt b/CMakeLists-implied-options.txt index 4ec90bc5..197ad690 100644 --- a/CMakeLists-implied-options.txt +++ b/CMakeLists-implied-options.txt @@ -141,6 +141,7 @@ if (NOT LWS_WITH_NETWORK) set(LWS_ROLE_DBUS 0) set(LWS_WITH_LWS_DSH 0) set(LWS_WITH_THREADPOOL 0) + set(LWS_WITH_SYS_SMD 0) endif() if (LWS_WITH_CGI) @@ -376,5 +377,5 @@ if (LWS_WITH_SSL OR LWS_WITH_MBEDTLS) endif() if (NOT LWS_WITH_SSL) - set(LWS_WITHOUT_BUILTIN_SHA1 OFF PARENT_SCOPE) + set(LWS_WITHOUT_BUILTIN_SHA1 OFF) endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 311e9f9e..bd74640a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,7 @@ option(LWS_WITH_SYS_DHCP_CLIENT "Build in tiny DHCP client" OFF) option(LWS_WITH_HTTP_BASIC_AUTH "Support Basic Auth" ON) option(LWS_WITH_HTTP_UNCOMMON_HEADERS "Include less common http header support" ON) option(LWS_WITH_SYS_STATE "lws_system state support" ON) +option(LWS_WITH_SYS_SMD "Lws System Message Distribution" ON) # # Secure Streams diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index c24af00f..b45302a6 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -170,6 +170,7 @@ #cmakedefine LWS_WITH_SELFTESTS #cmakedefine LWS_WITH_SEQUENCER #cmakedefine LWS_WITH_SERVER_STATUS +#cmakedefine LWS_WITH_SYS_SMD #cmakedefine LWS_WITH_SMTP #cmakedefine LWS_WITH_SOCKS5 #cmakedefine LWS_WITH_STATEFUL_URLDECODE diff --git a/include/libwebsockets.h b/include/libwebsockets.h index ac226bb1..dd139f06 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -348,10 +348,6 @@ struct lws_pollfd { #define LWS_POLLIN (FD_READ | FD_ACCEPT) #define LWS_POLLOUT (FD_WRITE) -#if !defined(pid_t) -#define pid_t int -#endif - #else @@ -535,6 +531,9 @@ struct lws; #include #include +#if defined(LWS_WITH_SYS_SMD) +#include +#endif #include #include #include @@ -547,7 +546,9 @@ struct lws; #include #include #include + #include + #if defined(LWS_ROLE_MQTT) #include #endif diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index 14ca4c98..8e081285 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -799,6 +799,18 @@ struct lws_context_creation_info { * to make disappear, in order to simulate and test udp retry flow */ #endif +#if defined(LWS_WITH_SYS_SMD) + lws_smd_notification_cb_t early_smd_cb; + /**< CONTEXT: NULL, or an smd notification callback that will be registered + * immediately after the smd in the context is initialized. This ensures + * you can get all notifications without having to intercept the event loop + * creation, eg, when using an event library. Other callbacks can be + * registered later manually without problems. + */ + void *early_smd_opaque; + lws_smd_class_t early_smd_class_filter; +#endif + /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility * diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index 66f0818e..c466c454 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -252,6 +252,20 @@ enum lws_ss_state_return_t { * to create the requested stream. */ +enum { + LWSSSINFLAGS_REGISTER_SINK = (1 << 0), + /**< If set, we're not creating a specific stream, but registering + * ourselves as the "sink" for .streamtype. It's analogous to saying + * we want to be the many-to-one "server" for .streamtype; when other + * streams are created with that streamtype, they should be forwarded + * to this stream owner, where they join and part from the sink via + * (*state) LWSSSCS_SINK_JOIN / _PART events, the new client handle + * being provided in the h_src parameter. + */ + LWSSSINFLAGS_PROXIED = (1 << 1), + /**< Set if the stream is being created as a stand-in at the proxy */ +}; + typedef struct lws_ss_info { const char *streamtype; /**< type of stream we want to create */ size_t user_alloc; /**< size of user allocation */ @@ -276,16 +290,13 @@ typedef struct lws_ss_info { int manual_initial_tx_credit; /**< 0 = manage any tx credit automatically, nonzero explicitly sets the * peer stream to have the given amount of tx credit, if the protocol - * can support it. */ - char register_sink; - /**< If set, we're not creating a specific stream, but registering - * ourselves as the "sink" for .streamtype. It's analogous to saying - * we want to be the many-to-one "server" for .streamtype; when other - * streams are created with that streamtype, they should be forwarded - * to this stream owner, where they join and part from the sink via - * (*state) LWSSSCS_SINK_JOIN / _PART events, the new client handle - * being provided in the h_src parameter. - */ + * can support it. + * + * In the special case of _lws_smd streamtype, this is used to indicate + * the connection's rx class mask. + * */ + uint8_t flags; + } lws_ss_info_t; /** diff --git a/include/libwebsockets/lws-smd.h b/include/libwebsockets/lws-smd.h new file mode 100644 index 00000000..66484d73 --- /dev/null +++ b/include/libwebsockets/lws-smd.h @@ -0,0 +1,175 @@ +/* + * lws System Message Distribution + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +#define LWS_SMD_MAX_PAYLOAD 384 +#define LWS_SMD_CLASS_BITFIELD_BYTES 4 + +#define LWS_SMD_STREAMTYPENAME "_lws_smd" +#define LWS_SMD_SS_RX_HEADER_LEN 16 + +typedef uint32_t lws_smd_class_t; + +struct lws_smd_msg; /* opaque */ +struct lws_smd_peer; /* opaque */ + +/* + * Well-known device classes + */ + +enum { + LWSSMDCL_INTERACTION = (1 << 0), + /**< + * Any kind of event indicating a user was interacting with the device, + * eg, press a button, touched the screen, lifted the device etc + */ + LWSSMDCL_SYSTEM_STATE = (1 << 1), + /**< + * The lws_system state changed, eg, to OPERATIONAL + */ + LWSSMDCL_NETWORK = (1 << 2), + /**< + * Something happened on the network, eg, link-up or DHCP, or captive + * portal state update + */ +}; + +/** + * lws_smd_msg_alloc() - allocate a message of length len + * + * \param ctx: the lws_context + * \param _class: the smd message class, recipients filter on this + * \param len: the required payload length + * + * This helper returns an opaque lws_smd_msg pointer and sets *buf to a buffer + * associated with it of length \p len. + * + * In this way the lws_msg_smd type remains completely opaque and the allocated + * area can be prepared by the caller directly, without copying. + * + * On failure, it returns NULL... it may fail for OOM but it may also fail if + * you request to allocate for a message class that the system has no + * participant who is listening for that class of event currently... the event + * generation action at the caller should be bypassed without error then. + * + * This is useful if you have a message you know the length of. For text-based + * messages like JSON, lws_smd_msg_printf() is more convenient. + */ +LWS_VISIBLE LWS_EXTERN void * /* payload */ +lws_smd_msg_alloc(struct lws_context *ctx, lws_smd_class_t _class, size_t len); + +/** + * lws_smd_msg_free() - abandon a previously allocated message before sending + * + * \param payload: pointer the previously-allocated message payload + * + * Destroys a previously-allocated opaque message object and the requested + * buffer space, in the case that between allocating it and sending it, some + * condition was met that means it can no longer be sent, eg, an error + * generating the content. Otherwise there is no need to destroy allocated + * message objects with this, lws will take care of it. + */ +LWS_VISIBLE LWS_EXTERN void +lws_smd_msg_free(void **payload); + +/** + * lws_smd_msg_send() - queue a previously allocated message + * + * \param ctx: the lws_context + * \param msg: the prepared message + * + * Queues an allocated, prepared message for delivery to smd clients + * + * This is threadsafe to call from a non-service thread. + */ +LWS_VISIBLE LWS_EXTERN int +lws_smd_msg_send(struct lws_context *ctx, void *payload); + +/** + * lws_smd_msg_printf() - queue a previously allocated message + * + * \param ctx: the lws_context + * \param _class: the message class + * \param format: the format string to prepare the payload with + * \param ...: arguments for the format string, if any + * + * For string-based messages, eg, JSON, allows formatted creating of the payload + * size discovery, allocation and message send all in one step. + * + * Unlike lws_smd_msg_alloc() you do not need to know the length beforehand as + * this computes it and calls lws_smd_msg_alloc() with the correct length. + * + * To be clear this also calls through to lws_smd_msg_send(), it really does + * everything in one step. If there are no registered participants that want + * messages of \p _class, this function returns immediately without doing any + * allocation or anything else. + * + * This is threadsafe to call from a non-service thread. + */ +LWS_VISIBLE LWS_EXTERN int +lws_smd_msg_printf(struct lws_context *ctx, lws_smd_class_t _class, + const char *format, ...) LWS_FORMAT(3); + +typedef int (*lws_smd_notification_cb_t)(void *opaque, lws_smd_class_t _class, + lws_usec_t timestamp, void *buf, + size_t len); + +#define LWSSMDREG_FLAG_PROXIED_SS (1 << 0) +/**< It's actually a proxied SS connection registering, opaque is the ss h */ + +/* + * lws_smd_register() - register to receive smd messages + * + * \param ctx: the lws_context + * \param opaque: an opaque pointer handed to the callback + * \param flags: typically 0 + * \param _class_filter: bitmap of message classes we care about + * \param cb: the callback to receive messages + * + * Queues an allocated, prepared message for delivery to smd clients. + * + * Returns NULL on failure, or an opaque handle which may be given to + * lws_smd_unregister() to stop participating in the shared message queue. + * + * This is threadsafe to call from a non-service thread. + */ + +LWS_VISIBLE LWS_EXTERN struct lws_smd_peer * +lws_smd_register(struct lws_context *ctx, void *opaque, int flags, + lws_smd_class_t _class_filter, lws_smd_notification_cb_t cb); + +/* + * lws_smd_unregister() - unregister receiving smd messages + * + * \param pr: the handle returned from the registration + * + * Destroys the registration of the callback for messages and ability to send + * messages. + * + * It's not necessary to call this if the registration wants to survive for as + * long as the lws_context... lws_context_destroy will also clean up any + * registrations still active by then. + */ + +LWS_VISIBLE LWS_EXTERN void +lws_smd_unregister(struct lws_smd_peer *pr); diff --git a/include/libwebsockets/lws-state.h b/include/libwebsockets/lws-state.h index dfa688f1..78281539 100644 --- a/include/libwebsockets/lws-state.h +++ b/include/libwebsockets/lws-state.h @@ -39,10 +39,14 @@ typedef struct lws_state_notify_link { typedef struct lws_state_manager { lws_dll2_owner_t notify_list; + struct lws_context *context; void *parent; +#if defined(LWS_WITH_SYS_SMD) + lws_smd_class_t smd_class; +#endif /**< optional opaque pointer to owning object... useful to make such * a pointer available to a notification callback. Ignored by lws */ - const char **state_names; /* may be NULL */ + const char **state_names; const char *name; int state; } lws_state_manager_t; diff --git a/lib/core-net/connect.c b/lib/core-net/connect.c index 6c517c70..af5c9a9d 100644 --- a/lib/core-net/connect.c +++ b/lib/core-net/connect.c @@ -174,7 +174,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) } if (local) { - lwsl_info("%s: protocol binding to %s\n", __func__, local); + lwsl_info("%s: vh %s protocol binding to %s\n", __func__, wsi->vhost->name, local); p = lws_vhost_name_to_protocol(wsi->vhost, local); if (p) lws_bind_protocol(wsi, p, __func__); diff --git a/lib/core-net/service.c b/lib/core-net/service.c index af16ffa4..67ba84f7 100644 --- a/lib/core-net/service.c +++ b/lib/core-net/service.c @@ -299,6 +299,14 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi) if (!context) return 1; +#if defined(LWS_WITH_SYS_SMD) + if (!tsi && lws_smd_message_pending(context)) { + lws_smd_msg_distribute(context); + if (lws_smd_message_pending(context)) + return 0; + } +#endif + pt = &context->pt[tsi]; /* diff --git a/lib/core-net/state.c b/lib/core-net/state.c index 660cf917..2063f06b 100644 --- a/lib/core-net/state.c +++ b/lib/core-net/state.c @@ -109,6 +109,13 @@ _lws_state_transition(lws_state_manager_t *mgr, int target) /* Indicate success by calling the notifers again with both args same */ _report(mgr, target, target); +#if defined(LWS_WITH_SYS_SMD) + if (mgr->smd_class) + (void)lws_smd_msg_printf(mgr->context, + mgr->smd_class, "{\"state\":\"%s\"}", + mgr->state_names[target]); +#endif + return 0; } diff --git a/lib/core/context.c b/lib/core/context.c index adf43e0f..b3d3d51b 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -84,7 +84,6 @@ lws_sul_peer_limits_cb(lws_sorted_usec_list_t *sul) #if defined(LWS_WITH_SYS_STATE) -#if defined(_DEBUG) static const char * system_state_names[] = { "undef", "CONTEXT_CREATED", @@ -101,7 +100,6 @@ static const char * system_state_names[] = { "OPERATIONAL", "POLICY_INVALID" }; -#endif /* @@ -217,8 +215,31 @@ lws_context_creation_completion_cb(lws_sorted_usec_list_t *sul) LWS_SYSTATE_OPERATIONAL); } #endif /* WITH_SYS_STATE */ + +#if defined(LWS_WITH_SYS_SMD) +static int +lws_system_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ + struct lws_context *cx = (struct lws_context *)opaque; + + if (_class != LWSSMDCL_NETWORK) + return 0; + + if (!lws_json_simple_strcmp(buf, len, "\"trigger\":", "cpdcheck")) { + lwsl_notice("%s: SMD -> Captive Portal Detect request\n", + __func__); + lws_system_cpd_start(cx); + } + + return 0; +} #endif + + +#endif /* NETWORK */ + struct lws_context * lws_create_context(const struct lws_context_creation_info *info) { @@ -591,6 +612,27 @@ lws_create_context(const struct lws_context_creation_info *info) context->fd_limit_per_thread = context->max_fds / context->count_threads; +#if defined(LWS_WITH_SYS_SMD) + lws_mutex_init(context->smd.lock_messages); + lws_mutex_init(context->smd.lock_peers); + + /* lws_system smd participant */ + + if (!lws_smd_register(context, context, 0, LWSSMDCL_NETWORK, + lws_system_smd_cb)) { + lwsl_err("%s: early smd register failed\n", __func__); + } + + /* user smd participant */ + + if (info->early_smd_cb && + !lws_smd_register(context, info->early_smd_opaque, 0, + info->early_smd_class_filter, + info->early_smd_cb)) { + lwsl_err("%s: early smd register failed\n", __func__); + } +#endif + #if defined(LWS_WITH_NETWORK) context->default_retry.retry_ms_table = default_backoff_table; @@ -832,15 +874,18 @@ lws_create_context(const struct lws_context_creation_info *info) /* * init the lws_state mgr for the system state */ -#if defined(_DEBUG) - context->mgr_system.state_names = system_state_names; + + context->mgr_system.state_names = system_state_names; + context->mgr_system.name = "system"; + context->mgr_system.state = LWS_SYSTATE_CONTEXT_CREATED; + context->mgr_system.parent = context; + context->mgr_system.context = context; +#if defined(LWS_WITH_SYS_SMD) + context->mgr_system.smd_class = LWSSMDCL_SYSTEM_STATE; #endif - context->mgr_system.name = "system"; - context->mgr_system.state = LWS_SYSTATE_CONTEXT_CREATED; - context->mgr_system.parent = context; - context->protocols_notify.name = "prot_init"; - context->protocols_notify.notify_cb = lws_state_notify_protocol_init; + context->protocols_notify.name = "prot_init"; + context->protocols_notify.notify_cb = lws_state_notify_protocol_init; lws_state_reg_notifier(&context->mgr_system, &context->protocols_notify); @@ -997,9 +1042,7 @@ lws_system_cpd_start(struct lws_context *cx) #endif } -#if (_LWS_ENABLED_LOGS & LLL_NOTICE) -static const char *cname[] = { "?", "OK", "Captive", "No internet" }; -#endif +static const char *cname[] = { "Unknown", "OK", "Captive", "No internet" }; void lws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result) @@ -1010,7 +1053,14 @@ lws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result) lwsl_notice("%s: setting CPD result %s\n", __func__, cname[result]); cx->captive_portal_detect = (uint8_t)result; + #if defined(LWS_WITH_SYS_STATE) +#if defined(LWS_WITH_SYS_SMD) + lws_smd_msg_printf(cx, LWSSMDCL_NETWORK, + "{\"type\":\"cpd\",\"result\":\"%s\"}", + cname[cx->captive_portal_detect]); +#endif + /* if nothing is there to intercept anything, go all the way */ if (cx->mgr_system.state != LWS_SYSTATE_POLICY_INVALID) lws_state_transition_steps(&cx->mgr_system, @@ -1096,6 +1146,10 @@ lws_context_destroy3(struct lws_context *context) #endif } +#if defined(LWS_WITH_SYS_SMD) + _lws_smd_destroy(context); +#endif + #if defined(LWS_WITH_SYS_ASYNC_DNS) lws_async_dns_deinit(&context->async_dns); #endif @@ -1122,7 +1176,7 @@ lws_context_destroy3(struct lws_context *context) #endif lws_free(context); - lwsl_info("%s: ctx %p freed\n", __func__, context); + lwsl_debug("%s: ctx %p freed\n", __func__, context); if (pcontext_finalize) *pcontext_finalize = NULL; @@ -1450,7 +1504,7 @@ struct lws_context * lws_system_context_from_system_mgr(lws_state_manager_t *mgr) { #if defined(LWS_WITH_NETWORK) - return lws_container_of(mgr, struct lws_context, mgr_system); + return mgr->context; #else return NULL; #endif diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 9fcddb0d..3f6dbba9 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -62,8 +62,14 @@ #include #endif -#if LWS_MAX_SMP > 1 +#if LWS_MAX_SMP > 1 || defined(LWS_WITH_SYS_SMD) + /* https://stackoverflow.com/questions/33557506/timespec-redefinition-error */ + #define HAVE_STRUCT_TIMESPEC #include +#else + #if !defined(pid_t) && defined(WIN32) + #define pid_t int + #endif #endif #ifndef LWS_DEF_HEADER_LEN @@ -212,6 +218,11 @@ struct lws; #include "private-lib-secure-streams.h" #endif + +#if defined(LWS_WITH_SYS_SMD) +#include "private-lib-system-smd.h" +#endif + struct lws_io_watcher { #ifdef LWS_WITH_LIBEV struct lws_io_watcher_libev ev; @@ -326,6 +337,10 @@ struct lws_context { lws_system_blob_t system_blobs[LWS_SYSBLOB_TYPE_COUNT]; +#if defined(LWS_WITH_SYS_SMD) + lws_smd_t smd; +#endif + #if defined(LWS_WITH_NETWORK) struct lws_context_per_thread pt[LWS_MAX_SMP]; lws_retry_bo_t default_retry; diff --git a/lib/plat/freertos/freertos-service.c b/lib/plat/freertos/freertos-service.c index f528bd1d..55b62276 100644 --- a/lib/plat/freertos/freertos-service.c +++ b/lib/plat/freertos/freertos-service.c @@ -46,7 +46,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* stay dead once we are dead */ - if (!context || !context->vhost_list) + if (!context) return 1; pt = &context->pt[tsi]; @@ -86,7 +86,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) timeout_ms = 2000000000; timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS; - if (!pt->service_tid_detected) { + if (!pt->service_tid_detected && context->vhost_list) { struct lws *_lws = pt->fake_wsi; if (!_lws) diff --git a/lib/plat/optee/network.c b/lib/plat/optee/network.c index 05427df3..90f37f13 100644 --- a/lib/plat/optee/network.c +++ b/lib/plat/optee/network.c @@ -96,7 +96,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* stay dead once we are dead */ - if (!context || !context->vhost_list) + if (!context) return 1; pt = &context->pt[tsi]; @@ -106,7 +106,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) else timeout_ms = 2000000000; - if (!pt->service_tid_detected) { + if (!pt->service_tid_detected && context->vhost_list) { struct lws _lws; memset(&_lws, 0, sizeof(_lws)); diff --git a/lib/plat/unix/unix-service.c b/lib/plat/unix/unix-service.c index c7edfa68..3e1e8fc7 100644 --- a/lib/plat/unix/unix-service.c +++ b/lib/plat/unix/unix-service.c @@ -78,7 +78,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* stay dead once we are dead */ - if (!context || !context->vhost_list) + if (!context) return 1; pt = &context->pt[tsi]; @@ -96,7 +96,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) if (context->event_loop_ops->run_pt) context->event_loop_ops->run_pt(context, tsi); - if (!pt->service_tid_detected) { + if (!pt->service_tid_detected && context->vhost_list) { struct lws _lws; memset(&_lws, 0, sizeof(_lws)); diff --git a/lib/plat/windows/private-lib-plat-windows.h b/lib/plat/windows/private-lib-plat-windows.h index 56bfc3c0..56361a4f 100644 --- a/lib/plat/windows/private-lib-plat-windows.h +++ b/lib/plat/windows/private-lib-plat-windows.h @@ -69,8 +69,7 @@ #endif #if defined(LWS_HAVE_PTHREAD_H) -#include -typedef pthread_mutex_t lws_mutex_t; +#define lws_mutex_t pthread_mutex_t #define lws_mutex_init(x) pthread_mutex_init(&(x), NULL) #define lws_mutex_destroy(x) pthread_mutex_destroy(&(x)) #define lws_mutex_lock(x) pthread_mutex_lock(&(x)) diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index 51eb2d27..78827411 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -71,12 +71,12 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) int interrupt_requested; /* stay dead once we are dead */ - if (context == NULL || !context->vhost_list) + if (context == NULL) return 1; pt = &context->pt[tsi]; - if (!pt->service_tid_detected) { + if (!pt->service_tid_detected && context->vhost_list) { struct lws _lws; memset(&_lws, 0, sizeof(_lws)); diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index ae862f38..cdd55b1f 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -27,6 +27,12 @@ #include +#if defined(LWS_WITH_SYS_SMD) +const lws_ss_policy_t pol_smd = { + .flags = 0, /* have to set something for windows */ +}; +#endif + const lws_ss_policy_t * lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype) { @@ -35,6 +41,11 @@ lws_ss_policy_lookup(const struct lws_context *context, const char *streamtype) if (!streamtype) return NULL; +#if defined(LWS_WITH_SYS_SMD) + if (!strcmp(streamtype, LWS_SMD_STREAMTYPENAME)) + return &pol_smd; +#endif + while (p) { if (!strcmp(p->streamtype, streamtype)) return p; @@ -212,7 +223,7 @@ lws_ss_policy_set(struct lws_context *context, const char *name) if (!pol->trust_store) { pol = pol->next; - if (!pol && !context->vhost_list) { + if (!pol) { /* corner case... there's no trust store used */ i.options = context->options; i.vhost_name = "_ss_default"; @@ -254,6 +265,7 @@ lws_ss_policy_set(struct lws_context *context, const char *name) for (n = 1; v && n < pol->trust_store->count; n++) { lwsl_info("%s: add '%s' to trust store\n", __func__, pol->trust_store->ssx509[n]->vhost_name); +#if defined(LWS_WITH_TLS) if (lws_tls_client_vhost_extra_cert_mem(v, pol->trust_store->ssx509[n]->ca_der, pol->trust_store->ssx509[n]->ca_der_len)) { @@ -261,6 +273,7 @@ lws_ss_policy_set(struct lws_context *context, const char *name) __func__); ret = 1; } +#endif } pol = pol->next; diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 48e5efe6..f0dd8585 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -120,6 +120,12 @@ typedef struct lws_ss_handle { const char *subscribe_to; size_t subscribe_to_len; } mqtt; +#endif +#if defined(LWS_WITH_SYS_SMD) + struct { + struct lws_smd_peer *smd_peer; + lws_sorted_usec_list_t sul_write; + } smd; #endif } u; @@ -257,6 +263,8 @@ typedef struct lws_sspc_handle { uint8_t rsidx; uint8_t destroying:1; + uint8_t non_wsi:1; + uint8_t ignore_txc:1; } lws_sspc_handle_t; typedef struct backoffs { @@ -299,6 +307,10 @@ struct policy_cb_args { int count; }; +#if defined(LWS_WITH_SYS_SMD) +extern const lws_ss_policy_t pol_smd; +#endif + int lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, struct lws_context *context, diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index ce207757..38f045f9 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -57,6 +57,8 @@ lws_sspc_sul_retry_cb(lws_sorted_usec_list_t *sul) return; } + + lwsl_notice("%s: sspc ss wsi %p\n", __func__, h->cwsi); } static int @@ -172,7 +174,7 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, if (!h) break; - lwsl_info("%s: WRITEABLE %p: (%s) state %d\n", __func__, wsi, + lwsl_notice("%s: WRITEABLE %p: (%s) state %d\n", __func__, wsi, h->ssi.streamtype, h->state); n = 0; @@ -250,7 +252,7 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, /* we can't write anything if we don't have credit */ - if (h->txc.tx_cr <= 0) { + if (!h->ignore_txc && h->txc.tx_cr <= 0) { lwsl_notice("%s: WRITEABLE / OPERATIONAL:" " lack credit (%d)\n", __func__, h->txc.tx_cr); @@ -289,8 +291,6 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, if (!n) break; - // lwsl_hexdump_notice(cp, n); - n = lws_write(wsi, (uint8_t *)cp, n, LWS_WRITE_RAW); if (n < 0) { lwsl_notice("%s: WRITEABLE: %d\n", __func__, n); @@ -347,11 +347,15 @@ lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, memcpy(p, ssi->streamtype, strlen(ssi->streamtype) + 1); h->ssi.streamtype = (const char *)p; h->context = context; + if (!ssi->manual_initial_tx_credit) h->txc.peer_tx_cr_est = 500000000; else h->txc.peer_tx_cr_est = ssi->manual_initial_tx_credit; + if (!strcmp(ssi->streamtype, "_lws_smd")) + h->ignore_txc = 1; + lws_dll2_add_head(&h->client_list, &context->pt[tsi].ss_client_owner); /* fill in the things the real api does for the caller */ @@ -409,7 +413,8 @@ lws_sspc_destroy(lws_sspc_handle_t **ph) if (h->cwsi) { struct lws *wsi = h->cwsi; h->cwsi = NULL; - lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); + if (h->cwsi) + lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); } /* clean out any pending metadata changes that didn't make it */ diff --git a/lib/secure-streams/secure-streams-process.c b/lib/secure-streams/secure-streams-process.c index 65362cb6..cb9cbb16 100644 --- a/lib/secure-streams/secure-streams-process.c +++ b/lib/secure-streams/secure-streams-process.c @@ -91,6 +91,8 @@ ss_proxy_onward_rx(void *userobj, const uint8_t *buf, size_t len, int flags) const char *rsp = NULL; int n; + // lwsl_notice("%s: len %d\n", __func__, (int)len); + /* * The onward secure stream connection has received something. */ diff --git a/lib/secure-streams/secure-streams-serialize.c b/lib/secure-streams/secure-streams-serialize.c index cd85f0ae..ecf326ce 100644 --- a/lib/secure-streams/secure-streams-serialize.c +++ b/lib/secure-streams/secure-streams-serialize.c @@ -774,10 +774,18 @@ payload_ff: __func__, par->streamtype, par->txcr_out); ssi->streamtype = par->streamtype; - if (par->txcr_out) + if (par->txcr_out) // !!! ssi->manual_initial_tx_credit = par->txcr_out; - if (lws_ss_create(context, 0, ssi, parconn, pss, NULL, NULL)) { + /* + * Even for a synthetic SS proxing action like _lws_smd, + * we create an actual SS in the proxy representing the + * connection + */ + + ssi->flags |= LWSSSINFLAGS_PROXIED; + if (lws_ss_create(context, 0, ssi, parconn, pss, + NULL, NULL)) { /* * We're unable to create the onward secure * stream he asked for... schedule a chance to @@ -794,9 +802,19 @@ payload_ff: if (*pss) { (*pss)->being_serialized = 1; - lwsl_notice("%s: Created SS initial credit %d\n", - __func__, par->txcr_out); - (*pss)->info.manual_initial_tx_credit = par->txcr_out; +#if defined(LWS_WITH_SYS_SMD) + if ((*pss)->policy != &pol_smd) + /* + * In SMD case we overloaded the + * initial credit to be the class mask + */ +#endif + { + lwsl_info("%s: Created SS initial credit %d\n", + __func__, par->txcr_out); + + (*pss)->info.manual_initial_tx_credit = par->txcr_out; + } } /* parent needs to schedule write on client conn */ diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index a8f4ed84..4ffd5a9a 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -220,6 +220,84 @@ lws_ss_backoff(lws_ss_handle_t *h) return 0; } +#if defined(LWS_WITH_SYS_SMD) + +/* + * Local SMD <-> SS + * + * We pass received messages through to the SS handler synchronously, using the + * lws service thread context. + * + * After the SS is created and registered, still nothing is going to come here + * until the peer sends us his rx_class_mask and we update his registration with + * it, because from SS creation his rx_class_mask defaults to 0. + */ + +static int +lws_smd_ss_cb(void *opaque, lws_smd_class_t _class, + lws_usec_t timestamp, void *buf, size_t len) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)opaque; + uint8_t *p = (uint8_t *)buf - LWS_SMD_SS_RX_HEADER_LEN; + + /* + * When configured with SS enabled, lws over-allocates + * LWS_SMD_SS_RX_HEADER_LEN bytes behind the payload of the queued + * message, for prepending serialized class and timestamp data in-band + * with the payload. + */ + + lws_ser_wu64be(p, _class); + lws_ser_wu64be(p + 8, timestamp); + + if (h->info.rx) + h->info.rx((void *)&h[1], p, len + LWS_SMD_SS_RX_HEADER_LEN, + LWSSS_FLAG_SOM | LWSSS_FLAG_EOM); + + return 0; +} + +static void +lws_ss_smd_tx_cb(lws_sorted_usec_list_t *sul) +{ + lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, u.smd.sul_write); + uint8_t buf[LWS_SMD_SS_RX_HEADER_LEN + LWS_SMD_MAX_PAYLOAD], *p; + size_t len = sizeof(buf); + lws_smd_class_t _class; + int flags = 0, n; + + if (!h->info.tx) + return; + + n = h->info.tx(&h[1], h->txord++, buf, &len, &flags); + if (n) + /* nonzero return means don't want to send anything */ + return; + + // lwsl_notice("%s: (SS %p bound to _lws_smd creates message) tx len %d\n", __func__, h, (int)len); + // lwsl_hexdump_notice(buf, len); + + assert(len >= LWS_SMD_SS_RX_HEADER_LEN); + _class = (lws_smd_class_t)lws_ser_ru64be(buf); + p = lws_smd_msg_alloc(h->context, _class, len - LWS_SMD_SS_RX_HEADER_LEN); + if (!p) { + lwsl_notice("%s: failed to alloc\n", __func__); + return; + } + + memcpy(p, buf + LWS_SMD_SS_RX_HEADER_LEN, len - LWS_SMD_SS_RX_HEADER_LEN); + if (lws_smd_msg_send(h->context, p)) { + lwsl_notice("%s: failed to queue\n", __func__); + return; + } +} + +#endif + +/* + * This is a local SS binding to a local SMD server + */ + int lws_ss_client_connect(lws_ss_handle_t *h) { @@ -245,6 +323,34 @@ lws_ss_client_connect(lws_ss_handle_t *h) if (h->h_sink) return 0; +#if defined(LWS_WITH_SYS_SMD) + if (h->policy == &pol_smd) { + + if (h->u.smd.smd_peer) { + // lwsl_notice("%s: peer already set\n", __func__); + return 0; + } + + // lwsl_notice("%s: received connect for _lws_smd, registering for class mask 0x%x\n", + // __func__, h->info.manual_initial_tx_credit); + + h->u.smd.smd_peer = lws_smd_register(h->context, h, + (h->info.flags & LWSSSINFLAGS_PROXIED) ? + LWSSMDREG_FLAG_PROXIED_SS : 0, + h->info.manual_initial_tx_credit, + lws_smd_ss_cb); + if (!h->u.smd.smd_peer) + return -1; + + if (lws_ss_event_helper(h, LWSSSCS_CONNECTING)) + return -1; + // lwsl_err("%s: registered SS SMD\n", __func__); + if (lws_ss_event_helper(h, LWSSSCS_CONNECTED)) + return -1; + return 0; + } +#endif + /* * We're going to substitute ${metadata} in the endpoint at connection- * time, so this can be set dynamically... @@ -367,7 +473,6 @@ lws_ss_client_connect(lws_ss_handle_t *h) return 0; } - /* * Public API */ @@ -397,7 +502,7 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, return 1; } - if (ssi->register_sink) { + if (ssi->flags & LWSSSINFLAGS_REGISTER_SINK) { /* * This can register a secure streams sink as well as normal * secure streams connections. If that's what's happening, @@ -505,13 +610,41 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, if (ppayload_fmt) *ppayload_fmt = pol->payload_fmt; - if (ssi->register_sink) { +#if defined(LWS_WITH_SYS_SMD) + /* + * For a local Secure Streams connection + */ + if (!(ssi->flags & LWSSSINFLAGS_PROXIED) && + pol == &pol_smd) { + /* + * So he has asked to be wired up to SMD over a SS link. + * Register him as an smd participant in his own right. + * + * Just for this case, ssi->manual_initial_tx_credit is used + * to set the rx class mask (this is part of the SS serialization + * format as well) + */ + h->u.smd.smd_peer = lws_smd_register(context, h, 0, + ssi->manual_initial_tx_credit, + lws_smd_ss_cb); + if (!h->u.smd.smd_peer) + goto late_bail; + lwsl_info("%s: registered SS SMD\n", __func__); + if (lws_ss_event_helper(h, LWSSSCS_CONNECTING)) + return -1; + if (lws_ss_event_helper(h, LWSSSCS_CONNECTED)) + return -1; + } +#endif + + if (ssi->flags & LWSSSINFLAGS_REGISTER_SINK) { /* * */ } if (lws_ss_event_helper(h, LWSSSCS_CREATING)) { +late_bail: lws_pt_lock(pt, __func__); lws_dll2_remove(&h->list); lws_pt_unlock(pt); @@ -520,7 +653,14 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, return 1; } - if (!ssi->register_sink && (h->policy->flags & LWSSSPOLF_NAILED_UP)) + if (!(ssi->flags & LWSSSINFLAGS_REGISTER_SINK) && + ((h->policy->flags & LWSSSPOLF_NAILED_UP) +#if defined(LWS_WITH_SYS_SMD) + || ((h->policy == &pol_smd) //&& + //(ssi->flags & LWSSSINFLAGS_PROXIED)) + ) +#endif + )) if (lws_ss_client_connect(h)) lws_ss_backoff(h); @@ -552,6 +692,15 @@ lws_ss_destroy(lws_ss_handle_t **ppss) lws_set_timeout(h->wsi, 1, LWS_TO_KILL_SYNC); } + /* + * if we bound an smd registration to the SS, unregister it + */ + + if (h->policy == &pol_smd && h->u.smd.smd_peer) { + lws_smd_unregister(h->u.smd.smd_peer); + h->u.smd.smd_peer = NULL; + } + pt = &h->context->pt[h->tsi]; lws_pt_lock(pt, __func__); @@ -588,6 +737,22 @@ lws_ss_request_tx(lws_ss_handle_t *h) return; } +#if defined(LWS_WITH_SYS_SMD) + if (h->policy == &pol_smd) { + /* + * He's an _lws_smd... and no wsi... since we're just going + * to queue it, we could call his tx() right here, but rather + * than surprise him let's set a sul to do it next time around + * the event loop + */ + + lws_sul_schedule(h->context, 0, &h->u.smd.sul_write, + lws_ss_smd_tx_cb, 1); + + return; + } +#endif + if (h->seqstate != SSSEQ_IDLE && h->seqstate != SSSEQ_DO_RETRY) return; diff --git a/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c b/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c index 228d65ea..75f83043 100644 --- a/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c +++ b/lib/secure-streams/system/captive-portal-detect/captive-portal-detect.c @@ -32,8 +32,6 @@ typedef struct ss_cpd { /* ... application specific state ... */ lws_sorted_usec_list_t sul; - - uint8_t partway; } ss_cpd_t; static int @@ -70,21 +68,18 @@ ss_cpd_state(void *userobj, void *sh, lws_ss_constate_t state, return LWSSSSRET_OK; } +static const lws_ss_info_t ssi_cpd = { + .handle_offset = offsetof(ss_cpd_t, ss), + .opaque_user_data_offset = offsetof(ss_cpd_t, opaque_data), + .state = ss_cpd_state, + .user_alloc = sizeof(ss_cpd_t), + .streamtype = "captive_portal_detect", +}; + int lws_ss_sys_cpd(struct lws_context *cx) { - lws_ss_info_t ssi; - - /* We're making an outgoing secure stream ourselves */ - - memset(&ssi, 0, sizeof(ssi)); - ssi.handle_offset = offsetof(ss_cpd_t, ss); - ssi.opaque_user_data_offset = offsetof(ss_cpd_t, opaque_data); - ssi.state = ss_cpd_state; - ssi.user_alloc = sizeof(ss_cpd_t); - ssi.streamtype = "captive_portal_detect"; - - if (lws_ss_create(cx, 0, &ssi, cx, NULL, NULL, NULL)) { + if (lws_ss_create(cx, 0, &ssi_cpd, cx, NULL, NULL, NULL)) { lwsl_info("%s: Create stream failed (policy?)\n", __func__); return 1; diff --git a/lib/system/CMakeLists.txt b/lib/system/CMakeLists.txt index a46122f4..7b2c42bb 100644 --- a/lib/system/CMakeLists.txt +++ b/lib/system/CMakeLists.txt @@ -51,7 +51,11 @@ if (LWS_WITH_NETWORK) list(APPEND SOURCES system/dhcpclient/dhcpclient.c) endif() - + + if (LWS_WITH_SYS_SMD) + add_subdir_include_dirs(smd) + endif() + endif() # diff --git a/lib/system/smd/CMakeLists.txt b/lib/system/smd/CMakeLists.txt new file mode 100644 index 00000000..e05f6c1a --- /dev/null +++ b/lib/system/smd/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories(.) + +list(APPEND SOURCES + system/smd/smd.c +) + +exports_to_parent_scope() + diff --git a/lib/system/smd/README.md b/lib/system/smd/README.md new file mode 100644 index 00000000..214f32a5 --- /dev/null +++ b/lib/system/smd/README.md @@ -0,0 +1,223 @@ +# LWS System Message Distribution + +## Overview + +Independent pieces of a system may need to become aware of events and state +changes in the other pieces quickly, along with the new state if it is small. +These messages are local to inside a system, although they may be triggered by +events outside of it. Examples include keypresses, or networking state changes. +Individual OSes and frameworks typically have their own fragmented apis for +message-passing, but the lws apis operate the same across any platforms +including, eg, Windows and RTOS and allow crossplatform code to be written once. + +Message payloads are short, less than 384 bytes, below system limits for atomic +pipe or UDS datagrams and consistent with heap usage on smaller systems, but +large enough to carry JSON usefully. Messages are typically low duty cycle. + +Messages may be sent by any registered participant, they are allocated on heap +in a linked-list, and delivered no sooner than next time around the event loop. +This retains the ability to handle multiple event queuing in one event loop trip +while guaranteeing message handling is nonrecursive. Messages are passed to all +other registered participants before being destroyed. + +`lws_smd` apis allow publication and subscription of message objects between +participants that are in a single process and are informed by callback from lws +service thread context, and, via Secure Streams proxying as the IPC method, also +between those in different processes. Registering as a participant and sending +messages are threadsafe APIs. + +## Message Class + +Message class is a bitfield messages use to indicate their general type, eg, +network status, or UI event like a keypress. Participants set a bitmask to +filter what kind of messages they care about, classes that are 0 in the peer's +filter are never delivered to the peer. A message usually indicates it is a +single class, but it's possible to set multiple class bits and match on any. If +so, care must be taken the payload can be parsed by readers expecting any of the +indicated classes, eg, by using JSON. + +`lws_smd` tracks a global union mask for all participants' class mask. Requests +to allocate a message of a class that no participant listens for are rejected, +not at distribution-time but at message allocation-time, so no heap or cpu is +wasted on things that are not currently interesting; but such messages start to +appear as soon as a participant appears that wants them. The message generation +action should be bypassed without error in the case lws_smd_msg_alloc() +returns NULL. + +## Messaging guarantees + +Sent messages are delivered to all registered participants whose class mask +indicates they want it, including the sender. The send apis are threadsafe. + +Locally-delivered message delivery callbacks occur from lws event loop thread +context 0 (the only one in the default case LWS_MAX_SMP = 1). Clients in +different processes receive callbacks from the thread context of their UDS +networking thread. + +The message payload may be destroyed immediately when you return from the +callback, you can't store references to it or expect it to be there later. + +Messages are timestamped with a systemwide monotonic timestamp. When +participants are on the lws event loop, messages are delivered in-order. When +participants are on different threads, delivery order depends on platform lock +acquisition. External process participants are connected by the Unix Domain +Socket capability of Secure Streams, and may be delivered out-of-order; +receivers that care must consult the message creation timestamps. + +## Message Refcounting + +To avoid keeping a list of the length of the number of participants for each +message, a refcount is used in the message, computed at the time the message +arrived considering the number of active participants that indicated a desire to +receive messages of that class. + +Since peers may detach / close their link asynchronously, the logical peer +objects at the distributor defer destroying themselves until there is no more +possibility of messages arriving timestamped with the period they were active. +A grace period (default 2s) is used to ensure departing peers correctly account +for message refcounts before being destroyed. + +## Message creation + +Messages may contain arbitrary text or binary data depending on the class. JSON +is recommended since lws_smd messages are small and low duty cycle but have +open-ended content: JSON is maintainable, extensible, debuggable and self- +documenting and avoids, eg, fragile dependencies on header versions shared +between teams. To simplify issuing JSON, a threadsafe api to create and send +messages in one step using format strings is provided: + +``` +int +lws_smd_msg_printf(struct lws_context *ctx, lws_smd_class_t _class, + const char *format, ...); +``` + +## Secure Streams `lws_smd` streamtype + +When built with LWS_WITH_SECURE_STREAMS, lws_smd exposes a built-in streamtype +`_lws_smd` which user Secure Streams may use to interoperate with lws_smd using +SS payload semantics. + +When using `_lws_smd`, the SS info struct member `manual_initial_tx_credit` +provided by the user when creating the Secure Stream is overloaded to be used as +the RX class mask for the SMD connection associated with the Secure Stream. + +Both RX and TX payloads have a 16-byte binary header before the actual payload. +For TX, although the header is 16-bytes, only the first 64-bit class bitfield +needs setting, the timestamp is fetched and added by lws. + + - MSB-first 64-bit class bitfield (currently only 32 least-sig in use) + - MSB-First Order 64-bit us-resolution timestamp + +## Well-known message schema + +Class|Schema +---|--- +LWSSMDCL_INTERACTION|lws_button events +LWSSMDCL_NETWORK|captive portal detection requests and results +LWSSMDCL_SYSTEM_STATE|lws_system state progression + +### User interaction Button events + +Class: `LWSSMDCL_INTERACTION` + +Produced by lws_button when a user interacts with a defined button. + +Click-related events are produced alongside up and down related events, the +participant can choose which to attend to according to the meaning of the +interaction. + +Both kinds of event go through sophisticated filtering before being issued, see +`./lib/drivers/button/README.md` for details. + +#### SMD Button interaction event + +Schema: +``` +{ + "type": "button", + "src": "/", + "event": "" +} +``` + +For example, `{"type":"button","src":"bc/user","event":"doubleclick"}` + +Event name|Meaning +---|--- +down|The button passes a filter for being down, useful for duration-based response +up|The button has come up, useful for duration-based response +click|The button activity resulted in a classification as a single-click +longclick|The button activity resulted in a classification as a long-click +doubleclick|The button activity resulted in a classification as a double-click + +### Captive Portal Detection + +Class: `LWSSMDCL_NETWORK` + +Actively detects if the network can reach the internet or if it is +intercepted by a captive portal. The detection steps are programmable +via the Secure Streams Policy for a streamtype `captive_portal_detect`, eg + +``` + "captive_portal_detect": { + "endpoint": "connectivitycheck.android.com", + "http_url": "generate_204", + "port": 80, + "protocol": "h1", + "http_method": "GET", + "opportunistic": true, + "http_expect": 204, + "http_fail_redirect": true + } +``` + +#### SMD Report Result + +Schema: `{"type": "cpd", "result":""}` + +result|meaning +---|--- +OK|Internet is reachable +Captive|Internet is behind a captive portal +No internet|There is no connectivity + +#### SMD Request re-detection + +Schema: `{"trigger": "cpdcheck"}` + +### lws_system state progression + +Class: `LWSSMDCL_SYSTEM_STATE` + +Lws system state changes are forwarded to lws_smd messages so participants not +on the lws event loop directly can be aware of progress. Code registering a +lws_system notifier callback, on the main lws loop, can synchronously veto state +changes and hook proposed state changes, lws_smd events are asynchronous +notifications of state changes after they were decided only... however they are +available over the whole system. + +It's not possible to make validated TLS connections until the system has +acquired the date as well as acquired an IP on a non-captive portal connection, +for that reason user code will usually be dependent on the system reaching +"OPERATIONAL" state if lws is responsible for managing the boot process. + +#### System state event + +Schema: `{"state":""}"` + +State|Meaning +---|--- +CONTEXT_CREATED|We're creating the lws_context +INITIALIZED|Initial vhosts and protocols initialized +IFACE_COLDPLUG|Network interfaces discovered +DHCP|DHCP acquired +CPD_PRE_TIME|Captive portal detect hook before we have system time +TIME_VALID|Ntpclient has run +CPD_POST_TIME|Captive portal detect hook after system time (tls-based check) +POLICY_VALID|The system policy has been acquired and parsed +REGISTERED|This device is registered with an authority +AUTH1|We acquired auth1 from the authority using our registration info +AUTH2|We acquired auth2 from the authority using our registration info +OPERATIONAL|We are active and able to make authenticated tls connections +POLICY_INVALID|The policy is being changed diff --git a/lib/system/smd/private-lib-system-smd.h b/lib/system/smd/private-lib-system-smd.h new file mode 100644 index 00000000..8ee8367c --- /dev/null +++ b/lib/system/smd/private-lib-system-smd.h @@ -0,0 +1,114 @@ +/* + * lws System Message Distribution + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +/* + * Number of seconds registered peers must remain as zombies to handle in-flight + * older messages correctly + */ +#if !defined(LWS_SMD_INFLIGHT_GRACE_SECS) +#define LWS_SMD_INFLIGHT_GRACE_SECS (2) +#endif +#if !defined(LWS_SMD_MAX_QUEUE_DEPTH) +#define LWS_SMD_MAX_QUEUE_DEPTH (12) +#endif + +#if defined(LWS_WITH_SECURE_STREAMS) +#define LWS_SMD_SS_RX_HEADER_LEN_EFF (LWS_SMD_SS_RX_HEADER_LEN) +#else +#define LWS_SMD_SS_RX_HEADER_LEN_EFF (0) +#endif + +typedef struct lws_smd_msg { + lws_dll2_t list; + + lws_usec_t timestamp; + lws_smd_class_t _class; + + uint16_t length; + uint16_t refcount; + + /* message itself is over-allocated after this */ +} lws_smd_msg_t; + +/* + * The peer's relationship to the lws instance doing the distribution + */ + +typedef enum { + LSMDT_SAME_PROCESS, /* we call him back ourselves */ + LSMDT_SECURE_STREAMS_LOCAL, /* we call him back ourselves */ + LSMDT_SECURE_STREAMS_PROXIED, /* we ask to write and wait */ +} lws_smd_type_t; + +typedef struct lws_smd_peer { + lws_dll2_t list; + + lws_usec_t timestamp_joined; + lws_usec_t timestamp_left; + +#if defined(LWS_WITH_SECURE_STREAMS) + lws_ss_handle_t *ss_handle; /* LSMDT_SECURE_STREAMS */ +#endif + + lws_smd_notification_cb_t cb; /* LSMDT_ */ + void *opaque; + + /* NULL, or next message we will handle */ + lws_smd_msg_t *tail; + + lws_smd_class_t _class_filter; + lws_smd_type_t type; +} lws_smd_peer_t; + +/* + * Manages message distribution + * + * There is one of these in the lws_context, but the distribution action also + * gets involved in delivering to pt event loops individually for SMP case + */ + +typedef struct lws_smd { + lws_dll2_owner_t owner_messages; /* lws_smd_msg_t */ + lws_mutex_t lock_messages; + lws_dll2_owner_t owner_peers; /* lws_smd_peer_t */ + lws_mutex_t lock_peers; + + /* union of peer class filters, suppress creation of msg classes not set */ + lws_smd_class_t _class_filter; + + lws_sorted_usec_list_t sul_tail_stale; + + char delivering; +} lws_smd_t; + +/* check if this tsi has pending messages to deliver */ + +int +lws_smd_message_pending(struct lws_context *ctx); + +int +lws_smd_msg_distribute(struct lws_context *ctx); + +int +_lws_smd_destroy(struct lws_context *ctx); diff --git a/lib/system/smd/smd.c b/lib/system/smd/smd.c new file mode 100644 index 00000000..2070fa0c --- /dev/null +++ b/lib/system/smd/smd.c @@ -0,0 +1,524 @@ +/* + * lws System Message Distribution + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 "private-lib-core.h" +#include + +void * +lws_smd_msg_alloc(struct lws_context *ctx, lws_smd_class_t _class, size_t len) +{ + lws_smd_msg_t *msg; + + /* only allow it if someone wants to consume this class of event */ + + if (!(ctx->smd._class_filter & _class)) { + lwsl_info("%s: rejecting class 0x%x as no participant wants it\n", __func__, + (unsigned int)_class); + return NULL; + } + + assert(len <= LWS_SMD_MAX_PAYLOAD); + + + /* + * If SS configured, over-allocate LWS_SMD_SS_RX_HEADER_LEN behind + * payload, ie, msg_t (gap LWS_SMD_SS_RX_HEADER_LEN) payload + */ + msg = lws_malloc(sizeof(*msg) + LWS_SMD_SS_RX_HEADER_LEN_EFF + len, + __func__); + if (!msg) + return NULL; + + memset(msg, 0, sizeof(*msg)); + msg->timestamp = lws_now_usecs(); + msg->length = (uint16_t)len; + msg->_class = _class; + + return ((uint8_t *)&msg[1]) + LWS_SMD_SS_RX_HEADER_LEN_EFF; +} + +void +lws_smd_msg_free(void **ppay) +{ + lws_smd_msg_t *msg = (lws_smd_msg_t *)(((uint8_t *)*ppay) - + LWS_SMD_SS_RX_HEADER_LEN_EFF - sizeof(*msg)); + + /* if SS configured, actual alloc is LWS_SMD_SS_RX_HEADER_LEN behind */ + lws_free(msg); + *ppay = NULL; +} + +/* + * Figure out what to set the initial refcount for the message to + */ + +static int +_lws_smd_msg_assess_peers_interested(lws_smd_t *smd, lws_smd_msg_t *msg) +{ + struct lws_context *ctx = lws_container_of(smd, struct lws_context, smd); + int interested = 0; + + lws_start_foreach_dll(struct lws_dll2 *, p, ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + /* + * In order to optimize the tail managment into a refcount, + * we have to account exactly for when peers arrived and + * departed (including deferring the logical peer destruction + * until no message pending he may have contributed to the + * refcount of) + */ + + if (pr->timestamp_joined <= msg->timestamp && + (!pr->timestamp_left || /* if zombie, only contribute to + * refcount if msg from before we + * left */ + pr->timestamp_left < msg->timestamp) && + (msg->_class & pr->_class_filter)) + /* + * This peer wants to consume it + */ + interested++; + + } lws_end_foreach_dll(p); + + return interested; +} + +static int +_lws_smd_class_mask_union(lws_smd_t *smd) +{ + uint32_t mask = 0; + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + smd->owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + /* may destroy pr if zombie */ + mask |= pr->_class_filter; + + } lws_end_foreach_dll_safe(p, p1); + + smd->_class_filter = mask; + + return 0; +} + +int +lws_smd_msg_send(struct lws_context *ctx, void *pay) +{ + lws_smd_msg_t *msg = (lws_smd_msg_t *)(((uint8_t *)pay) - + LWS_SMD_SS_RX_HEADER_LEN_EFF - sizeof(*msg)); + + if (ctx->smd.owner_messages.count >= LWS_SMD_MAX_QUEUE_DEPTH) + /* reject the message due to max queue depth reached */ + return 1; + + if (!ctx->smd.delivering) + lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + + msg->refcount = _lws_smd_msg_assess_peers_interested(&ctx->smd, msg); + + lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++++++++++ messages */ + lws_dll2_add_tail(&msg->list, &ctx->smd.owner_messages); + lws_mutex_unlock(ctx->smd.lock_messages); /* --------------- messages */ + + /* + * Any peer with no active tail needs to check our class to see if we + * should become his tail + */ + + lws_start_foreach_dll(struct lws_dll2 *, p, ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + if (!pr->tail && (pr->_class_filter & msg->_class)) + pr->tail = msg; + + } lws_end_foreach_dll(p); + + if (!ctx->smd.delivering) + lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ + + /* we may be happening from another thread context */ + lws_cancel_service(ctx); + + return 0; +} + +int +lws_smd_msg_printf(struct lws_context *ctx, lws_smd_class_t _class, + const char *format, ...) +{ + lws_smd_msg_t *msg; + va_list ap; + char *p; + int n; + + if (!(ctx->smd._class_filter & _class)) + /* + * There's nobody interested in messages of this class atm. + * Don't bother generating it, and act like all is well. + */ + return 0; + + va_start(ap, format); + n = vsnprintf(NULL, 0, format, ap); + va_end(ap); + if (n > LWS_SMD_MAX_PAYLOAD) + /* too large to send */ + return 1; + + p = lws_smd_msg_alloc(ctx, _class, (size_t)n + 2); + if (!p) + return 1; + msg = (lws_smd_msg_t *)(((uint8_t *)p) - LWS_SMD_SS_RX_HEADER_LEN_EFF - + sizeof(*msg)); + msg->length = (uint16_t)n; + va_start(ap, format); + vsnprintf(p, n + 2, format, ap); + va_end(ap); + + /* + * locks taken and released in here + */ + + if (lws_smd_msg_send(ctx, p)) { + lws_smd_msg_free((void **)&p); + return 1; + } + + return 0; +} + + +static void +_lws_smd_peer_finalize_destroy(lws_smd_peer_t *pr) +{ + lws_dll2_remove(&pr->list); + lws_free(pr); +} + +/* + * Peers that deregister may need to hang around as zombies, so they account + * for refcounts on messages they already contributed to. Because older + * messages may be in flight over UDS links, we have to stick around and make + * sure all cases have their refcount handled correctly. + */ + +static void +_lws_smd_peer_zombify(lws_smd_peer_t *pr) +{ + lws_smd_t *smd = lws_container_of(pr->list.owner, lws_smd_t, + owner_peers); + + /* update the class mask union to reflect this peer no longer active */ + _lws_smd_class_mask_union(smd); + + pr->timestamp_left = lws_now_usecs(); +} + +static lws_smd_msg_t * +_lws_smd_msg_next_matching_filter(lws_dll2_t *tail, lws_smd_class_t filter) +{ + lws_smd_msg_t *msg; + + do { + tail = tail->next; + if (!tail) + return NULL; + + msg = lws_container_of(tail, lws_smd_msg_t, list); + if (msg->_class & filter) + return msg; + } while (1); + + return NULL; +} + +/* + * Note: May destroy zombie peers when it sees grace period has expired. + * + * Delivers only one message to the peer and advances the tail, or sets to NULL + * if no more filtered queued messages. Returns nonzero if tail non-NULL. + * + * For Proxied SS, only asks for writeable and does not advance or change the + * tail. + * + * This is done so if multiple messages queued, we don't get a situation where + * one participant gets them all spammed, then the next etc. Instead they are + * delivered round-robin. + */ + +static int +_lws_smd_msg_deliver_peer(struct lws_context *ctx, lws_smd_peer_t *pr) +{ + lws_smd_msg_t *msg; + + if (!pr->tail) + return 0; + + msg = lws_container_of(pr->tail, lws_smd_msg_t, list); + + /* + * Check if zombie peer and the message predates our leaving + */ + + if (pr->timestamp_left && + msg->timestamp > pr->timestamp_left) { + /* + * We do not need to modify message refcount, if it was + * generated after we became a zombie, and so we + * definitely did not contribute to its refcount... + * + * ...have we waited out the grace period? + */ + + if (lws_now_usecs() - pr->timestamp_left > + LWS_SMD_INFLIGHT_GRACE_SECS * LWS_US_PER_SEC) + /* + * ... ok, it's time for the zombie to abandon + * its attachment to the Earth and rejoin the + * cosmic mandela + */ + _lws_smd_peer_finalize_destroy(pr); + + /* ... either way, nothing further to do for this guy */ + + return 0; + } + + if (!pr->timestamp_left) { + + /* + * Peer is not a zombie... deliver the tail + */ +#if 0 + if (pr->type == LSMDT_SECURE_STREAMS_PROXIED) { +#if defined(LWS_WITH_SECURE_STREAMS) + if (pr->ss_handle) + lws_ss_request_tx(pr->ss_handle); +#endif + return 0; + } +#endif + + pr->cb(pr->opaque, msg->_class, msg->timestamp, + ((uint8_t *)&msg[1]) + + LWS_SMD_SS_RX_HEADER_LEN_EFF, + (size_t)msg->length); + } + + assert(msg->refcount); + + /* + * If there is one, move forward to the next queued + * message that meets our filters + */ + pr->tail = _lws_smd_msg_next_matching_filter( + &pr->tail->list, pr->_class_filter); + + if (!--msg->refcount) { + /* + * We have fully delivered the message now, it + * can be unlinked and destroyed + */ + lws_dll2_remove(&msg->list); + lws_free(msg); + } + + /* + * Wait out the grace period even if no live messages + * for a zombie peer... there may be some in flight + */ + + return !!pr->tail; +} + +/* + * Called when the event loop could deliver messages synchronously, eg, on + * entry to idle + */ + +int +lws_smd_msg_distribute(struct lws_context *ctx) +{ + char more; + + /* commonly, no messages and nothing to do... */ + + if (!ctx->smd.owner_messages.count) + return 0; + + ctx->smd.delivering = 1; + + do { + more = 0; + lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + /* may destroy pr if zombie, hence _safe iterator */ + more |= _lws_smd_msg_deliver_peer(ctx, pr); + + } lws_end_foreach_dll_safe(p, p1); + + lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ + } while (more); + + ctx->smd.delivering = 0; + + return 0; +} + +struct lws_smd_peer * +lws_smd_register(struct lws_context *ctx, void *opaque, int flags, + lws_smd_class_t _class_filter, lws_smd_notification_cb_t cb) +{ + lws_smd_peer_t *pr = lws_zalloc(sizeof(*pr), __func__); + + if (!pr) + return NULL; + + pr->cb = cb; + pr->opaque = opaque; + pr->_class_filter = _class_filter; + pr->timestamp_joined = lws_now_usecs(); + + /* + * Figure out the type of peer from the situation... + */ + +#if 0 +#if defined(LWS_WITH_SECURE_STREAMS) + if (!ctx->smd.listen_vh) { + /* + * The guy who is regsitering is actually a SS proxy link + * between a client and SMD + */ + } else +#endif +#endif + pr->type = LSMDT_SAME_PROCESS; + + if (!ctx->smd.delivering) + lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + lws_dll2_add_tail(&pr->list, &ctx->smd.owner_peers); + + /* update the global class mask union to account for new peer mask */ + _lws_smd_class_mask_union(&ctx->smd); + if (!ctx->smd.delivering) + lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ + + lwsl_debug("%s: registered\n", __func__); + + return pr; +} + +void +lws_smd_unregister(struct lws_smd_peer *pr) +{ + lws_smd_t *smd = lws_container_of(pr->list.owner, lws_smd_t, owner_peers); + + lws_mutex_lock(smd->lock_peers); /* +++++++++++++++++++++++++++ peers */ + _lws_smd_peer_zombify(pr); + lws_mutex_unlock(smd->lock_peers); /* ------------------------- peers */ +} + +int +lws_smd_message_pending(struct lws_context *ctx) +{ + int ret = 1; + + /* + * First cheaply check the common case no messages pending, so there's + * definitely nothing for this tsi or anything else + */ + + if (!ctx->smd.owner_messages.count) + return 0; + + /* + * Walk the peer list + */ + + lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++++++++++ peers */ + lws_start_foreach_dll(struct lws_dll2 *, p, ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + if (pr->tail && pr->type == LSMDT_SAME_PROCESS) + goto bail; + + } lws_end_foreach_dll(p); + + /* + * There's no message pending that we need to handle + */ + + ret = 0; + +bail: + lws_mutex_unlock(ctx->smd.lock_peers); /* --------------------- peers */ + + return ret; +} + +int +_lws_smd_destroy(struct lws_context *ctx) +{ + /* stop any message creation */ + + ctx->smd._class_filter = 0; + + /* + * Walk the message list, destroying them + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + ctx->smd.owner_messages.head) { + lws_smd_msg_t *msg = lws_container_of(p, lws_smd_msg_t, list); + + lws_free(msg); + + } lws_end_foreach_dll_safe(p, p1); + + lws_mutex_destroy(ctx->smd.lock_messages); + + /* + * Walk the peer list, destroying them + */ + + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, + ctx->smd.owner_peers.head) { + lws_smd_peer_t *pr = lws_container_of(p, lws_smd_peer_t, list); + + _lws_smd_peer_finalize_destroy(pr); + + } lws_end_foreach_dll_safe(p, p1); + + lws_mutex_destroy(ctx->smd.lock_peers); + + return 0; +} diff --git a/lib/system/system.c b/lib/system/system.c index af7c3341..3f7ce71a 100644 --- a/lib/system/system.c +++ b/lib/system/system.c @@ -128,7 +128,7 @@ lws_system_blob_destroy(lws_system_blob_t *b) { if (!b) return; - lwsl_info("%s: blob %p\n", __func__, b); + // lwsl_info("%s: blob %p\n", __func__, b); if (!b->is_direct) lws_buflist_destroy_all_segments(&b->u.bl); } diff --git a/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt b/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt new file mode 100644 index 00000000..3c93ba74 --- /dev/null +++ b/minimal-examples/api-tests/api-test-lws_smd/CMakeLists.txt @@ -0,0 +1,27 @@ +project(lws-api-test-lws_smd) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(requirements 1) +require_pthreads(requirements) +require_lws_config(LWS_WITH_SYS_SMD 1 requirements) + +if (requirements) + add_executable(${PROJECT_NAME} main.c) + add_test(NAME api-test-lws_smd COMMAND lws-api-test-lws_smd -d1039) + set_tests_properties(api-test-lws_smd + PROPERTIES + RUN_SERIAL TRUE + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/api-tests/api-test-lws_smd + TIMEOUT 60) + + if (websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${PROJECT_NAME} websockets_shared) + else() + target_link_libraries(${PROJECT_NAME} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff --git a/minimal-examples/api-tests/api-test-lws_smd/main.c b/minimal-examples/api-tests/api-test-lws_smd/main.c new file mode 100644 index 00000000..9f3676ed --- /dev/null +++ b/minimal-examples/api-tests/api-test-lws_smd/main.c @@ -0,0 +1,202 @@ +/* + * lws-api-test-lws_smd + * + * Written in 2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This api test confirms lws_smd System Message Distribution + */ + +#include +#define HAVE_STRUCT_TIMESPEC +#include +#include + +static int interrupted, ok, fail, _exp = 111; +static lws_sorted_usec_list_t sul; +struct lws_context *context; +static pthread_t thread_spam; + +static void +timeout_cb(lws_sorted_usec_list_t *sul) +{ + /* We should have completed the test before this fires */ + interrupted = 1; + lws_cancel_service(context); +} + +static int +smd_cb1int(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ +#if 0 + lwsl_notice("%s: ts %llu, len %d\n", __func__, + (unsigned long long)timestamp, (int)len); + lwsl_hexdump_notice(buf, len); +#endif + ok++; + + return 0; +} + +static int +smd_cb2int(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ +#if 0 + lwsl_notice("%s: ts %llu, len %d\n", __func__, + (unsigned long long)timestamp, (int)len); + lwsl_hexdump_notice(buf, len); +#endif + ok++; + + return 0; +} + +static void * +_thread_spam(void *d) +{ + int n; + + n = 0; + while (n++ < 100) { + + if (lws_smd_msg_printf(context, LWSSMDCL_SYSTEM_STATE, + "{\"s\":\"state\",\"msg\":%d}", + (unsigned int)n)) { + lwsl_info("%s: send failed\n", __func__); + n--; + } +#if defined(WIN32) + Sleep(3); +#else + usleep(3000); +#endif + } +#if !defined(WIN32) + pthread_exit(NULL); +#endif + + return NULL; +} + +void sigint_handler(int sig) +{ + interrupted = 1; +} + +static int +system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + // struct lws_context *context = mgr->parent; + + if (current != LWS_SYSTATE_OPERATIONAL || target != LWS_SYSTATE_OPERATIONAL) + return 0; + + lwsl_info("%s: operational\n", __func__); + + /* + * spawn the test thread, it's going to spam 100 messages at 20ms + * intervals... check we got everything + */ + + if (pthread_create(&thread_spam, NULL, _thread_spam, NULL)) + lwsl_err("%s: failed to create the spamming thread\n", __func__); + + return 0; +} + +int +main(int argc, const char **argv) +{ + lws_state_notify_link_t notifier = { {0}, system_notify_cb, "app" }; + lws_state_notify_link_t *na[] = { ¬ifier, NULL }; + int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + struct lws_context_creation_info info; + const char *p; + void *retval; + + /* the normal lws init */ + + signal(SIGINT, sigint_handler); + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS API selftest: lws_smd\n"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.port = CONTEXT_PORT_NO_LISTEN; + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.register_notifier_list = na; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + lws_sul_schedule(context, 0, &sul, timeout_cb, 5 * LWS_US_PER_SEC); + + /* register a messaging participant to hear INTERACTION class */ + + if (!lws_smd_register(context, NULL, 0, LWSSMDCL_INTERACTION, + smd_cb1int)) { + lwsl_err("%s: smd register 1 failed\n", __func__); + goto bail; + } + + /* register a messaging participant to hear SYSTEM_STATE class */ + + if (!lws_smd_register(context, NULL, 0, LWSSMDCL_SYSTEM_STATE, + smd_cb2int)) { + lwsl_err("%s: smd register 2 failed\n", __func__); + goto bail; + } + + + /* generate an INTERACTION class message */ + + if (lws_smd_msg_printf(context, LWSSMDCL_INTERACTION, + "{\"s\":\"interaction\"}")) { + lwsl_err("%s: problem sending smd\n", __func__); + goto bail; + } + + /* generate a SYSTEM_STATE class message */ + + if (lws_smd_msg_printf(context, LWSSMDCL_SYSTEM_STATE, + "{\"s\":\"state\"}")) { + lwsl_err("%s: problem sending smd\n", __func__); + goto bail; + } + + /* no participant listens for this class, so it should be skipped */ + + if (lws_smd_msg_printf(context, LWSSMDCL_NETWORK, "{\"s\":\"network\"}")) { + lwsl_err("%s: problem sending smd\n", __func__); + goto bail; + } + + /* the usual lws event loop */ + + while (!interrupted && lws_service(context, 0) >= 0) + ; + + pthread_join(thread_spam, &retval); + +bail: + lws_context_destroy(context); + + if (fail || ok >= _exp) + lwsl_user("Completed: PASS: %d / %d, FAIL: %d\n", ok, _exp, + fail); + else + lwsl_user("Completed: ALL PASS: %d / %d\n", ok, _exp); + + return !(ok >= _exp && !fail); +} diff --git a/minimal-examples/api-tests/api-test-lws_tokenize/main.c b/minimal-examples/api-tests/api-test-lws_tokenize/main.c index e6d26d63..08332961 100644 --- a/minimal-examples/api-tests/api-test-lws_tokenize/main.c +++ b/minimal-examples/api-tests/api-test-lws_tokenize/main.c @@ -461,7 +461,8 @@ int main(int argc, const char **argv) mcp = lws_json_simple_find(t1, strlen(t1), "\"myname1\":", &alen); if (mcp != t1 + 11 || alen != 4) { - lwsl_err("%s: lws_json_simple_find 1 failed: (%d) %s\n", __func__, (int)alen, mcp); + lwsl_err("%s: lws_json_simple_find 1 failed: (%d) %s\n", + __func__, (int)alen, mcp); return 1; } diff --git a/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c b/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c index 33e0d461..4d2c7a70 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-proxy/main.c @@ -133,8 +133,18 @@ static const char * const default_ss_policy = "]" "}" "]," - "\"s\": [" - "{\"fetch_policy\": {" + "\"s\": [{" + "\"captive_portal_detect\": {" + "\"endpoint\": \"connectivitycheck.android.com\"," + "\"http_url\": \"generate_204\"," + "\"port\": 80," + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"opportunistic\": true," + "\"http_expect\": 204," + "\"http_fail_redirect\": true" + "}," + "\"fetch_policy\": {" "\"endpoint\":" "\"warmcat.com\"," "\"port\":" "443," "\"protocol\":" "\"h1\"," diff --git a/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt new file mode 100644 index 00000000..7c9a4295 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-smd/CMakeLists.txt @@ -0,0 +1,46 @@ +project(lws-minimal-secure-streams-smd C) +cmake_minimum_required(VERSION 2.8) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(requirements 1) +require_lws_config(LWS_ROLE_H1 1 requirements) +require_lws_config(LWS_WITH_CLIENT 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) +require_lws_config(LWS_WITH_SYS_SMD 1 requirements) +require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements) +require_lws_config(LWS_WITH_SYS_STATE 1 requirements) + +if (requirements) + add_executable(${PROJECT_NAME} minimal-secure-streams-smd.c) + + if (LWS_CTEST_INTERNET_AVAILABLE) + add_test(NAME ss-smd COMMAND lws-minimal-secure-streams-smd) + set_tests_properties(ss-smd + PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/secure-streams/minimal-secure-streams-smd + TIMEOUT 10) + endif() + + if (websockets_shared) + target_link_libraries(${PROJECT_NAME} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${PROJECT_NAME} websockets_shared) + else() + target_link_libraries(${PROJECT_NAME} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() + + if (LWS_WITH_SECURE_STREAMS_PROXY_API) + add_compile_options(-DLWS_SS_USE_SSPC) + + add_executable(${PROJECT_NAME}-client minimal-secure-streams-smd.c) + if (websockets_shared) + target_link_libraries(${PROJECT_NAME}-client websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${PROJECT_NAME}-client websockets_shared) + else() + target_link_libraries(${PROJECT_NAME}-client websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() + endif() + +endif() diff --git a/minimal-examples/secure-streams/minimal-secure-streams-smd/README.md b/minimal-examples/secure-streams/minimal-secure-streams-smd/README.md new file mode 100644 index 00000000..d91c29f8 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-smd/README.md @@ -0,0 +1,126 @@ +# lws minimal secure streams SMD + +This application creates a Secure Stream link to LWS SMD, System +Message Distribution. + +The SS is able to receive system messages matching a specified +class filter, and issue system messages also using SS payload +semantics. + +Both a direct api lws_smd participant and an SS based one are instantiated. +They both filter on system messages. + +When the Secure Stream is created, it asks to send using normal the SS api. +In the SS tx callback, it prepares a header and then send a NETWORK class +message. + +Numbers of messages received each way and sent is compared after 2s and the +test exits with a success or a fail. + +### Building and testing + +Build with + + -DLWS_WITH_SECURE_STREAMS=1 + -DLWS_WITH_SECURE_STREAMS_PROXY_API=1 + -DLWS_WITH_MINIMAL_EXAMPLES=1 + +The run ./bin/lws-minimal-secure-streams-smd alone (local SS and direct SMD tests) +and after run ./bin/lws-minimal-secure-streams-proxy in one console and +./bin-lws-minimal-secure-streams-smd-client in the other (SS proxy tests) + +### What's going on in the -client test + +The -client build version contains the test logic as usual, but outsources the +policy and smd_ server part to the Secure Streams Proxy. + + - start lws-minimal-secure-streams-proxy first + + - start lws-minimal-secure-streams-smd-client + +1) When the client starts, we waits to hear the client state is OPERATIONAL in +a direct smd participant callback. When it is, he creates a Secure Stream of +streamtype "_lws_smd", creating a local SS handle. + +2) The SS creation request is proxied to the SS proxy process over Unix Domain +Sockets. There it creates a Secure Stream object proxyside, and registers as +an SMD participant... this smd-related behaviour is tied to the special +streamtype name "_lws_smd". The SMD registration uses a class mask passed to +the proxy in the tx credit field of the serialization. + +3) SMD messages that pass the class mask filter are proxied back to the client +over the connection. + +4) SMD messages created at the client are passed to the proxy and added to the +proxy's SMD queue, if the same connection's class mask accepts the message then +it will be proxied back to the client same as other messages. + +The minimal example produces a variety of messages on the SS link, including +CPD detect trigger. The SS link is set up to only accept messages of classes +LWSSMDCL_SYSTEM_STATE and LWSSMDCL_NETWORK, INTERACTION type messages are +not accepted. + +## build + +``` + $ cmake . && make +``` + +## usage + +Commandline option|Meaning +---|--- +-d |Debug verbosity in decimal, eg, -d15 + +``` +$ ./bin/lws-minimal-secure-streams-smd -d 1151 +[2020/06/18 21:44:54:5148] U: LWS Secure Streams SMD test client [-d] +[2020/06/18 21:44:54:5601] I: Initial logging level 1151 +[2020/06/18 21:44:54:5605] I: Libwebsockets version: 4.0.99-v4.0.0-174-ga8a2eb954 v4.0.0-174-ga8a2eb954 +[2020/06/18 21:44:54:5607] I: IPV6 not compiled in +... +[2020/06/18 21:44:54:7906] D: _lws_state_transition: system: changed 11 'AUTH2' -> 12 'OPERATIONAL' +[2020/06/18 21:44:54:7906] D: _realloc: size 81: lws_smd_msg_alloc +[2020/06/18 21:44:54:7907] I: lws_cancel_service +[2020/06/18 21:44:54:7912] I: lws_state_transition_steps: CONTEXT_CREATED -> OPERATIONAL +[2020/06/18 21:44:54:7919] N: myss_tx: sending SS smd +[2020/06/18 21:44:54:7940] D: _realloc: size 84: lws_smd_msg_alloc +[2020/06/18 21:44:54:7944] I: lws_cancel_service +[2020/06/18 21:44:54:7966] D: direct_smd_cb: class: 0x2, ts: 3139600721554 +[2020/06/18 21:44:54:7972] D: +[2020/06/18 21:44:54:7990] D: 0000: 7B 22 73 74 61 74 65 22 3A 22 49 4E 49 54 49 41 {"state":"INITIA +[2020/06/18 21:44:54:7998] D: 0010: 4C 49 5A 45 44 22 7D LIZED"} +[2020/06/18 21:44:54:8001] D: +[2020/06/18 21:44:54:8016] I: myss_rx: len 39, flags: 3 +[2020/06/18 21:44:54:8018] I: +[2020/06/18 21:44:54:8021] I: 0000: 00 00 00 00 00 00 00 02 00 00 02 DA FE C9 26 92 ..............&. +[2020/06/18 21:44:54:8022] I: 0010: 7B 22 73 74 61 74 65 22 3A 22 49 4E 49 54 49 41 {"state":"INITIA +[2020/06/18 21:44:54:8023] I: 0020: 4C 49 5A 45 44 22 7D LIZED"} +[2020/06/18 21:44:54:8023] I: +[2020/06/18 21:44:54:8029] D: direct_smd_cb: class: 0x2, ts: 3139600724243 +[2020/06/18 21:44:54:8029] D: +[2020/06/18 21:44:54:8030] D: 0000: 7B 22 73 74 61 74 65 22 3A 22 49 46 41 43 45 5F {"state":"IFACE_ +[2020/06/18 21:44:54:8031] D: 0010: 43 4F 4C 44 50 4C 55 47 22 7D COLDPLUG"} +[2020/06/18 21:44:54:8032] D: +... +[2020/06/18 21:44:54:8112] D: direct_smd_cb: class: 0x4, ts: 3139600732952 +[2020/06/18 21:44:54:8112] D: +[2020/06/18 21:44:54:8114] D: 0000: 7B 22 73 6F 6D 74 68 69 6E 67 22 3A 22 6E 6F 74 {"somthing":"not +[2020/06/18 21:44:54:8115] D: 0010: 73 65 65 6E 62 79 73 73 72 78 22 7D seenbyssrx"} +[2020/06/18 21:44:54:8115] D: +[2020/06/18 21:44:57:5823] I: 11 12 1 +[2020/06/18 21:44:57:5838] I: lws_context_destroy: ctx 0x4f61db0 +[2020/06/18 21:44:57:5849] D: _lws_state_transition: system: changed 12 'OPERATIONAL' -> 13 'POLICY_INVALID' +[2020/06/18 21:44:57:5851] D: _realloc: size 84: lws_smd_msg_alloc +[2020/06/18 21:44:57:5853] I: lws_cancel_service +[2020/06/18 21:44:57:5871] I: lws_destroy_event_pipe +[2020/06/18 21:44:57:5906] I: lws_pt_destroy: pt destroyed +[2020/06/18 21:44:57:5913] I: lws_context_destroy2: ctx 0x4f61db0 +[2020/06/18 21:44:57:5936] D: lwsac_free: head (nil) +[2020/06/18 21:44:57:5947] D: 0x455970: post vh listl +[2020/06/18 21:44:57:5950] D: 0x455970: post pdl +[2020/06/18 21:44:57:5961] D: 0x455970: baggage +[2020/06/18 21:44:57:5968] D: 0x455970: post dc2 +[2020/06/18 21:44:57:6010] D: lws_context_destroy3: ctx 0x4f61db0 freed +[2020/06/18 21:44:57:6014] U: Completed: OK +``` \ No newline at end of file diff --git a/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c b/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c new file mode 100644 index 00000000..3bc62e75 --- /dev/null +++ b/minimal-examples/secure-streams/minimal-secure-streams-smd/minimal-secure-streams-smd.c @@ -0,0 +1,319 @@ +/* + * lws-minimal-secure-streams-smd + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * + * This demonstrates a minimal http client using secure streams to access the + * SMD api. + */ + +#include +#include +#include + +static int interrupted, bad = 1, count_p1, count_p2, count_tx; +static lws_sorted_usec_list_t sul_timeout; + +/* + * If the -proxy app is fulfilling our connection, then we don't need to have + * the policy in the client. + * + * When we build with LWS_SS_USE_SSPC, the apis hook up to a proxy process over + * a Unix Domain Socket. To test that, you need to separately run the + * ./lws-minimal-secure-streams-proxy test app on the same machine. + */ + +#if !defined(LWS_SS_USE_SSPC) +static const char * const default_ss_policy = + "{" + "\"schema-version\":1," + "\"s\": [" + "{" + /* + * "captive_portal_detect" describes + * what to do in order to check if the path to + * the Internet is being interrupted by a + * captive portal. If there's a larger policy + * fetched from elsewhere, it should also include + * this since it needs to be done at least after + * every DHCP acquisition + */ + "\"captive_portal_detect\": {" + "\"endpoint\": \"connectivitycheck.android.com\"," + "\"http_url\": \"generate_204\"," + "\"port\": 80," + "\"protocol\": \"h1\"," + "\"http_method\": \"GET\"," + "\"opportunistic\": true," + "\"http_expect\": 204," + "\"http_fail_redirect\": true" + "}" + "}" + "]" + "}" +; + +#endif + +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ + lws_sorted_usec_list_t sul; + char alternate; +} myss_t; + + +/* secure streams payload interface */ + +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ +// myss_t *m = (myss_t *)userobj; + + lwsl_notice("%s: len %d, flags: %d\n", __func__, (int)len, flags); + lwsl_hexdump_notice(buf, len); + + count_p1++; + + return 0; +} + +static void +sul_tx_periodic_cb(lws_sorted_usec_list_t *sul) +{ + myss_t *m = lws_container_of(sul, myss_t, sul); + + lwsl_notice("%s: requesting TX\n", __func__); + lws_ss_request_tx(m->ss); +} + +static int +myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, + int *flags) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_notice("%s: sending SS smd\n", __func__); + + /* + * The SS RX isn't going to see INTERACTION messages, because its class + * filter doesn't accept INTERACTION class messages. The direct + * participant we also set up for the test will see them though. + * + * Let's alternate between sending NETWORK class smd messages and + * INTERACTION so we can test both rx paths + */ + + m->alternate++; + lws_ser_wu64be(buf, (m->alternate & 1) ? LWSSMDCL_NETWORK : LWSSMDCL_INTERACTION); + lws_ser_wu64be(buf + 8, 0); /* valgrind notices uninitialized if left */ + + if (m->alternate == 4) { + /* + * after a few, let's request a CPD check + */ + *len = LWS_SMD_SS_RX_HEADER_LEN + + lws_snprintf((char *)buf + LWS_SMD_SS_RX_HEADER_LEN, *len, + "{\"trigger\": \"cpdcheck\", \"src\":\"SS-test\"}"); + } else + + *len = LWS_SMD_SS_RX_HEADER_LEN + + lws_snprintf((char *)buf + LWS_SMD_SS_RX_HEADER_LEN, *len, + (m->alternate & 1) ? "{\"class\":\"NETWORK\"}" : + "{\"class\":\"INTERACTION\"}"); + + *flags = LWSSS_FLAG_SOM | LWSSS_FLAG_EOM; + + count_tx++; + + lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, + sul_tx_periodic_cb, 250 * LWS_US_PER_MS); + + return 0; +} + +static int +myss_state(void *userobj, void *h_src, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + if (state == LWSSSCS_DESTROYING) { + lws_sul_cancel(&m->sul); + return 0; + } + + if (state == LWSSSCS_CONNECTED) { + lwsl_notice("%s: CONNECTED\n", __func__); + lws_sul_schedule(lws_ss_get_context(m->ss), 0, &m->sul, + sul_tx_periodic_cb, 1); + return 0; + } + + return 0; +} + +static const lws_ss_info_t ssi_lws_smd = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .rx = myss_rx, + .tx = myss_tx, + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = LWS_SMD_STREAMTYPENAME, + .manual_initial_tx_credit = LWSSMDCL_SYSTEM_STATE | + LWSSMDCL_NETWORK, +}; + +/* for comparison, this is a non-SS lws_smd participant */ + +static int +direct_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ + struct lws_context **pctx = (struct lws_context **)opaque; + + lwsl_notice("%s: class: 0x%x, ts: %llu\n", __func__, _class, + (unsigned long long)timestamp); + lwsl_hexdump_notice(buf, len); + + count_p2++; + + if (_class != LWSSMDCL_SYSTEM_STATE) + return 0; + + if (!lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) { + +#if !defined(LWS_SS_USE_SSPC) + /* + * Let's trigger a CPD check, just as a test. SS can't see it + * anyway since it doesn't listen for NETWORK but the direct / + * local participant will see it and the result + * + * This process doesn't run the smd / captive portal action + * when it's a client of the SS proxy. SMD has to be passed + * via the SS _lws_smd proxied connection in that case. + */ + (void)lws_smd_msg_printf(*pctx, LWSSMDCL_NETWORK, + "{\"trigger\": \"cpdcheck\", \"src\":\"direct-test\"}"); +#endif + + /* + * Create the SS link to lws_smd... notice in ssi_lws_smd + * above, we tell this link to use a class filter that excludes + * NETWORK messages. + */ + + if (lws_ss_create(*pctx, 0, &ssi_lws_smd, NULL, NULL, NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + + return -1; + } + } + + return 0; +} + + +static void +sul_timeout_cb(lws_sorted_usec_list_t *sul) +{ + interrupted = 1; +} + + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + struct lws_context *context; + + signal(SIGINT, sigint_handler); + + memset(&info, 0, sizeof info); + lws_cmdline_option_handle_builtin(argc, argv, &info); + + lwsl_user("LWS Secure Streams SMD test client [-d]\n"); + + info.fd_limit_per_thread = 1 + 6 + 1; + info.port = CONTEXT_PORT_NO_LISTEN; +#if !defined(LWS_SS_USE_SSPC) + info.pss_policies_json = default_ss_policy; +#else + info.protocols = lws_sspc_protocols; +#endif + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + + info.early_smd_cb = direct_smd_cb; + info.early_smd_class_filter = 0xffffffff; + info.early_smd_opaque = &context; + + /* create the context */ + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + +#if defined(LWS_SS_USE_SSPC) + if (!lws_create_vhost(context, &info)) { + lwsl_err("%s: failed to create default vhost\n", __func__); + goto bail; + } +#endif + + /* set up the test timeout */ + + lws_sul_schedule(context, 0, &sul_timeout, sul_timeout_cb, + 4 * LWS_US_PER_SEC); + + /* the event loop */ + + while (lws_service(context, 0) >= 0 && !interrupted) + ; + + /* compare what happened with what we expect */ + +#if defined(LWS_SS_USE_SSPC) + /* if SSPC + * + * - the SS _lws_smd link does not enable INTERACTION class, so doesn't + * see these messages (count_p1 is half count_tx) + * + * - the direct smd participant sees local state, but it doesn't send + * any local CPD request, since as a client it doesn't do CPD + * directly (count_p2 -= 1 compared to non-SSPC) + * + * - one CPD trigger is sent on the proxied SS link (countp1 += 1) + */ + if (count_p1 >= 6 && count_p2 >= 11 && count_tx >= 12) +#else + /* if not SSPC, then we can see direct smd activity */ + if (count_p1 >= 2 && count_p2 >= 15 && count_tx >= 5) +#endif + bad = 0; + + lwsl_notice("%d %d %d\n", count_p1, count_p2, count_tx); + +#if defined(LWS_SS_USE_SSPC) +bail: +#endif + lws_context_destroy(context); + + lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); + + return bad; +} -- Gitee From a75a476026cf421b0c14c9f3917cd970efd241a3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 26 Jun 2020 07:34:27 +0100 Subject: [PATCH 0183/1062] ah: use unk_pos to clean up unknown header starts even without CUSTOM_HEADERS --- lib/roles/http/client/client-http.c | 6 ------ lib/roles/http/parsers.c | 16 +++++----------- lib/roles/http/private-lib-roles-http.h | 2 +- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index cf6ffa8e..00db780f 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -349,9 +349,7 @@ start_ws_handshake: #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART; wsi->http.ah->lextable_pos = 0; -#if defined(LWS_WITH_CUSTOM_HEADERS) wsi->http.ah->unk_pos = 0; -#endif /* If we're (re)starting on hdr, need other implied init */ wsi->http.ah->ues = URIES_IDLE; #endif @@ -383,9 +381,7 @@ client_http_body_sent: /* prepare ourselves to do the parsing */ wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART; wsi->http.ah->lextable_pos = 0; -#if defined(LWS_WITH_CUSTOM_HEADERS) wsi->http.ah->unk_pos = 0; -#endif #endif lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY); lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, @@ -553,9 +549,7 @@ lws_http_transaction_completed_client(struct lws *wsi) wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART; wsi->http.ah->lextable_pos = 0; -#if defined(LWS_WITH_CUSTOM_HEADERS) wsi->http.ah->unk_pos = 0; -#endif lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, wsi->context->timeout_secs); diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index 78956539..18c7bde0 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -96,8 +96,8 @@ _lws_header_table_reset(struct allocated_headers *ah) ah->http_response = 0; ah->parser_state = WSI_TOKEN_NAME_PART; ah->lextable_pos = 0; -#if defined(LWS_WITH_CUSTOM_HEADERS) ah->unk_pos = 0; +#if defined(LWS_WITH_CUSTOM_HEADERS) ah->unk_ll_head = 0; ah->unk_ll_tail = 0; #endif @@ -1097,9 +1097,6 @@ swallow: if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; - -#if defined(LWS_WITH_CUSTOM_HEADERS) - /* * ...in case it's an unknown header, speculatively * store it as the name comes in. If we recognize it as @@ -1108,6 +1105,7 @@ swallow: if (!wsi->mux_substream && !ah->unk_pos) { ah->unk_pos = ah->pos; +#if defined(LWS_WITH_CUSTOM_HEADERS) /* * Prepare new unknown header linked-list entry * @@ -1118,8 +1116,8 @@ swallow: for (n = 0; n < 8; n++) if (!lws_pos_in_bounds(wsi)) ah->data[ah->pos++] = 0; - } #endif + } if (lws_pos_in_bounds(wsi)) return LPR_FAIL; @@ -1201,7 +1199,6 @@ nope: /* b7 = 0, end or 3-byte */ if (lextable_h1[pos] < FAIL_CHAR) { -#if defined(LWS_WITH_CUSTOM_HEADERS) if (!wsi->mux_substream) { /* * We hit a terminal marker, so @@ -1212,7 +1209,7 @@ nope: ah->pos = ah->unk_pos; ah->unk_pos = 0; } -#endif + ah->lextable_pos = pos; break; } @@ -1390,10 +1387,7 @@ excessive: goto forbid; if (c == '\x0a') { ah->parser_state = WSI_TOKEN_NAME_PART; -#if defined(LWS_WITH_CUSTOM_HEADERS) - ah->unk_pos = 0; -#endif - ah->lextable_pos = 0; + ah->unk_pos = ah->lextable_pos = 0; } else ah->parser_state = WSI_TOKEN_SKIPPING; break; diff --git a/lib/roles/http/private-lib-roles-http.h b/lib/roles/http/private-lib-roles-http.h index 0d9812da..7d02c7ef 100644 --- a/lib/roles/http/private-lib-roles-http.h +++ b/lib/roles/http/private-lib-roles-http.h @@ -125,9 +125,9 @@ struct allocated_headers { ah_data_idx_t pos; ah_data_idx_t http_response; ah_data_idx_t current_token_limit; + ah_data_idx_t unk_pos; /* to undo speculative unknown header */ #if defined(LWS_WITH_CUSTOM_HEADERS) - ah_data_idx_t unk_pos; /* to undo speculative unknown header */ ah_data_idx_t unk_value_pos; ah_data_idx_t unk_ll_head; -- Gitee From 84f8137fa68f34a27fd0586ab1e17d1b790d3cf5 Mon Sep 17 00:00:00 2001 From: Jed Lu Date: Tue, 30 Jun 2020 17:49:14 +0100 Subject: [PATCH 0184/1062] ah-un_pos-cleanup-fix-other-path --- lib/roles/http/parsers.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index 18c7bde0..d91b40d3 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -1105,6 +1105,7 @@ swallow: if (!wsi->mux_substream && !ah->unk_pos) { ah->unk_pos = ah->pos; + #if defined(LWS_WITH_CUSTOM_HEADERS) /* * Prepare new unknown header linked-list entry @@ -1283,6 +1284,9 @@ nope: goto forbid; } if (ah->lextable_pos < 0) { + /* + * It's not a header that lws knows about... + */ #if defined(LWS_WITH_CUSTOM_HEADERS) if (!wsi->mux_substream) goto unknown_hdr; @@ -1309,11 +1313,21 @@ nope: return LPR_FAIL; } + if (!wsi->mux_substream) { + /* + * Whether we are collecting unknown names or not, + * if we matched an internal header we can dispense + * with the header name part we were keeping + */ + ah->pos = ah->unk_pos; + ah->unk_pos = 0; + } + +#if defined(LWS_ROLE_WS) /* * WSORIGIN is protocol equiv to ORIGIN, * JWebSocket likes to send it, map to ORIGIN */ -#if defined(LWS_ROLE_WS) if (n == WSI_TOKEN_SWORIGIN) n = WSI_TOKEN_ORIGIN; #endif -- Gitee From 04c20d746056fd051bd748680cbf8886c737c3a3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 30 Jun 2020 17:50:01 +0100 Subject: [PATCH 0185/1062] ah: workaround for broken routers with no http header delimiter There's a type of router in the wild issuing malformed http when in captive portal mode... there's no \x0a\x0d but just \x0a --- .gitignore | 1 + lib/roles/http/parsers.c | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index fd50d029..1fb8b7e0 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ doc /cros/ /q/ /b1/ +/destdir/ diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index d91b40d3..b74669b1 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -1065,12 +1065,18 @@ lws_parse(struct lws *wsi, unsigned char *buf, int *len) check_eol: /* bail at EOL */ if (ah->parser_state != WSI_TOKEN_CHALLENGE && - c == '\x0d') { + (c == '\x0d' || c == '\x0a')) { if (ah->ues != URIES_IDLE) goto forbid; + if (c == '\x0a') { + /* broken peer */ + ah->parser_state = WSI_TOKEN_NAME_PART; + ah->unk_pos = ah->lextable_pos = 0; + } else + ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; + c = '\0'; - ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; lwsl_parser("*\n"); } @@ -1095,6 +1101,10 @@ swallow: (unsigned long)lwsi_role(wsi), ah->lextable_pos); + if (!ah->unk_pos && c == '\x0a') + /* broken peer */ + goto set_parsing_complete; + if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; /* @@ -1391,6 +1401,12 @@ excessive: case WSI_TOKEN_SKIPPING: lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c); + if (c == '\x0a') { + /* broken peer */ + ah->parser_state = WSI_TOKEN_NAME_PART; + ah->unk_pos = ah->lextable_pos = 0; + } + if (c == '\x0d') ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; break; -- Gitee From 0fb8504b20952905d050e3c37a071a53eea939e0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 26 Jun 2020 09:58:20 +0100 Subject: [PATCH 0186/1062] client: suppress CONNECTION_ERROR if still in client_connect_via_info If the client connection attempt fails early, we report it will a NULL return from the client connection api. If it fails later, perhaps after more times around the event loop, we report it as a CONNECTION_ERROR. This patch makes sure we don't do CONNECTION_ERROR flow if in fact we are still in the client_connect_via_info() and in a position to report the failure by returning NULL from there, without it under some conditions we will do both a CONNECTION_ERROR and return NULL. --- lib/core-net/close.c | 7 ++++--- lib/core-net/connect.c | 15 ++++++++++++++- lib/core-net/private-lib-core-net.h | 3 +++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index f10cea42..a92f258f 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -214,9 +214,10 @@ lws_inform_client_conn_fail(struct lws *wsi, void *arg, size_t len) if (!wsi->protocol) return; - wsi->protocol->callback(wsi, - LWS_CALLBACK_CLIENT_CONNECTION_ERROR, - wsi->user_space, arg, len); + if (!wsi->client_suppress_CONNECTION_ERROR) + wsi->protocol->callback(wsi, + LWS_CALLBACK_CLIENT_CONNECTION_ERROR, + wsi->user_space, arg, len); } #endif diff --git a/lib/core-net/connect.c b/lib/core-net/connect.c index af5c9a9d..1fae6c79 100644 --- a/lib/core-net/connect.c +++ b/lib/core-net/connect.c @@ -58,6 +58,12 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) if (wsi == NULL) goto bail; + /* + * Until we exit, we can report connection failure directly to the + * caller without needing to call through to protocol CONNECTION_ERROR. + */ + wsi->client_suppress_CONNECTION_ERROR = 1; + if (i->keep_warm_secs) wsi->keep_warm_secs = i->keep_warm_secs; else @@ -356,9 +362,16 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) /* fallthru */ - lws_http_client_connect_via_info2(wsi); + wsi = lws_http_client_connect_via_info2(wsi); } + if (wsi) + /* + * If it subsequently fails, report CONNECTION_ERROR, + * because we're going to return a non-error return now. + */ + wsi->client_suppress_CONNECTION_ERROR = 0; + return wsi; #if defined(LWS_WITH_TLS) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 065b2526..a688e03b 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -823,6 +823,9 @@ struct lws { unsigned int client_mux_migrated:1; unsigned int client_subsequent_mime_part:1; unsigned int client_no_follow_redirect:1; + unsigned int client_suppress_CONNECTION_ERROR:1; + /**< because the client connection creation api is still the parent of + * this activity, and will report the failure */ #endif #ifdef _WIN32 -- Gitee From 2ba3b7b72b21b93e188368f224250eefe5caad2e Mon Sep 17 00:00:00 2001 From: Yichen Gu Date: Fri, 26 Jun 2020 10:35:06 +0100 Subject: [PATCH 0187/1062] ss: rideshare fix for when h2 not available --- lib/secure-streams/protocols/ss-h1.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index a97c9f73..aa6c71a2 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -474,6 +474,7 @@ malformed: if (!h->rideshare) h->rideshare = h->policy; + buflen = lws_ptr_diff(end, p); #if defined(LWS_WITH_SS_RIDESHARE) if (!h->inside_msg && h->rideshare->u.http.multipart_name) lws_client_http_multipart(wsi, @@ -482,10 +483,8 @@ malformed: h->rideshare->u.http.multipart_content_type, (char **)&p, (char *)end); - buflen = lws_ptr_diff(end, p); if (h->policy->u.http.multipart_name) buflen -= 24; /* allow space for end of multipart */ - #endif switch(h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f)) { @@ -513,23 +512,22 @@ malformed: p += buflen; if (f & LWSSS_FLAG_EOM) { -#if defined(LWS_WITH_SS_RIDESHARE) + conceal_eom = 1; /* end of rideshares */ if (!h->rideshare->rideshare_streamtype) { lws_client_http_body_pending(wsi, 0); +#if defined(LWS_WITH_SS_RIDESHARE) if (h->rideshare->u.http.multipart_name) lws_client_http_multipart(wsi, NULL, NULL, NULL, (char **)&p, (char *)end); conceal_eom = 0; - } else { #endif + } else { h->rideshare = lws_ss_policy_lookup(wsi->context, h->rideshare->rideshare_streamtype); lws_callback_on_writable(wsi); -#if defined(LWS_WITH_SS_RIDESHARE) } -#endif h->inside_msg = 0; } else { -- Gitee From 64aee81ba7b8a2c4df67f81f7a2e6bf6f784b5aa Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 26 Jun 2020 11:28:25 +0100 Subject: [PATCH 0188/1062] ss: reset retry count for explicit connection request This differentiates between client connections for retry / writeable requests and explicit lws_ss_client_connect() api calls. The former effectively uses retry / backoff, and the latter resets the retry / backoff. If you receive ALL_RETRIES_FAILED due to the retry policy, you can do whatever you need to do there and call lws_ss_client_connect() to try to connect again with a fresh, reset retry / backoff state. --- .../private-lib-secure-streams.h | 3 +++ lib/secure-streams/secure-streams-serialize.c | 2 +- lib/secure-streams/secure-streams.c | 23 +++++++++++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index f0dd8585..d88561f9 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -377,6 +377,9 @@ int lws_ss_exp_cb_metadata(void *priv, const char *name, char *out, size_t *pos, size_t olen, size_t *exp_ofs); +int +_lws_ss_client_connect(lws_ss_handle_t *h, int is_retry); + int lws_ss_sys_cpd(struct lws_context *cx); diff --git a/lib/secure-streams/secure-streams-serialize.c b/lib/secure-streams/secure-streams-serialize.c index ecf326ce..db24f14a 100644 --- a/lib/secure-streams/secure-streams-serialize.c +++ b/lib/secure-streams/secure-streams-serialize.c @@ -351,7 +351,7 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, goto hangup; par->ps = RPAR_TYPE; if (*pss) - lws_ss_client_connect(*pss); + _lws_ss_client_connect(*pss, 0); break; case LWSSS_SER_TXPRE_STREAMTYPE: diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 4ffd5a9a..36880f7b 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -294,12 +294,8 @@ lws_ss_smd_tx_cb(lws_sorted_usec_list_t *sul) #endif -/* - * This is a local SS binding to a local SMD server - */ - int -lws_ss_client_connect(lws_ss_handle_t *h) +_lws_ss_client_connect(lws_ss_handle_t *h, int is_retry) { const char *prot, *_prot, *ipath, *_ipath, *ads, *_ads; struct lws_client_connect_info i; @@ -323,6 +319,9 @@ lws_ss_client_connect(lws_ss_handle_t *h) if (h->h_sink) return 0; + if (!is_retry) + h->retry = 0; + #if defined(LWS_WITH_SYS_SMD) if (h->policy == &pol_smd) { @@ -473,6 +472,12 @@ lws_ss_client_connect(lws_ss_handle_t *h) return 0; } +int +lws_ss_client_connect(lws_ss_handle_t *h) +{ + return _lws_ss_client_connect(h, 0); +} + /* * Public API */ @@ -661,7 +666,7 @@ late_bail: ) #endif )) - if (lws_ss_client_connect(h)) + if (_lws_ss_client_connect(h, 0)) lws_ss_backoff(h); return 0; @@ -760,7 +765,11 @@ lws_ss_request_tx(lws_ss_handle_t *h) h->seqstate = SSSEQ_TRY_CONNECT; lws_ss_event_helper(h, LWSSSCS_POLL); - if (lws_ss_client_connect(h)) + /* + * Retries operate via lws_ss_request_tx(), explicitly ask for a + * reconnection to clear the retry limit + */ + if (_lws_ss_client_connect(h, 1)) lws_ss_backoff(h); } -- Gitee From 4bcc446bf6dabf3d72a34d6fcbfecd6eeca485db Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 26 Jun 2020 13:13:58 +0100 Subject: [PATCH 0189/1062] docs: ss: document ss state flow --- doc-assets/ss-state-flow.png | Bin 0 -> 201758 bytes lib/secure-streams/README.md | 31 +++++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 doc-assets/ss-state-flow.png diff --git a/doc-assets/ss-state-flow.png b/doc-assets/ss-state-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..078100fad286d3c9a26639c2947e197db08e460f GIT binary patch literal 201758 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≺=MNhSmwC5o%D?yyB^Ty;j> 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

&1dQI<1KHilUt@h{tm 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 not send anything -tx|<0|Finished with stream +tx|`LWSSSSRET_OK`|Send the amount of `buf` stored in `*len` +tx|`LWSSSSRET_TX_DONT_SEND`|Do not send anything +tx|`LWSSSSRET_DISCONNECT_ME`|Close the current connection +tx|`LWSSSSRET_DESTROY_ME`|Destroy the Secure Stream rx|>=0|accepted -rx|<0|Finished with stream +rx|<0|Close the current connection +## Secure Streams State lifecycle + +![overview](../doc-assets/ss-state-flow.png) + +Secure Streams are created using `lws_ss_create()`, after that they may acquire +underlying connections, and lose them, but the lifecycle of the Secure Stream +itself is not directly related to any underlying connection. + +Once created, Secure Streams may attempt connections, these may fail and once +the number of failures exceeds the count of attempts to conceal in the retry / +backoff policy, the stream reaches `LWSSSCS_ALL_RETRIES_FAILED`. The stream becomes +idle again until another explicit connection attempt is given. + +Once connected, the user code can use `lws_ss_request_tx()` to ask for a slot +to write to the peer, when this if forthcoming the tx handler can send a message. +If the underlying protocol gives indications of transaction success, such as, +eg, a 200 for http, or an ACK from MQTT, the stream state is called back with +an `LWSSSCS_QOS_ACK_REMOTE` or `LWSSSCS_QOS_NACK_REMOTE`. + +State callbacks and tx() can indicate they want to drop the connection +(`LWSSSRET_DISCONNECT_ME`) or destroy the whole logical Secure Stream +(`LWSSSRET_DESTROY_ME`). # JSON Policy Database -- Gitee From 57bfaa9ccb030b4defa0f5c7ddbc1b56291f57cb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 26 Jun 2020 14:33:17 +0100 Subject: [PATCH 0190/1062] sai: disable opensslv3 check until after release --- .sai.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.sai.json b/.sai.json index 1cf7a153..efbfc29e 100644 --- a/.sai.json +++ b/.sai.json @@ -70,10 +70,10 @@ "cmake": "", "platforms": "windows-10/x86_64-amd/msvc, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, freertos-espidf/xl6-esp32/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64" }, - "default-examples-openssl-v3": { - "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_GENCRYPTO=1", - "platforms": "none,linux-fedora-32/x86_64-amd/gcc" - }, +# "default-examples-openssl-v3": { +# "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_GENCRYPTO=1", +# "platforms": "none,linux-fedora-32/x86_64-amd/gcc" +# }, "default-examples-boringssl": { "cmake": "cmake .. -DLWS_WITH_BORINGSSL=1 -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/boringssl/include\" -DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/boringssl/build/ssl/libssl.so;/usr/local/src/boringssl/build/crypto/libcrypto.so\" -DLWS_WITH_MINIMAL_EXAMPLES=1", "platforms": "none,linux-fedora-32/x86_64-amd/gcc" -- Gitee From 63c1e8ba0007d920cec68a88cce83d268f6fec8a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 25 Jun 2020 14:44:05 +0100 Subject: [PATCH 0191/1062] esp32-wrover-kit Add lws_display and minimal example support for esp32-wrover to match wsp32-heltec-wb32 Since no usable buttons that don't affect something else on wrover kit, assumes a button to 0V on GPIO14. --- .sai.json | 12 +- include/libwebsockets.h | 7 +- include/libwebsockets/lws-bb-spi.h | 62 + include/libwebsockets/lws-display.h | 78 +- include/libwebsockets/lws-ili9341-spi.h | 54 + include/libwebsockets/lws-led.h | 27 +- include/libwebsockets/lws-pwm.h | 5 +- include/libwebsockets/lws-spi.h | 73 + include/libwebsockets/lws-ssd1306-i2c.h | 4 +- lib/core/private-lib-core.h | 2 + lib/drivers/CMakeLists.txt | 5 +- lib/drivers/button/README.md | 5 + lib/drivers/devices/display/ili9341.h | 95 + lib/drivers/display/README.md | 36 + lib/drivers/display/ili9341-spi.c | 187 + lib/drivers/display/lws-display.c | 124 +- lib/drivers/display/ssd1306-i2c.c | 17 +- lib/drivers/led/README.md | 1 + lib/drivers/led/led-seq.c | 90 +- lib/drivers/led/private-lib-drivers-led.h | 19 - lib/drivers/pwm/pwm.c | 11 +- lib/drivers/spi/bitbang/lws-bb-spi.c | 126 + lib/drivers/spi/lws-spi.c | 26 + lib/plat/freertos/esp32/drivers/pwm-esp32.c | 2 + lib/plat/freertos/freertos-misc.c | 12 + lib/plat/optee/lws-plat-optee.c | 7 + lib/plat/unix/unix-misc.c | 12 + lib/plat/windows/windows-misc.c | 11 + .../esp-heltec-wb32}/CMakeLists.txt | 0 .../esp-heltec-wb32}/banded-img.h | 0 .../esp-heltec-wb32}/main/CMakeLists.txt | 0 .../esp-heltec-wb32}/main/lws-minimal-esp32.c | 36 +- .../esp-heltec-wb32}/scan/output.bmp | Bin .../esp-heltec-wb32}/scan/pic.h | 0 .../esp-heltec-wb32}/scan/pic.h.1 | 0 .../esp-heltec-wb32}/scan/scan | Bin .../esp-heltec-wb32}/scan/scan.c | 0 .../esp-heltec-wb32}/scan/scan.sh | 0 .../esp-heltec-wb32}/sdkconfig | 0 .../esp-heltec-wb32}/sdkconfig.h | 0 .../esp32/esp-wrover-kit/CMakeLists.txt | 25 + .../esp32/esp-wrover-kit/main/CMakeLists.txt | 6 + .../esp32/esp-wrover-kit/main/cat-565.h | 19200 ++++++++++++++++ .../esp-wrover-kit/main/lws-minimal-esp32.c | 306 + .../esp32/esp-wrover-kit/partitions.csv | 5 + .../esp32/esp-wrover-kit/rgb565/rgb565.c | 26 + .../embedded/esp32/esp-wrover-kit/sdkconfig | 1151 + .../embedded/esp32/esp-wrover-kit/sdkconfig.h | 426 + 48 files changed, 22094 insertions(+), 197 deletions(-) create mode 100644 include/libwebsockets/lws-bb-spi.h create mode 100644 include/libwebsockets/lws-ili9341-spi.h create mode 100644 include/libwebsockets/lws-spi.h create mode 100644 lib/drivers/devices/display/ili9341.h create mode 100644 lib/drivers/display/README.md create mode 100644 lib/drivers/display/ili9341-spi.c create mode 100644 lib/drivers/spi/bitbang/lws-bb-spi.c create mode 100644 lib/drivers/spi/lws-spi.c rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/CMakeLists.txt (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/banded-img.h (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/main/CMakeLists.txt (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/main/lws-minimal-esp32.c (94%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/scan/output.bmp (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/scan/pic.h (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/scan/pic.h.1 (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/scan/scan (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/scan/scan.c (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/scan/scan.sh (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/sdkconfig (100%) rename minimal-examples/embedded/{lws-minimal-esp32 => esp32/esp-heltec-wb32}/sdkconfig.h (100%) create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/main/cat-565.h create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/partitions.csv create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/rgb565/rgb565.c create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h diff --git a/.sai.json b/.sai.json index efbfc29e..9433b9eb 100644 --- a/.sai.json +++ b/.sai.json @@ -55,7 +55,7 @@ "freertos-espidf/xl6-esp32/gcc": { # official way to get sdkconfig.h is idf.py menuconfig, but # no obvious way to do that in CI - "build": "rm -rf ebuild ; mkdir ebuild; cd ebuild; cp -rp ../minimal-examples/embedded/lws-minimal-esp32 . ; cd lws-minimal-esp32 ; . /opt/esp/esp-idf/export.sh ; ln -sf ../.. libwebsockets ; idf.py set-target esp32 && cp libwebsockets/minimal-examples/embedded/lws-minimal-esp32/sdkconfig . && cp sdkconfig.h build && idf.py build && cd build && /usr/local/bin/sai-device freertos-espidf ESPPORT=0 ctest --output-on-failure", + "build": "rm -rf ebuild ; mkdir ebuild; cd ebuild; cp -rp ../minimal-examples/embedded/esp32/${cmake} . ; cd ${cmake} ; . /opt/esp/esp-idf/export.sh ; ln -sf ../.. libwebsockets ; idf.py set-target esp32 && cp libwebsockets/minimal-examples/embedded/esp32/${cmake}/sdkconfig . && cp sdkconfig.h build && idf.py build && cd build && /usr/local/bin/sai-device ${cmake} ESPPORT=0 ctest --output-on-failure", "default": false }, "linux-fedora-32/riscv64-virt/gcc": { @@ -68,7 +68,15 @@ "configurations": { "default": { "cmake": "", - "platforms": "windows-10/x86_64-amd/msvc, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, freertos-espidf/xl6-esp32/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64" + "platforms": "windows-10/x86_64-amd/msvc, freertos-linkit/arm32-m4-mt7697-usi/gcc, linux-ubuntu-2004/aarch64-a72-bcm2711-rpi4/gcc, windows-10/x86_64-amd/mingw32, windows-10/x86_64-amd/mingw64" + }, + "emb1": { + "cmake": "esp-heltec-wb32", + "platforms": "none, freertos-espidf/xl6-esp32/gcc" + }, + "emb2": { + "cmake": "esp-wrover-kit", + "platforms": "none, freertos-espidf/xl6-esp32/gcc" }, # "default-examples-openssl-v3": { # "cmake": "-DLWS_OPENSSL_LIBRARIES=\"/usr/local/src/openssl/v3/usr/local/lib64/libssl.a;/usr/local/src/openssl/v3/usr/local/lib64/libcrypto.a\" -DLWS_OPENSSL_INCLUDE_DIRS=\"/usr/local/src/openssl/v3/usr/local/include/\" -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_GENCRYPTO=1", diff --git a/include/libwebsockets.h b/include/libwebsockets.h index dd139f06..ac8e22fc 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -610,14 +610,17 @@ struct lws; #endif -#include #include +#include #include #include -#include +#include #include #include #include +#include +#include +#include #ifdef __cplusplus } diff --git a/include/libwebsockets/lws-bb-spi.h b/include/libwebsockets/lws-bb-spi.h new file mode 100644 index 00000000..52c801c6 --- /dev/null +++ b/include/libwebsockets/lws-bb-spi.h @@ -0,0 +1,62 @@ +/* + * I2C - bitbanged generic gpio implementation + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for gpio, a real implementation provides + * functions for the ops that use the underlying OS gpio arrangements. + */ + +#define LWSBBSPI_FLAG_USE_NCMD3 (1 << 7) +#define LWSBBSPI_FLAG_USE_NCMD2 (1 << 6) +#define LWSBBSPI_FLAG_USE_NCMD1 (1 << 5) +#define LWSBBSPI_FLAG_USE_NCMD0 (1 << 4) +#define LWSBBSPI_FLAG_USE_NCS3 (1 << 3) +#define LWSBBSPI_FLAG_USE_NCS2 (1 << 2) +#define LWSBBSPI_FLAG_USE_NCS1 (1 << 1) +#define LWSBBSPI_FLAG_USE_NCS0 (1 << 0) + +#define LWS_SPI_BB_MAX_CH 4 + +typedef struct lws_bb_spi { + lws_spi_ops_t bb_ops; /* init to lws_bb_spi_ops */ + + /* implementation-specific members */ + const lws_gpio_ops_t *gpio; + + _lws_plat_gpio_t clk; + _lws_plat_gpio_t ncs[LWS_SPI_BB_MAX_CH]; + _lws_plat_gpio_t ncmd[LWS_SPI_BB_MAX_CH]; + _lws_plat_gpio_t mosi; + _lws_plat_gpio_t miso; + + uint8_t flags; +} lws_bb_spi_t; + +#define lws_bb_spi_ops \ + .init = lws_bb_spi_init, \ + .queue = lws_bb_spi_queue + +int +lws_bb_spi_init(const lws_spi_ops_t *octx); + +int +lws_bb_spi_queue(const lws_spi_ops_t *octx, const lws_spi_desc_t *desc); diff --git a/include/libwebsockets/lws-display.h b/include/libwebsockets/lws-display.h index 8ac9e289..203cfc57 100644 --- a/include/libwebsockets/lws-display.h +++ b/include/libwebsockets/lws-display.h @@ -28,52 +28,73 @@ #include typedef uint16_t lws_display_scalar; -typedef uint8_t lws_display_brightness; /* * This is embedded in the actual display implementation object at the top, * so a pointer to this can be cast to a pointer to the implementation object * by any code that is specific to how it was implemented. + * + * Notice for the backlight / display intensity we contain pwm_ops... these can + * be some other pwm_ops like existing gpio pwm ops, or handled in a customized + * way like set oled contrast. Either way, the pwm level is arrived at via a + * full set of lws_led_sequences capable of generic lws transitions */ typedef struct lws_display { int (*init)(const struct lws_display *disp); - int (*brightness)(const struct lws_display *disp, lws_display_brightness b); + const lws_pwm_ops_t *bl_pwm_ops; + int (*contrast)(const struct lws_display *disp, uint8_t contrast); int (*blit)(const struct lws_display *disp, const uint8_t *src, lws_display_scalar x, lws_display_scalar y, lws_display_scalar w, lws_display_scalar h); int (*power)(const struct lws_display *disp, int state); - void *variant; - lws_display_scalar w; - lws_display_scalar h; + + const lws_led_sequence_def_t *bl_active; + const lws_led_sequence_def_t *bl_dim; + const lws_led_sequence_def_t *bl_transition; + + void *variant; + + int bl_index; + + lws_display_scalar w; + /**< display surface width in pixels */ + lws_display_scalar h; + /**< display surface height in pixels */ + + uint8_t latency_wake_ms; + /**< ms required after wake from sleep before display usable again... + * delay bringing up the backlight for this amount of time on wake. + * This is managed via a sul on the event loop, not blocking. */ } lws_display_t; /* * This contains dynamic data related to display state */ -enum lws_display_state { - LWSDISPS_OFF, /* managed in display_state */ - LWSDISPS_AUTODIMMED, - LWSDISPS_ACTIVE, +enum lws_display_controller_state { + LWSDISPS_OFF, + LWSDISPS_AUTODIMMED, /* is in pre- blanking static dim mode */ + LWSDISPS_BECOMING_ACTIVE, /* waiting for wake latency before active */ + LWSDISPS_ACTIVE, /* is active */ + LWSDISPS_GOING_OFF /* dimming then off */ }; -typedef struct lws_diplay_state { +typedef struct lws_display_state { + + lws_sorted_usec_list_t sul_autodim; + const lws_display_t *disp; + struct lws_context *ctx; + + int autodim_ms; + int off_ms; - lws_sorted_usec_list_t sul; - lws_sorted_usec_list_t sul_autodim; - const lws_display_t *disp; - struct lws_context *ctx; + struct lws_led_state *bl_lcs; - int autodim_ms; - int off_ms; + lws_led_state_chs_t chs; + /* set of sequencer transition channels */ - lws_display_brightness bl_current; - lws_display_brightness bl_target; - lws_display_brightness bl_step; - lws_display_brightness bl_active; - lws_display_brightness bl_dim; - enum lws_display_state state; + enum lws_display_controller_state state; } lws_display_state_t; @@ -84,8 +105,7 @@ typedef struct lws_diplay_state { * \param ctx: the lws context * \param autodim_ms: ms since last active report to dim display (<0 = never) * \param off_ms: ms since dim to turn display off (<0 = never) - * \param active: brightness level to use when active (0-255) - * \param dim: brightness level to use when dim (0-255) + * \param bl_lcs: the led controller instance that has the backlight * \param disp: generic display object we belong to * * This initializes a display's state, and sets up the optional screen auto-dim @@ -98,22 +118,20 @@ typedef struct lws_diplay_state { */ LWS_VISIBLE LWS_EXTERN void lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx, - int autodim_ms, int off_ms, lws_display_brightness active, - lws_display_brightness dim, const lws_display_t *disp); + int autodim_ms, int off_ms, struct lws_led_state *bl_lcs, + const lws_display_t *disp); /** * lws_display_state_set_brightness() - gradually change the brightness * * \param lds: the display state we are changing - * \param target: the target brightness - * \param step: the step change for each gradual brightness change + * \param target: the target brightness to transition to * * Adjusts the brightness gradually twoards the target at 20Hz */ LWS_VISIBLE LWS_EXTERN void lws_display_state_set_brightness(lws_display_state_t *lds, - lws_display_brightness target, - lws_display_brightness step); + const lws_led_sequence_def_t *pwmseq); /* * lws_display_state_active() - inform the system the display is active diff --git a/include/libwebsockets/lws-ili9341-spi.h b/include/libwebsockets/lws-ili9341-spi.h new file mode 100644 index 00000000..70a361a4 --- /dev/null +++ b/include/libwebsockets/lws-ili9341-spi.h @@ -0,0 +1,54 @@ +/* + * lws abstract display implementation for ili9341 on spi + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +#if !defined(__LWS_DISPLAY_ILI9341_SPI_H__) +#define __LWS_DISPLAY_ILI9341_SPI_H__ + + +typedef struct lws_display_ili9341 { + + lws_display_t disp; /* use lws_display_ili9341_ops to set */ + const lws_spi_ops_t *spi; /* spi ops */ + + const lws_gpio_ops_t *gpio; /* NULL or gpio ops */ + _lws_plat_gpio_t reset_gpio; /* if gpio ops, nReset gpio # */ + + uint8_t spi_index; /* cs index starting from 0 */ + +} lws_display_ili9341_t; + +int +lws_display_ili9341_spi_init(const struct lws_display *disp); +int +lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h); +int +lws_display_ili9341_spi_power(const struct lws_display *disp, int state); + +#define lws_display_ili9341_ops \ + .init = lws_display_ili9341_spi_init, \ + .blit = lws_display_ili9341_spi_blit, \ + .power = lws_display_ili9341_spi_power +#endif diff --git a/include/libwebsockets/lws-led.h b/include/libwebsockets/lws-led.h index 7f131b89..79e03432 100644 --- a/include/libwebsockets/lws-led.h +++ b/include/libwebsockets/lws-led.h @@ -25,9 +25,6 @@ * functions for the ops that use the underlying, eg, OS gpio arrangements. */ -#if !defined(__LWS_LED_H__) -#define __LWS_LED_H__ - /* only b15 significant for GPIO */ typedef uint16_t lws_led_intensity_t; typedef uint16_t lws_led_seq_phase_t; @@ -55,6 +52,29 @@ typedef struct lws_led_sequence_def_t { uint8_t flags; } lws_led_sequence_def_t; +enum { + LLSI_CURR, + LLSI_NEXT, + LLSI_TRANS +}; + +typedef struct lws_led_state_ch +{ + const lws_led_sequence_def_t *seq; /* NULL = inactive */ + lws_led_seq_phase_t ph; + lws_led_seq_phase_t step; + int phase_budget; + lws_led_intensity_t last; + /**< at the end of the sequence we decouple the sequencer, but leave + * the last computed sample behind for further transitions to base off + */ +} lws_led_state_ch_t; + +typedef struct lws_led_state_chs +{ + lws_led_state_ch_t seqs[3]; +} lws_led_state_chs_t; + /* this should always be first in the subclassed implementation types */ typedef struct lws_led_ops { @@ -124,4 +144,3 @@ lws_led_transition(struct lws_led_state *lcs, const char *name, .intensity = lws_led_gpio_intensity, \ } -#endif diff --git a/include/libwebsockets/lws-pwm.h b/include/libwebsockets/lws-pwm.h index ed3d558f..b57635f7 100644 --- a/include/libwebsockets/lws-pwm.h +++ b/include/libwebsockets/lws-pwm.h @@ -25,6 +25,7 @@ typedef struct lws_pwm_map { _lws_plat_gpio_t gpio; uint8_t index; + uint8_t active_level; } lws_pwm_map_t; typedef struct lws_pwm_ops { @@ -61,4 +62,6 @@ extern const lws_led_sequence_def_t lws_pwmseq_sine_endless_slow, lws_pwmseq_sine_endless_fast, lws_pwmseq_linear_wipe, lws_pwmseq_sine_up, lws_pwmseq_sine_down, - lws_pwmseq_static_on, lws_pwmseq_static_off; + lws_pwmseq_static_on, + lws_pwmseq_static_half, + lws_pwmseq_static_off; diff --git a/include/libwebsockets/lws-spi.h b/include/libwebsockets/lws-spi.h new file mode 100644 index 00000000..666113ef --- /dev/null +++ b/include/libwebsockets/lws-spi.h @@ -0,0 +1,73 @@ +/* + * Generic I2C ops + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + * This is like an abstract class for spi, a real implementation provides + * functions for the ops that use the underlying OS arrangements. + * + * It uses descriptor / queuing semantics but eg the GPIO BB implementantion is + * synchronous. + */ + +#if !defined(__LWS_SPI_H__) +#define __LWS_SPI_H__ + +#include +#include + +typedef int (*lws_spi_cb_t)(void *opaque); + +enum { + LWSSPIMODE_CPOL = (1 << 0), + LWSSPIMODE_CPHA = (1 << 1), + + LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_RISING = 0, + LWS_SPI_BUSMODE_CLK_IDLE_HIGH_SAMP_RISING = LWSSPIMODE_CPOL, + LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_FALLING = LWSSPIMODE_CPHA, + LWS_SPI_BUSMODE_CLK_IDLE_HIGH_SAMP_FALLING = LWSSPIMODE_CPHA | + LWSSPIMODE_CPOL, + + LWS_SPI_TXN_HALF_DUPLEX_DISCRETE = 0, + /**< separate MISO and MOSI, but only either MISO or MOSI has data at + * one time... i2c style in SPI */ +}; + +typedef struct lws_spi_desc { + const uint8_t *src; + const uint8_t *data; + uint8_t *dest; + void *opaque; + lws_spi_cb_t completion_cb; + uint16_t count_cmd; + uint16_t count_write; + uint16_t count_read; + uint8_t txn_type; + uint8_t channel; +} lws_spi_desc_t; + +typedef struct lws_spi_ops { + int (*init)(const struct lws_spi_ops *ctx); + int (*queue)(const struct lws_spi_ops *ctx, const lws_spi_desc_t *desc); + uint8_t bus_mode; +} lws_spi_ops_t; + +#endif diff --git a/include/libwebsockets/lws-ssd1306-i2c.h b/include/libwebsockets/lws-ssd1306-i2c.h index bd50551a..4f757904 100644 --- a/include/libwebsockets/lws-ssd1306-i2c.h +++ b/include/libwebsockets/lws-ssd1306-i2c.h @@ -48,7 +48,7 @@ typedef struct lws_display_ssd1306 { int lws_display_ssd1306_i2c_init(const struct lws_display *disp); int -lws_display_ssd1306_i2c_brightness(const struct lws_display *disp, uint8_t b); +lws_display_ssd1306_i2c_contrast(const struct lws_display *disp, uint8_t b); int lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, lws_display_scalar x, lws_display_scalar y, @@ -58,7 +58,7 @@ lws_display_ssd1306_i2c_power(const struct lws_display *disp, int state); #define lws_display_ssd1306_ops \ .init = lws_display_ssd1306_i2c_init, \ - .brightness = lws_display_ssd1306_i2c_brightness, \ + .contrast = lws_display_ssd1306_i2c_contrast, \ .blit = lws_display_ssd1306_i2c_blit, \ .power = lws_display_ssd1306_i2c_power #endif diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 3f6dbba9..0a0062f5 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -751,6 +751,8 @@ lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len); LWS_EXTERN int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf, lws_filepos_t *amount); +void lws_msleep(unsigned int); + void lws_context_destroy2(struct lws_context *context); diff --git a/lib/drivers/CMakeLists.txt b/lib/drivers/CMakeLists.txt index b15a7c38..1320d885 100644 --- a/lib/drivers/CMakeLists.txt +++ b/lib/drivers/CMakeLists.txt @@ -1,8 +1,11 @@ list(APPEND SOURCES drivers/display/lws-display.c drivers/display/ssd1306-i2c.c - drivers/i2c/lws-i2c.c + drivers/display/ili9341-spi.c + drivers/i2c/lws-i2c.c drivers/i2c/bitbang/lws-bb-i2c.c + drivers/spi/lws-spi.c + drivers/spi/bitbang/lws-bb-spi.c drivers/button/lws-button.c drivers/led/led-gpio.c drivers/led/led-seq.c diff --git a/lib/drivers/button/README.md b/lib/drivers/button/README.md index 6c7b9ce8..758823df 100644 --- a/lib/drivers/button/README.md +++ b/lib/drivers/button/README.md @@ -85,6 +85,7 @@ ms_min_down|20ms|Down events shorter than this are ignored ms_min_down_longpress|300ms|Down events longer than this are reported as a long-click ms_up_settle|20ms|After the first indication a button is no longer down, the button is ignored for this interval ms_doubleclick_grace|120ms|The time allowed after a click to see if a second, double-click, is forthcoming +ms_repeat_down|0 / disabled|If held down, interval at which to issue `stilldown` events flags|LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK|Control which classifications can apply ### lws_smd System Message Distribution Events @@ -117,6 +118,7 @@ the interaction, eg, that it can be understood as a single "double-click" event. Event name|Meaning ---|--- down|The button passes a filter for being down, useful for duration-based response +stilldown|The regime can be configured to issue "repeat" notifications at intervals up|The button has come up, useful for duration-based response click|The button activity resulted in a classification as a single-click longclick|The button activity resulted in a classification as a long-click @@ -149,3 +151,6 @@ Classification|Sequencing click|down-up-click (it's classified when it went up and cannot be a longclick) longclick|down-longclick-up (it's classified while still down) doubleclick|down-up-down-doubleclick-up (classified as soon as second click down long enough) + +If the regime is configured for it, any "down" may be followed by one or more +"stilldown" at intervals if the button is down long enough diff --git a/lib/drivers/devices/display/ili9341.h b/lib/drivers/devices/display/ili9341.h new file mode 100644 index 00000000..cb4bc249 --- /dev/null +++ b/lib/drivers/devices/display/ili9341.h @@ -0,0 +1,95 @@ +/* + * Private register map for ILI9341 + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + * + */ + +#if !defined(__LWS_ILI9341_H__) +#define __LWS_ILI9341_H__ + +enum { + + ILI9341_NOP = 0x00, + ILI9341_SWRESET = 0x01, + ILI9341_RDDID = 0x04, + ILI9341_RDDST = 0x09, + + ILI9341_SLPIN = 0x10, + ILI9341_SLPOUT = 0x11, + ILI9341_PTLON = 0x12, + ILI9341_NORON = 0x13, + + ILI9341_RDMODE = 0x0a, + ILI9341_RDMADCTL = 0x0b, + ILI9341_RDPIXFMT = 0x0c, + ILI9341_RDIMGFMT = 0x0d, + ILI9341_RDSELFDIAG = 0x0f, + + ILI9341_INVOFF = 0x20, + ILI9341_INVON = 0x21, + ILI9341_GAMMASET = 0x26, + ILI9341_DISPOFF = 0x28, + ILI9341_DISPON = 0x29, + ILI9341_CASET = 0x2a, + ILI9341_PASET = 0x2b, + ILI9341_RAMWR = 0x2c, + ILI9341_RAMRD = 0x2e, + + ILI9341_PTLAR = 0x30, + ILI9341_VSCRDEF = 0x33, + ILI9341_MADCTL = 0x36, + ILI9341_VSCRSADD = 0x37, + ILI9341_PIXFMT = 0x3a, + + ILI9341_FRMCTR1 = 0xb1, + ILI9341_FRMCTR2 = 0xb2, + ILI9341_FRMCTR3 = 0xb3, + ILI9341_INVCTR = 0xb4, + ILI9341_DFUNCTR = 0xb6, + + ILI9341_PWCTR1 = 0xc0, + ILI9341_PWCTR2 = 0xc1, + ILI9341_PWCTR3 = 0xc2, + ILI9341_PWCTR4 = 0xc3, + ILI9341_PWCTR5 = 0xc4, + ILI9341_VMCTR1 = 0xc5, + ILI9341_VMCTR2 = 0xc7, + ILI9341_FACPUMPRAT = 0xcb, + ILI9341_FACPWCTRB = 0xcf, + + ILI9341_RDID1 = 0xda, + ILI9341_RDID2 = 0xdb, + ILI9341_RDID3 = 0xdc, + ILI9341_RDID4 = 0xdd, + + ILI9341_GMCTRP1 = 0xe0, + ILI9341_GMCTRN1 = 0xe1, + ILI9341_FACPWCTRA = 0xe8, + ILI9341_FACPWCTR1 = 0xea, + ILI9341_FACDRTIMCTRA = 0xed, + + ILI9341_FACSETGAMMACRV = 0xf2, + ILI9341_FACDRTIMCTR = 0xf7, +}; + +#endif + diff --git a/lib/drivers/display/README.md b/lib/drivers/display/README.md new file mode 100644 index 00000000..f3c8b0d9 --- /dev/null +++ b/lib/drivers/display/README.md @@ -0,0 +1,36 @@ +# lws_display + +lws provides a generic "display" object that is independent of the connection +to the display, i2c and spi implementations are provided. + +Its purpose is to provide basic blit, backlight binding to lws_pwm, backlight / +power management and display info like pixels wide and high in a generic way. + +The generic display object `lws_display_t` can be included at the top of a +specific display implementation object, eg, binding it to additional members +to define the actual IO operations to be used, eg, i2c or spi. + +When the display is instantiated, it allocates an additional structure on heap +that contains dynamic information about display state, `lws_display_state_t`. + +## Power state machine + +lws_display objects have convenient power state management using a single lws +sul event loop timer that is managed automatically. + +State|Meaning +---|--- +OFF|The display is in sleep and not showing anything +BECOMING_ACTIVE|The display was asked to come out of sleep and is waiting for .latency_wake_ms befor proceeding to ACTIVE. The backlight if any is off. After the delay, the backlight is sequenced up to `.bl_active` using `.bl_transition` sequencer +ACTIVE|The backlight is ON and the dim timer is running +AUTODIMMED|The dim timer was not told the display was active for `.autodim_ms`, we are at `.bl_dim` brightness. After `.off_ms` we will transition to OFF + +The lws_pwm sequencers are used to provide customizable, smooth transitions for +the backlight, which may be nonlinear. + +## Active notification + +Calling `lws_display_state_active(&lds)` on eg, user interaction causes the +display state to transition to ACTIVE smoothly, taking care of waking the display +and waiting out a display-specific wake period, and sequencing the backlight +transition to active level as specified in the display structure. diff --git a/lib/drivers/display/ili9341-spi.c b/lib/drivers/display/ili9341-spi.c new file mode 100644 index 00000000..1d01be32 --- /dev/null +++ b/lib/drivers/display/ili9341-spi.c @@ -0,0 +1,187 @@ +/* + * lws abstract display implementation for ili9341 on spi + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 +#include + + +static uint8_t ili9341_320x240_init[] = { + /* + * This provides 70Hz 320x240 at RGB565, we assume im[3:0] is 1110 + * which is 4-bit SPI + */ + + 3, ILI9341_FACPWCTRB, 0x00, 0x83, 0x30, + 4, ILI9341_FACDRTIMCTRA, 0x64, 0x03, 0x12, 0x81, + 3, ILI9341_FACPWCTRA, 0x85, 0x01, 0x79, + 5, ILI9341_FACPUMPRAT, 0x39, 0x2c, 0x00, 0x34, 0x02, + 1, ILI9341_FACDRTIMCTR, 0x20, + 2, ILI9341_FACPWCTR1, 0x00, 0x00, + + 1, ILI9341_PWCTR1, 0x26, + 1, ILI9341_PWCTR2, 0x11, + 2, ILI9341_VMCTR1, 0x35, 0x3e, + 1, ILI9341_VMCTR2, 0xbe, + 1, ILI9341_MADCTL, 0x28, + 1, ILI9341_VSCRSADD, 0x00, + 1, ILI9341_PIXFMT, 0x55, + 2, ILI9341_FRMCTR1, 0x00, 0x1b, + 1, ILI9341_FACSETGAMMACRV, 0x00, + 1, ILI9341_GAMMASET, 0x01, + 15, ILI9341_GMCTRP1, 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, + 0xf1, 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, + 0x00, + 15, ILI9341_GMCTRN1, 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, + 0xc1, 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, + 0x0f, + 4, ILI9341_DFUNCTR, 0x0a, 0x82, 0x27, 0x00, +}; + +int +lws_display_ili9341_spi_init(const struct lws_display *disp) +{ + const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)disp; + lws_spi_desc_t desc; + size_t pos = 0; + uint8_t u[8]; + + lwsl_user("%s\n", __func__); + + /* hardware nRESET */ + + if (ili->gpio) { + ili->gpio->mode(ili->reset_gpio, LWSGGPIO_FL_WRITE | + LWSGGPIO_FL_PULLUP); + ili->gpio->set(ili->reset_gpio, 0); + + lws_msleep(1); + ili->gpio->set(ili->reset_gpio, 1); + lws_msleep(1); + } + + /* + * We cut the init table up into transactions... atm we just go with + * the fact that bb spi is synchronous, using async / dma we can't use + * a single desc on the stack like this + */ + + memset(&desc, 0, sizeof(desc)); + desc.count_cmd = 1; + + while (pos < LWS_ARRAY_SIZE(ili9341_320x240_init)) { + desc.count_write = ili9341_320x240_init[pos++]; + desc.src = &ili9341_320x240_init[pos++]; + desc.data = &ili9341_320x240_init[pos]; + pos += desc.count_write; + + ili->spi->queue(ili->spi, &desc); + } + + u[0] = ILI9341_SLPOUT; + desc.src = &u[0]; + desc.count_write = 0; + ili->spi->queue(ili->spi, &desc); + + lws_msleep(5); + + u[0] = ILI9341_DISPON; + ili->spi->queue(ili->spi, &desc); + + return 0; +} + +/* backlight handled by PWM */ + +int +lws_display_ili9341_spi_brightness(const struct lws_display *disp, uint8_t b) +{ + return 0; +} + +int +lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, + lws_display_scalar x, lws_display_scalar y, + lws_display_scalar w, lws_display_scalar h) +{ + const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)disp; + lws_spi_desc_t desc; + uint8_t u[5]; + + memset(&desc, 0, sizeof(desc)); + desc.count_cmd = 1; + desc.src = &u[0]; + desc.count_write = 0; + + /* + * Blit a line at a time + */ + + while (h--) { + + u[0] = ILI9341_CASET; + desc.data = &u[1]; + u[1] = x; + u[2] = x; + u[3] = w >> 8; + u[4] = w & 0xff; + desc.count_write = 4; + ili->spi->queue(ili->spi, &desc); + + u[0] = ILI9341_PASET; + u[1] = y >> 8; + u[2] = y & 0xff; + u[3] = (y + 1) >> 8; + u[4] = (y + 1) & 0xff; + desc.count_write = 4; + ili->spi->queue(ili->spi, &desc); + + u[0] = ILI9341_RAMWR; + desc.data = src; + desc.count_write = w * 2; + ili->spi->queue(ili->spi, &desc); + src += w * 2; + y++; + } + + return 0; +} + +int +lws_display_ili9341_spi_power(const struct lws_display *disp, int state) +{ + + const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)disp; + lws_spi_desc_t desc; + uint8_t u[1]; + + memset(&desc, 0, sizeof(desc)); + desc.count_cmd = 1; + desc.data = desc.src = &u[0]; + u[0] = state ? ILI9341_SLPOUT : ILI9341_SLPIN; + ili->spi->queue(ili->spi, &desc); + + /* we're not going to do anything useful for 5ms after this */ + + return 0; +} diff --git a/lib/drivers/display/lws-display.c b/lib/drivers/display/lws-display.c index 32e85368..28d0c97f 100644 --- a/lib/drivers/display/lws-display.c +++ b/lib/drivers/display/lws-display.c @@ -24,103 +24,109 @@ #include -static void -sul_cb(lws_sorted_usec_list_t *sul) -{ - lws_display_state_t *lds = lws_container_of(sul, lws_display_state_t, - sul); - - if (lds->bl_target > lds->bl_current) { - if (lds->bl_target - lds->bl_current < lds->bl_step) - lds->bl_current = lds->bl_target; - else - lds->bl_current += lds->bl_step; - } else { - if (lds->bl_current - lds->bl_target < lds->bl_step) - lds->bl_current = lds->bl_target; - else - lds->bl_current -= lds->bl_step; - } - - lds->disp->brightness(lds->disp, lds->bl_current); - - if (lds->bl_current != lds->bl_target) - /* - * Come back and move towards the target again in 50ms - */ - lws_sul_schedule(lds->ctx, 0, &lds->sul, - sul_cb, 50 * LWS_US_PER_MS); -} - static void sul_autodim_cb(lws_sorted_usec_list_t *sul) { lws_display_state_t *lds = lws_container_of(sul, lws_display_state_t, - sul_autodim); + sul_autodim); + int next_ms = -1; /* we fire both to dim and to blank... if already in dim state, blank */ - if (lds->state == LWSDISPS_AUTODIMMED) { + switch (lds->state) { + case LWSDISPS_BECOMING_ACTIVE: + lws_display_state_set_brightness(lds, lds->disp->bl_active); + lds->state = LWSDISPS_ACTIVE; + next_ms = lds->autodim_ms; + break; + + case LWSDISPS_ACTIVE: + /* active -> autodimmed */ + lds->state = LWSDISPS_AUTODIMMED; + next_ms = lds->off_ms; + lws_display_state_set_brightness(lds, lds->disp->bl_dim); + break; + + case LWSDISPS_AUTODIMMED: + /* dimmed -> OFF */ + lws_display_state_set_brightness(lds, &lws_pwmseq_static_off); + lds->state = LWSDISPS_GOING_OFF; + next_ms = 600; + break; + + case LWSDISPS_GOING_OFF: + /* off dimming completed, actual display OFF */ lws_display_state_off(lds); return; - } - lds->state = LWSDISPS_AUTODIMMED; - lws_display_state_set_brightness(lds, lds->bl_dim, lds->bl_step); + default: + return; + } - if (lds->off_ms >= 0) + if (next_ms >= 0) lws_sul_schedule(lds->ctx, 0, &lds->sul_autodim, sul_autodim_cb, - lds->off_ms * LWS_US_PER_MS); + next_ms * LWS_US_PER_MS); } void -lws_display_state_init(lws_display_state_t *ds, struct lws_context *ctx, - int dim_ms, int off_ms, lws_display_brightness active, - lws_display_brightness dim, const lws_display_t *disp) +lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx, + int dim_ms, int off_ms, struct lws_led_state *bl_lcs, + const lws_display_t *disp) { - memset(ds, 0, sizeof(*ds)); - ds->disp = disp; - ds->ctx = ctx; - ds->autodim_ms = dim_ms; - ds->off_ms = off_ms; - ds->bl_active = active; - ds->bl_dim = dim; + memset(lds, 0, sizeof(*lds)); + + lds->disp = disp; + lds->ctx = ctx; + lds->autodim_ms = dim_ms; + lds->off_ms = off_ms; + lds->bl_lcs = bl_lcs; + lds->state = LWSDISPS_OFF; + + lws_led_transition(lds->bl_lcs, "backlight", &lws_pwmseq_static_off, + &lws_pwmseq_static_on); + + disp->init(disp); } void lws_display_state_set_brightness(lws_display_state_t *lds, - lws_display_brightness target, - lws_display_brightness step) + const lws_led_sequence_def_t *pwmseq) { - lds->bl_target = target; - lds->bl_step = step; - - lws_sul_schedule(lds->ctx, 0, &lds->sul, sul_cb, 1); + lws_led_transition(lds->bl_lcs, "backlight", pwmseq, + lds->disp->bl_transition); } void lws_display_state_active(lws_display_state_t *lds) { - if (lds->state == LWSDISPS_OFF) + int waiting_ms; + + if (lds->state == LWSDISPS_OFF) { + /* power us up */ lds->disp->power(lds->disp, 1); + lds->state = LWSDISPS_BECOMING_ACTIVE; + waiting_ms = lds->disp->latency_wake_ms; + } else { - if (lds->bl_current != lds->bl_active) - lws_display_state_set_brightness(lds, lds->bl_active, 2); + if (lds->state != LWSDISPS_ACTIVE) + lws_display_state_set_brightness(lds, + lds->disp->bl_active); + + lds->state = LWSDISPS_ACTIVE; + waiting_ms = lds->autodim_ms; + } /* reset the autodim timer */ - if (lds->autodim_ms >= 0) + if (waiting_ms >= 0) lws_sul_schedule(lds->ctx, 0, &lds->sul_autodim, sul_autodim_cb, - lds->autodim_ms * LWS_US_PER_MS); + waiting_ms * LWS_US_PER_MS); - lds->state = LWSDISPS_ACTIVE; } void lws_display_state_off(lws_display_state_t *lds) { lds->disp->power(lds->disp, 0); - lws_sul_cancel(&lds->sul); lws_sul_cancel(&lds->sul_autodim); - lds->bl_current = 0; lds->state = LWSDISPS_OFF; } diff --git a/lib/drivers/display/ssd1306-i2c.c b/lib/drivers/display/ssd1306-i2c.c index a050271f..bfcb7558 100644 --- a/lib/drivers/display/ssd1306-i2c.c +++ b/lib/drivers/display/ssd1306-i2c.c @@ -22,7 +22,7 @@ * IN THE SOFTWARE. */ -#include +#include #include @@ -56,18 +56,9 @@ lws_display_ssd1306_i2c_init(const struct lws_display *disp) si->gpio->mode(si->reset_gpio, LWSGGPIO_FL_WRITE | LWSGGPIO_FL_PULLUP); si->gpio->set(si->reset_gpio, 0); - -#if defined(LWS_PLAT_FREERTOS) - vTaskDelay(10); -#else - usleep(10000); -#endif + lws_msleep(1); si->gpio->set(si->reset_gpio, 1); -#if defined(LWS_PLAT_FREERTOS) - vTaskDelay(1); -#else - usleep(1000); -#endif + lws_msleep(1); } if (lws_i2c_command_list(si->i2c, si->i2c7_address, @@ -81,7 +72,7 @@ lws_display_ssd1306_i2c_init(const struct lws_display *disp) } int -lws_display_ssd1306_i2c_brightness(const struct lws_display *disp, uint8_t b) +lws_display_ssd1306_i2c_contrast(const struct lws_display *disp, uint8_t b) { const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; uint8_t ba[2]; diff --git a/lib/drivers/led/README.md b/lib/drivers/led/README.md index 1fef8558..794b10ff 100644 --- a/lib/drivers/led/README.md +++ b/lib/drivers/led/README.md @@ -151,4 +151,5 @@ lws_pwmseq_linear_wipe|single 0 - 100% ramp over 0.3s lws_pwmseq_sine_up|single 0 - 100% using sine curve over 0.3s lws_pwmseq_sine_down|single 100% - 0 using sine curve over 0.3s lws_pwmseq_static_on|100% static +lws_pwmseq_static_half|50% static lws_pwmseq_static_off|0% static diff --git a/lib/drivers/led/led-seq.c b/lib/drivers/led/led-seq.c index 49381d39..2fd2f62b 100644 --- a/lib/drivers/led/led-seq.c +++ b/lib/drivers/led/led-seq.c @@ -59,8 +59,8 @@ lws_seq_advance(lws_led_state_t *lcs, lws_led_state_ch_t *ch) if (!ch->seq) return; - if (ch->phase_budget != -1 && - ch->phase_budget < ch->step) { + if (ch->phase_budget != LWS_SEQ_LEDPHASE_TOTAL_ENDLESS && + (ch->phase_budget < ch->step || !ch->phase_budget)) { /* we are done */ @@ -75,40 +75,42 @@ lws_seq_advance(lws_led_state_t *lcs, lws_led_state_ch_t *ch) } ch->ph += ch->step; - if (ch->phase_budget != -1) + if (ch->phase_budget != LWS_SEQ_LEDPHASE_TOTAL_ENDLESS) ch->phase_budget -= ch->step; } static lws_led_intensity_t lws_seq_sample(const lws_led_gpio_map_t *map, lws_led_state_chs_t *chs) { - unsigned int i = 0, mix, nx; + unsigned int i; - if (chs->seqs[LWS_LED_SEQ_IDX_CURR].seq) - i = chs->seqs[LWS_LED_SEQ_IDX_CURR].seq-> - func(chs->seqs[LWS_LED_SEQ_IDX_CURR].ph); + if (chs->seqs[LLSI_CURR].seq) + chs->seqs[LLSI_CURR].last = chs->seqs[LLSI_CURR].seq-> + func(chs->seqs[LLSI_CURR].ph); - if (chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].seq) { + if (chs->seqs[LLSI_TRANS].seq) { /* * If a transition is ongoing, we need to use the transition * intensity as the mixing factor between the still-live current * and newly-live next sequences */ - mix = chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].seq-> - func(chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].ph); - nx = 0; - if (chs->seqs[LWS_LED_SEQ_IDX_NEXT].seq) - nx = chs->seqs[LWS_LED_SEQ_IDX_NEXT].seq-> - func(chs->seqs[LWS_LED_SEQ_IDX_NEXT].ph); - - i = (lws_led_intensity_t)( - ((i * (65535 - mix) / 65536) + - ((nx * mix) / 65536))); - } - - return map->intensity_correction ? - map->intensity_correction(i) : - cie_antilog((lws_led_intensity_t)i); + chs->seqs[LLSI_TRANS].last = chs->seqs[LLSI_TRANS].seq-> + func(chs->seqs[LLSI_TRANS].ph); + + if (chs->seqs[LLSI_NEXT].seq) + chs->seqs[LLSI_NEXT].last = chs->seqs[LLSI_NEXT].seq-> + func(chs->seqs[LLSI_NEXT].ph); + + i = (lws_led_intensity_t)((( + (unsigned int)chs->seqs[LLSI_CURR].last * + (65535 - chs->seqs[LLSI_TRANS].last) >> 16) + + (((unsigned int)chs->seqs[LLSI_NEXT].last * + (unsigned int)chs->seqs[LLSI_TRANS].last) >> 16))); + } else + i = chs->seqs[LLSI_CURR].last; + + return map->intensity_correction ? map->intensity_correction(i) : + cie_antilog((lws_led_intensity_t)i); } void @@ -121,21 +123,27 @@ lws_seq_timer_handle(lws_led_state_t *lcs) for (n = 0; n < lgc->count_leds; n++) { - lws_seq_advance(lcs, &chs->seqs[LWS_LED_SEQ_IDX_CURR]); + lgc->led_ops.intensity(&lgc->led_ops, map->name, + lws_seq_sample(map, chs)); + + lws_seq_advance(lcs, &chs->seqs[LLSI_CURR]); + + if (chs->seqs[LLSI_TRANS].seq) { + lws_seq_advance(lcs, &chs->seqs[LLSI_NEXT]); + lws_seq_advance(lcs, &chs->seqs[LLSI_TRANS]); - if (chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].seq) { - lws_seq_advance(lcs, &chs->seqs[LWS_LED_SEQ_IDX_NEXT]); - lws_seq_advance(lcs, &chs->seqs[LWS_LED_SEQ_IDX_TRANSITION]); - if (!chs->seqs[LWS_LED_SEQ_IDX_TRANSITION].seq) { - chs->seqs[LWS_LED_SEQ_IDX_CURR] = - chs->seqs[LWS_LED_SEQ_IDX_NEXT]; - chs->seqs[LWS_LED_SEQ_IDX_NEXT].seq = NULL; + /* + * When we finished the transition, we can make the + * "next" sequence the current sequence and no need for + * a "next" or a transition any more. + */ + + if (!chs->seqs[LLSI_TRANS].seq) { + chs->seqs[LLSI_CURR] = chs->seqs[LLSI_NEXT]; + chs->seqs[LLSI_NEXT].seq = NULL; } } - lgc->led_ops.intensity(&lgc->led_ops, map->name, - lws_seq_sample(map, chs)); - map++; chs++; } @@ -162,10 +170,10 @@ lws_led_set_chs_seq(struct lws_led_state *lcs, lws_led_state_ch_t *dest, */ steps = def->ms / LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS; - dest->step = (def->ledphase_total != -1 ? + dest->step = (def->ledphase_total != LWS_SEQ_LEDPHASE_TOTAL_ENDLESS ? def->ledphase_total : LWS_LED_FUNC_PHASE) / (steps ? steps : 1); - if (steps && !lcs->timer_refcount++) { + if (!lcs->timer_refcount++) { #if defined(LWS_PLAT_TIMER_START) LWS_PLAT_TIMER_START(lcs->timer); #endif @@ -181,18 +189,12 @@ lws_led_transition(struct lws_led_state *lcs, const char *name, { lws_led_state_chs_t *chs = (lws_led_state_chs_t *)&lcs[1]; int index = lws_led_gpio_lookup(&lcs->controller->led_ops, name); - const lws_led_gpio_map_t *map; if (index < 0) return 1; - map = &lcs->controller->led_map[index]; - - lws_led_set_chs_seq(lcs, &chs[index].seqs[LWS_LED_SEQ_IDX_TRANSITION], trans); - lws_led_set_chs_seq(lcs, &chs[index].seqs[LWS_LED_SEQ_IDX_NEXT], next); - - lcs->controller->led_ops.intensity(&lcs->controller->led_ops, map->name, - lws_seq_sample(map, chs)); + lws_led_set_chs_seq(lcs, &chs[index].seqs[LLSI_TRANS], trans); + lws_led_set_chs_seq(lcs, &chs[index].seqs[LLSI_NEXT], next); return 0; } diff --git a/lib/drivers/led/private-lib-drivers-led.h b/lib/drivers/led/private-lib-drivers-led.h index 43cfd738..deefe099 100644 --- a/lib/drivers/led/private-lib-drivers-led.h +++ b/lib/drivers/led/private-lib-drivers-led.h @@ -32,25 +32,6 @@ typedef struct lws_led_state int timer_refcount; } lws_led_state_t; -enum { - LWS_LED_SEQ_IDX_CURR, - LWS_LED_SEQ_IDX_NEXT, - LWS_LED_SEQ_IDX_TRANSITION -}; - -typedef struct lws_led_state_ch -{ - const lws_led_sequence_def_t *seq; /* NULL = inactive */ - lws_led_seq_phase_t ph; - lws_led_seq_phase_t step; - int phase_budget; -} lws_led_state_ch_t; - -typedef struct lws_led_state_chs -{ - lws_led_state_ch_t seqs[3]; -} lws_led_state_chs_t; - void lws_seq_timer_handle(lws_led_state_t *lcs); diff --git a/lib/drivers/pwm/pwm.c b/lib/drivers/pwm/pwm.c index 20f95e15..b7f578d4 100644 --- a/lib/drivers/pwm/pwm.c +++ b/lib/drivers/pwm/pwm.c @@ -96,7 +96,7 @@ lws_led_func_linear(lws_led_seq_phase_t n) static lws_led_intensity_t lws_led_func_static(lws_led_seq_phase_t n) { - return n ? LWS_LED_MAX_INTENSITY : 0; + return ((int)n * LWS_LED_MAX_INTENSITY) / 2; } const lws_led_sequence_def_t lws_pwmseq_static_off = { @@ -106,13 +106,20 @@ const lws_led_sequence_def_t lws_pwmseq_static_off = { .ms = 0 }; -const lws_led_sequence_def_t lws_pwmseq_static_on = { +const lws_led_sequence_def_t lws_pwmseq_static_half = { .func = lws_led_func_static, .ledphase_offset = 1, .ledphase_total = 0, .ms = 0 }; +const lws_led_sequence_def_t lws_pwmseq_static_on = { + .func = lws_led_func_static, + .ledphase_offset = 2, + .ledphase_total = 0, + .ms = 0 +}; + const lws_led_sequence_def_t lws_pwmseq_sine_up = { .func = lws_led_func_sine, .ledphase_offset = 0, /* already at 0 amp at 0 phase */ diff --git a/lib/drivers/spi/bitbang/lws-bb-spi.c b/lib/drivers/spi/bitbang/lws-bb-spi.c new file mode 100644 index 00000000..285e53ac --- /dev/null +++ b/lib/drivers/spi/bitbang/lws-bb-spi.c @@ -0,0 +1,126 @@ +/* + * SPI bitbang implementation using generic gpio + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +int +lws_bb_spi_init(const lws_spi_ops_t *octx) +{ + lws_bb_spi_t *ctx = (lws_bb_spi_t *)octx; + int n; + + for (n = 0; n < LWS_SPI_BB_MAX_CH; n++) { + if (ctx->flags & (1 << n)) + ctx->gpio->mode(ctx->ncs[n], LWSGGPIO_FL_WRITE); + if (ctx->flags & (1 << (n + 4))) + ctx->gpio->mode(ctx->ncmd[n], LWSGGPIO_FL_WRITE); + } + + ctx->gpio->mode(ctx->clk, LWSGGPIO_FL_WRITE | + ((octx->bus_mode & LWSSPIMODE_CPOL) ? + 0 : LWSGGPIO_FL_START_LOW)); + ctx->gpio->mode(ctx->mosi, LWSGGPIO_FL_WRITE | LWSGGPIO_FL_START_LOW); + ctx->gpio->mode(ctx->miso, LWSGGPIO_FL_READ | LWSGGPIO_FL_PULLUP); + + return 0; +} + +/* if active, prepare DnC before this and call separately for Cmd / Data */ + +static void +lws_bb_spi_write(lws_bb_spi_t *ctx, const uint8_t *buf, size_t len) +{ + uint8_t u, inv = !!(ctx->bb_ops.bus_mode & LWSSPIMODE_CPOL); + + while (len--) { + int n; + + u = *buf++; + + for (n = 0; n < 4; n++) { + ctx->gpio->set(ctx->clk, inv); + ctx->gpio->set(ctx->mosi, !!(u & 0x80)); + ctx->gpio->set(ctx->clk, !inv); + ctx->gpio->set(ctx->clk, inv); + ctx->gpio->set(ctx->mosi, !!(u & 0x40)); + ctx->gpio->set(ctx->clk, !inv); + u <<= 2; + } + } + + ctx->gpio->set(ctx->clk, 0 ^ inv); +} + +static void +lws_bb_spi_read(lws_bb_spi_t *ctx, uint8_t *buf, size_t len) +{ + uint8_t u, inv = !!(ctx->bb_ops.bus_mode & LWSSPIMODE_CPOL); + + while (len--) { + int n; + + for (n = 0; n < 8; n++) { + ctx->gpio->set(ctx->clk, inv); + u = (u << 1) | !!ctx->gpio->read(ctx->miso); + ctx->gpio->set(ctx->mosi, !!(u & 0x80)); + ctx->gpio->set(ctx->clk, !inv); + } + *buf++ = u; + } + + ctx->gpio->set(ctx->clk, 0 ^ inv); +} + +int +lws_bb_spi_queue(const lws_spi_ops_t *octx, const lws_spi_desc_t *desc) +{ + lws_bb_spi_t *ctx = (lws_bb_spi_t *)octx; + const uint8_t *src = desc->src; + + /* clock to idle */ + ctx->gpio->set(ctx->clk, 0 ^ !!(octx->bus_mode & LWSSPIMODE_CPOL)); + /* enable nCS */ + ctx->gpio->set(ctx->ncs[desc->channel], 0); + + if (desc->count_cmd) { + ctx->gpio->set(ctx->ncmd[desc->channel], 0); + lws_bb_spi_write(ctx, src, desc->count_cmd); + ctx->gpio->set(ctx->ncmd[desc->channel], 1); + + src += desc->count_cmd; + } + + if (desc->count_write) + lws_bb_spi_write(ctx, desc->data, desc->count_write); + + if (desc->count_read) + lws_bb_spi_read(ctx, desc->dest, desc->count_read); + + /* disable nCS */ + ctx->gpio->set(ctx->ncs[desc->channel], 1); + + /* clock to idle */ + ctx->gpio->set(ctx->clk, 0 ^ !!(octx->bus_mode & LWSSPIMODE_CPOL)); + + return 0; +} diff --git a/lib/drivers/spi/lws-spi.c b/lib/drivers/spi/lws-spi.c new file mode 100644 index 00000000..2d41ecf2 --- /dev/null +++ b/lib/drivers/spi/lws-spi.c @@ -0,0 +1,26 @@ +/* + * Generic SPI + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + diff --git a/lib/plat/freertos/esp32/drivers/pwm-esp32.c b/lib/plat/freertos/esp32/drivers/pwm-esp32.c index e65d1520..a13e10b3 100644 --- a/lib/plat/freertos/esp32/drivers/pwm-esp32.c +++ b/lib/plat/freertos/esp32/drivers/pwm-esp32.c @@ -66,6 +66,8 @@ lws_pwm_plat_intensity(const struct lws_pwm_ops *lo, _lws_plat_gpio_t gpio, for (n = 0; n < lo->count_pwm_map; n++) { if (lo->pwm_map[n].gpio == gpio) { + if (!lo->pwm_map[n].active_level) + inten = 65535 - inten; ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0 + lo->pwm_map[n].index, inten >> 3); ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0 + diff --git a/lib/plat/freertos/freertos-misc.c b/lib/plat/freertos/freertos-misc.c index d0c9634a..62bc0348 100644 --- a/lib/plat/freertos/freertos-misc.c +++ b/lib/plat/freertos/freertos-misc.c @@ -24,6 +24,18 @@ #include "private-lib-core.h" +/* + * Normally you don't want this, use lws_sul instead inside the event loop. + * But sometimes for drivers it makes sense, so there's an internal-only + * crossplatform api for it. + */ + +void +lws_msleep(unsigned int ms) +{ + vTaskDelay(portTICK_PERIOD_MS > ms ? 1 : ms / portTICK_PERIOD_MS); +} + lws_usec_t lws_now_usecs(void) { diff --git a/lib/plat/optee/lws-plat-optee.c b/lib/plat/optee/lws-plat-optee.c index 08c60c3c..6171fafd 100644 --- a/lib/plat/optee/lws-plat-optee.c +++ b/lib/plat/optee/lws-plat-optee.c @@ -252,3 +252,10 @@ lws_plat_ntpclient_config(struct lws_context *context) #endif return 0; } + +void +lws_msleep(unsigned int ms) +{ +} + + diff --git a/lib/plat/unix/unix-misc.c b/lib/plat/unix/unix-misc.c index a172fff0..ef8a9af1 100644 --- a/lib/plat/unix/unix-misc.c +++ b/lib/plat/unix/unix-misc.c @@ -27,6 +27,18 @@ #endif #include "private-lib-core.h" +/* + * Normally you don't want this, use lws_sul instead inside the event loop. + * But sometimes for drivers it makes sense, so there's an internal-only + * crossplatform api for it. + */ + +void +lws_msleep(unsigned int ms) +{ + usleep(ms * LWS_US_PER_MS); +} + lws_usec_t lws_now_usecs(void) { diff --git a/lib/plat/windows/windows-misc.c b/lib/plat/windows/windows-misc.c index e5dae442..02008c6b 100644 --- a/lib/plat/windows/windows-misc.c +++ b/lib/plat/windows/windows-misc.c @@ -27,6 +27,17 @@ #endif #include "private-lib-core.h" +/* + * Normally you don't want this, use lws_sul instead inside the event loop. + * But sometimes for drivers it makes sense, so there's an internal-only + * crossplatform api for it. + */ + +void +lws_msleep(unsigned int ms) +{ + Sleep(ms); +} lws_usec_t lws_now_usecs(void) diff --git a/minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/CMakeLists.txt rename to minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt diff --git a/minimal-examples/embedded/lws-minimal-esp32/banded-img.h b/minimal-examples/embedded/esp32/esp-heltec-wb32/banded-img.h similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/banded-img.h rename to minimal-examples/embedded/esp32/esp-heltec-wb32/banded-img.h diff --git a/minimal-examples/embedded/lws-minimal-esp32/main/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/main/CMakeLists.txt rename to minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt diff --git a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c similarity index 94% rename from minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c rename to minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c index 4cc8f864..77221693 100644 --- a/minimal-examples/embedded/lws-minimal-esp32/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c @@ -49,18 +49,6 @@ static const lws_bb_i2c_t li2c = { .delay = esp32_i2c_delay }; -static const lws_display_ssd1306_t disp = { - .disp = { - lws_display_ssd1306_ops, - .w = 128, - .h = 64 - }, - .i2c = (lws_i2c_ops_t *)&li2c, - .gpio = &lws_gpio_plat, - .reset_gpio = GPIO_NUM_16, - .i2c7_address = SSD1306_I2C7_ADS1 -}; - /* * Button controller */ @@ -85,7 +73,7 @@ static const lws_button_controller_t bc = { */ static const lws_pwm_map_t pwm_map[] = { - { .gpio = GPIO_NUM_25, .index = 0 } + { .gpio = GPIO_NUM_25, .index = 0, .active_level = 1 } }; static const lws_pwm_ops_t pwm_ops = { @@ -94,6 +82,18 @@ static const lws_pwm_ops_t pwm_ops = { .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) }; +static const lws_display_ssd1306_t disp = { + .disp = { + lws_display_ssd1306_ops, + .w = 128, + .h = 64 + }, + .i2c = (lws_i2c_ops_t *)&li2c, + .gpio = &lws_gpio_plat, + .reset_gpio = GPIO_NUM_16, + .i2c7_address = SSD1306_I2C7_ADS1 +}; + /* * led controller */ @@ -184,6 +184,7 @@ app_main(void) info.port = CONTEXT_PORT_NO_LISTEN; info.early_smd_cb = smd_cb; info.early_smd_class_filter = LWSSMDCL_INTERACTION; + context = lws_create_context(&info); if (!context) { lwsl_err("lws init failed\n"); @@ -199,8 +200,6 @@ app_main(void) /* pwm init must go after the led controller init */ pwm_ops.init(&pwm_ops); - lgc.led_ops.intensity(&lgc.led_ops, "alert", 0); -// lws_led_transition(lls, 0, &lws_pwmseq_sine_endless, NULL); bcs = lws_button_controller_create(context, &bc); if (!bcs) { @@ -212,12 +211,13 @@ app_main(void) * Show the lws logo on the display */ - lws_display_state_init(&lds, context, 10000, 20000, 200, 10, &disp.disp); - lws_display_state_active(&lds); + lws_display_state_init(&lds, context, 10000, 20000, lls, &disp.disp); disp.disp.blit(lds.disp, img, 0, 0, 128, 64); + lws_display_state_active(&lds); lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); - lgc.led_ops.intensity(&lgc.led_ops, "alert", 0); + lws_led_transition(lls, "alert", &lws_pwmseq_static_off, + &lws_pwmseq_static_on); /* * We say the test succeeded if we survive 3s around the event loop diff --git a/minimal-examples/embedded/lws-minimal-esp32/scan/output.bmp b/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/output.bmp similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/scan/output.bmp rename to minimal-examples/embedded/esp32/esp-heltec-wb32/scan/output.bmp diff --git a/minimal-examples/embedded/lws-minimal-esp32/scan/pic.h b/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/scan/pic.h rename to minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h diff --git a/minimal-examples/embedded/lws-minimal-esp32/scan/pic.h.1 b/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h.1 similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/scan/pic.h.1 rename to minimal-examples/embedded/esp32/esp-heltec-wb32/scan/pic.h.1 diff --git a/minimal-examples/embedded/lws-minimal-esp32/scan/scan b/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/scan/scan rename to minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan diff --git a/minimal-examples/embedded/lws-minimal-esp32/scan/scan.c b/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.c similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/scan/scan.c rename to minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.c diff --git a/minimal-examples/embedded/lws-minimal-esp32/scan/scan.sh b/minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.sh similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/scan/scan.sh rename to minimal-examples/embedded/esp32/esp-heltec-wb32/scan/scan.sh diff --git a/minimal-examples/embedded/lws-minimal-esp32/sdkconfig b/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/sdkconfig rename to minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig diff --git a/minimal-examples/embedded/lws-minimal-esp32/sdkconfig.h b/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h similarity index 100% rename from minimal-examples/embedded/lws-minimal-esp32/sdkconfig.h rename to minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt new file mode 100644 index 00000000..e17a99ca --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.5) + +if (ESP_PLATFORM) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) + project(lws-minimal-esp32) + enable_testing() + + target_link_libraries(lws-minimal-esp32.elf websockets) + + option(LWS_WITH_DRIVERS "With generic drivers for gpio, i2c, display etc" ON) + set(LWS_WITH_DRIVERS ON) + + add_subdirectory(libwebsockets) + + add_test(NAME flashing COMMAND idf.py flash) + set_tests_properties(flashing PROPERTIES + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + TIMEOUT 120) + + add_test(NAME boot COMMAND /usr/local/bin/sai-expect) + set_tests_properties(boot PROPERTIES + DEPENDS flashing + TIMEOUT 20) + +endif() diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt new file mode 100644 index 00000000..c38b4767 --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt @@ -0,0 +1,6 @@ +idf_component_register(SRCS + "lws-minimal-esp32.c" + INCLUDE_DIRS "../libwebsockets/include;${IDF_PATH}/components/spi_flash/include;${IDF_PATH}/components/nvs_flash/include;${IDF_PATH}/components/mdns/include") + +target_link_libraries(${COMPONENT_LIB} websockets) +include_directories(../build/libwebsockets) diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/cat-565.h b/minimal-examples/embedded/esp32/esp-wrover-kit/main/cat-565.h new file mode 100644 index 00000000..46eaefbb --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/cat-565.h @@ -0,0 +1,19200 @@ +0x62, 0xEB, 0x5A, 0xAA, 0x52, 0x8A, 0x52, 0x69, +0x5A, 0xAA, 0x62, 0xEB, 0x73, 0x0C, 0x72, 0xEB, +0x52, 0x08, 0x31, 0x24, 0x4A, 0x08, 0x4A, 0x07, +0x41, 0xE7, 0x39, 0xC6, 0x39, 0xC6, 0x31, 0x85, +0x29, 0x44, 0x21, 0x24, 0x31, 0x85, 0x41, 0xE7, +0x41, 0xE7, 0x39, 0x85, 0x41, 0xA6, 0x39, 0x45, +0x31, 0x24, 0x29, 0x04, 0x20, 0xC3, 0x28, 0xC3, +0x28, 0xC2, 0x28, 0xC2, 0x31, 0x04, 0x49, 0xA6, +0x5A, 0x27, 0x62, 0x48, 0x62, 0x48, 0x52, 0x27, +0x39, 0x86, 0x20, 0xE3, 0x29, 0x24, 0x41, 0xE8, +0x39, 0xA6, 0x4A, 0x48, 0x4A, 0x49, 0x39, 0xC7, +0x31, 0x65, 0x29, 0x24, 0x6B, 0x2C, 0x4A, 0x29, +0x52, 0x69, 0x84, 0x10, 0x63, 0x0B, 0x52, 0x6A, +0x62, 0xEB, 0x4A, 0x08, 0x6B, 0x0C, 0x6B, 0x2C, +0x5A, 0xAB, 0x39, 0xC7, 0x31, 0x86, 0x73, 0xAF, +0xDE, 0xFD, 0xDE, 0xDC, 0xBD, 0xF8, 0x94, 0x92, +0x4A, 0x28, 0x29, 0x44, 0x39, 0xE6, 0x4A, 0x48, +0x6B, 0x2C, 0x52, 0x8A, 0x73, 0x6D, 0x6B, 0x4D, +0x52, 0x69, 0x52, 0x69, 0x84, 0x10, 0xAD, 0x14, +0xBD, 0xB6, 0xC5, 0xF6, 0xC5, 0xB4, 0xA4, 0xAF, +0xA4, 0xAE, 0xA4, 0x8E, 0xA4, 0xAF, 0xB5, 0x10, +0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x51, 0xBD, 0x51, +0xBD, 0x51, 0xBD, 0x52, 0xBD, 0x72, 0xBD, 0x72, +0xB5, 0x31, 0xAC, 0xF0, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, +0xAD, 0x11, 0xAD, 0x10, 0xB5, 0x10, 0xC5, 0x92, +0xC5, 0x51, 0xAC, 0xD0, 0x9C, 0x8E, 0x9C, 0x6E, +0x94, 0x2E, 0x8B, 0xED, 0x7B, 0xAC, 0x7B, 0x8C, +0x7B, 0x8C, 0x83, 0xAC, 0x8C, 0x0D, 0x94, 0x4D, +0xB5, 0x10, 0x94, 0x0D, 0x83, 0xCC, 0x7B, 0x8B, +0x73, 0x6B, 0x84, 0x0E, 0x94, 0x6F, 0x83, 0xCD, +0x7B, 0xAD, 0x7B, 0xCD, 0x8C, 0x2F, 0x8C, 0x2F, +0xDE, 0xB8, 0xDE, 0xD9, 0xC6, 0x16, 0x9C, 0xB0, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x52, +0xAD, 0x52, 0xB5, 0x93, 0xCE, 0x35, 0xA4, 0xAF, +0xAC, 0xCF, 0xBD, 0x93, 0x8C, 0x4F, 0x8C, 0x4F, +0x73, 0xAD, 0x7B, 0xAF, 0x4A, 0x29, 0x52, 0x8A, +0x6B, 0x4D, 0x73, 0xAE, 0x7B, 0xCE, 0x9C, 0xB1, +0xA5, 0x33, 0x94, 0xB1, 0x8C, 0x70, 0x94, 0x90, +0x84, 0x2F, 0x8C, 0x4F, 0x84, 0x2F, 0x6B, 0x6D, +0x84, 0x2F, 0x8C, 0x4F, 0x84, 0x0E, 0x8C, 0x70, +0x9C, 0xF2, 0xBD, 0x94, 0xAD, 0x53, 0xAD, 0x12, +0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x53, 0xC5, 0xF6, +0xB5, 0xB4, 0xAD, 0x33, 0xAD, 0x33, 0xA5, 0x32, +0xB5, 0x73, 0x9C, 0xF1, 0xAD, 0x33, 0xBD, 0xD5, +0xAD, 0x53, 0xB5, 0x94, 0xB5, 0x74, 0xB5, 0x94, +0xB5, 0x53, 0xBD, 0xB5, 0xA5, 0x12, 0x7B, 0xAD, +0xAD, 0x32, 0x9C, 0xB0, 0xAD, 0x53, 0xA5, 0x11, +0x9C, 0xB0, 0xAD, 0x32, 0xA4, 0xF1, 0xA5, 0x12, +0x94, 0x4F, 0x83, 0xEE, 0x83, 0xED, 0x8C, 0x2E, +0x94, 0x4F, 0x94, 0x8F, 0x94, 0x6F, 0x94, 0x6F, +0x94, 0x4F, 0xA5, 0x11, 0xAD, 0x31, 0xAD, 0x32, +0xB5, 0x52, 0xA4, 0xF0, 0xAD, 0x31, 0xB5, 0x51, +0xAD, 0x31, 0xAD, 0x31, 0xAD, 0x11, 0xAC, 0xF1, +0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x52, 0xBD, 0xB3, +0xAD, 0x32, 0xAC, 0xF1, 0xD5, 0xB3, 0xD5, 0x72, +0xCD, 0x71, 0xBD, 0x10, 0xB5, 0x10, 0xB5, 0x11, +0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xD0, +0xAC, 0xD0, 0xBD, 0x52, 0xC5, 0xB3, 0xC5, 0x92, +0xCD, 0xF3, 0xCD, 0xF3, 0xC5, 0x92, 0xC5, 0xB3, +0xBD, 0x72, 0xC5, 0xB3, 0xC5, 0xB3, 0xAC, 0xF0, +0xB5, 0x52, 0xB5, 0x53, 0xB5, 0x52, 0xD6, 0x35, +0xCD, 0xD3, 0xBD, 0x72, 0xCD, 0xB3, 0xCD, 0xD4, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x73, 0xB5, 0x73, +0xA4, 0xF1, 0xA4, 0xF2, 0x94, 0x70, 0xA4, 0xF1, +0xA4, 0xF2, 0x94, 0x90, 0x94, 0x71, 0x8C, 0x70, +0x9C, 0xD2, 0xA5, 0x13, 0xA4, 0xF3, 0x8C, 0x50, +0x8C, 0x50, 0x8C, 0x30, 0x7B, 0xCF, 0x6B, 0x4D, +0x4A, 0x6A, 0x29, 0x66, 0x21, 0x25, 0x21, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x29, 0x66, 0x4A, 0x6A, +0x6B, 0x6E, 0x8C, 0x51, 0xA4, 0xF4, 0xA5, 0x14, +0xA5, 0x35, 0xA5, 0x14, 0x9C, 0xD3, 0x8C, 0x51, +0x7B, 0xEF, 0x7B, 0xAE, 0x84, 0x10, 0x84, 0x10, +0x6B, 0x2C, 0x7B, 0xAE, 0x84, 0x10, 0x84, 0x32, +0x7C, 0x12, 0x73, 0xD1, 0x7C, 0x12, 0x8C, 0x94, +0x94, 0xD5, 0x8C, 0xB5, 0x94, 0xD5, 0x94, 0xD5, +0x94, 0xD5, 0x94, 0xF5, 0x8C, 0xD5, 0x94, 0xD5, +0x95, 0x16, 0x94, 0xD5, 0x84, 0x73, 0x84, 0x32, +0x84, 0x32, 0x73, 0xD0, 0x7B, 0xD0, 0x84, 0x31, +0x7B, 0xF0, 0x73, 0xAF, 0x73, 0x8F, 0x6B, 0x4E, +0x4A, 0x28, 0x42, 0x07, 0x4A, 0x07, 0x41, 0xE7, +0x4A, 0x08, 0x41, 0xE7, 0x73, 0x4C, 0x7B, 0x4C, +0x31, 0x45, 0x29, 0x03, 0x41, 0xE6, 0x39, 0xA6, +0x39, 0xA6, 0x31, 0x85, 0x39, 0xC6, 0x42, 0x07, +0x39, 0xE7, 0x29, 0x64, 0x31, 0x85, 0x21, 0x03, +0x29, 0x04, 0x31, 0x65, 0x42, 0x07, 0x29, 0x24, +0x31, 0x45, 0x20, 0xC3, 0x28, 0xE3, 0x39, 0x85, +0x5A, 0x28, 0x72, 0xCA, 0x8B, 0x4C, 0x8B, 0x4B, +0xB4, 0x4F, 0xC4, 0xF1, 0xC4, 0xD1, 0xCD, 0x12, +0xB4, 0xB1, 0xA4, 0x71, 0xA4, 0xB2, 0x52, 0x69, +0x18, 0xE3, 0x18, 0xE3, 0x10, 0xA2, 0x18, 0xC3, +0x29, 0x24, 0x41, 0xE7, 0x63, 0x0C, 0x21, 0x24, +0x39, 0xA7, 0x6B, 0x4D, 0x5A, 0xCB, 0x52, 0x69, +0x5A, 0xAA, 0x4A, 0x28, 0x4A, 0x49, 0x42, 0x07, +0x41, 0xE7, 0x39, 0xA6, 0x6B, 0x6D, 0xDE, 0xFD, +0xDE, 0xFD, 0xC6, 0x3A, 0xA4, 0xF4, 0x52, 0x6A, +0x29, 0x45, 0x31, 0x85, 0x52, 0x89, 0x63, 0x2C, +0x6B, 0x2C, 0x31, 0x66, 0x42, 0x28, 0x63, 0x0B, +0x4A, 0x69, 0x39, 0xC7, 0x8C, 0x31, 0xA4, 0xF4, +0xCE, 0x18, 0xD6, 0x38, 0xE6, 0xDA, 0xC5, 0x94, +0x9C, 0x6F, 0x94, 0x4F, 0x9C, 0x6F, 0xA4, 0xD0, +0xBD, 0x92, 0xBD, 0x72, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0x94, 0x0D, 0x94, 0x2D, +0xA4, 0xAF, 0xB5, 0x10, 0xAC, 0xF0, 0x83, 0xAB, +0x94, 0x0C, 0x94, 0x2D, 0x94, 0x2D, 0x9C, 0x4E, +0x9C, 0x6E, 0x9C, 0x6E, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xCF, 0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x30, +0xB5, 0x10, 0xB5, 0x11, 0xAC, 0xF0, 0xB5, 0x11, +0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x11, 0xB4, 0xEF, +0xB5, 0x0F, 0xAC, 0xCF, 0xB4, 0xF0, 0xB5, 0x10, +0xBD, 0x11, 0xB5, 0x31, 0xBD, 0x51, 0xB5, 0x30, +0xB5, 0x10, 0xB5, 0x10, 0xAD, 0x11, 0xA4, 0xD0, +0xA4, 0x8F, 0xA4, 0xAF, 0xA4, 0xCF, 0x9C, 0x8E, +0x9C, 0x6E, 0xA4, 0xAF, 0x9C, 0x8E, 0x94, 0x2D, +0x9C, 0xAF, 0xB5, 0x72, 0x9C, 0x6E, 0xAC, 0xEF, +0xA4, 0xCF, 0xB5, 0x31, 0x9C, 0xAF, 0x8C, 0x2E, +0x6B, 0x0B, 0x41, 0xE7, 0x20, 0xE4, 0x4A, 0x49, +0x73, 0x8E, 0x6B, 0x2C, 0x63, 0x2B, 0x9C, 0xF1, +0xCE, 0x56, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0xB4, +0xB5, 0xB4, 0xAD, 0x32, 0xA5, 0x12, 0x94, 0x70, +0xBD, 0xB4, 0xB5, 0x73, 0x94, 0x90, 0x84, 0x2F, +0xA4, 0xF2, 0xC5, 0xF5, 0xB5, 0x94, 0xB5, 0x94, +0xDE, 0xB8, 0xD6, 0x98, 0xC6, 0x16, 0xAD, 0x32, +0xCE, 0x37, 0xB5, 0xB4, 0xC6, 0x16, 0xC6, 0x37, +0xAD, 0x53, 0xA5, 0x33, 0xA5, 0x33, 0xB5, 0x94, +0xB5, 0x94, 0xC5, 0xF6, 0xC6, 0x16, 0xC6, 0x37, +0xC6, 0x16, 0xBD, 0xD5, 0xA4, 0xF2, 0x7B, 0xAC, +0xAD, 0x12, 0xAD, 0x33, 0x9C, 0x90, 0x9C, 0x90, +0x94, 0x4F, 0x94, 0x6F, 0xA4, 0xD0, 0xA5, 0x11, +0x94, 0x4F, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x52, +0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0x90, +0x8C, 0x4E, 0x9C, 0xB0, 0xA4, 0xD0, 0xA4, 0xF0, +0xA4, 0xCF, 0x9C, 0xAF, 0xA4, 0xF0, 0xAD, 0x31, +0xB5, 0x51, 0xAD, 0x31, 0xA5, 0x11, 0xA4, 0xF0, +0xA5, 0x11, 0xAD, 0x11, 0xBD, 0x93, 0xAD, 0x31, +0xAD, 0x32, 0xAD, 0x11, 0xDD, 0xF4, 0xDD, 0xB3, +0xCD, 0x71, 0xC5, 0x30, 0xBD, 0x51, 0xC5, 0x72, +0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x11, 0xAD, 0x10, +0x9C, 0x8F, 0xAC, 0xF0, 0xB5, 0x11, 0xB5, 0x31, +0xBD, 0x72, 0xC5, 0x92, 0xBD, 0x72, 0xC5, 0xB2, +0xC5, 0x92, 0xC5, 0xB3, 0xB5, 0x31, 0xB5, 0x72, +0xB5, 0x52, 0xBD, 0x73, 0xCD, 0xD4, 0xDE, 0x55, +0xCD, 0xD3, 0xBD, 0x71, 0xC5, 0x92, 0xCD, 0xB3, +0xCD, 0xD3, 0xDE, 0x35, 0xDE, 0x55, 0xDE, 0x55, +0xCD, 0xF4, 0xB5, 0x32, 0xA4, 0xD0, 0xAD, 0x12, +0xBD, 0x73, 0xC5, 0xD4, 0xCE, 0x16, 0xC5, 0xD6, +0x94, 0x70, 0x8C, 0x50, 0x94, 0xB2, 0x8C, 0x50, +0xAD, 0x33, 0xA5, 0x33, 0xA5, 0x13, 0x9C, 0xD2, +0x9C, 0xB2, 0x8C, 0x50, 0x6B, 0x4D, 0x4A, 0x6A, +0x39, 0xE7, 0x29, 0x86, 0x29, 0x45, 0x19, 0x04, +0x18, 0xE4, 0x29, 0x45, 0x42, 0x08, 0x4A, 0x49, +0x5A, 0xEC, 0x73, 0xAF, 0x8C, 0x52, 0x94, 0xB3, +0x9C, 0xD4, 0xB5, 0xB7, 0x9C, 0xD3, 0x9D, 0x14, +0x9C, 0xB3, 0x94, 0x72, 0x94, 0x92, 0x9C, 0xD4, +0xA5, 0x36, 0xAD, 0x76, 0xA5, 0x56, 0x9C, 0xF5, +0x8C, 0x93, 0x84, 0x32, 0x7C, 0x12, 0x7B, 0xF1, +0x73, 0xB0, 0x73, 0xD1, 0x7C, 0x12, 0x84, 0x53, +0x8C, 0x94, 0x84, 0x73, 0x7C, 0x12, 0x73, 0xB0, +0x6B, 0x8F, 0x5A, 0xED, 0x52, 0xCC, 0x52, 0xAC, +0x4A, 0x6B, 0x39, 0xE8, 0x31, 0xA7, 0x29, 0x87, +0x31, 0x65, 0x39, 0xA5, 0x39, 0xA5, 0x39, 0x85, +0x31, 0x85, 0x31, 0x65, 0x94, 0x51, 0xD6, 0x38, +0x83, 0xAE, 0x29, 0x44, 0x31, 0x65, 0x31, 0x65, +0x31, 0x85, 0x31, 0x85, 0x31, 0xA6, 0x39, 0xA6, +0x39, 0xA6, 0x21, 0x03, 0x21, 0x24, 0x21, 0x24, +0x73, 0xAE, 0xAD, 0x55, 0xAD, 0x75, 0xA5, 0x14, +0x8C, 0x51, 0x42, 0x07, 0x41, 0xC7, 0x62, 0x8A, +0x8B, 0x4C, 0x93, 0x6C, 0x9B, 0xAD, 0x72, 0x68, +0x82, 0xEA, 0xC4, 0xD0, 0xBC, 0x70, 0x93, 0x6C, +0x9C, 0x0F, 0xA4, 0x51, 0x6A, 0xCA, 0x20, 0xC2, +0x18, 0xC3, 0x18, 0xC3, 0x18, 0xE3, 0x18, 0xE3, +0x18, 0xC3, 0x29, 0x65, 0x42, 0x07, 0x29, 0x24, +0x29, 0x24, 0x4A, 0x69, 0x5A, 0xCA, 0x42, 0x07, +0x42, 0x08, 0x41, 0xE7, 0x39, 0xC6, 0x31, 0xA6, +0x31, 0xA6, 0x39, 0xA6, 0x8C, 0x72, 0xE7, 0x1D, +0xD6, 0x9B, 0xC6, 0x19, 0x7B, 0xD0, 0x31, 0x86, +0x42, 0x07, 0x4A, 0x48, 0x4A, 0x69, 0x4A, 0x28, +0x63, 0x0B, 0x31, 0x65, 0x31, 0xA6, 0x52, 0x8A, +0x42, 0x28, 0x42, 0x08, 0x5A, 0xCB, 0x8C, 0x10, +0xB5, 0x55, 0xBD, 0x96, 0xE6, 0xBA, 0xCD, 0xF7, +0x7B, 0x8D, 0x83, 0xEE, 0x63, 0x0A, 0x8C, 0x4F, +0xAD, 0x11, 0xAD, 0x51, 0x9C, 0x8F, 0xB5, 0x72, +0xBD, 0xB3, 0x94, 0x4F, 0x73, 0x8D, 0x84, 0x0F, +0x8C, 0x6F, 0x94, 0x6F, 0xA4, 0xF0, 0x7B, 0xAB, +0x9C, 0x8F, 0x94, 0x8F, 0x94, 0x6E, 0x94, 0x4E, +0x83, 0xEC, 0x83, 0xCC, 0x83, 0xCB, 0x83, 0xCC, +0x7B, 0x8B, 0x7B, 0x8A, 0x83, 0xCB, 0x83, 0x8B, +0x83, 0xAB, 0x83, 0xCB, 0x9C, 0x6E, 0xA4, 0x8E, +0x94, 0x2D, 0x7B, 0x8B, 0x73, 0x2A, 0x94, 0x2D, +0xAD, 0x10, 0xD6, 0x55, 0xD6, 0x55, 0xD6, 0x14, +0xD6, 0x14, 0xD5, 0xF4, 0xC5, 0x92, 0xB5, 0x30, +0xB5, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, 0xAC, 0xAF, +0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x51, +0xB5, 0x30, 0xB5, 0x10, 0xC5, 0x71, 0xBD, 0x31, +0xBD, 0x30, 0xB5, 0x10, 0xBD, 0x30, 0xBD, 0x50, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xF0, +0xAC, 0xD0, 0xA4, 0xF0, 0x73, 0x4B, 0x63, 0x2D, +0x84, 0x10, 0x73, 0x8E, 0x7B, 0xAD, 0x9C, 0xB0, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x6F, 0x94, 0x4E, +0x94, 0x6E, 0x83, 0xCC, 0x83, 0xED, 0x83, 0xED, +0x8C, 0x4E, 0x8C, 0x2E, 0x73, 0x6C, 0x6B, 0x4B, +0x9C, 0xB1, 0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0xB1, +0xBD, 0xB4, 0xB5, 0x73, 0xA5, 0x12, 0x83, 0xEE, +0xBD, 0xD5, 0xC5, 0xF5, 0xB5, 0x94, 0xA4, 0xF1, +0xA5, 0x12, 0xA4, 0xF2, 0xAD, 0x53, 0xC6, 0x16, +0xC6, 0x16, 0xCE, 0x36, 0xCE, 0x57, 0xC5, 0xF6, +0xC5, 0xF5, 0xCE, 0x57, 0x9C, 0xD1, 0x8C, 0x0E, +0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x12, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, +0x83, 0xED, 0xAD, 0x32, 0xAD, 0x52, 0xA5, 0x12, +0x9C, 0xD1, 0x9C, 0xB0, 0x94, 0x8F, 0xA4, 0xF1, +0x94, 0x8F, 0xAD, 0x32, 0xB5, 0x72, 0xA4, 0xF0, +0xAD, 0x31, 0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x51, +0xA4, 0xF0, 0xA5, 0x10, 0x9C, 0xAF, 0x94, 0x6E, +0x8C, 0x2D, 0x8C, 0x0D, 0x94, 0x4E, 0x83, 0xAB, +0xB5, 0x53, 0xB5, 0x52, 0xDD, 0xD3, 0xDD, 0xF3, +0xD5, 0xB3, 0xCD, 0x92, 0xC5, 0x72, 0xC5, 0x93, +0xBD, 0x52, 0xBD, 0x52, 0xB5, 0x31, 0xAD, 0x10, +0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xB5, 0x31, 0xC5, 0x92, 0xB5, 0x31, 0xBD, 0x72, +0xBD, 0x51, 0xC5, 0xB3, 0xC5, 0x93, 0xC5, 0xD4, +0xC5, 0xB3, 0xBD, 0x72, 0xDE, 0x55, 0xD5, 0xF3, +0xD5, 0xF4, 0xC5, 0x92, 0xC5, 0x92, 0xCD, 0x92, +0xC5, 0x92, 0xD6, 0x14, 0xD6, 0x14, 0xDE, 0x34, +0xD6, 0x14, 0xC5, 0x93, 0xB5, 0x10, 0xAC, 0xF1, +0xB5, 0x32, 0xCD, 0xF5, 0xBD, 0xB4, 0xD6, 0x57, +0xD6, 0x78, 0xBD, 0xB5, 0xAD, 0x53, 0x7B, 0xCE, +0x84, 0x2F, 0xA4, 0xF3, 0xAD, 0x54, 0x94, 0x91, +0x83, 0xEF, 0x8C, 0x50, 0x94, 0x91, 0x9C, 0xB2, +0x8C, 0x50, 0x7B, 0xEF, 0x73, 0x6D, 0x5A, 0xEB, +0x31, 0x86, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x21, 0x05, 0x29, 0x46, 0x29, 0x87, 0x3A, 0x08, +0x63, 0x0D, 0x84, 0x31, 0x73, 0x8F, 0x63, 0x4D, +0x6B, 0x6E, 0x73, 0xAF, 0x73, 0x8F, 0x73, 0x8F, +0x73, 0x6E, 0x73, 0x8E, 0x6B, 0x4D, 0x73, 0xAF, +0x9C, 0xD4, 0x9D, 0x15, 0x9D, 0x15, 0x9C, 0xF5, +0x9C, 0xF4, 0x9C, 0xF4, 0x9D, 0x15, 0x9D, 0x15, +0x9C, 0xD5, 0x9D, 0x15, 0xA5, 0x56, 0xAD, 0x97, +0xB5, 0xB8, 0xB5, 0xD9, 0xB5, 0xB8, 0xA5, 0x56, +0x94, 0xD4, 0x84, 0x53, 0x84, 0x32, 0x7B, 0xF1, +0x52, 0xAA, 0x52, 0xCB, 0x52, 0xCA, 0x4A, 0x49, +0x29, 0x24, 0x31, 0x86, 0x7B, 0xCE, 0xCD, 0xF7, +0xA4, 0x71, 0x39, 0x85, 0x21, 0x04, 0x39, 0xC6, +0x29, 0x65, 0x21, 0x24, 0x29, 0x44, 0x39, 0xC6, +0x4A, 0x48, 0x31, 0xA6, 0x31, 0x86, 0x4A, 0x48, +0x7B, 0xAE, 0x9C, 0xB2, 0x94, 0x71, 0x9C, 0xB2, +0x6B, 0x0B, 0x29, 0x03, 0x29, 0x44, 0x62, 0x89, +0x93, 0x6C, 0x83, 0x0A, 0x93, 0x4B, 0x83, 0x0A, +0x41, 0x64, 0x62, 0x89, 0x6A, 0x89, 0x52, 0x48, +0x62, 0xCA, 0x41, 0xE7, 0x5A, 0xCA, 0x4A, 0x28, +0x21, 0x24, 0x29, 0x65, 0x21, 0x24, 0x21, 0x24, +0x21, 0x24, 0x18, 0xC3, 0x18, 0xE3, 0x29, 0x45, +0x21, 0x04, 0x29, 0x44, 0x39, 0xE7, 0x39, 0xC6, +0x39, 0xC6, 0x31, 0xA6, 0x31, 0x85, 0x29, 0x85, +0x31, 0x85, 0x31, 0xC6, 0xB5, 0xD7, 0xE7, 0x5E, +0xD6, 0xBC, 0xB5, 0x77, 0x5A, 0xCB, 0x52, 0x8A, +0x42, 0x28, 0x31, 0x85, 0x42, 0x07, 0x39, 0xE7, +0x5A, 0xEB, 0x39, 0xC7, 0x31, 0x86, 0x39, 0xE7, +0x42, 0x28, 0x63, 0x0C, 0x62, 0xCB, 0x7B, 0xAE, +0xA4, 0xB2, 0xA4, 0xB2, 0xBD, 0x75, 0xDE, 0x79, +0xC5, 0xF7, 0x7B, 0x8D, 0x8C, 0x50, 0xBD, 0xB6, +0x4A, 0x28, 0x84, 0x0E, 0xCE, 0x36, 0xD6, 0x97, +0xD6, 0x56, 0x94, 0x70, 0x73, 0x8D, 0x8C, 0x70, +0x94, 0xB1, 0x94, 0x90, 0xAD, 0x11, 0x7B, 0x6B, +0xA4, 0xD0, 0xA4, 0xF0, 0x94, 0x6F, 0x94, 0x4E, +0x8C, 0x0D, 0x8C, 0x0D, 0x83, 0xCC, 0x8C, 0x2D, +0x94, 0x8F, 0x9C, 0x8F, 0x8C, 0x0C, 0x8C, 0x0D, +0x94, 0x6E, 0x94, 0x2D, 0xAC, 0xF0, 0x94, 0x0D, +0x94, 0x4E, 0xAD, 0x11, 0x9C, 0xD0, 0x94, 0x6F, +0x8C, 0x0D, 0xA5, 0x10, 0xD6, 0x55, 0xD6, 0x35, +0xC5, 0xB2, 0xD6, 0x35, 0xCD, 0xF4, 0x9C, 0x8E, +0x9C, 0x6F, 0x94, 0x2E, 0x94, 0x4E, 0xA4, 0xAF, +0xB5, 0x11, 0xAC, 0xF0, 0xB5, 0x52, 0xB5, 0x31, +0xCE, 0x14, 0xCD, 0xD3, 0xBD, 0x51, 0x94, 0x0C, +0x9C, 0x8E, 0xAD, 0x10, 0xAC, 0xCF, 0xAC, 0xEF, +0xB5, 0x51, 0xAC, 0xCF, 0x94, 0x4D, 0x8C, 0x0C, +0x94, 0x2D, 0xAC, 0xD0, 0xA4, 0xF2, 0x9C, 0xB3, +0x9C, 0xF3, 0x84, 0x0F, 0x8C, 0x0E, 0xA4, 0xD0, +0xA4, 0xAF, 0xA4, 0x8F, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xF0, 0xBD, 0x73, 0xB5, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x53, 0xB5, 0x94, +0xBD, 0xD5, 0xB5, 0xB4, 0xBD, 0x94, 0xB5, 0x94, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x33, 0xAD, 0x33, +0xA4, 0xD1, 0x94, 0x90, 0x94, 0x4F, 0x9C, 0x90, +0xA4, 0xD1, 0xA4, 0xD1, 0x9C, 0xB1, 0xA4, 0xD1, +0x9C, 0xB0, 0x9C, 0xB1, 0xA4, 0xF1, 0x9C, 0xB0, +0x94, 0x6F, 0x94, 0x70, 0x83, 0xED, 0x73, 0x6C, +0xA4, 0xD1, 0x8C, 0x0E, 0x8C, 0x0E, 0x7B, 0xAC, +0x7B, 0xAC, 0x7B, 0xAC, 0x83, 0xED, 0x84, 0x0E, +0x6B, 0x4B, 0x73, 0x6B, 0x9C, 0xB0, 0x8C, 0x2E, +0x62, 0xEA, 0x84, 0x0E, 0x8C, 0x4E, 0xAD, 0x32, +0xB5, 0x53, 0xB5, 0x93, 0xBD, 0x93, 0xAD, 0x11, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0x92, 0xB5, 0x51, 0xA4, 0xF0, 0x94, 0x8E, +0x84, 0x0C, 0x7B, 0x8B, 0x7B, 0xAB, 0x83, 0xCC, +0xB5, 0x73, 0xAD, 0x11, 0xDE, 0x56, 0xCD, 0xB3, +0xBD, 0x51, 0xB5, 0x31, 0xB5, 0x31, 0xBD, 0x52, +0xB5, 0x31, 0xB5, 0x52, 0xB5, 0x72, 0xBD, 0x93, +0xB5, 0x72, 0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x72, +0xC5, 0xB3, 0xCD, 0xD3, 0xC5, 0x93, 0xCD, 0xF4, +0xBD, 0x72, 0xB5, 0x51, 0xB5, 0x51, 0xAD, 0x10, +0xA4, 0xAF, 0xB5, 0x11, 0xCD, 0xF4, 0xD6, 0x14, +0xDE, 0x55, 0xD6, 0x14, 0xCD, 0xB2, 0xD5, 0xD3, +0xC5, 0x71, 0xCD, 0xB3, 0xDE, 0x55, 0xD5, 0xF3, +0xD5, 0xF3, 0xD5, 0xF3, 0xBD, 0x51, 0xA4, 0xAF, +0xB5, 0x31, 0xC5, 0xF4, 0xD6, 0x56, 0xDE, 0xB7, +0xC5, 0xF5, 0xA4, 0xF1, 0xDE, 0xB8, 0xCE, 0x37, +0x94, 0x91, 0x7B, 0xCE, 0x83, 0xEF, 0x84, 0x2F, +0x7B, 0xCF, 0x7B, 0xCE, 0x84, 0x0F, 0x9C, 0xB2, +0xA5, 0x33, 0x9C, 0xD2, 0x94, 0x71, 0x84, 0x30, +0x63, 0x2C, 0x39, 0xE8, 0x29, 0x66, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xC4, 0x18, 0xE4, 0x21, 0x25, +0x29, 0x87, 0x42, 0x29, 0x6B, 0x6E, 0x9C, 0xF4, +0xA5, 0x35, 0xA5, 0x15, 0x9C, 0xF5, 0x94, 0x93, +0x84, 0x32, 0x7C, 0x11, 0x73, 0xAF, 0x6B, 0x4E, +0x63, 0x0C, 0x6B, 0x6E, 0x84, 0x31, 0x7B, 0xCF, +0x6B, 0x2C, 0x83, 0xCF, 0x9C, 0xD3, 0x94, 0x93, +0x94, 0x93, 0x9C, 0xD4, 0xA5, 0x15, 0x9C, 0xF5, +0x94, 0xD4, 0x9C, 0xF4, 0xA5, 0x36, 0xAD, 0x77, +0xB5, 0xB8, 0xB5, 0xB8, 0xAD, 0x77, 0x9D, 0x15, +0xAD, 0x96, 0xAD, 0x96, 0xAD, 0x76, 0xA5, 0x55, +0x8C, 0x72, 0x7C, 0x10, 0x73, 0x4D, 0xCD, 0xD6, +0x8B, 0xAE, 0x62, 0xEB, 0x5A, 0xEB, 0x73, 0xAE, +0x73, 0x8D, 0x73, 0x6D, 0x7B, 0xAE, 0x84, 0x2F, +0x8C, 0x30, 0x84, 0x0F, 0x6B, 0x4C, 0x73, 0x8D, +0x39, 0xA6, 0x31, 0x65, 0x62, 0xCA, 0x5A, 0x69, +0x52, 0x69, 0x39, 0xC7, 0x5A, 0xAA, 0x72, 0xEB, +0x8B, 0x4C, 0x82, 0xEA, 0x82, 0xEA, 0x8B, 0x0B, +0x62, 0x68, 0x83, 0xAD, 0x8B, 0xCD, 0x94, 0x0E, +0x8B, 0xED, 0x7B, 0x8D, 0x8C, 0x2F, 0x83, 0xEE, +0x62, 0xEB, 0x4A, 0x69, 0x31, 0xA6, 0x21, 0x03, +0x29, 0x44, 0x29, 0x45, 0x21, 0x24, 0x29, 0x65, +0x21, 0x24, 0x21, 0x03, 0x29, 0x44, 0x29, 0x64, +0x29, 0x44, 0x29, 0x65, 0x29, 0x44, 0x29, 0x24, +0x29, 0x44, 0x63, 0x0C, 0xE7, 0x3D, 0xDE, 0xDC, +0xAD, 0x35, 0x9C, 0xB3, 0xA5, 0x14, 0x7B, 0xEF, +0x39, 0xA6, 0x21, 0x24, 0x4A, 0x48, 0x41, 0xE7, +0x4A, 0x28, 0x31, 0xA6, 0x42, 0x08, 0x5A, 0xEB, +0x5A, 0xEB, 0x6B, 0x2D, 0x83, 0xEF, 0x94, 0x71, +0xAD, 0x13, 0xA4, 0xB2, 0xBD, 0x55, 0xC5, 0x96, +0xDE, 0x9A, 0xC5, 0xD7, 0xAD, 0x55, 0xEF, 0x7D, +0xC6, 0x18, 0x39, 0xC7, 0x52, 0x68, 0x7B, 0xCD, +0x7B, 0xAD, 0x8C, 0x2F, 0x73, 0x8D, 0x9C, 0xD2, +0xA5, 0x53, 0xB5, 0x73, 0xAC, 0xF1, 0x8C, 0x2E, +0xAD, 0x11, 0xA4, 0xF1, 0x94, 0x8F, 0x94, 0x4E, +0x8C, 0x0D, 0x8C, 0x2D, 0x83, 0xED, 0x8C, 0x0D, +0x9C, 0xB0, 0x9C, 0xB0, 0x8C, 0x0D, 0x83, 0xEC, +0x94, 0x6E, 0x9C, 0x8F, 0xB5, 0x31, 0x8C, 0x0C, +0xB5, 0x93, 0xC6, 0x15, 0xB5, 0x93, 0xBD, 0xB4, +0xAD, 0x32, 0x7B, 0xCC, 0xB5, 0x93, 0xCE, 0x35, +0xB5, 0x72, 0xAD, 0x11, 0xA4, 0xD0, 0xBD, 0x94, +0xBD, 0xD4, 0xBD, 0xD4, 0xB5, 0x93, 0xA5, 0x11, +0xC5, 0xD4, 0x8C, 0x0E, 0x7B, 0xAC, 0x8C, 0x4F, +0xAD, 0x32, 0xAC, 0xEF, 0xC5, 0x51, 0x83, 0x6A, +0x8C, 0x6F, 0xB5, 0x93, 0x8C, 0x4E, 0x94, 0x6F, +0x9C, 0xB0, 0x94, 0x4E, 0x9C, 0x90, 0x94, 0x4E, +0xA4, 0xF1, 0xA4, 0xD1, 0xB5, 0x54, 0xA5, 0x35, +0xA5, 0x14, 0x84, 0x10, 0x6B, 0x4B, 0x94, 0x4E, +0xAD, 0x11, 0xAD, 0x11, 0xBD, 0xB3, 0xBD, 0x93, +0xBD, 0x72, 0xA4, 0xAF, 0x9C, 0x6F, 0x73, 0x6C, +0x63, 0x0B, 0x62, 0xEA, 0x6B, 0x2B, 0x83, 0xEE, +0x9C, 0x90, 0xA4, 0xF1, 0x94, 0x6F, 0x83, 0xEE, +0x8C, 0x2E, 0x94, 0x70, 0x94, 0x70, 0x94, 0x4F, +0xAD, 0x12, 0x9C, 0x90, 0x9C, 0xB1, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xF2, +0xA4, 0xF2, 0xAD, 0x12, 0xAD, 0x32, 0xA4, 0xF1, +0xAD, 0x33, 0xB5, 0x53, 0xBD, 0x94, 0xAD, 0x53, +0xBD, 0x94, 0xB5, 0x74, 0xBD, 0x94, 0xB5, 0x74, +0xB5, 0x94, 0xB5, 0x74, 0xBD, 0x95, 0xBD, 0xB5, +0xB5, 0x94, 0xA5, 0x12, 0xA4, 0xD2, 0xAD, 0x13, +0xB5, 0x74, 0xAD, 0x33, 0xA4, 0xF1, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0x90, 0x94, 0x6F, +0x94, 0x4E, 0x94, 0x4E, 0x94, 0x8F, 0x9C, 0x8F, +0xA4, 0xD0, 0xA4, 0xF0, 0xB5, 0x52, 0xAD, 0x31, +0xA4, 0xD0, 0x9C, 0x8F, 0x73, 0x6A, 0x73, 0x4B, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x32, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0xB0, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x8F, 0x9C, 0xB0, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x90, 0x9C, 0x6F, +0x9C, 0xB0, 0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xB0, +0x9C, 0x8F, 0x9C, 0x6E, 0xA4, 0xD0, 0xB5, 0x52, +0x8C, 0x0D, 0xB5, 0x32, 0x9C, 0x6E, 0xAD, 0x11, +0xB5, 0x11, 0xB5, 0x11, 0xB4, 0xF0, 0xB5, 0x11, +0xAC, 0xCF, 0xA4, 0xAF, 0xB5, 0x11, 0xBD, 0x51, +0xBD, 0x31, 0xC5, 0x71, 0xCD, 0xD3, 0xA4, 0xAF, +0xAC, 0xD0, 0xB5, 0x31, 0xBD, 0x93, 0xD6, 0x56, +0xE6, 0xD8, 0xDE, 0xB8, 0xD6, 0x77, 0xC5, 0xD5, +0xAD, 0x13, 0x8C, 0x50, 0x8C, 0x70, 0xBD, 0xF6, +0xC5, 0xF6, 0xA5, 0x33, 0x7B, 0xCE, 0x9C, 0xD2, +0xB5, 0x74, 0xB5, 0x74, 0xAD, 0x54, 0x9C, 0xD2, +0x8C, 0x50, 0x73, 0xAE, 0x63, 0x0B, 0x4A, 0x8A, +0x42, 0x08, 0x31, 0x86, 0x21, 0x25, 0x21, 0x04, +0x18, 0xE4, 0x21, 0x04, 0x31, 0xA7, 0x52, 0x8A, +0x73, 0xCF, 0x84, 0x11, 0x8C, 0x93, 0x94, 0xB4, +0x9C, 0xF5, 0x9C, 0xF5, 0x9D, 0x15, 0xA5, 0x15, +0x9D, 0x15, 0x94, 0x93, 0x84, 0x10, 0x6B, 0x4D, +0x6B, 0x2C, 0x73, 0x4C, 0x8C, 0x2F, 0xA4, 0xF3, +0x9C, 0x91, 0x8C, 0x0F, 0x83, 0xCF, 0x83, 0xCE, +0x7B, 0xCE, 0x7B, 0xCE, 0x7B, 0xCF, 0x7B, 0xCF, +0x7C, 0x10, 0x84, 0x32, 0x8C, 0x93, 0x9C, 0xF5, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x35, +0x9D, 0x14, 0x8C, 0x92, 0x52, 0x8A, 0x8B, 0xCE, +0x6B, 0x0B, 0x6B, 0x2C, 0x73, 0x8D, 0x73, 0xAD, +0x73, 0x8D, 0x83, 0xEE, 0x84, 0x0E, 0x8C, 0x4F, +0x94, 0x70, 0x94, 0x90, 0x94, 0x70, 0x83, 0xCD, +0x31, 0x65, 0x39, 0xC6, 0x31, 0x85, 0x6B, 0x2B, +0x73, 0x4B, 0x6B, 0x2B, 0x73, 0x4C, 0x5A, 0x68, +0x7A, 0xEB, 0x7A, 0xCA, 0x82, 0xEB, 0x7A, 0xEA, +0x5A, 0x07, 0x62, 0xA9, 0x83, 0x8C, 0x83, 0xAD, +0x8B, 0xEE, 0x8B, 0xEE, 0x94, 0x4F, 0x8B, 0xED, +0x83, 0xED, 0x8C, 0x0E, 0x8C, 0x2E, 0x7B, 0x8C, +0x4A, 0x07, 0x31, 0x85, 0x29, 0x65, 0x29, 0x44, +0x29, 0x65, 0x21, 0x24, 0x19, 0x03, 0x21, 0x24, +0x21, 0x03, 0x21, 0x03, 0x21, 0x03, 0x19, 0x03, +0x21, 0x45, 0xAD, 0x76, 0xE7, 0x1D, 0xBD, 0xD8, +0x5A, 0xAB, 0x6B, 0x4D, 0xA5, 0x35, 0x8C, 0x51, +0x42, 0x08, 0x42, 0x28, 0x84, 0x30, 0x39, 0xC7, +0x42, 0x07, 0x4A, 0x69, 0x4A, 0x49, 0x4A, 0x69, +0x52, 0x8A, 0x4A, 0x6A, 0x4A, 0x29, 0x5A, 0xCB, +0x7B, 0xAE, 0x83, 0xCF, 0x6B, 0x0C, 0xA4, 0x92, +0xC5, 0x95, 0xA4, 0xB2, 0x84, 0x10, 0xD6, 0xBA, +0xE7, 0x3C, 0x9C, 0xD3, 0x39, 0x66, 0x62, 0xCA, +0xBD, 0xB6, 0x8C, 0x50, 0x6B, 0x6D, 0x94, 0xD2, +0xA5, 0x54, 0xBD, 0xB4, 0xA4, 0xD0, 0x9C, 0x8F, +0xA5, 0x11, 0x9C, 0xB0, 0x9C, 0x8F, 0x9C, 0x8F, +0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x0D, 0x83, 0xCC, +0x8C, 0x0D, 0x94, 0x6F, 0x8C, 0x2E, 0x83, 0xEC, +0x94, 0x6E, 0x9C, 0x6E, 0xB5, 0x31, 0x83, 0xAB, +0xAD, 0x52, 0xC5, 0xD5, 0xBD, 0xB4, 0xC6, 0x16, +0xBD, 0xB4, 0x83, 0xCD, 0x7B, 0xAD, 0x84, 0x0E, +0x83, 0xED, 0x84, 0x0E, 0xB5, 0x93, 0xC6, 0x15, +0xC6, 0x16, 0xC5, 0xF5, 0xCE, 0x36, 0xC6, 0x15, +0xBD, 0xD4, 0x73, 0xAC, 0x6B, 0x4B, 0x73, 0x8C, +0x94, 0x6F, 0xA4, 0xAF, 0xC5, 0x71, 0x83, 0x6B, +0x9C, 0xD1, 0xB5, 0x93, 0x94, 0x6F, 0x9C, 0xD0, +0x8C, 0x4E, 0x94, 0x8F, 0xA5, 0x12, 0x9C, 0xB0, +0x9C, 0xD1, 0x9C, 0xD1, 0xB5, 0x95, 0xAD, 0x96, +0xA5, 0x35, 0x94, 0x92, 0x73, 0x8D, 0x94, 0x70, +0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x52, 0xAD, 0x31, +0xAD, 0x52, 0xA4, 0xB0, 0xA4, 0xB0, 0x73, 0x6C, +0x8C, 0x2F, 0x94, 0x70, 0x84, 0x0E, 0x83, 0xEE, +0x8C, 0x4F, 0x94, 0x4F, 0x7B, 0xCD, 0x73, 0x4C, +0x94, 0x70, 0xAD, 0x32, 0x9C, 0xD1, 0x9C, 0x90, +0xA4, 0xD1, 0x9C, 0x90, 0xA4, 0xF2, 0xA4, 0xD1, +0xA4, 0xD1, 0x8C, 0x2F, 0x8C, 0x2F, 0x8C, 0x4F, +0x8C, 0x2E, 0x94, 0x70, 0xA4, 0xF2, 0x9C, 0x90, +0xAD, 0x12, 0x8C, 0x0E, 0x8C, 0x0E, 0xA4, 0xF2, +0xAD, 0x12, 0xAD, 0x33, 0xB5, 0x74, 0xB5, 0x94, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x33, 0xA4, 0xF2, +0x9C, 0xB1, 0xAD, 0x12, 0xAD, 0x33, 0xB5, 0x74, +0xA5, 0x12, 0xAD, 0x53, 0x9C, 0xD1, 0x9C, 0x90, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x33, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xB5, 0xBD, 0x94, +0xBD, 0xB4, 0xAD, 0x12, 0xA4, 0xD0, 0xB5, 0x73, +0xAC, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x33, 0xAD, 0x33, 0xBD, 0x94, 0xC5, 0xD5, +0xBD, 0xB5, 0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xF6, +0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xD5, +0xC5, 0xD5, 0xC5, 0xF5, 0xC5, 0xD5, 0xC5, 0xF6, +0xCD, 0xF5, 0xC5, 0xD5, 0xC5, 0xD5, 0xCD, 0xF6, +0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x74, 0xC5, 0xF5, 0xBD, 0x94, 0xB5, 0x53, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x74, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x73, 0xAD, 0x12, 0xA4, 0xF1, +0xAD, 0x11, 0xAC, 0xF1, 0xA4, 0xAF, 0xA4, 0x8F, +0x9C, 0x6F, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4F, +0x9C, 0x90, 0xAD, 0x12, 0xB5, 0x32, 0xA4, 0xB0, +0xA4, 0xF1, 0xA4, 0xF2, 0x7B, 0xCE, 0x83, 0xEE, +0xA4, 0xF1, 0xBD, 0xD5, 0x83, 0xEE, 0x9C, 0xD2, +0x9C, 0xD1, 0x9C, 0xD2, 0xAD, 0x33, 0xB5, 0x74, +0xAD, 0x13, 0x9C, 0xD2, 0x94, 0x91, 0x8C, 0x50, +0x84, 0x30, 0x7B, 0xEF, 0x6B, 0x6E, 0x5A, 0xCB, +0x39, 0xE8, 0x29, 0x45, 0x21, 0x05, 0x19, 0x04, +0x18, 0xE4, 0x21, 0x45, 0x42, 0x08, 0x5A, 0xCB, +0x6B, 0x4E, 0x7B, 0xD0, 0x7C, 0x10, 0x7C, 0x11, +0x84, 0x31, 0x8C, 0x72, 0x94, 0x92, 0x9C, 0xB3, +0x9C, 0xD2, 0x9C, 0xB2, 0x8C, 0x0F, 0x7B, 0xAD, +0x7B, 0x8C, 0x8B, 0xCE, 0x6B, 0x0B, 0x7B, 0x6C, +0x7B, 0xAD, 0x7B, 0x6C, 0x73, 0x4B, 0x63, 0x2B, +0x6B, 0x2D, 0x7B, 0xF0, 0x7B, 0xF0, 0x84, 0x32, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x34, +0x9C, 0xF4, 0x8C, 0x51, 0x41, 0xE7, 0x42, 0x07, +0x52, 0x68, 0x63, 0x0B, 0x6B, 0x4B, 0x7B, 0xAD, +0x84, 0x0E, 0x8C, 0x4F, 0x94, 0x4F, 0x8C, 0x0E, +0x8C, 0x2D, 0x9C, 0x8E, 0x9C, 0x8E, 0x94, 0x2D, +0x73, 0x2B, 0x73, 0x4B, 0x5A, 0x88, 0x9C, 0x8F, +0xA4, 0xB0, 0xA4, 0x8F, 0xA4, 0x8F, 0x62, 0xAA, +0x5A, 0x28, 0x6A, 0x69, 0x72, 0x8A, 0x7A, 0xCA, +0x6A, 0x8A, 0x62, 0x89, 0x72, 0xEB, 0x83, 0x8D, +0x83, 0x8D, 0xA4, 0x90, 0xAC, 0xF0, 0xAC, 0xF0, +0xB5, 0x11, 0xB5, 0x31, 0xB5, 0x11, 0xB5, 0x31, +0xA4, 0xD0, 0x4A, 0x27, 0x29, 0x65, 0x29, 0x65, +0x31, 0x65, 0x29, 0x44, 0x29, 0x65, 0x21, 0x24, +0x21, 0x24, 0x19, 0x03, 0x18, 0xE3, 0x29, 0x87, +0x94, 0xB4, 0xE7, 0x3E, 0xCE, 0x5A, 0x9C, 0xD4, +0x39, 0xC8, 0x9C, 0xD3, 0xBD, 0xF7, 0x84, 0x31, +0x84, 0x10, 0x9C, 0xF4, 0xA4, 0xF4, 0x42, 0x29, +0x7B, 0xCF, 0xBD, 0xD7, 0xBD, 0xF8, 0xB5, 0x96, +0x84, 0x10, 0x52, 0x8A, 0x52, 0xAA, 0x5A, 0xEB, +0x39, 0xC7, 0x52, 0x8A, 0x62, 0xCB, 0x5A, 0xAA, +0xA4, 0x91, 0x62, 0xAA, 0x73, 0x6E, 0xBD, 0xF8, +0xD6, 0x9A, 0xC6, 0x39, 0x6B, 0x0C, 0xC5, 0xF6, +0xC5, 0xF6, 0x8C, 0x30, 0x6B, 0x6D, 0x8C, 0x71, +0xB5, 0x94, 0xB5, 0x93, 0xA4, 0xD0, 0x9C, 0xAF, +0xB5, 0x93, 0xB5, 0x52, 0xA4, 0xF0, 0xA4, 0xD0, +0xA4, 0xF0, 0xA4, 0xF0, 0x83, 0xCC, 0x83, 0xEC, +0x8C, 0x4E, 0xA4, 0xF0, 0x8C, 0x2E, 0x8C, 0x0D, +0x84, 0x0C, 0x94, 0x6E, 0xB5, 0x10, 0x7B, 0x8B, +0xB5, 0x93, 0xBD, 0xD4, 0xBD, 0xD5, 0xC6, 0x16, +0xBD, 0xD4, 0x8C, 0x2E, 0x7B, 0xCD, 0x84, 0x0E, +0x83, 0xED, 0x94, 0x6F, 0xAD, 0x53, 0xC6, 0x15, +0xCE, 0x36, 0xC6, 0x15, 0xC6, 0x35, 0xCE, 0x36, +0xBD, 0xD4, 0x8C, 0x4F, 0x73, 0x8C, 0x73, 0xAC, +0x7B, 0x8C, 0xA4, 0xB0, 0xBD, 0x51, 0x7B, 0x4A, +0x9C, 0xD1, 0xB5, 0x73, 0x94, 0xB0, 0xAD, 0x32, +0xA5, 0x11, 0x9C, 0xD1, 0xA5, 0x32, 0x9C, 0xD0, +0x9C, 0xD1, 0x9C, 0xD1, 0xB5, 0xB6, 0xAD, 0x55, +0xA5, 0x15, 0x94, 0x92, 0x6B, 0x6C, 0x9D, 0x12, +0xAD, 0x73, 0xAD, 0x73, 0xB5, 0x73, 0xAD, 0x52, +0xB5, 0x94, 0x8C, 0x2E, 0xA4, 0xF1, 0x83, 0xCD, +0x83, 0xEE, 0x8C, 0x4F, 0x84, 0x0E, 0x83, 0xEE, +0x8C, 0x2F, 0x83, 0xEE, 0x7B, 0xAD, 0x7B, 0xAD, +0xA4, 0xF2, 0xAD, 0x53, 0xA5, 0x12, 0xAD, 0x73, +0xA5, 0x12, 0xA4, 0xF2, 0xA4, 0xF2, 0xA5, 0x12, +0xAD, 0x73, 0xA5, 0x32, 0xA5, 0x12, 0xA5, 0x32, +0x94, 0x70, 0x84, 0x0E, 0xA4, 0xD1, 0xA4, 0xD1, +0x9C, 0xB1, 0x9C, 0xB1, 0xB5, 0x94, 0xBD, 0x94, +0xAD, 0x53, 0xB5, 0x53, 0xB5, 0x73, 0xBD, 0xB4, +0xB5, 0x94, 0xB5, 0x73, 0xAD, 0x53, 0xA4, 0xF1, +0xAD, 0x12, 0xB5, 0x74, 0xAD, 0x12, 0xAD, 0x53, +0x9C, 0x90, 0xAC, 0xF2, 0x83, 0xCD, 0x8C, 0x0E, +0x84, 0x0E, 0x6B, 0x2B, 0x8C, 0x4F, 0x8C, 0x2E, +0x84, 0x0E, 0x9C, 0x90, 0x9C, 0xB0, 0x8C, 0x2E, +0x9C, 0xD1, 0x94, 0x6F, 0x84, 0x0E, 0x84, 0x0D, +0x83, 0xCD, 0x83, 0xCC, 0x94, 0x6E, 0xA4, 0xAF, +0x94, 0x4E, 0x94, 0x6E, 0x94, 0x2E, 0x7B, 0x8B, +0x8C, 0x0D, 0x8C, 0x2D, 0x8C, 0x2D, 0x94, 0x2E, +0x8C, 0x2D, 0x83, 0xCC, 0x8C, 0x2E, 0xB5, 0x52, +0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x0D, 0x94, 0x4E, +0x9C, 0x8F, 0x9C, 0xB0, 0x9C, 0x90, 0x94, 0x4F, +0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x12, 0xAC, 0xF1, +0xAC, 0xF2, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x12, +0xAC, 0xF2, 0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, +0xB5, 0x32, 0xBD, 0x73, 0xC5, 0xD5, 0xCE, 0x16, +0xCE, 0x36, 0xBD, 0x73, 0xAC, 0xF1, 0xAD, 0x11, +0xAC, 0xF1, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x12, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x11, 0xAD, 0x11, +0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x74, 0xB5, 0x53, +0xA4, 0xF2, 0x94, 0x4F, 0x94, 0x90, 0xA5, 0x12, +0xAD, 0x13, 0xA5, 0x13, 0x94, 0x70, 0x8C, 0x0F, +0x94, 0x70, 0xA4, 0xF2, 0xB5, 0x54, 0xB5, 0x74, +0xAD, 0x33, 0xA4, 0xF3, 0x9C, 0xD2, 0x94, 0x92, +0x8C, 0x71, 0x73, 0xAE, 0x5A, 0xEB, 0x42, 0x08, +0x29, 0x66, 0x21, 0x45, 0x21, 0x45, 0x29, 0x45, +0x29, 0x45, 0x31, 0xA7, 0x42, 0x49, 0x5A, 0xEC, +0x63, 0x2D, 0x7C, 0x11, 0x84, 0x31, 0x7C, 0x11, +0x73, 0xAE, 0x73, 0x8E, 0x7B, 0xCF, 0x83, 0xEF, +0x83, 0xEF, 0x8C, 0x10, 0x73, 0x6D, 0x52, 0x89, +0x6B, 0x2B, 0x7B, 0x6C, 0x7B, 0x8C, 0x52, 0x89, +0x52, 0x6A, 0x5A, 0xCB, 0x73, 0x6D, 0x7B, 0xD0, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x14, +0x9C, 0xF4, 0x84, 0x51, 0x4A, 0x28, 0x7B, 0xCD, +0x8C, 0x2E, 0x9C, 0xB0, 0x94, 0x8F, 0x9C, 0x8F, +0xB5, 0x72, 0xBD, 0xB3, 0xC5, 0xD3, 0xBD, 0xB2, +0xBD, 0x51, 0xC5, 0xB2, 0xC5, 0xB2, 0xBD, 0x71, +0xBD, 0x71, 0xBD, 0x51, 0xBD, 0x71, 0xBD, 0x92, +0xBD, 0x72, 0xBD, 0x72, 0xBD, 0x51, 0x94, 0x2E, +0x6B, 0x0B, 0x5A, 0x28, 0x62, 0x69, 0x72, 0xAA, +0x7A, 0xEB, 0x72, 0xCB, 0x83, 0x6D, 0x8B, 0xCE, +0x83, 0x8C, 0x9C, 0x6F, 0xA4, 0x8F, 0xA4, 0xAF, +0x9C, 0x6E, 0xA4, 0x8F, 0xA4, 0x8F, 0xA4, 0xAF, +0xAC, 0xF0, 0x8C, 0x0E, 0x39, 0xA5, 0x31, 0x85, +0x29, 0x24, 0x29, 0x65, 0x29, 0x64, 0x29, 0x64, +0x29, 0x64, 0x52, 0xAB, 0xA5, 0x15, 0xD6, 0xBC, +0xE7, 0x3E, 0xCE, 0x7A, 0xAD, 0x15, 0x6B, 0x2D, +0x7B, 0xCF, 0xA5, 0x14, 0xB5, 0x96, 0xA5, 0x34, +0xAD, 0x76, 0xA5, 0x35, 0x94, 0x92, 0x5A, 0xEB, +0x7B, 0xEF, 0x6B, 0x6D, 0x63, 0x0C, 0x6B, 0x4D, +0x6B, 0x2C, 0x4A, 0x49, 0x63, 0x2C, 0x83, 0xF0, +0x4A, 0x49, 0x42, 0x08, 0x39, 0xA7, 0x52, 0x69, +0x73, 0x6D, 0x62, 0xEC, 0x84, 0x31, 0xA5, 0x35, +0xBD, 0xF8, 0xD6, 0x7A, 0xA5, 0x34, 0xAD, 0x34, +0xC6, 0x17, 0xC5, 0xF8, 0x84, 0x10, 0xAD, 0x54, +0xBD, 0xD5, 0xB5, 0x73, 0xAC, 0xF0, 0xA4, 0xF0, +0xBD, 0x93, 0xBD, 0xB3, 0xAD, 0x32, 0x9C, 0xAF, +0x94, 0x6E, 0xA4, 0xD0, 0x9C, 0x8F, 0x8C, 0x2D, +0x94, 0x6F, 0xA4, 0xD0, 0x94, 0x6F, 0x9C, 0x8F, +0x94, 0x6E, 0x94, 0x8F, 0xAC, 0xF0, 0x83, 0xAC, +0xA5, 0x32, 0xC6, 0x15, 0xC5, 0xF5, 0xCE, 0x36, +0xC5, 0xF5, 0x7B, 0xCD, 0x83, 0xED, 0x7B, 0xAC, +0x8C, 0x6F, 0xA4, 0xF1, 0xBD, 0xB4, 0xCE, 0x36, +0xC6, 0x35, 0xCE, 0x56, 0xCE, 0x56, 0xC5, 0xF5, +0xAD, 0x53, 0x8C, 0x4F, 0x7B, 0xCD, 0x6B, 0x2B, +0x6B, 0x6C, 0x83, 0xEC, 0xBD, 0x51, 0x73, 0x2A, +0xA4, 0xF2, 0xAD, 0x32, 0x9C, 0xB0, 0xAD, 0x32, +0x94, 0x6F, 0x8C, 0x4E, 0xBD, 0xB4, 0xA4, 0xF1, +0x9C, 0xD1, 0x9C, 0xF2, 0xBD, 0xD6, 0xAD, 0x55, +0xA5, 0x14, 0x9C, 0xD3, 0x7B, 0xCE, 0x9D, 0x12, +0xAD, 0x94, 0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x93, +0xBD, 0xD5, 0x94, 0x6F, 0xAD, 0x32, 0x8C, 0x2E, +0x8C, 0x4F, 0x94, 0x90, 0x94, 0x70, 0x84, 0x0E, +0x9C, 0x90, 0x83, 0xED, 0x83, 0xEE, 0x7B, 0xCE, +0x9C, 0xB1, 0xA5, 0x12, 0x9C, 0xD1, 0xAD, 0x53, +0x9C, 0xD1, 0x94, 0x90, 0x9C, 0xD1, 0xA4, 0xF2, +0xB5, 0x74, 0xA4, 0xF2, 0x9C, 0xF1, 0xAD, 0x53, +0x94, 0x90, 0x8C, 0x2F, 0xA4, 0xF2, 0xA4, 0xF1, +0x9C, 0x90, 0xAD, 0x53, 0xA4, 0xF1, 0x9C, 0xB0, +0xA5, 0x12, 0xAD, 0x32, 0xCE, 0x36, 0xCE, 0x16, +0xC6, 0x16, 0xC6, 0x15, 0xC5, 0xD4, 0xBD, 0xB4, +0xC5, 0xF5, 0xCE, 0x36, 0xC6, 0x15, 0xC5, 0xD5, +0x9C, 0xD1, 0xB5, 0x53, 0xA5, 0x12, 0x84, 0x0E, +0x6B, 0x4B, 0x84, 0x2E, 0xA4, 0xF1, 0x9C, 0xD0, +0x9C, 0xD0, 0x9C, 0xD0, 0x94, 0x6F, 0x83, 0xED, +0x9C, 0xD1, 0xA5, 0x11, 0xAD, 0x52, 0xAD, 0x52, +0x9C, 0x8F, 0x9C, 0xB0, 0xBD, 0xB2, 0xCE, 0x13, +0xCE, 0x13, 0xBD, 0x71, 0xAD, 0x10, 0x7B, 0x8B, +0x94, 0x6E, 0xA4, 0xF0, 0xAD, 0x10, 0xB5, 0x50, +0xBD, 0x91, 0xA4, 0xCF, 0x83, 0xEC, 0xB5, 0x52, +0x94, 0x6E, 0x9C, 0x8F, 0x94, 0x6E, 0xA4, 0xD0, +0xA4, 0xD0, 0xAD, 0x10, 0xAD, 0x10, 0xA4, 0xCF, +0xA4, 0xD0, 0xAC, 0xF0, 0x9C, 0x8F, 0x7B, 0x8B, +0x9C, 0x6F, 0xA4, 0xD0, 0xA4, 0xD0, 0x9C, 0xB0, +0xA4, 0xB0, 0xAD, 0x11, 0x9C, 0x6F, 0xA4, 0xF1, +0xAD, 0x32, 0xAD, 0x32, 0x9C, 0xB0, 0xAC, 0xF2, +0xAD, 0x12, 0x9C, 0x6F, 0x9C, 0xB0, 0xB5, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0x94, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x94, +0xBD, 0x93, 0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x12, +0x8C, 0x2F, 0x8C, 0x2F, 0x9C, 0xD2, 0xA4, 0xF2, +0x9C, 0xB1, 0x8C, 0x2F, 0x83, 0xEE, 0x94, 0x91, +0xAD, 0x33, 0xAD, 0x54, 0xAD, 0x34, 0xA5, 0x13, +0xA5, 0x13, 0x9D, 0x13, 0x9D, 0x13, 0x9C, 0xD2, +0x7C, 0x0F, 0x5A, 0xEB, 0x3A, 0x08, 0x29, 0x87, +0x31, 0xC8, 0x3A, 0x08, 0x39, 0xE8, 0x31, 0xC7, +0x39, 0xE8, 0x52, 0xAB, 0x6B, 0x4E, 0x84, 0x32, +0xA4, 0xF4, 0xA5, 0x15, 0xA5, 0x15, 0x9C, 0xF4, +0x8C, 0x52, 0x73, 0xAF, 0x6B, 0x4E, 0x63, 0x0D, +0x5A, 0xEB, 0x62, 0xEB, 0x62, 0xEB, 0x5A, 0xEB, +0x5A, 0xCB, 0x52, 0x49, 0x4A, 0x28, 0x52, 0x6A, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x15, +0x9C, 0xF4, 0x84, 0x31, 0x62, 0xEA, 0x9C, 0xB0, +0x94, 0x6E, 0x9C, 0x6E, 0x94, 0x4D, 0xA4, 0xCF, +0xB5, 0x92, 0xBD, 0x92, 0xC5, 0xD2, 0xC5, 0xB2, +0xC5, 0xB2, 0xC5, 0xB1, 0xC5, 0xB1, 0xB5, 0x2F, +0xBD, 0x71, 0xBD, 0x71, 0xCD, 0xF3, 0xC5, 0xB2, +0xC5, 0x92, 0xCD, 0xD3, 0xC5, 0xB2, 0xAC, 0xF0, +0xB5, 0x32, 0x8B, 0xEE, 0x72, 0xEA, 0x7A, 0xEB, +0x72, 0xCA, 0x7B, 0x0B, 0x83, 0x8D, 0x83, 0xAD, +0x94, 0x4F, 0x83, 0xED, 0x7B, 0xAC, 0x8B, 0xED, +0x94, 0x4E, 0x9C, 0x8F, 0x83, 0xCC, 0x83, 0xEC, +0x94, 0x6F, 0x9C, 0xB0, 0x6B, 0x4B, 0x31, 0xA6, +0x29, 0x44, 0x29, 0x65, 0x31, 0x65, 0x31, 0x85, +0x5A, 0xEB, 0xD6, 0xBB, 0xE7, 0x3D, 0xDE, 0xFC, +0xBD, 0xD7, 0x8C, 0x11, 0x73, 0x6E, 0x73, 0x6D, +0x84, 0x30, 0x8C, 0x30, 0xAD, 0x34, 0x94, 0xB2, +0xBD, 0xD7, 0xB5, 0x96, 0xC6, 0x18, 0xA5, 0x34, +0x4A, 0x49, 0x4A, 0x49, 0x42, 0x28, 0x31, 0x66, +0x31, 0x86, 0x39, 0xC7, 0x39, 0xA7, 0x52, 0x6A, +0x52, 0x69, 0x52, 0x8A, 0x52, 0x8A, 0x4A, 0x69, +0x7B, 0x8E, 0x94, 0x92, 0xAD, 0x75, 0xB5, 0xB7, +0xB5, 0x97, 0xDE, 0xDB, 0xC6, 0x18, 0xC6, 0x39, +0xE7, 0x3D, 0xE7, 0x1C, 0xAD, 0x55, 0x8C, 0x2F, +0xA4, 0xD0, 0xAC, 0xF0, 0xA4, 0xCF, 0x9C, 0x6E, +0xA4, 0xD0, 0x9C, 0xAF, 0x9C, 0xAF, 0xA4, 0xD0, +0x9C, 0xAF, 0x94, 0x6E, 0x94, 0x4E, 0xA4, 0xAF, +0xAD, 0x11, 0xB5, 0x72, 0xC5, 0xB3, 0xB5, 0x31, +0x94, 0x4E, 0x94, 0x6E, 0xA4, 0xAF, 0x73, 0x4A, +0x8C, 0x4E, 0xA4, 0xD0, 0xB5, 0x73, 0xB5, 0x93, +0xA4, 0xF1, 0x94, 0x6F, 0x9C, 0xF1, 0x9C, 0xB1, +0x7B, 0xED, 0x9C, 0xB0, 0xC5, 0xF5, 0xD6, 0x77, +0xCE, 0x36, 0xCE, 0x76, 0xCE, 0x55, 0xBD, 0xD4, +0xB5, 0x73, 0x8C, 0x6F, 0x8C, 0x4F, 0x7B, 0xCD, +0x73, 0x8C, 0x73, 0x6A, 0xB5, 0x31, 0x6B, 0x0A, +0x9C, 0xF1, 0xBD, 0xD5, 0x9C, 0xD1, 0x9C, 0xD0, +0x8C, 0x2E, 0x94, 0x8F, 0xB5, 0x73, 0xA5, 0x12, +0x9C, 0xD1, 0xA5, 0x12, 0xBD, 0xF7, 0xAD, 0x76, +0x9C, 0xD3, 0x8C, 0x71, 0x8C, 0x50, 0xA5, 0x32, +0xB5, 0x93, 0xB5, 0x93, 0xB5, 0xB4, 0xB5, 0x94, +0xBD, 0xB4, 0xAD, 0x32, 0xAD, 0x32, 0x8C, 0x2E, +0x94, 0x70, 0x94, 0x70, 0x8C, 0x2F, 0x8C, 0x2F, +0x94, 0x4F, 0x7B, 0xCD, 0x84, 0x0E, 0x84, 0x0E, +0x94, 0xB1, 0xAD, 0x53, 0xA5, 0x12, 0xAD, 0x53, +0xAD, 0x33, 0x9C, 0xD1, 0xA5, 0x33, 0xA4, 0xF2, +0x9C, 0xD1, 0x94, 0x70, 0x94, 0x70, 0x9C, 0xD1, +0x8C, 0x4F, 0x8C, 0x2F, 0xA4, 0xF2, 0xAD, 0x32, +0xA5, 0x32, 0x9C, 0xF1, 0x7B, 0xAD, 0x8C, 0x70, +0xA5, 0x12, 0x94, 0x6F, 0xC6, 0x15, 0xDE, 0xD8, +0xD6, 0x77, 0xCE, 0x56, 0xC5, 0xF5, 0xC5, 0xF5, +0xC5, 0xF5, 0xCE, 0x16, 0xCE, 0x15, 0xC6, 0x15, +0xA4, 0xD1, 0xB5, 0x73, 0xB5, 0x73, 0x94, 0x90, +0x73, 0x8C, 0x7B, 0xAD, 0xAD, 0x32, 0xA5, 0x11, +0xA5, 0x12, 0xA5, 0x11, 0x9C, 0xD0, 0x83, 0xED, +0xA4, 0xF1, 0x9C, 0x8F, 0xB5, 0x93, 0xB5, 0x52, +0xAD, 0x31, 0xB5, 0x72, 0xCE, 0x34, 0xA4, 0xEF, +0x9C, 0x8D, 0xAC, 0xEF, 0xB5, 0x71, 0x83, 0xCB, +0x8C, 0x4E, 0xA4, 0xCF, 0xAC, 0xF0, 0xB5, 0x50, +0xB5, 0x51, 0xAD, 0x10, 0x8C, 0x2E, 0xB5, 0x73, +0x7B, 0xAC, 0x73, 0x4A, 0x6B, 0x29, 0x83, 0xEC, +0x83, 0xCC, 0x9C, 0x8F, 0x9C, 0xAF, 0xA4, 0xF0, +0xB5, 0x72, 0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x73, +0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x32, 0xA4, 0xD0, +0xA4, 0xF1, 0xBD, 0x94, 0xAD, 0x12, 0xAD, 0x11, +0xBD, 0x93, 0xBD, 0xB3, 0xAD, 0x11, 0xB5, 0x33, +0xAC, 0xF1, 0x9C, 0xD1, 0x9C, 0xD1, 0xB5, 0x53, +0xC5, 0xD4, 0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB4, +0xC5, 0xD4, 0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xD4, +0xC5, 0xD4, 0xCE, 0x15, 0xD6, 0x36, 0xC5, 0xD4, +0xCE, 0x15, 0xCE, 0x36, 0x9C, 0x90, 0x73, 0x8C, +0x9C, 0xB1, 0xAD, 0x33, 0xAD, 0x54, 0x94, 0x91, +0x83, 0xEF, 0x8C, 0x30, 0x8C, 0x50, 0x94, 0x91, +0x9C, 0xD2, 0x94, 0xB2, 0x9C, 0xD2, 0xA5, 0x13, +0x94, 0xB2, 0x8C, 0x71, 0x84, 0x0F, 0x6B, 0x4D, +0x42, 0x49, 0x29, 0x86, 0x21, 0x45, 0x29, 0x46, +0x31, 0xA7, 0x4A, 0x6A, 0x5A, 0xEC, 0x6B, 0x6E, +0x7B, 0xD0, 0x7B, 0xF0, 0x7B, 0xF1, 0x84, 0x11, +0x8C, 0x72, 0x94, 0xB4, 0x9C, 0xF5, 0x9D, 0x15, +0xA5, 0x35, 0xA5, 0x35, 0x9C, 0xF4, 0x94, 0xD4, +0x94, 0xB4, 0x94, 0xD4, 0x8C, 0x72, 0x84, 0x51, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x34, +0x9C, 0xF4, 0x84, 0x50, 0x63, 0x0A, 0x9C, 0xAF, +0x94, 0x6D, 0x94, 0x4D, 0x9C, 0x8E, 0xA4, 0xF0, +0xAD, 0x51, 0xBD, 0x71, 0xC5, 0xB2, 0xC5, 0xD2, +0xC5, 0xB1, 0xB5, 0x0F, 0xA4, 0xAE, 0xA4, 0xAE, +0xC5, 0xB2, 0x8B, 0xEB, 0xB5, 0x30, 0xB5, 0x10, +0xAD, 0x0F, 0xAD, 0x0F, 0xAD, 0x0F, 0x94, 0x2D, +0xB5, 0x51, 0xA4, 0xAF, 0xA4, 0x6F, 0x83, 0x6C, +0x83, 0xAD, 0x83, 0xCD, 0x8B, 0xEE, 0x62, 0xEA, +0x83, 0xED, 0x83, 0xCD, 0x73, 0x6B, 0x84, 0x0D, +0x5A, 0xC9, 0x63, 0x0A, 0x5A, 0xA8, 0x52, 0x67, +0x6B, 0x4B, 0x84, 0x0E, 0x6B, 0x2B, 0x63, 0x2B, +0x39, 0xC6, 0x29, 0x64, 0x29, 0x64, 0x31, 0xA6, +0xA5, 0x35, 0xE7, 0x1D, 0xB5, 0xB7, 0x94, 0x92, +0x84, 0x10, 0x42, 0x28, 0x4A, 0x28, 0x5A, 0xEB, +0x52, 0x69, 0x7B, 0xAE, 0x8C, 0x50, 0x94, 0x71, +0xB5, 0x96, 0xBD, 0xB6, 0xBD, 0xD7, 0xB5, 0x76, +0x52, 0x69, 0x52, 0x8A, 0x73, 0x6D, 0x42, 0x28, +0x52, 0x89, 0x42, 0x28, 0x31, 0x65, 0x31, 0x86, +0x52, 0x8A, 0x6B, 0x2C, 0x5A, 0xEB, 0x4A, 0x49, +0x73, 0x8E, 0x94, 0x92, 0xA5, 0x35, 0xB5, 0x76, +0x8C, 0x52, 0xD6, 0x9B, 0xAD, 0x56, 0xCE, 0x5A, +0xB5, 0xB7, 0xB5, 0xB7, 0xB5, 0x96, 0x94, 0x90, +0x9C, 0x8F, 0xAC, 0xF0, 0xB5, 0x31, 0x8C, 0x0C, +0x8C, 0x0D, 0x94, 0x2D, 0x94, 0x6E, 0x94, 0x4E, +0xAC, 0xCF, 0xAC, 0xD0, 0xB5, 0x11, 0xC5, 0x92, +0x94, 0x0C, 0x94, 0x2D, 0x94, 0x0C, 0x8B, 0xEC, +0x8C, 0x0C, 0x8B, 0xEC, 0x9C, 0x6E, 0xA4, 0xCF, +0x9C, 0x8F, 0x94, 0x4E, 0x94, 0x2D, 0xA4, 0xAF, +0x9C, 0x6E, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x6F, +0x8C, 0x0D, 0x94, 0x6E, 0xA4, 0xD0, 0xB5, 0x52, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x52, 0xA4, 0xF0, +0xA5, 0x11, 0x94, 0xB0, 0x94, 0x6F, 0x84, 0x2E, +0x7B, 0xCD, 0x73, 0x4A, 0xB5, 0x10, 0x62, 0xC8, +0x9C, 0xF1, 0xBD, 0xD4, 0xAD, 0x32, 0xAD, 0x52, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x73, 0xB5, 0x73, +0xA5, 0x12, 0xB5, 0x74, 0xC6, 0x58, 0xB5, 0xB7, +0xA5, 0x35, 0x84, 0x30, 0x94, 0xB1, 0xBD, 0xD5, +0xBD, 0xD4, 0xB5, 0x93, 0xB5, 0x94, 0xB5, 0x93, +0xB5, 0x93, 0xB5, 0x73, 0xAD, 0x32, 0x8C, 0x2F, +0x8C, 0x4F, 0x94, 0x70, 0x8C, 0x2E, 0x84, 0x0E, +0x94, 0x6F, 0x83, 0xED, 0x84, 0x0E, 0x94, 0x90, +0xAD, 0x53, 0xB5, 0xD5, 0xB5, 0x74, 0xB5, 0x94, +0xAD, 0x74, 0xAD, 0x74, 0xBD, 0xD6, 0xA5, 0x33, +0x9C, 0xF2, 0x84, 0x0E, 0x8C, 0x2F, 0x8C, 0x4F, +0x8C, 0x4F, 0x8C, 0x2F, 0xB5, 0x53, 0xB5, 0x74, +0xA4, 0xF2, 0x9C, 0xB1, 0x8C, 0x2F, 0x94, 0x90, +0xAD, 0x33, 0x94, 0x6F, 0xCE, 0x57, 0xCE, 0x56, +0xD6, 0x97, 0xCE, 0x36, 0xCE, 0x35, 0xCE, 0x15, +0xCE, 0x36, 0xCE, 0x56, 0xC6, 0x15, 0xC5, 0xF5, +0x9C, 0x90, 0xB5, 0x74, 0xC5, 0xF5, 0x9C, 0xD1, +0x94, 0x90, 0x94, 0x90, 0xAD, 0x52, 0xA4, 0xF1, +0xAD, 0x53, 0xA4, 0xF1, 0x9C, 0xB0, 0x7B, 0x8C, +0x8C, 0x4F, 0x9C, 0xB0, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xB3, 0xC5, 0xD3, 0x73, 0x8A, +0x9C, 0xAE, 0x9C, 0x6D, 0x94, 0x2D, 0x94, 0x6E, +0xAD, 0x52, 0xC5, 0xF4, 0xB5, 0x71, 0xBD, 0x92, +0xBD, 0x71, 0xAD, 0x30, 0x9C, 0xAF, 0xAD, 0x12, +0x7B, 0x8B, 0x7B, 0x8B, 0x73, 0xAC, 0x94, 0x6F, +0x94, 0x4E, 0x94, 0x6E, 0x9C, 0x8E, 0xAD, 0x10, +0xA4, 0xCF, 0x94, 0x6E, 0xA4, 0xD0, 0xC5, 0xF5, +0xAD, 0x32, 0xA4, 0xF1, 0xB5, 0x93, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x32, 0x94, 0x8F, +0xA4, 0xF0, 0xA5, 0x10, 0xA4, 0xF1, 0xBD, 0x73, +0x9C, 0x90, 0x7B, 0xCE, 0x8C, 0x4F, 0xA5, 0x32, +0xBD, 0xD4, 0xBD, 0x93, 0xB5, 0x72, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x94, 0xB5, 0x53, +0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0xB3, 0xC5, 0xB4, 0xCD, 0xF5, 0xBD, 0x94, +0xBD, 0xB3, 0xD6, 0x56, 0xD6, 0x57, 0x94, 0x4F, +0xA4, 0xF2, 0xAD, 0x33, 0x9C, 0xD2, 0x9C, 0xD1, +0xA4, 0xF2, 0xA5, 0x13, 0x9C, 0xB1, 0xA5, 0x12, +0x8C, 0x70, 0x7B, 0xEE, 0x94, 0x70, 0x94, 0x91, +0x9C, 0xD2, 0x9C, 0xB1, 0x94, 0x91, 0x8C, 0x50, +0x7B, 0xCE, 0x6B, 0x4D, 0x5A, 0xCB, 0x52, 0x8A, +0x39, 0xE8, 0x31, 0x86, 0x29, 0x46, 0x39, 0xE8, +0x52, 0xCB, 0x73, 0x8F, 0x84, 0x31, 0x84, 0x52, +0x6B, 0x6F, 0x63, 0x0D, 0x5A, 0xEC, 0x5A, 0xEC, +0x73, 0x8F, 0x84, 0x31, 0x94, 0xB3, 0x94, 0xD4, +0x94, 0xB3, 0x8C, 0x93, 0x9C, 0xD4, 0x9C, 0xF5, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x34, +0x9C, 0xF4, 0x84, 0x30, 0x62, 0xE9, 0x94, 0x2D, +0x94, 0x2C, 0x8C, 0x0C, 0x94, 0x4D, 0x94, 0x2C, +0x9C, 0xAE, 0xAD, 0x0F, 0xAC, 0xEF, 0xBD, 0x91, +0xA4, 0xCE, 0xAD, 0x10, 0xB5, 0x50, 0xAD, 0x10, +0xBD, 0x92, 0x73, 0x29, 0x94, 0x4D, 0x9C, 0x8E, +0x9C, 0x6D, 0xA4, 0xCF, 0xAC, 0xCF, 0x8B, 0xEC, +0xA4, 0xEF, 0xAD, 0x10, 0x94, 0x0D, 0x83, 0xCD, +0x7B, 0xAD, 0x9C, 0xB0, 0xA4, 0xF1, 0x6B, 0x6B, +0x94, 0x6F, 0x8C, 0x4F, 0x8C, 0x6F, 0xAD, 0x53, +0x73, 0x6C, 0x73, 0x8D, 0x6B, 0x4C, 0x7B, 0xAD, +0x73, 0x8C, 0x94, 0x4F, 0x8C, 0x0E, 0x9C, 0xB0, +0x7B, 0xCD, 0x39, 0xC6, 0x29, 0x65, 0x39, 0xE7, +0x94, 0xB3, 0xD6, 0xBA, 0xAD, 0x55, 0x4A, 0x29, +0x4A, 0x48, 0x42, 0x28, 0x4A, 0x28, 0x42, 0x28, +0x73, 0x6D, 0x8C, 0x30, 0x94, 0x71, 0x9C, 0xB3, +0xA5, 0x14, 0xAD, 0x34, 0xAD, 0x75, 0xAD, 0x34, +0x6B, 0x6D, 0x5A, 0xCB, 0x63, 0x0B, 0x29, 0x45, +0x39, 0xC7, 0x39, 0xE7, 0x42, 0x28, 0x4A, 0x28, +0x52, 0x89, 0x5A, 0xEB, 0x42, 0x28, 0x4A, 0x69, +0x5A, 0xEB, 0x7C, 0x10, 0x94, 0xD3, 0xAD, 0x96, +0xBD, 0xB7, 0xBD, 0xF8, 0xBD, 0xD8, 0xC6, 0x39, +0xD6, 0xBB, 0xCE, 0x5A, 0xC6, 0x18, 0x9C, 0xD2, +0xAD, 0x52, 0xB5, 0x93, 0xC6, 0x15, 0x9C, 0xD0, +0x8C, 0x2E, 0x8C, 0x2E, 0x94, 0x4E, 0x94, 0x4E, +0x94, 0x4E, 0x8C, 0x2D, 0x94, 0x2D, 0xAC, 0xCF, +0x7B, 0x8B, 0x73, 0x6B, 0x8C, 0x0D, 0x83, 0xEC, +0x73, 0x8B, 0x73, 0x4A, 0x62, 0xC9, 0x83, 0xED, +0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, 0xBD, 0x31, +0xA4, 0x6D, 0xAC, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, +0xAC, 0xCF, 0xAC, 0xD0, 0xAC, 0xCF, 0x9C, 0x4D, +0x8C, 0x0D, 0x9C, 0x6E, 0x94, 0x2D, 0x8B, 0xEC, +0x8B, 0xEC, 0xAC, 0xF0, 0xBD, 0x51, 0xAC, 0xAF, +0xA4, 0xCF, 0xA4, 0x8F, 0x9C, 0x4E, 0x9C, 0x6E, +0x94, 0x2D, 0x94, 0x4E, 0x9C, 0x8F, 0xA4, 0xD0, +0x94, 0x4E, 0x94, 0x90, 0xC6, 0x38, 0xB5, 0xD7, +0xB5, 0x76, 0x8C, 0x51, 0x9C, 0xD1, 0xB5, 0xB3, +0xC5, 0xF5, 0xC6, 0x36, 0xC5, 0xF5, 0xBD, 0xB4, +0xA4, 0xF1, 0x83, 0xED, 0xAD, 0x53, 0x94, 0x4F, +0x94, 0x70, 0x9C, 0xD1, 0x94, 0x90, 0x9C, 0xB1, +0xA5, 0x12, 0x94, 0x90, 0x9C, 0xB1, 0xB5, 0x74, +0xB5, 0x74, 0xCE, 0x57, 0xBD, 0xD5, 0xC5, 0xF6, +0xBD, 0xF5, 0xA5, 0x33, 0xBD, 0xD5, 0x9C, 0xD1, +0xA5, 0x12, 0x94, 0x90, 0x9C, 0xB1, 0x8C, 0x2F, +0x9C, 0xD1, 0x94, 0x90, 0xAD, 0x33, 0xA4, 0xF2, +0xBD, 0xD5, 0xB5, 0x94, 0x8C, 0x4F, 0x94, 0x70, +0xA5, 0x12, 0x9C, 0xB0, 0xD6, 0x98, 0xD6, 0x97, +0xD6, 0x97, 0xD6, 0x97, 0xDE, 0xB7, 0xC5, 0xD4, +0xC5, 0xF5, 0xCE, 0x36, 0xD6, 0x76, 0xC5, 0xF5, +0x8C, 0x4F, 0xAD, 0x32, 0xAD, 0x12, 0x9C, 0xD1, +0x94, 0xB0, 0x9C, 0xD1, 0xA5, 0x12, 0xA4, 0xF1, +0x9C, 0x90, 0xA4, 0xD1, 0x94, 0x6F, 0x73, 0x8C, +0x84, 0x0E, 0x9C, 0x8F, 0xBD, 0x92, 0xC5, 0xD3, +0x94, 0x8E, 0xA4, 0xD0, 0xC5, 0xD3, 0xBD, 0xB3, +0xCE, 0x14, 0xC5, 0xD3, 0x94, 0x6E, 0x9C, 0xD0, +0xBD, 0xD4, 0xCE, 0x35, 0xBD, 0xB2, 0xBD, 0xD3, +0xBD, 0xB3, 0xAD, 0x10, 0xA4, 0xF0, 0xA4, 0xF1, +0x7B, 0xAC, 0x94, 0x6F, 0x9C, 0xB0, 0x7B, 0xAC, +0x8C, 0x4E, 0x94, 0x8F, 0xA4, 0xF0, 0xAD, 0x31, +0xA4, 0xF1, 0x94, 0x6E, 0x94, 0x6F, 0xAD, 0x52, +0xB5, 0x94, 0xB5, 0xB4, 0xB5, 0x94, 0x9C, 0xD1, +0xA4, 0xF1, 0xAD, 0x53, 0xAD, 0x33, 0x94, 0x8F, +0xA5, 0x11, 0xA5, 0x11, 0xAD, 0x11, 0xB5, 0x73, +0x9C, 0x90, 0x83, 0xEE, 0x84, 0x2F, 0x9C, 0xD1, +0xB5, 0x72, 0xB5, 0x31, 0xA4, 0xF0, 0xA4, 0xF0, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x74, +0xBD, 0x94, 0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0xB3, +0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xF4, 0xDE, 0x76, 0xB5, 0x32, +0xBD, 0x94, 0xB5, 0x53, 0xAD, 0x53, 0xB5, 0x53, +0xBD, 0xB5, 0xAD, 0x53, 0xA4, 0xF2, 0xC5, 0xD5, +0xD6, 0x57, 0x94, 0x50, 0x7B, 0xAD, 0x8C, 0x2F, +0x8C, 0x50, 0x94, 0x91, 0x9C, 0xD2, 0x9C, 0xD2, +0x8C, 0x50, 0x83, 0xEF, 0x83, 0xEF, 0x84, 0x0F, +0x7B, 0xEF, 0x6B, 0x8D, 0x52, 0x8A, 0x39, 0xC7, +0x29, 0x45, 0x21, 0x04, 0x21, 0x45, 0x39, 0xC8, +0x4A, 0x6A, 0x63, 0x2D, 0x73, 0x8F, 0x73, 0xAF, +0x7B, 0xD0, 0x7B, 0xD0, 0x7B, 0xD0, 0x7C, 0x11, +0x7B, 0xF0, 0x73, 0xAF, 0x7B, 0xF0, 0x73, 0xB0, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x34, +0x9C, 0xF4, 0x7C, 0x0F, 0x5A, 0xC9, 0x83, 0xAB, +0x83, 0xAB, 0x7B, 0x8B, 0x83, 0xCC, 0x83, 0xCC, +0x8C, 0x0D, 0x9C, 0x8E, 0x9C, 0xAE, 0x94, 0x4D, +0x73, 0x49, 0x94, 0x4D, 0xAD, 0x31, 0xBD, 0x92, +0xC5, 0xD4, 0x8C, 0x0D, 0x94, 0x6E, 0xA4, 0xCF, +0xAC, 0xF0, 0x94, 0x6E, 0x9C, 0x6E, 0x8C, 0x0C, +0x9C, 0x8E, 0xAC, 0xEF, 0x94, 0x2D, 0x7B, 0x8C, +0x7B, 0x8C, 0xA4, 0xD1, 0xA4, 0xF1, 0x7B, 0xCD, +0x9C, 0x91, 0x9C, 0xB1, 0x9C, 0xB0, 0xAD, 0x53, +0x9C, 0xB0, 0xAD, 0x32, 0xAD, 0x33, 0xAD, 0x53, +0xA5, 0x32, 0xA5, 0x12, 0x94, 0x90, 0x9C, 0xD0, +0x8C, 0x4F, 0x73, 0x8C, 0x31, 0xA5, 0x31, 0xA6, +0x41, 0xE7, 0x62, 0xEB, 0x7B, 0xAE, 0x31, 0x86, +0x29, 0x65, 0x39, 0xE7, 0x52, 0x8A, 0x6B, 0x4C, +0x73, 0xAE, 0x7B, 0xCF, 0x8C, 0x51, 0x8C, 0x30, +0x84, 0x10, 0xAD, 0x35, 0xB5, 0x96, 0x94, 0xB2, +0x84, 0x10, 0x8C, 0x71, 0x94, 0xB1, 0x6B, 0x6D, +0x29, 0x24, 0x39, 0xA6, 0x42, 0x28, 0x31, 0x85, +0x31, 0x85, 0x39, 0xE7, 0x31, 0xA6, 0x5A, 0xCA, +0x63, 0x0C, 0x6B, 0x4D, 0x7B, 0xCF, 0xAD, 0x76, +0xA5, 0x35, 0xAD, 0x76, 0xBD, 0xF8, 0xCE, 0x7B, +0xE7, 0x1D, 0xD6, 0xBB, 0xCE, 0x59, 0xB5, 0xB6, +0xB5, 0x74, 0xB5, 0x93, 0xBD, 0xD4, 0xAD, 0x53, +0xA4, 0xF1, 0x9C, 0xD0, 0xA5, 0x11, 0xA5, 0x11, +0xA4, 0xF1, 0xA4, 0xF0, 0xA4, 0xCF, 0xA4, 0xCF, +0x7B, 0x8B, 0x7B, 0xAC, 0x7B, 0x8C, 0x83, 0xED, +0x84, 0x2E, 0x83, 0xED, 0x7B, 0xAD, 0x8C, 0x4F, +0x94, 0x6F, 0x8C, 0x4E, 0x8B, 0xEC, 0xA4, 0x8E, +0x8C, 0x0C, 0x9C, 0x8E, 0x8C, 0x0D, 0x73, 0x6B, +0x73, 0x4A, 0x62, 0xE9, 0x62, 0xA9, 0x62, 0xE9, +0x6B, 0x09, 0x73, 0x4A, 0x94, 0x2D, 0x8B, 0xCB, +0x7B, 0x8A, 0x8B, 0xCB, 0x94, 0x2D, 0x94, 0x0D, +0x83, 0xAB, 0x83, 0x8A, 0x8B, 0xEC, 0xA4, 0x6E, +0xAC, 0xCF, 0xAC, 0x8E, 0xBD, 0x31, 0xB5, 0x10, +0xBD, 0x30, 0xBD, 0x31, 0xB5, 0x30, 0xB5, 0x10, +0xAC, 0xF0, 0xA4, 0xF1, 0xCE, 0x79, 0xBD, 0xD8, +0xBD, 0xB7, 0x9C, 0xD1, 0xA4, 0xF0, 0xAD, 0x10, +0xAC, 0xD0, 0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x6E, +0x94, 0x6E, 0xA4, 0xD1, 0xBD, 0x94, 0xAD, 0x53, +0xA4, 0xF2, 0x94, 0x90, 0x94, 0x70, 0x8C, 0x4F, +0x8C, 0x4F, 0x8C, 0x4F, 0x8C, 0x4F, 0x94, 0x70, +0x8C, 0x2F, 0x8C, 0x2F, 0x84, 0x0E, 0x8C, 0x4F, +0x94, 0x70, 0x7B, 0xAD, 0x83, 0xEE, 0x94, 0x6F, +0xA5, 0x32, 0xAD, 0x33, 0xA5, 0x12, 0xAD, 0x53, +0xA5, 0x33, 0x83, 0xEE, 0xA5, 0x12, 0x9C, 0xD1, +0xB5, 0xB4, 0xB5, 0x94, 0x9C, 0xB1, 0x94, 0x90, +0xAD, 0x32, 0xAD, 0x32, 0xCE, 0x36, 0xCE, 0x77, +0xD6, 0x77, 0xD6, 0x56, 0xB5, 0x53, 0x94, 0x90, +0x94, 0x6F, 0x8C, 0x0E, 0xBD, 0xB4, 0xB5, 0x94, +0x83, 0xEE, 0xB5, 0x53, 0x9C, 0xD1, 0xC6, 0x36, +0x9C, 0xB1, 0xAD, 0x32, 0xAD, 0x52, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0xB0, 0x7B, 0xED, +0x7B, 0xCD, 0x94, 0x8F, 0xAD, 0x51, 0xBD, 0xD3, +0xB5, 0x72, 0x73, 0x6B, 0x9C, 0x8F, 0xC6, 0x14, +0xCE, 0x35, 0xD6, 0x96, 0x9C, 0xAF, 0xAD, 0x31, +0xCE, 0x15, 0xCE, 0x35, 0xBD, 0xD3, 0xCE, 0x35, +0xCE, 0x35, 0xB5, 0x72, 0xA4, 0xCF, 0xA4, 0xF1, +0x62, 0xE9, 0x5A, 0xE9, 0x6B, 0x2A, 0x83, 0xED, +0x94, 0x8F, 0xB5, 0x73, 0xC5, 0xD5, 0xAD, 0x53, +0xAD, 0x32, 0x9C, 0xB0, 0x9C, 0xB0, 0xA5, 0x12, +0xB5, 0x94, 0xBD, 0xF5, 0xA5, 0x32, 0x9C, 0xD1, +0xB5, 0x74, 0xC6, 0x16, 0xBD, 0xD5, 0xAD, 0x53, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x73, +0x8C, 0x4F, 0x7B, 0xCE, 0x8C, 0x50, 0x9C, 0xD1, +0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xAF, 0x9C, 0x8F, +0xA5, 0x11, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x32, 0xB5, 0x93, 0xB5, 0x73, +0xB5, 0x73, 0xB5, 0x73, 0xBD, 0xB3, 0xC5, 0xB3, +0xCD, 0xF4, 0xC5, 0xF4, 0xC5, 0xD4, 0xB5, 0x32, +0xB5, 0x53, 0x9C, 0xB1, 0x9C, 0xD1, 0x9C, 0xD0, +0xAD, 0x32, 0xC5, 0xD5, 0xBD, 0xD5, 0xBD, 0xD5, +0xC5, 0xF5, 0x8C, 0x4F, 0x94, 0x70, 0xB5, 0x54, +0xA4, 0xD2, 0x8C, 0x2F, 0x94, 0x91, 0x9C, 0xB1, +0x94, 0x91, 0x94, 0x71, 0x94, 0x70, 0x8C, 0x70, +0x8C, 0x50, 0x8C, 0x50, 0x84, 0x0F, 0x73, 0x8E, +0x5B, 0x0C, 0x4A, 0x69, 0x39, 0xE7, 0x31, 0x86, +0x21, 0x25, 0x21, 0x25, 0x21, 0x45, 0x31, 0xA7, +0x42, 0x29, 0x5A, 0xCC, 0x63, 0x2D, 0x6B, 0x8F, +0x7B, 0xF1, 0x8C, 0x93, 0x8C, 0x72, 0x84, 0x52, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x34, +0x9C, 0xF4, 0x7B, 0xCF, 0x52, 0x68, 0x6A, 0xE9, +0x5A, 0x88, 0x62, 0xC9, 0x62, 0xE9, 0x52, 0x68, +0x62, 0xE9, 0x73, 0x6B, 0x73, 0x6B, 0x83, 0xEC, +0x6B, 0x2A, 0x83, 0xED, 0x9C, 0xAF, 0x8C, 0x2D, +0xC5, 0xF4, 0x9C, 0xAF, 0xA4, 0xF0, 0xB5, 0x51, +0xA4, 0xF0, 0x94, 0x6E, 0x9C, 0xAF, 0x9C, 0xAF, +0xA4, 0xAF, 0xA4, 0xCF, 0x83, 0xAB, 0x5A, 0xA9, +0x5A, 0xCA, 0x94, 0x90, 0x94, 0x6F, 0x63, 0x0A, +0x8C, 0x2F, 0x7B, 0xCD, 0x94, 0x90, 0x94, 0x90, +0x7B, 0xAC, 0x9C, 0xD0, 0x8C, 0x4F, 0xA4, 0xF1, +0x9C, 0xB0, 0x9C, 0xD0, 0x9C, 0xD1, 0x8C, 0x4E, +0x8C, 0x2E, 0x94, 0x6F, 0x5A, 0xEA, 0x31, 0x85, +0x39, 0xE7, 0x42, 0x28, 0x42, 0x07, 0x31, 0x86, +0x31, 0xA6, 0x42, 0x28, 0x52, 0xAA, 0x52, 0xAA, +0x5A, 0xCA, 0x63, 0x0C, 0x73, 0x8D, 0x7B, 0xAE, +0x73, 0x6D, 0x94, 0xB2, 0xB5, 0x96, 0x84, 0x30, +0x52, 0x8A, 0x52, 0x69, 0x9C, 0xD2, 0xAD, 0x74, +0x8C, 0x70, 0x29, 0x65, 0x21, 0x04, 0x29, 0x65, +0x31, 0x85, 0x31, 0x85, 0x4A, 0x48, 0x5A, 0xAA, +0x5A, 0xEB, 0x5A, 0xEB, 0x63, 0x4D, 0x8C, 0x51, +0xAD, 0x76, 0xBD, 0xD8, 0xBD, 0xD8, 0xCE, 0x5A, +0xC6, 0x39, 0x94, 0x92, 0x8C, 0x51, 0xDE, 0xBB, +0x94, 0x91, 0xB5, 0x94, 0xC6, 0x16, 0xB5, 0x94, +0xA5, 0x12, 0x94, 0x8F, 0x94, 0x8F, 0x9C, 0xD0, +0x8C, 0x2E, 0x9C, 0xAF, 0x9C, 0x6E, 0xA4, 0x8E, +0x8C, 0x0D, 0x7B, 0xED, 0x7B, 0xCD, 0x7B, 0xED, +0x94, 0xB1, 0x8C, 0x4F, 0x7B, 0xCE, 0x8C, 0x70, +0x9C, 0xD1, 0x94, 0x70, 0x8B, 0xED, 0xA4, 0x8F, +0x7B, 0xAC, 0x84, 0x0D, 0x8C, 0x2E, 0x84, 0x0E, +0x84, 0x0E, 0x8C, 0x4F, 0x7B, 0xAD, 0x4A, 0x27, +0x6B, 0x4B, 0x83, 0xCD, 0x94, 0x6F, 0x8C, 0x0D, +0x8B, 0xEC, 0x8C, 0x2D, 0x94, 0x4E, 0xA4, 0xF0, +0xB5, 0x73, 0x8C, 0x6F, 0x9C, 0xB0, 0xC5, 0xF4, +0xD6, 0x55, 0xB5, 0x30, 0xAC, 0xCF, 0x9C, 0x4D, +0x9C, 0x4D, 0xB5, 0x10, 0xB5, 0x51, 0xA4, 0xD0, +0x9C, 0x8F, 0xA4, 0xF2, 0xDE, 0xFB, 0xBD, 0xF8, +0xAD, 0x34, 0x9C, 0x90, 0x94, 0x2E, 0x94, 0x0D, +0x94, 0x2D, 0xA4, 0xCF, 0x94, 0x4D, 0x94, 0x2D, +0x94, 0x2D, 0x8C, 0x0D, 0x94, 0x4E, 0x9C, 0xD1, +0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x12, 0xBD, 0xB5, +0xAD, 0x33, 0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x53, +0xBD, 0x94, 0xB5, 0x54, 0xB5, 0x53, 0xB5, 0x53, +0xAD, 0x53, 0xB5, 0x74, 0xB5, 0x74, 0xB5, 0x74, +0xAD, 0x32, 0xA4, 0xF1, 0xA5, 0x12, 0xA5, 0x12, +0xA5, 0x12, 0x9C, 0xB1, 0xB5, 0x74, 0xBD, 0xB5, +0xAD, 0x53, 0x94, 0x90, 0x9C, 0x90, 0x94, 0x70, +0x94, 0x6F, 0x8C, 0x0E, 0x84, 0x0F, 0x84, 0x0E, +0x84, 0x0E, 0x94, 0x2F, 0x9C, 0xB0, 0xA5, 0x12, +0xA4, 0xF1, 0x8C, 0x0F, 0x7B, 0xAD, 0x73, 0x8C, +0x8C, 0x2F, 0xAD, 0x12, 0x7B, 0xAC, 0xB5, 0x94, +0xA4, 0xD1, 0x94, 0x8F, 0x94, 0x6F, 0x83, 0xCD, +0x83, 0xED, 0xA4, 0xF1, 0xA5, 0x12, 0x94, 0x4F, +0x7B, 0xAD, 0x9C, 0xB0, 0xB5, 0x92, 0xC5, 0xF3, +0xCE, 0x14, 0xBD, 0xB3, 0xBD, 0xB3, 0xB5, 0x92, +0xD6, 0x55, 0xDE, 0xB7, 0x94, 0x4E, 0xCE, 0x35, +0xCE, 0x35, 0xD6, 0x55, 0xCE, 0x35, 0xD6, 0x96, +0xD6, 0x75, 0xBD, 0xB2, 0xA4, 0xF0, 0xA4, 0xF1, +0x6B, 0x4B, 0x5A, 0xCA, 0x5A, 0xC9, 0x7B, 0x8C, +0x94, 0x6F, 0xA5, 0x31, 0xA5, 0x11, 0x9C, 0x90, +0x7B, 0xCC, 0x9C, 0xB0, 0xA4, 0xF1, 0xB5, 0x73, +0xB5, 0x73, 0xB5, 0xB4, 0xAD, 0x53, 0xB5, 0xB4, +0xB5, 0xB4, 0xAD, 0x93, 0x9C, 0xB1, 0x7B, 0xAD, +0x94, 0x6F, 0xAD, 0x11, 0xA4, 0xF1, 0xB5, 0x73, +0x7B, 0xAD, 0x7B, 0xCE, 0x84, 0x2F, 0x9C, 0xD1, +0xA4, 0xF1, 0x9C, 0xAF, 0xA4, 0xD0, 0x9C, 0x8F, +0x9C, 0xB0, 0xA5, 0x12, 0xA5, 0x12, 0xAD, 0x33, +0xBD, 0xB5, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x12, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0x9C, 0xB0, +0xB5, 0x52, 0xB5, 0x51, 0xB5, 0x72, 0xAD, 0x12, +0xB5, 0x53, 0x9C, 0xB0, 0x9C, 0xB1, 0xA4, 0xF1, +0x9C, 0xB0, 0x9C, 0xD0, 0x94, 0x6F, 0xA4, 0xF1, +0xCE, 0x15, 0xC6, 0x15, 0xBD, 0xB4, 0xAD, 0x33, +0xAD, 0x12, 0xA4, 0xD2, 0x84, 0x0F, 0x7B, 0x8D, +0x73, 0x8C, 0x84, 0x0F, 0x8C, 0x50, 0x9C, 0xB1, +0x9C, 0xB1, 0x94, 0x91, 0x94, 0x91, 0x8C, 0x50, +0x84, 0x2F, 0x83, 0xEF, 0x73, 0x8E, 0x6B, 0x4C, +0x5A, 0xEB, 0x42, 0x29, 0x31, 0xA6, 0x29, 0x45, +0x21, 0x25, 0x21, 0x24, 0x21, 0x25, 0x29, 0x66, +0x39, 0xC8, 0x63, 0x2D, 0x84, 0x11, 0x84, 0x31, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x14, +0x9C, 0xF3, 0x84, 0x0F, 0x62, 0xC9, 0x6B, 0x09, +0x73, 0x4A, 0x73, 0x6B, 0x7B, 0x8B, 0x7B, 0x8B, +0x73, 0x4A, 0x73, 0x2A, 0x73, 0x4B, 0x7B, 0xAB, +0x83, 0xCC, 0x6B, 0x2A, 0x73, 0x4A, 0x5A, 0xA8, +0x8C, 0x4E, 0x7B, 0x8B, 0x9C, 0x8F, 0x83, 0xED, +0x73, 0x6A, 0x8C, 0x0D, 0x9C, 0x8E, 0x94, 0x6E, +0xAD, 0x10, 0xAC, 0xCF, 0x8B, 0xEC, 0x8C, 0x4F, +0x8C, 0x2F, 0x94, 0x6F, 0xAD, 0x12, 0x8C, 0x4F, +0x84, 0x0E, 0x84, 0x0E, 0x8C, 0x6F, 0x94, 0x4F, +0x94, 0x4F, 0x94, 0x6F, 0x9C, 0xD1, 0x9C, 0xD0, +0x7B, 0xAC, 0x63, 0x2A, 0x73, 0x6B, 0x73, 0x4B, +0x7B, 0xCD, 0x73, 0x8C, 0x8C, 0x4F, 0x4A, 0x48, +0x31, 0x85, 0x39, 0xC6, 0x31, 0x85, 0x39, 0xC6, +0x39, 0xC6, 0x42, 0x07, 0x4A, 0x28, 0x39, 0xC6, +0x5A, 0xCA, 0x6B, 0x2C, 0x73, 0x6D, 0x7B, 0xEF, +0x5A, 0xEB, 0x84, 0x30, 0x84, 0x30, 0x94, 0x92, +0x8C, 0x30, 0x42, 0x29, 0x7B, 0xEF, 0xAD, 0x73, +0xBD, 0xB4, 0x9C, 0xD1, 0x63, 0x0B, 0x4A, 0x28, +0x21, 0x04, 0x31, 0x86, 0x39, 0xE7, 0x4A, 0x48, +0x5A, 0xEB, 0x63, 0x2C, 0x6B, 0x6D, 0x73, 0x8E, +0x8C, 0x72, 0x9C, 0xF4, 0xB5, 0x76, 0x9C, 0xF4, +0xA5, 0x15, 0xC5, 0xF8, 0xCE, 0x5A, 0xDE, 0xDC, +0xCE, 0x59, 0xAD, 0x54, 0xBD, 0xD5, 0xB5, 0xB4, +0xAD, 0x53, 0x94, 0x6F, 0x7B, 0xAC, 0xA5, 0x11, +0xA4, 0xD1, 0x8C, 0x2E, 0x9C, 0x8F, 0x94, 0x2D, +0x94, 0x6F, 0x73, 0xAC, 0x6B, 0x6C, 0x7C, 0x0E, +0xA5, 0x33, 0x94, 0x90, 0x8C, 0x70, 0x9C, 0xD2, +0x9C, 0xF2, 0x9C, 0xD1, 0x94, 0x2E, 0x9C, 0x8F, +0x8C, 0x0E, 0x94, 0x90, 0x94, 0x6F, 0x8C, 0x4F, +0x8C, 0x4F, 0xA5, 0x12, 0x7B, 0xAD, 0x6B, 0x2C, +0x73, 0x8C, 0x94, 0x90, 0xA5, 0x11, 0x94, 0x8F, +0x8C, 0x4E, 0x94, 0x6F, 0x94, 0x6F, 0xAD, 0x52, +0xCE, 0x76, 0xBD, 0xD4, 0xC6, 0x15, 0xDE, 0xB6, +0xD6, 0x55, 0xBD, 0x92, 0xA4, 0xAF, 0x9C, 0x6D, +0xAC, 0xF0, 0xB5, 0x71, 0xC6, 0x14, 0xCE, 0x35, +0xBD, 0xD5, 0xCE, 0x58, 0xC6, 0x18, 0x5A, 0xAC, +0x94, 0xB2, 0xD6, 0x98, 0xC5, 0xF4, 0xC5, 0xF4, +0xBD, 0xB3, 0xCE, 0x36, 0xB5, 0x73, 0xAD, 0x52, +0xAD, 0x11, 0xA5, 0x11, 0xBD, 0xD4, 0xCE, 0x36, +0xD6, 0x76, 0xCE, 0x56, 0x94, 0x70, 0xB5, 0x74, +0x9C, 0xB1, 0xCE, 0x16, 0xB5, 0x53, 0x94, 0x70, +0x8C, 0x0E, 0x94, 0x6F, 0x9C, 0x90, 0xA4, 0xF1, +0xAD, 0x12, 0x94, 0x4F, 0x9C, 0xB1, 0x94, 0x90, +0x94, 0x4F, 0x9C, 0xB0, 0x9C, 0xB0, 0x83, 0xED, +0x8C, 0x2E, 0x9C, 0xB0, 0xB5, 0x74, 0x94, 0x6F, +0x94, 0x6F, 0xA4, 0xF1, 0xA5, 0x12, 0xBD, 0x94, +0xA4, 0xF1, 0xA5, 0x12, 0xA5, 0x12, 0xAD, 0x53, +0xB5, 0x53, 0xAD, 0x32, 0xA4, 0xF1, 0x9C, 0x90, +0xA4, 0xF2, 0xA4, 0xF2, 0xAD, 0x33, 0xB5, 0x95, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x53, 0xBD, 0xD4, +0xB5, 0x94, 0xBD, 0x94, 0xBD, 0xB5, 0xB5, 0x74, +0xBD, 0x94, 0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x33, +0xBD, 0xB5, 0xBD, 0xB4, 0xAD, 0x51, 0x9C, 0xAF, +0x9C, 0xAF, 0x9C, 0xB0, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x90, 0x94, 0x8F, 0x83, 0xCC, 0x94, 0x6F, +0xA4, 0xF1, 0xA4, 0xD0, 0xA4, 0xF0, 0xAD, 0x51, +0xAD, 0x10, 0xA4, 0xAF, 0xA4, 0xAF, 0xAD, 0x11, +0xA4, 0xD1, 0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x2E, +0x9C, 0xB0, 0x9C, 0xAF, 0x9C, 0xB0, 0x9C, 0xB0, +0x9C, 0xB0, 0xA4, 0xD1, 0xB5, 0x73, 0xB5, 0xB4, +0xAD, 0x32, 0xB5, 0x94, 0xAD, 0x53, 0xB5, 0xB4, +0xBD, 0xD5, 0xC5, 0xF5, 0xB5, 0x94, 0xAD, 0x53, +0xB5, 0x74, 0x9C, 0xD0, 0x94, 0x6F, 0xA4, 0xD1, +0x8C, 0x4F, 0x94, 0x90, 0x73, 0xAE, 0x94, 0x70, +0x9C, 0xB0, 0x94, 0x2E, 0x94, 0x4E, 0x8C, 0x2E, +0x9C, 0xB0, 0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xD1, +0xA4, 0xF2, 0xB5, 0x94, 0xAD, 0x12, 0x94, 0x70, +0x94, 0x6F, 0xA4, 0xF1, 0xA5, 0x12, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x31, 0xB5, 0x72, 0xAD, 0x12, +0xB5, 0x53, 0x9C, 0x90, 0x9C, 0xB1, 0x9C, 0xB0, +0x9C, 0xB1, 0x9C, 0xB0, 0x94, 0x6F, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0x8F, 0xA4, 0xF1, 0xA4, 0xF1, +0xB5, 0x73, 0xA4, 0xF2, 0x9C, 0xD1, 0xAD, 0x53, +0xAD, 0x33, 0xB5, 0x94, 0x83, 0xCE, 0x73, 0x6C, +0x83, 0xCE, 0x8C, 0x2F, 0x9C, 0xB2, 0xA4, 0xD2, +0x9C, 0xB1, 0x9C, 0xB1, 0x94, 0x70, 0x8C, 0x4F, +0x84, 0x0F, 0x73, 0xAD, 0x63, 0x0B, 0x4A, 0x8A, +0x42, 0x08, 0x31, 0xA7, 0x29, 0x86, 0x29, 0x86, +0x31, 0xA7, 0x52, 0x8B, 0x6B, 0x4E, 0x84, 0x11, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x55, 0x9D, 0x14, +0x9C, 0xF4, 0x7B, 0xCF, 0x62, 0xC9, 0x73, 0x4A, +0x7B, 0x6A, 0x83, 0xAB, 0x8B, 0xEC, 0x94, 0x4D, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0x8F, 0x9C, 0x6E, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xCF, 0xA4, 0x8F, +0x9C, 0x8F, 0x94, 0x4E, 0x94, 0x2D, 0x9C, 0x6E, +0x94, 0x4E, 0x94, 0x2D, 0x94, 0x2D, 0x8B, 0xEC, +0x9C, 0x4D, 0xB4, 0xEF, 0x94, 0x0C, 0x73, 0x6B, +0x7B, 0x8C, 0x73, 0x6B, 0x83, 0xED, 0x8C, 0x4E, +0x8C, 0x0E, 0x94, 0x4F, 0x9C, 0xB0, 0x8C, 0x4F, +0x94, 0x6F, 0x73, 0x6B, 0x9C, 0x90, 0xAD, 0x52, +0x9C, 0xD1, 0x83, 0xEE, 0x7B, 0xAC, 0x8C, 0x2F, +0x94, 0x70, 0x9C, 0xD1, 0x94, 0x70, 0x63, 0x2B, +0x4A, 0x48, 0x39, 0xE7, 0x39, 0xC6, 0x41, 0xE7, +0x42, 0x07, 0x42, 0x28, 0x4A, 0x48, 0x4A, 0x48, +0x5A, 0xCA, 0x63, 0x2C, 0x7B, 0xCE, 0x8C, 0x71, +0x94, 0xB2, 0x7B, 0xEF, 0x84, 0x31, 0xA4, 0xF4, +0x94, 0x71, 0x4A, 0x69, 0x84, 0x30, 0xBD, 0xB4, +0xB5, 0x73, 0xB5, 0x94, 0x9C, 0xB0, 0x94, 0xB0, +0x63, 0x0A, 0x42, 0x27, 0x31, 0x85, 0x41, 0xE7, +0x52, 0xAA, 0x63, 0x2C, 0x6B, 0x4D, 0x5A, 0xEB, +0x6B, 0x6D, 0x7B, 0xAF, 0x94, 0xB3, 0xA5, 0x14, +0xBD, 0xD8, 0xCE, 0x59, 0x94, 0x93, 0xA5, 0x15, +0xCE, 0x7A, 0xC6, 0x18, 0xBD, 0xF6, 0xB5, 0x94, +0xAD, 0x53, 0x8C, 0x4E, 0x73, 0x8B, 0x94, 0x8F, +0xA5, 0x11, 0xA5, 0x11, 0x9C, 0x8F, 0x9C, 0x8E, +0x94, 0x6F, 0x73, 0x8C, 0x73, 0x8C, 0x84, 0x2F, +0x8C, 0x4F, 0x4A, 0x48, 0x8C, 0x70, 0xA5, 0x33, +0xA5, 0x32, 0xA5, 0x12, 0x94, 0x6F, 0x9C, 0x8F, +0x94, 0x6F, 0xA5, 0x12, 0x94, 0x90, 0x9C, 0xD1, +0xA5, 0x32, 0xB5, 0x94, 0x7B, 0xAD, 0x7B, 0xEE, +0x84, 0x2F, 0x94, 0xB1, 0xAD, 0x32, 0xA4, 0xF1, +0x8C, 0x4E, 0x94, 0x8F, 0xA4, 0xF1, 0xB5, 0x93, +0xD6, 0x77, 0xCE, 0x56, 0xD6, 0x76, 0xDE, 0x96, +0xD6, 0x55, 0xBD, 0x72, 0xA4, 0xCF, 0xA4, 0xAE, +0xAD, 0x31, 0xBD, 0xD3, 0xC5, 0xF4, 0xCE, 0x55, +0xCE, 0x36, 0xCE, 0x78, 0x9C, 0xD3, 0x52, 0xAB, +0x94, 0xB2, 0xD6, 0xB8, 0xC6, 0x15, 0xCE, 0x35, +0xBD, 0xF4, 0xD6, 0x77, 0xC6, 0x15, 0xC5, 0xF5, +0xC5, 0xF5, 0xC6, 0x15, 0xB5, 0x93, 0xCE, 0x36, +0xD6, 0x76, 0xE6, 0xD8, 0x94, 0x90, 0xBD, 0x94, +0xA4, 0xD1, 0xCE, 0x57, 0xBD, 0xD5, 0x9C, 0xD1, +0x8C, 0x4F, 0xAD, 0x12, 0xA5, 0x11, 0xA4, 0xF1, +0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x73, +0xA5, 0x12, 0xAD, 0x52, 0xA5, 0x11, 0xAD, 0x32, +0xA4, 0xF1, 0x94, 0x6F, 0xBD, 0x94, 0xBD, 0xB4, +0xBD, 0x94, 0xAD, 0x52, 0x8C, 0x2E, 0xB5, 0x73, +0xA4, 0xF1, 0xAD, 0x12, 0xA5, 0x12, 0xB5, 0x73, +0xC5, 0xD4, 0xBD, 0x93, 0xB5, 0x32, 0x94, 0x6F, +0x8C, 0x2E, 0x94, 0x4F, 0xAD, 0x12, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0xB4, 0x9C, 0x90, 0xB5, 0x53, +0xA4, 0xF1, 0xAD, 0x12, 0xA5, 0x11, 0x9C, 0xB0, +0xA4, 0xD1, 0xAC, 0xF1, 0xAD, 0x12, 0xB5, 0x53, +0xA4, 0xF1, 0xB5, 0x53, 0xAD, 0x52, 0xAD, 0x32, +0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x52, 0xB5, 0x53, +0xBD, 0x94, 0xCD, 0xF6, 0xA4, 0xD1, 0x94, 0x6F, +0xB5, 0x52, 0xB5, 0x52, 0xAD, 0x32, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x11, 0xBD, 0xB4, 0xC5, 0xF5, +0xCD, 0xF5, 0xBD, 0xB4, 0xBD, 0x94, 0xBD, 0x94, +0xC5, 0xB4, 0xBD, 0xB4, 0xC5, 0xD5, 0xC5, 0xD5, +0xCE, 0x16, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xC5, 0xD5, 0xBD, 0x94, 0xB5, 0x32, 0xB5, 0x52, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF2, 0xB5, 0x32, 0xC5, 0xB4, +0xB5, 0x53, 0xB5, 0x73, 0xA4, 0xF2, 0x9C, 0xD1, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x52, 0xAD, 0x32, +0xAC, 0xF2, 0xA4, 0xF1, 0x9C, 0xD1, 0x8C, 0x2F, +0x94, 0x50, 0xA4, 0xF2, 0xA4, 0xD1, 0x9C, 0x90, +0x94, 0x90, 0x94, 0x6F, 0x94, 0x90, 0x94, 0x6F, +0x9C, 0xB0, 0x8C, 0x2E, 0xBD, 0x93, 0xC5, 0xD4, +0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x73, 0x9C, 0xB0, +0xA4, 0xF1, 0xA5, 0x12, 0xA4, 0xF2, 0xA4, 0xF1, +0xA4, 0xF2, 0x9C, 0xB0, 0x94, 0x6F, 0x83, 0xCD, +0x8C, 0x2E, 0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x94, +0xB5, 0x74, 0xBD, 0xB5, 0xBD, 0xD5, 0xAD, 0x74, +0xA5, 0x13, 0x83, 0xEE, 0x6B, 0x2C, 0x83, 0xEE, +0x9C, 0xB1, 0xAD, 0x13, 0xAD, 0x33, 0xA4, 0xF2, +0x94, 0x91, 0x8C, 0x2F, 0x7B, 0xEE, 0x6B, 0x6D, +0x63, 0x0C, 0x52, 0x8A, 0x3A, 0x08, 0x31, 0xA7, +0x29, 0x66, 0x29, 0x86, 0x31, 0xA6, 0x39, 0xE8, +0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x35, 0x9D, 0x14, +0x94, 0xD3, 0x83, 0xEF, 0x6B, 0x2B, 0x6B, 0x2A, +0x62, 0xE9, 0x62, 0xE9, 0x73, 0x4A, 0x7B, 0x6B, +0x83, 0xCB, 0x83, 0xCB, 0x8B, 0xEC, 0x8B, 0xCC, +0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, 0x94, 0x0D, +0xAC, 0xD0, 0xBD, 0x51, 0xB5, 0x30, 0xA4, 0xAF, +0xAC, 0xD0, 0xAC, 0xF0, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xEF, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x8F, 0x9C, 0x6E, +0x9C, 0x6E, 0x94, 0x4E, 0x8C, 0x0D, 0x83, 0xCC, +0x83, 0xCC, 0x83, 0xCC, 0x7B, 0x8C, 0x7B, 0x8B, +0x83, 0xCC, 0x7B, 0x8B, 0x6B, 0x2A, 0x62, 0xE9, +0x62, 0xE9, 0x63, 0x0A, 0x62, 0xE9, 0x6B, 0x2A, +0x52, 0x68, 0x39, 0xC6, 0x39, 0xC6, 0x39, 0xC6, +0x39, 0xC6, 0x31, 0xA6, 0x42, 0x07, 0x4A, 0x48, +0x5A, 0xCA, 0x63, 0x2C, 0x83, 0xEF, 0x8C, 0x50, +0x9C, 0xB2, 0x94, 0x71, 0xB5, 0x96, 0xBD, 0xD7, +0x8C, 0x51, 0x31, 0x86, 0x7B, 0xEE, 0xB5, 0x73, +0xB5, 0x73, 0xBD, 0xB4, 0xB5, 0x93, 0xA5, 0x11, +0x7B, 0xAC, 0x9C, 0x90, 0x4A, 0x27, 0x42, 0x07, +0x42, 0x27, 0x52, 0x89, 0x5A, 0xEB, 0x63, 0x0B, +0x5A, 0xEB, 0x63, 0x0C, 0x94, 0x72, 0xA5, 0x35, +0xAD, 0x55, 0x8C, 0x51, 0x83, 0xF0, 0x8C, 0x31, +0xC6, 0x18, 0xE7, 0x1C, 0x94, 0xB2, 0xB5, 0x94, +0xBD, 0xF5, 0xA5, 0x12, 0xA5, 0x11, 0x9C, 0xD0, +0x8C, 0x6E, 0x9C, 0xD0, 0x83, 0xCB, 0x9C, 0x8E, +0x8C, 0x4E, 0x8C, 0x2E, 0x84, 0x2E, 0x8C, 0x6F, +0x84, 0x0E, 0x4A, 0x48, 0x8C, 0x70, 0xB5, 0x94, +0xB5, 0x94, 0xB5, 0x94, 0x9C, 0x8F, 0xA4, 0xAF, +0x94, 0x6F, 0x9C, 0xF2, 0xA5, 0x12, 0xAD, 0x73, +0xAD, 0x73, 0xB5, 0x73, 0x8C, 0x2F, 0x8C, 0x70, +0x8C, 0x90, 0x9C, 0xF1, 0xB5, 0x93, 0xBD, 0x93, +0x9C, 0x8F, 0x8C, 0x4E, 0xAD, 0x32, 0xBD, 0xF4, +0xD6, 0x77, 0xC6, 0x15, 0xD6, 0x96, 0xDE, 0xB6, +0xD6, 0x76, 0xBD, 0x92, 0xAC, 0xEF, 0x9C, 0x8E, +0xA4, 0xAF, 0xAD, 0x31, 0xB5, 0x72, 0xC6, 0x15, +0xC6, 0x15, 0xCE, 0x78, 0x9C, 0xF3, 0x8C, 0x72, +0xA5, 0x54, 0xD6, 0x98, 0xD6, 0x76, 0xD6, 0x76, +0xC6, 0x15, 0xCE, 0x36, 0xCE, 0x35, 0xCE, 0x35, +0xD6, 0x97, 0xD6, 0x56, 0xAD, 0x52, 0xCE, 0x36, +0xDE, 0x97, 0xDE, 0xD8, 0x94, 0x6F, 0xB5, 0x74, +0xA4, 0xF2, 0xCE, 0x36, 0xBD, 0xB4, 0x9C, 0xB0, +0x94, 0x70, 0xA4, 0xF1, 0xAD, 0x32, 0xA4, 0xF1, +0xB5, 0x73, 0xB5, 0x73, 0xBD, 0xD5, 0xC5, 0xF5, +0xA4, 0xF1, 0xAD, 0x12, 0x83, 0xED, 0x9C, 0xB0, +0xB5, 0x94, 0x9C, 0xB0, 0xBD, 0xB4, 0xB5, 0xB4, +0xB5, 0x94, 0xAD, 0x32, 0x8C, 0x2E, 0xA5, 0x12, +0x9C, 0xB0, 0x94, 0x8F, 0x9C, 0xB0, 0xA5, 0x11, +0x9C, 0xAF, 0xAD, 0x10, 0xB5, 0x31, 0xA4, 0xF1, +0x94, 0x6F, 0x9C, 0x90, 0xBD, 0xB5, 0xC5, 0xD5, +0xBD, 0xB4, 0xB5, 0x73, 0x94, 0x6F, 0xA4, 0xF1, +0xA4, 0xD0, 0x9C, 0xAF, 0x94, 0x4E, 0x8C, 0x2D, +0xA4, 0xD0, 0xAD, 0x32, 0xBD, 0x93, 0xBD, 0xB4, +0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0x8F, 0x9C, 0x8F, +0x9C, 0x8F, 0x9C, 0xB0, 0xAD, 0x32, 0xA4, 0xF1, +0x94, 0x4F, 0xB5, 0x53, 0x9C, 0x90, 0xC5, 0xD4, +0xBD, 0x93, 0xBD, 0x94, 0xC5, 0xF5, 0xC5, 0xB4, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, 0xA4, 0xF1, +0xAD, 0x32, 0xBD, 0x94, 0xAC, 0xF1, 0x9C, 0xB0, +0x9C, 0x8F, 0x94, 0x4F, 0xA4, 0xD1, 0x9C, 0x6F, +0x8C, 0x0E, 0x8C, 0x0D, 0x94, 0x4F, 0x9C, 0x90, +0xA4, 0xD1, 0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xD1, +0xB5, 0x73, 0xB5, 0x32, 0xA4, 0xF1, 0xAD, 0x12, +0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x73, 0xB5, 0x32, 0xAD, 0x12, 0xBD, 0x94, +0xCE, 0x36, 0xCD, 0xF6, 0xCD, 0xF5, 0xCE, 0x16, +0xCE, 0x36, 0xCE, 0x16, 0xCE, 0x16, 0xCE, 0x36, +0xCE, 0x36, 0xCE, 0x16, 0xD6, 0x36, 0xCD, 0xF5, +0xC5, 0xD5, 0xC5, 0xB4, 0xBD, 0x94, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x32, 0xAC, 0xF1, +0x94, 0x4F, 0x83, 0xED, 0x8C, 0x0E, 0x83, 0xED, +0x83, 0xCD, 0x7B, 0x8C, 0x7B, 0xAD, 0x7B, 0xAD, +0x7B, 0xAD, 0x83, 0xCD, 0x8C, 0x2F, 0x94, 0x4F, +0x94, 0x4F, 0x94, 0x90, 0xAD, 0x12, 0xBD, 0xB4, +0xBD, 0xD5, 0xC5, 0xD5, 0xCE, 0x36, 0xC6, 0x16, +0xCE, 0x37, 0xCE, 0x17, 0x9C, 0xB1, 0x8C, 0x2F, +0x7B, 0xAD, 0x73, 0x8C, 0x83, 0xEE, 0x9C, 0xD1, +0xAD, 0x33, 0xA5, 0x13, 0x9C, 0xB1, 0x8C, 0x50, +0x84, 0x0F, 0x7B, 0xEF, 0x73, 0xAE, 0x6B, 0x8D, +0x63, 0x0C, 0x4A, 0x69, 0x31, 0xC7, 0x31, 0x86, +0x94, 0xD3, 0x9D, 0x14, 0x9C, 0xF4, 0x94, 0xB3, +0x94, 0xB3, 0x83, 0xEF, 0x73, 0x8C, 0x7B, 0x8C, +0x7B, 0xAC, 0x6B, 0x2A, 0x7B, 0x8B, 0x8C, 0x0D, +0x94, 0x2E, 0x94, 0x2D, 0x94, 0x2E, 0x8C, 0x0D, +0x94, 0x2D, 0x9C, 0x6E, 0x9C, 0x8F, 0x73, 0x2A, +0x6A, 0xE8, 0x94, 0x2D, 0xA4, 0x8E, 0x9C, 0x6E, +0x83, 0xAB, 0x83, 0x8B, 0x7B, 0x6B, 0x7B, 0x6B, +0x73, 0x29, 0x73, 0x29, 0x8C, 0x0D, 0x7B, 0x6A, +0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xED, 0x8B, 0xCC, +0x8B, 0xEC, 0x8B, 0xED, 0x94, 0x0D, 0x83, 0xCC, +0x83, 0xAC, 0x8B, 0xED, 0x8C, 0x0D, 0x9C, 0x4E, +0x9C, 0x4E, 0xAC, 0xD0, 0x94, 0x0D, 0x8C, 0x2E, +0x94, 0x0E, 0x94, 0x2E, 0x94, 0x4E, 0x94, 0x2E, +0x8C, 0x0E, 0x52, 0x68, 0x31, 0xA6, 0x39, 0xC6, +0x31, 0x85, 0x31, 0x85, 0x42, 0x07, 0x4A, 0x28, +0x52, 0x89, 0x52, 0xAA, 0x63, 0x0B, 0x73, 0x8D, +0x8C, 0x30, 0x94, 0x71, 0xB5, 0x96, 0xBD, 0xD7, +0xB5, 0x76, 0x39, 0xC7, 0x39, 0xE7, 0x8C, 0x2E, +0x8C, 0x0D, 0x83, 0xCC, 0x83, 0xCC, 0x83, 0xAC, +0x83, 0xCD, 0xAD, 0x10, 0x9C, 0x6E, 0x6B, 0x0A, +0x42, 0x07, 0x4A, 0x69, 0x52, 0x89, 0x63, 0x0C, +0x52, 0xAA, 0x5A, 0xEC, 0x63, 0x2D, 0x84, 0x10, +0xA5, 0x14, 0x73, 0x8E, 0x63, 0x0D, 0x8C, 0x51, +0x94, 0xB3, 0xAD, 0x55, 0x7B, 0xEF, 0xB5, 0x74, +0xB5, 0x74, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xD0, +0x8C, 0x4E, 0x9C, 0x8F, 0x8B, 0xEC, 0x94, 0x0D, +0x62, 0xC8, 0x6B, 0x4A, 0x73, 0x6B, 0x83, 0xED, +0x83, 0xED, 0x4A, 0x68, 0x7C, 0x0E, 0xAD, 0x73, +0xBD, 0xB4, 0xB5, 0x73, 0x9C, 0x8E, 0xA4, 0xAF, +0x8C, 0x2D, 0xA5, 0x12, 0xA4, 0xF1, 0xAD, 0x32, +0xAD, 0x53, 0xAD, 0x32, 0x9C, 0xD1, 0x94, 0x90, +0x8C, 0x4F, 0xA5, 0x12, 0xBD, 0xD4, 0xBD, 0xD4, +0x94, 0x8F, 0x7B, 0xAC, 0xB5, 0x93, 0xCE, 0x35, +0xCE, 0x56, 0xAD, 0x51, 0xCE, 0x14, 0xD6, 0x96, +0xDE, 0xB6, 0xBD, 0x92, 0xB5, 0x10, 0x94, 0x2C, +0x9C, 0x8E, 0xB5, 0x51, 0xAD, 0x51, 0xC5, 0xF4, +0xBD, 0xD4, 0xCE, 0x78, 0xAD, 0x55, 0xA4, 0xF4, +0xC6, 0x17, 0xCE, 0x36, 0xCE, 0x35, 0xB5, 0x93, +0xCE, 0x55, 0xCE, 0x56, 0xBD, 0xD4, 0xCE, 0x36, +0xD6, 0x97, 0xCE, 0x55, 0xCE, 0x56, 0xD6, 0x77, +0xDE, 0xB7, 0xDE, 0xD8, 0x8C, 0x4F, 0xB5, 0x74, +0xA4, 0xF2, 0xCE, 0x37, 0xBD, 0x94, 0x9C, 0x90, +0x94, 0x90, 0xA4, 0xF1, 0xA5, 0x11, 0xAD, 0x32, +0xBD, 0xD5, 0xB5, 0x73, 0xB5, 0x73, 0xCE, 0x36, +0xB5, 0x73, 0xB5, 0x74, 0xAD, 0x12, 0x94, 0x90, +0xCE, 0x36, 0xC6, 0x16, 0xC5, 0xF5, 0xC6, 0x16, +0xC5, 0xF5, 0xB5, 0x94, 0x8C, 0x2E, 0xA4, 0xF2, +0x94, 0x6F, 0x8C, 0x2E, 0x94, 0x8F, 0x9C, 0xAF, +0xA4, 0xAF, 0xC5, 0xB3, 0xC5, 0xB3, 0xA4, 0xF1, +0x83, 0xED, 0xA4, 0xD1, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x32, 0x94, 0x6F, 0xB5, 0x32, +0xB5, 0x72, 0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xD0, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x52, 0xAD, 0x11, +0x94, 0x4E, 0x94, 0x6E, 0x8C, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0x8C, 0x2D, 0x9C, 0x8F, 0xAD, 0x12, +0x94, 0x4F, 0xBD, 0xB4, 0xBD, 0x93, 0xCE, 0x15, +0xC5, 0xF5, 0xC5, 0xB4, 0xCE, 0x15, 0xC5, 0xF4, +0xC5, 0xF5, 0xC5, 0xD4, 0xBD, 0xB3, 0xC5, 0xF5, +0xBD, 0xB4, 0xAD, 0x32, 0x8C, 0x2E, 0x8C, 0x2E, +0xA4, 0xF1, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xD1, 0x94, 0x90, 0x9C, 0x90, 0x94, 0x90, +0x8C, 0x2F, 0xAD, 0x12, 0xBD, 0xB4, 0xCE, 0x36, +0xCE, 0x36, 0xCE, 0x16, 0xD6, 0x57, 0xD6, 0x57, +0xA4, 0xF1, 0x83, 0xED, 0x83, 0xED, 0xAC, 0xF2, +0xB5, 0x32, 0x94, 0x4F, 0x94, 0x4F, 0x9C, 0x90, +0x9C, 0x6F, 0x9C, 0xB0, 0x94, 0x6F, 0x8C, 0x4E, +0x94, 0x6F, 0xA4, 0xF1, 0x9C, 0x90, 0x9C, 0x6F, +0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x53, 0xAD, 0x11, +0xB5, 0x32, 0xB5, 0x32, 0xAD, 0x11, 0xAC, 0xF1, +0xB5, 0x32, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x53, +0xB5, 0x33, 0xB5, 0x53, 0xBD, 0x73, 0xBD, 0x94, +0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x53, 0x94, 0x70, +0xA4, 0xD1, 0xA4, 0xF1, 0xA4, 0xF1, 0xB5, 0x53, +0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x53, 0xB5, 0x52, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0xB4, 0x9C, 0x90, 0xA5, 0x12, +0xAD, 0x33, 0x9C, 0xD2, 0x94, 0x70, 0x7B, 0xAD, +0x7B, 0x8D, 0x7B, 0xCE, 0x8C, 0x50, 0x9C, 0xB1, +0x9C, 0xD2, 0x9C, 0xB1, 0x94, 0x70, 0x8C, 0x50, +0x8C, 0x50, 0x84, 0x30, 0x7B, 0xCE, 0x5A, 0xEB, +0xAD, 0x75, 0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x35, +0x9C, 0xF4, 0x84, 0x10, 0x6B, 0x2B, 0x7B, 0x8C, +0x83, 0xED, 0x84, 0x0D, 0x84, 0x0D, 0x8C, 0x0D, +0x8C, 0x0D, 0x8C, 0x2E, 0xA4, 0xB0, 0x94, 0x6F, +0x94, 0x4E, 0x7B, 0x8B, 0x8B, 0xED, 0x83, 0xCC, +0x94, 0x6E, 0xA4, 0xCF, 0xAC, 0xAF, 0xB5, 0x11, +0xA4, 0x8F, 0x9C, 0x4E, 0x9C, 0x4F, 0xA4, 0x90, +0x8B, 0xED, 0x8C, 0x2E, 0xA4, 0xB0, 0x8C, 0x0D, +0xA4, 0xB0, 0xA4, 0xD0, 0xB5, 0x52, 0x9C, 0x8F, +0x94, 0x4F, 0x9C, 0x8F, 0xA4, 0xF0, 0x94, 0x6E, +0x83, 0xCC, 0x9C, 0x6F, 0xB5, 0x32, 0xB5, 0x72, +0x83, 0xCC, 0x9C, 0x4E, 0x7B, 0x4A, 0x8B, 0xCD, +0x83, 0xCD, 0x83, 0xAC, 0x83, 0xAC, 0x7B, 0x8B, +0x8B, 0xEE, 0x73, 0x8D, 0x4A, 0x28, 0x39, 0xE7, +0x31, 0xA6, 0x31, 0x85, 0x39, 0xC6, 0x41, 0xE7, +0x4A, 0x28, 0x4A, 0x28, 0x5A, 0xCB, 0x73, 0x8D, +0x8C, 0x30, 0x94, 0x92, 0xA4, 0xF3, 0xC6, 0x18, +0xBD, 0xD7, 0x83, 0xF0, 0x20, 0xE4, 0x8C, 0x4F, +0xA4, 0xB0, 0x94, 0x2D, 0x9C, 0x8F, 0x9C, 0x6F, +0x9C, 0x6F, 0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x6F, +0x62, 0xEA, 0x52, 0x89, 0x5B, 0x0B, 0x73, 0xAE, +0x52, 0x8A, 0x5A, 0xAA, 0x4A, 0x49, 0x63, 0x0C, +0x8C, 0x51, 0x94, 0x92, 0xA4, 0xF4, 0xB5, 0x97, +0xB5, 0x96, 0xCE, 0x59, 0xB5, 0xB6, 0xCE, 0x38, +0xBD, 0x95, 0x9C, 0x70, 0x9C, 0x4E, 0x9C, 0x4D, +0x94, 0x4D, 0x9C, 0x6E, 0xA4, 0x8E, 0xBD, 0x51, +0xBD, 0x71, 0xB5, 0x30, 0xAC, 0xEF, 0xAC, 0xCF, +0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xD0, 0xA4, 0xAF, +0xA4, 0xCF, 0xAC, 0xCF, 0xB5, 0x30, 0xA4, 0x8E, +0x83, 0xCC, 0x8B, 0xEC, 0x83, 0xAB, 0x83, 0xEC, +0x94, 0x4D, 0x83, 0xEC, 0x83, 0xED, 0x7B, 0xAC, +0x83, 0xED, 0x9C, 0xAF, 0xAD, 0x52, 0xAD, 0x31, +0x8C, 0x4E, 0x5A, 0xC8, 0xAD, 0x32, 0xCE, 0x56, +0xBD, 0xB3, 0x94, 0x6E, 0xBD, 0xB3, 0xD6, 0x55, +0xDE, 0x76, 0xA4, 0xAF, 0xB5, 0x30, 0x94, 0x0C, +0xA4, 0xEF, 0xBD, 0xD3, 0xB5, 0x72, 0xC5, 0xD4, +0xB5, 0x72, 0xC6, 0x17, 0xB5, 0x96, 0xA5, 0x35, +0xD6, 0x78, 0xD6, 0x76, 0xCE, 0x35, 0xBD, 0xD4, +0xCE, 0x15, 0xD6, 0x76, 0xBD, 0xD4, 0xD6, 0x76, +0xDE, 0xB7, 0xD6, 0x76, 0xD6, 0x97, 0xDE, 0x97, +0xDE, 0xB8, 0xDE, 0xD8, 0x94, 0x70, 0xB5, 0x53, +0xB5, 0x73, 0xCE, 0x36, 0xAD, 0x53, 0x9C, 0xB0, +0x9C, 0xD0, 0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0xB4, +0xC5, 0xF5, 0xBD, 0xD5, 0xCE, 0x36, 0xC5, 0xF5, +0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0xD5, 0xAD, 0x33, +0xD6, 0x77, 0xCE, 0x57, 0xC5, 0xF5, 0xC6, 0x16, +0xBD, 0xD5, 0xBD, 0xB4, 0x8C, 0x4E, 0x9C, 0xD0, +0x8C, 0x2E, 0x7B, 0xAC, 0x8C, 0x2E, 0x7B, 0xCC, +0x8C, 0x0D, 0x9C, 0xAF, 0xA4, 0xD0, 0xA4, 0xF1, +0x7B, 0xAC, 0xA5, 0x12, 0xBD, 0xB4, 0xAD, 0x32, +0xB5, 0x73, 0xA4, 0xF1, 0x8C, 0x2E, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xCF, 0x9C, 0x8F, 0x9C, 0x6E, +0xB5, 0x73, 0x9C, 0xB0, 0xAD, 0x11, 0xA4, 0xF0, +0x9C, 0xAF, 0xA4, 0xF1, 0x9C, 0xAF, 0x9C, 0x8F, +0x8C, 0x2E, 0x94, 0x6E, 0xAD, 0x11, 0xB5, 0x73, +0x94, 0x6F, 0xBD, 0x94, 0xA4, 0xF1, 0xAD, 0x31, +0xBD, 0xB3, 0xC5, 0xF4, 0xCE, 0x35, 0xC5, 0xD4, +0xC5, 0xF4, 0xC5, 0xF4, 0xC5, 0xD4, 0xBD, 0xD4, +0xBD, 0x93, 0xB5, 0x52, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xF1, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD1, +0x84, 0x0E, 0xAD, 0x32, 0xA5, 0x12, 0xA4, 0xF1, +0xA4, 0xD1, 0x9C, 0x90, 0xA4, 0xD1, 0xA4, 0xF1, +0x9C, 0x90, 0x9C, 0xB0, 0x9C, 0xD1, 0x9C, 0x90, +0xAD, 0x32, 0xA4, 0xF1, 0xAD, 0x11, 0xA4, 0xD1, +0xAD, 0x12, 0xB5, 0x73, 0xBD, 0x94, 0xB5, 0x93, +0xB5, 0x73, 0xBD, 0xD5, 0xC5, 0xF5, 0xB5, 0x73, +0xA5, 0x11, 0x94, 0x6F, 0xA4, 0xD0, 0x9C, 0x6F, +0x9C, 0x6F, 0x9C, 0x6F, 0xA4, 0xB0, 0xA4, 0xD0, +0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xF1, 0xAD, 0x11, +0xAC, 0xF1, 0xA4, 0xF1, 0x9C, 0x8F, 0x94, 0x4F, +0x9C, 0x6F, 0xAC, 0xF1, 0xAD, 0x11, 0x94, 0x6F, +0xAC, 0xF1, 0x9C, 0x8F, 0x9C, 0x6F, 0xAD, 0x31, +0xAD, 0x31, 0xAD, 0x11, 0x9C, 0x8F, 0x9C, 0x6F, +0x94, 0x4E, 0x9C, 0x6F, 0x8C, 0x2D, 0x8C, 0x0D, +0x94, 0x4E, 0x9C, 0xB0, 0xAD, 0x32, 0xBD, 0x94, +0xAD, 0x12, 0xA5, 0x12, 0xAD, 0x32, 0xA5, 0x12, +0x9C, 0xB1, 0x8C, 0x0F, 0x6B, 0x2B, 0x8C, 0x30, +0x8C, 0x50, 0x94, 0x91, 0x94, 0x91, 0x8C, 0x70, +0x8C, 0x70, 0x8C, 0x50, 0x8C, 0x30, 0x7B, 0xCE, +0xAD, 0x76, 0xAD, 0x75, 0xAD, 0x55, 0xA5, 0x55, +0xA5, 0x35, 0x8C, 0x51, 0x5A, 0xC9, 0x73, 0x8B, +0x83, 0xCC, 0x84, 0x0D, 0x84, 0x0D, 0x8C, 0x4E, +0x8C, 0x2D, 0x8C, 0x0D, 0x94, 0x8F, 0x94, 0x6F, +0x9C, 0x90, 0x8C, 0x2E, 0x94, 0x4E, 0x52, 0x88, +0xA4, 0xD0, 0x9C, 0x8E, 0xA4, 0xAF, 0xAC, 0xD0, +0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xB0, +0x9C, 0x8F, 0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xF0, +0xA4, 0xF1, 0xAD, 0x31, 0xB5, 0x52, 0x9C, 0xAF, +0x94, 0x6F, 0xA4, 0xD0, 0xAD, 0x31, 0xB5, 0x52, +0x9C, 0xB0, 0xAD, 0x32, 0xB5, 0x52, 0xAD, 0x32, +0x94, 0x4E, 0x94, 0x4E, 0x73, 0x4A, 0x8C, 0x0D, +0x94, 0x2E, 0x8B, 0xCD, 0x7B, 0x8C, 0x73, 0x4B, +0x7B, 0xAD, 0x73, 0x8D, 0x62, 0xEB, 0x4A, 0x69, +0x41, 0xE7, 0x31, 0x85, 0x31, 0x65, 0x41, 0xE7, +0x41, 0xE7, 0x4A, 0x49, 0x52, 0x8A, 0x6B, 0x4C, +0x7B, 0xAE, 0x83, 0xEF, 0x94, 0x71, 0xB5, 0x76, +0xB5, 0x76, 0xD6, 0x7A, 0x4A, 0x6A, 0x73, 0x6C, +0x94, 0x2E, 0x7B, 0x8B, 0x73, 0x6B, 0x62, 0xC9, +0x62, 0xC9, 0x73, 0x4A, 0x73, 0x4A, 0x73, 0x4B, +0x73, 0x6B, 0x52, 0x89, 0x4A, 0x69, 0x5A, 0xEB, +0x52, 0xAA, 0x5A, 0xCB, 0x5A, 0xAA, 0x5A, 0xEB, +0x73, 0x8E, 0x84, 0x10, 0x9C, 0xD4, 0xC6, 0x39, +0xE6, 0xFC, 0xE7, 0x1C, 0xC5, 0xD7, 0xB5, 0x55, +0xD6, 0x59, 0xBD, 0x75, 0x8B, 0xED, 0x8B, 0xCB, +0x9C, 0x4D, 0x94, 0x2D, 0x9C, 0x4D, 0x93, 0xEB, +0xA4, 0x6D, 0xAC, 0xCF, 0xB4, 0xEF, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0x6E, 0xC5, 0x91, 0xBD, 0x30, +0xAC, 0xAE, 0xAC, 0xCF, 0xB5, 0x10, 0xB4, 0xEF, +0xA4, 0xAE, 0xB4, 0xEF, 0xBD, 0x51, 0xB4, 0xEF, +0xAC, 0xCF, 0xAC, 0xEF, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xCF, +0xA4, 0x8E, 0x94, 0x2D, 0x94, 0x2D, 0x9C, 0x6D, +0x94, 0x2C, 0x83, 0xEB, 0x94, 0x4D, 0x9C, 0x8E, +0x9C, 0x8E, 0x7B, 0x6A, 0xBD, 0x51, 0xA4, 0xAE, +0x94, 0x4C, 0x9C, 0x6E, 0xC5, 0xD3, 0xBD, 0xB3, +0xB5, 0x53, 0xCE, 0x38, 0xB5, 0xB7, 0xAD, 0x35, +0xDE, 0x98, 0xCE, 0x35, 0xD6, 0x76, 0xC6, 0x15, +0xCE, 0x15, 0xDE, 0x97, 0xD6, 0x97, 0xD6, 0x56, +0xCE, 0x15, 0xD6, 0x97, 0xDE, 0xB7, 0xD6, 0x97, +0xDE, 0xB7, 0xDE, 0xB8, 0x94, 0x90, 0xAD, 0x53, +0xB5, 0x53, 0xD6, 0x77, 0xC5, 0xF5, 0xAD, 0x52, +0x94, 0x90, 0xB5, 0x93, 0xB5, 0x73, 0xB5, 0x93, +0xC6, 0x15, 0xB5, 0xB4, 0xBD, 0xD4, 0xBD, 0xD4, +0xB5, 0x93, 0xBD, 0xD4, 0xBD, 0xD4, 0xAD, 0x73, +0xD6, 0x77, 0xD6, 0x77, 0xAD, 0x73, 0xBD, 0xB4, +0xAD, 0x53, 0xB5, 0xB4, 0x84, 0x0D, 0x9C, 0xD1, +0x94, 0x8F, 0x8C, 0x0E, 0x8C, 0x2E, 0x83, 0xED, +0x9C, 0x8F, 0x9C, 0xCF, 0xAD, 0x31, 0xAD, 0x52, +0x94, 0x6F, 0xA5, 0x12, 0xBD, 0xB4, 0xB5, 0x53, +0xBD, 0x94, 0x94, 0x90, 0x7B, 0xCD, 0xA5, 0x11, +0x94, 0x6E, 0x9C, 0xAF, 0x94, 0x6E, 0x94, 0x4E, +0xAD, 0x31, 0x94, 0x6E, 0xA4, 0xF0, 0xAD, 0x11, +0x9C, 0x8F, 0xA4, 0xF0, 0xA4, 0xF0, 0xB5, 0x72, +0xA4, 0xF0, 0xB5, 0x52, 0xA4, 0xD0, 0xBD, 0x94, +0x94, 0x6F, 0xBD, 0x73, 0x9C, 0x8F, 0xAD, 0x32, +0xBD, 0xB3, 0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0x93, +0xC5, 0xD4, 0xC5, 0xF4, 0xCE, 0x15, 0xCE, 0x35, +0xC5, 0xF4, 0xB5, 0x93, 0xBD, 0x94, 0xC5, 0xF5, +0xB5, 0x73, 0xB5, 0x53, 0xA4, 0xD1, 0xB5, 0x53, +0xAD, 0x33, 0xA4, 0xD1, 0xAD, 0x12, 0x9C, 0xB0, +0x8C, 0x2F, 0xB5, 0x53, 0xAD, 0x32, 0xAD, 0x52, +0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x52, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x53, 0xB5, 0x94, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x94, 0xA5, 0x12, +0xAD, 0x12, 0xB5, 0x73, 0xBD, 0xD5, 0xB5, 0x93, +0xB5, 0x93, 0xC5, 0xF5, 0xBD, 0xD4, 0xC5, 0xF5, +0xB5, 0x73, 0x9C, 0x90, 0x9C, 0xB0, 0xA5, 0x11, +0xA5, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x52, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xD1, 0x94, 0x6F, +0x94, 0x6F, 0x94, 0x2E, 0xB5, 0x32, 0x9C, 0x6E, +0xB5, 0x71, 0xBD, 0x72, 0xBD, 0x71, 0xB5, 0x71, +0xBD, 0x92, 0xBD, 0x72, 0xBD, 0xB3, 0xB5, 0x52, +0xB5, 0x72, 0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x32, +0xB5, 0x52, 0xBD, 0x93, 0xC5, 0xD4, 0xD6, 0x34, +0xCE, 0x14, 0xC5, 0xD3, 0xBD, 0x93, 0x8C, 0x0E, +0x9C, 0xD1, 0xAD, 0x33, 0x8C, 0x2F, 0xCE, 0x36, +0xC5, 0xD5, 0xB5, 0x53, 0x9C, 0xB1, 0x84, 0x2F, +0x84, 0x2F, 0x8C, 0x70, 0x8C, 0x50, 0x84, 0x2F, +0x8C, 0x92, 0x8C, 0x92, 0x8C, 0x92, 0x8C, 0x72, +0x94, 0x92, 0x7B, 0xCF, 0x42, 0x27, 0x63, 0x0A, +0x73, 0x4B, 0x73, 0x8C, 0x8C, 0x0D, 0x94, 0x4E, +0x8C, 0x0D, 0x8C, 0x4E, 0x94, 0x8F, 0x9C, 0xB0, +0x9C, 0xB0, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x9C, 0xD0, 0xA4, 0x8E, 0xAC, 0xF0, 0xAC, 0xF0, +0xA4, 0x8F, 0xA4, 0x8F, 0x94, 0x6F, 0xA4, 0xF1, +0xA4, 0xF1, 0xAD, 0x11, 0xB5, 0x73, 0xAD, 0x32, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x73, 0xA4, 0xF1, +0x94, 0x4E, 0xA4, 0xD0, 0xAD, 0x11, 0x94, 0x6E, +0x94, 0x6F, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, +0x94, 0x2E, 0xA4, 0x8F, 0x7B, 0x8B, 0x9C, 0x4F, +0xA4, 0x6F, 0x8B, 0xCC, 0x83, 0xAC, 0x83, 0xAC, +0x83, 0xCD, 0x84, 0x2F, 0x84, 0x0F, 0x6B, 0x4C, +0x39, 0xC6, 0x39, 0xC7, 0x39, 0xC6, 0x39, 0xC7, +0x41, 0xE7, 0x42, 0x08, 0x4A, 0x49, 0x5A, 0xAA, +0x5A, 0xCB, 0x7B, 0xAE, 0x9C, 0xD3, 0xA4, 0xF4, +0xB5, 0x96, 0xD6, 0x9A, 0xBD, 0xB7, 0x94, 0x91, +0x9C, 0xB1, 0x8C, 0x2E, 0x9C, 0x90, 0x8C, 0x0D, +0x7B, 0xAC, 0x83, 0xED, 0x7B, 0xAC, 0x8C, 0x0D, +0x9C, 0xB0, 0x8C, 0x0E, 0x52, 0x89, 0x42, 0x27, +0x42, 0x28, 0x52, 0x8A, 0x52, 0x89, 0x5A, 0xAA, +0x52, 0x8A, 0x5A, 0xEB, 0x6B, 0x4E, 0xB5, 0x76, +0xD6, 0x7A, 0xDE, 0xBB, 0xCE, 0x19, 0xCE, 0x18, +0xD6, 0x59, 0xBD, 0x96, 0xA4, 0xD2, 0x94, 0x4F, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0x8E, +0x9C, 0x6D, 0xB5, 0x52, 0xD6, 0x55, 0xD6, 0x34, +0xCE, 0x14, 0xBD, 0x72, 0xAC, 0xEF, 0xAC, 0xCF, +0x94, 0x4D, 0x8C, 0x0C, 0x9C, 0xAE, 0x8B, 0xCC, +0x94, 0x2D, 0x9C, 0x4D, 0x94, 0x0C, 0x94, 0x4D, +0xAD, 0x11, 0xB5, 0x51, 0x94, 0x0C, 0x8B, 0xEC, +0x8B, 0xCC, 0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0x8E, +0xB4, 0xF0, 0xB4, 0xF0, 0xB5, 0x10, 0xBD, 0x10, +0xB4, 0xF0, 0xB5, 0x10, 0xBD, 0x51, 0xB5, 0x10, +0xAC, 0xF0, 0xB5, 0x30, 0xBD, 0x51, 0xBD, 0x51, +0xC5, 0x72, 0xBD, 0x51, 0xAD, 0x10, 0xA4, 0xCF, +0x9C, 0xB1, 0xC6, 0x38, 0xB5, 0x97, 0x9C, 0xD3, +0x94, 0x6F, 0x94, 0x4D, 0x9C, 0x8E, 0x94, 0x6E, +0x94, 0x4D, 0x94, 0x6E, 0x9C, 0x8F, 0x94, 0x6E, +0x94, 0x4E, 0x9C, 0xB0, 0xAD, 0x11, 0xAD, 0x11, +0xAD, 0x32, 0x94, 0x90, 0x9C, 0xB1, 0xAD, 0x33, +0x9C, 0xB0, 0xB5, 0x73, 0xB5, 0x73, 0x9C, 0xB0, +0x83, 0xED, 0x94, 0x6F, 0x8C, 0x4E, 0x8C, 0x2E, +0x94, 0x8F, 0x94, 0x6F, 0x8C, 0x2E, 0xAD, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, 0xA5, 0x11, +0xB5, 0xB4, 0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0x94, +0xB5, 0x73, 0xB5, 0x73, 0x7B, 0xAC, 0x9C, 0xB0, +0xA4, 0xF1, 0xB5, 0x53, 0xA5, 0x11, 0x9C, 0xB0, +0xC5, 0xF5, 0xCE, 0x15, 0xCE, 0x35, 0xB5, 0x52, +0x8C, 0x4E, 0xAD, 0x32, 0xC5, 0xD5, 0xB5, 0x53, +0xB5, 0x93, 0x94, 0x4F, 0xAD, 0x32, 0xBD, 0x93, +0xA5, 0x11, 0xA4, 0xF0, 0x9C, 0xD0, 0x94, 0x8F, +0xAD, 0x32, 0xAD, 0x11, 0x9C, 0x8F, 0x9C, 0xAF, +0x8C, 0x2D, 0x9C, 0xAF, 0x9C, 0xB0, 0xB5, 0x52, +0xA4, 0xD0, 0xB5, 0x73, 0xB5, 0x52, 0xBD, 0xB4, +0x94, 0x6F, 0xB5, 0x53, 0xA4, 0xF1, 0xB5, 0x53, +0xB5, 0x73, 0xBD, 0x93, 0xB5, 0x72, 0xA4, 0xD0, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0xB3, 0xB5, 0x52, +0xAD, 0x31, 0xBD, 0xB3, 0xAD, 0x32, 0x9C, 0xB0, +0x9C, 0x90, 0xB5, 0x53, 0xB5, 0x73, 0xAD, 0x53, +0xB5, 0x53, 0xB5, 0x53, 0xAD, 0x12, 0x9C, 0x90, +0x9C, 0x90, 0xAD, 0x33, 0xA4, 0xF1, 0xBD, 0x94, +0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x73, 0xBD, 0x94, +0xC5, 0xF5, 0xBD, 0xD5, 0xBD, 0xB5, 0xBD, 0x94, +0xB5, 0x93, 0xB5, 0x93, 0xAD, 0x52, 0xAD, 0x52, +0xB5, 0x73, 0xBD, 0xB4, 0xC6, 0x15, 0xC6, 0x15, +0xAD, 0x32, 0x9C, 0xB0, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x32, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x93, +0xC5, 0xB4, 0xAD, 0x32, 0xB5, 0x52, 0xBD, 0x73, +0xA4, 0xF1, 0xA4, 0xF0, 0xA4, 0xD0, 0x9C, 0xB0, +0x94, 0x6F, 0x9C, 0x90, 0xBD, 0x73, 0x8C, 0x2D, +0xAD, 0x10, 0xAC, 0xEF, 0xAD, 0x30, 0xAD, 0x10, +0xAC, 0xEF, 0x8C, 0x0C, 0x9C, 0xAF, 0xA4, 0xCF, +0xA4, 0xD0, 0xA4, 0xF1, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xF0, 0xB5, 0x52, 0xB5, 0x72, 0xCD, 0xF3, +0xD6, 0x34, 0xD6, 0x13, 0xC5, 0xD3, 0xB5, 0x52, +0xCE, 0x36, 0xCE, 0x16, 0x9C, 0xB0, 0xDE, 0xD7, +0xDE, 0xB7, 0xDE, 0xB7, 0xDE, 0x97, 0xCE, 0x57, +0xB5, 0x94, 0x94, 0x70, 0x8C, 0x50, 0x94, 0x91, +0x8C, 0x92, 0x94, 0xD3, 0xA5, 0x55, 0x9D, 0x35, +0x9D, 0x14, 0x5A, 0xCB, 0x42, 0x07, 0x5A, 0xC9, +0x6B, 0x2A, 0x62, 0xE9, 0x73, 0x8B, 0x8C, 0x0D, +0x83, 0xEC, 0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, +0xAD, 0x11, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x52, +0xA4, 0xD0, 0x9C, 0x4D, 0xAC, 0xCF, 0xA4, 0x8F, +0xA4, 0x8F, 0xA4, 0x8F, 0x9C, 0xB0, 0xB5, 0x72, +0xBD, 0x93, 0xB5, 0x73, 0xB5, 0x93, 0x73, 0x4B, +0xBD, 0x94, 0xBD, 0x94, 0xC5, 0xD4, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x32, 0xA4, 0xD0, +0xA4, 0xD1, 0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x52, +0x8B, 0xED, 0xAC, 0xD0, 0x83, 0x8C, 0xA4, 0x90, +0xA4, 0x6F, 0x83, 0x8B, 0x83, 0xAC, 0x83, 0x8C, +0x8C, 0x2F, 0x8C, 0x70, 0x94, 0x70, 0xA5, 0x12, +0x5A, 0xCA, 0x41, 0xE7, 0x41, 0xE7, 0x39, 0xC6, +0x39, 0xC6, 0x39, 0xC6, 0x39, 0xE7, 0x4A, 0x48, +0x5A, 0xCA, 0x6B, 0x4D, 0x8C, 0x51, 0x9C, 0xD3, +0xA5, 0x14, 0xC5, 0xF8, 0xC6, 0x18, 0xD6, 0xBA, +0x9C, 0xB1, 0xA4, 0xD1, 0xBD, 0x93, 0xA4, 0xF1, +0x94, 0x6F, 0xA4, 0xF1, 0x94, 0x4F, 0x9C, 0xB0, +0xB5, 0x73, 0xBD, 0x94, 0xA4, 0xB0, 0x63, 0x0A, +0x31, 0xA5, 0x4A, 0x48, 0x62, 0xEB, 0x52, 0x69, +0x52, 0x69, 0x5A, 0xEC, 0x94, 0x72, 0xAD, 0x35, +0xC5, 0xF8, 0xCE, 0x59, 0xD6, 0x7A, 0xBD, 0x96, +0xB5, 0x55, 0xCE, 0x38, 0xA4, 0xD3, 0x94, 0x30, +0xBD, 0x73, 0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xCF, +0x9C, 0x6D, 0x94, 0x4E, 0xCE, 0x34, 0xDE, 0x95, +0xE6, 0xB6, 0xD6, 0x34, 0xAC, 0xEF, 0xB4, 0xEF, +0xAC, 0xF0, 0x83, 0xCC, 0x84, 0x0D, 0x8C, 0x0D, +0x94, 0x4E, 0x8C, 0x0D, 0x8C, 0x2D, 0xAD, 0x52, +0xC5, 0xF5, 0xB5, 0x73, 0x94, 0x6F, 0x73, 0x8B, +0x83, 0xED, 0x8C, 0x0E, 0x8C, 0x4E, 0x94, 0x6E, +0xAD, 0x31, 0xB5, 0x72, 0xB5, 0x31, 0x8C, 0x0C, +0x8B, 0xEC, 0x94, 0x2C, 0xAC, 0xCF, 0x8B, 0xCB, +0x83, 0xAB, 0x83, 0xCC, 0x94, 0x2D, 0x94, 0x0C, +0x7B, 0x8B, 0x8B, 0xEC, 0x94, 0x0C, 0x94, 0x2D, +0xA4, 0xF2, 0xC6, 0x38, 0xAD, 0x76, 0x9C, 0xF3, +0x94, 0x4F, 0x9C, 0x6E, 0x9C, 0x8F, 0x9C, 0x8F, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, +0x9C, 0xAF, 0xA4, 0xAF, 0xAC, 0xF1, 0xA4, 0xD1, +0x7B, 0xAD, 0x8C, 0x2E, 0x8C, 0x2F, 0xA5, 0x12, +0xAD, 0x12, 0xA4, 0xD1, 0xA4, 0xF1, 0xA5, 0x12, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x12, +0xAD, 0x33, 0xAD, 0x12, 0x9C, 0xB1, 0x9C, 0xD1, +0xA4, 0xD1, 0x9C, 0xB0, 0x94, 0x6F, 0x94, 0x6F, +0x94, 0x4F, 0x94, 0x6F, 0x94, 0x4F, 0x94, 0x4F, +0x84, 0x0D, 0x83, 0xED, 0x7B, 0xCD, 0x94, 0x70, +0x9C, 0xB0, 0xBD, 0xB4, 0xAD, 0x52, 0x8C, 0x4E, +0x9C, 0xB0, 0x94, 0x4E, 0x8C, 0x2E, 0x9C, 0x8F, +0x7B, 0xCC, 0x9C, 0xB0, 0xB5, 0x53, 0xA4, 0xF1, +0xAD, 0x52, 0x9C, 0xB0, 0x8C, 0x2E, 0xAD, 0x52, +0xC5, 0xF5, 0xC6, 0x15, 0xD6, 0x77, 0xBD, 0xB3, +0xCE, 0x35, 0xBD, 0x93, 0xA4, 0xD0, 0xB5, 0x52, +0xA4, 0xF0, 0xB5, 0x72, 0xA4, 0xF0, 0x8C, 0x4E, +0x8C, 0x2D, 0xAD, 0x11, 0xB5, 0x52, 0x9C, 0xB0, +0x83, 0xCD, 0xB5, 0x53, 0x8C, 0x2E, 0xAD, 0x11, +0xBD, 0x93, 0xBD, 0xB3, 0xCE, 0x15, 0xB5, 0x72, +0xB5, 0x52, 0xC5, 0xD4, 0xB5, 0x72, 0xA4, 0xF1, +0x9C, 0xB0, 0xBD, 0x73, 0xAD, 0x52, 0xAD, 0x11, +0x94, 0x4F, 0x9C, 0xB0, 0xA4, 0xF1, 0xB5, 0x52, +0xB5, 0x53, 0xAD, 0x32, 0xA4, 0xF1, 0x9C, 0xB0, +0x94, 0x4F, 0xA5, 0x11, 0x9C, 0xD0, 0xC5, 0xF5, +0xB5, 0x73, 0xB5, 0x53, 0xBD, 0x94, 0xBD, 0xB4, +0xAD, 0x12, 0xB5, 0x93, 0xCE, 0x16, 0xCE, 0x16, +0xC5, 0xF5, 0xC5, 0xD5, 0xB5, 0x94, 0xC5, 0xD5, +0xC6, 0x15, 0xC5, 0xF5, 0xBD, 0x94, 0xBD, 0xD5, +0xBD, 0xB4, 0xBD, 0xB4, 0xCE, 0x36, 0xC5, 0xF5, +0xAD, 0x32, 0xA4, 0xD0, 0xB5, 0x52, 0xC5, 0xD4, +0xBD, 0x72, 0xBD, 0x93, 0xB5, 0x52, 0xC5, 0xB3, +0xBD, 0x93, 0xA4, 0xD0, 0xB5, 0x73, 0xC5, 0xD4, +0x9C, 0xB0, 0x9C, 0x8F, 0xA4, 0xF1, 0x94, 0x6F, +0x83, 0xED, 0xA4, 0xB0, 0xB5, 0x32, 0x83, 0xEC, +0xAD, 0x11, 0xA4, 0xF0, 0xBD, 0x92, 0xB5, 0x72, +0xAD, 0x31, 0x94, 0x6F, 0x83, 0xCC, 0x94, 0x8F, +0xAD, 0x11, 0xA4, 0xD0, 0x9C, 0x8F, 0x8C, 0x2E, +0x83, 0xED, 0x94, 0x6F, 0x9C, 0x8F, 0xA4, 0xF0, +0xB5, 0x51, 0xB5, 0x30, 0xA4, 0xEF, 0xA4, 0xF0, +0xCE, 0x14, 0xBD, 0x73, 0xAC, 0xF1, 0xE6, 0xD7, +0xCE, 0x34, 0xCD, 0xF4, 0xCE, 0x14, 0xD6, 0x76, +0xD6, 0x97, 0xD6, 0x98, 0x9C, 0xD2, 0x84, 0x0F, +0x9D, 0x14, 0x9D, 0x14, 0x9C, 0xF4, 0x94, 0xD3, +0x9D, 0x14, 0x4A, 0x8A, 0x31, 0x85, 0x4A, 0x07, +0x5A, 0xA9, 0x5A, 0xA8, 0x63, 0x0A, 0x73, 0x4A, +0x73, 0x6B, 0x7B, 0x8C, 0x8C, 0x0D, 0x83, 0xEC, +0xA4, 0xF1, 0xAD, 0x12, 0xB5, 0x52, 0xA4, 0xD0, +0x9C, 0xAF, 0x9C, 0x4D, 0xA4, 0xAF, 0x9C, 0x6E, +0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x52, 0xAD, 0x32, +0xAD, 0x31, 0xAD, 0x11, 0xA4, 0xD0, 0x94, 0x6F, +0xA4, 0xF1, 0xB5, 0x52, 0xC5, 0xD4, 0xA4, 0xF1, +0xAD, 0x52, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x93, +0xAD, 0x11, 0xC5, 0xF5, 0xAD, 0x11, 0xB5, 0x73, +0x83, 0xAC, 0xAC, 0xF1, 0x83, 0x8B, 0xA4, 0x8F, +0xA4, 0x4F, 0x93, 0xED, 0x8C, 0x0E, 0x8C, 0x0E, +0x94, 0x90, 0x8C, 0x4F, 0x9C, 0xD1, 0xAD, 0x53, +0x7B, 0xAD, 0x5A, 0xCA, 0x31, 0x85, 0x29, 0x44, +0x31, 0x85, 0x31, 0xA6, 0x39, 0xC6, 0x4A, 0x69, +0x52, 0x89, 0x63, 0x2C, 0x7B, 0xCE, 0x94, 0x92, +0xA5, 0x35, 0xB5, 0xB7, 0xC6, 0x39, 0xE7, 0x1C, +0x9C, 0xD2, 0xB5, 0x73, 0xBD, 0xD4, 0xA4, 0xF1, +0xA4, 0xD0, 0xAD, 0x32, 0x94, 0x6F, 0xA4, 0xF1, +0xB5, 0x73, 0xA4, 0xD0, 0xBD, 0x72, 0xB5, 0x93, +0x73, 0x8C, 0x41, 0xE7, 0x4A, 0x28, 0x4A, 0x48, +0x52, 0xAA, 0x62, 0xEC, 0x4A, 0x69, 0x73, 0xAE, +0x8C, 0x51, 0x94, 0x72, 0xCE, 0x39, 0xBD, 0xB6, +0xA4, 0xD3, 0xBD, 0x76, 0x8C, 0x10, 0x62, 0xEB, +0xAD, 0x13, 0xBD, 0x74, 0xAC, 0xD0, 0xAC, 0xF0, +0x9C, 0x6E, 0x9C, 0x6E, 0xDE, 0x96, 0xDE, 0xB6, +0xE6, 0xB6, 0xD6, 0x34, 0xB5, 0x30, 0x9C, 0x6E, +0xB5, 0x31, 0x62, 0xE9, 0x63, 0x0A, 0x7B, 0xCD, +0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x4F, 0xC6, 0x36, +0xD6, 0x97, 0xCE, 0x36, 0x94, 0xB0, 0x7B, 0xAD, +0x84, 0x0E, 0x8C, 0x6F, 0x94, 0x6F, 0x94, 0xB0, +0xB5, 0x73, 0xC5, 0xF4, 0xB5, 0x72, 0x9C, 0xB0, +0x9C, 0x8F, 0x9C, 0x8E, 0xA4, 0xCF, 0x8B, 0xCC, +0x94, 0x4E, 0x9C, 0x8F, 0x94, 0x6F, 0x94, 0x6E, +0x83, 0xED, 0x8C, 0x2E, 0x94, 0x6F, 0x73, 0x8C, +0xB5, 0x95, 0xC6, 0x18, 0xAD, 0x76, 0x9C, 0xD3, +0xA5, 0x12, 0x7B, 0xAC, 0x7B, 0xAC, 0x8C, 0x0E, +0x84, 0x0D, 0x94, 0x6F, 0x94, 0x6F, 0x94, 0x8F, +0x8C, 0x0D, 0x83, 0xEC, 0xAD, 0x32, 0x94, 0x70, +0x62, 0xEA, 0x73, 0x8D, 0x73, 0xAD, 0x84, 0x0E, +0x8C, 0x0E, 0x84, 0x0E, 0x7B, 0xAD, 0x7B, 0xAC, +0x8C, 0x4F, 0x8C, 0x0E, 0x94, 0x4F, 0x8C, 0x0E, +0x8C, 0x0E, 0x9C, 0x90, 0x9C, 0x90, 0x8C, 0x4F, +0x8C, 0x4F, 0x8C, 0x2F, 0x83, 0xEE, 0x9C, 0x90, +0x8C, 0x0E, 0x8C, 0x4F, 0x9C, 0xD1, 0x8C, 0x2E, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x53, +0xAD, 0x32, 0x9C, 0xB1, 0xA4, 0xF1, 0xA4, 0xD1, +0xAC, 0xF2, 0xA4, 0xD1, 0xA4, 0xF2, 0x9C, 0xB1, +0xA4, 0xF1, 0xA5, 0x12, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x53, 0xA4, 0xF2, 0xAD, 0x33, 0xAD, 0x52, +0x9C, 0xB0, 0x94, 0x4F, 0xA4, 0xD1, 0x9C, 0xB0, +0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD1, 0xA4, 0xF1, +0xA4, 0xD0, 0x9C, 0xB0, 0x9C, 0xB0, 0xAD, 0x32, +0x9C, 0x90, 0x94, 0x6F, 0x94, 0x6F, 0x73, 0x6B, +0x7B, 0xAD, 0xBD, 0xB4, 0x8C, 0x2E, 0xA4, 0xD1, +0xB5, 0x53, 0xAD, 0x52, 0xB5, 0x73, 0xAD, 0x32, +0x9C, 0x8F, 0xB5, 0x73, 0x9C, 0xB0, 0x9C, 0x90, +0xA4, 0xF1, 0xAD, 0x12, 0x9C, 0x8F, 0x83, 0xED, +0x8C, 0x0E, 0xAD, 0x52, 0xAD, 0x32, 0xA4, 0xF1, +0xAD, 0x12, 0xB5, 0x73, 0xB5, 0x73, 0x94, 0x6F, +0x83, 0xED, 0x9C, 0xD1, 0xA4, 0xD0, 0xBD, 0x93, +0xA4, 0xF1, 0xB5, 0x32, 0xC5, 0xB4, 0xCD, 0xF5, +0xC5, 0xF5, 0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x36, +0xD6, 0x77, 0xCE, 0x36, 0xB5, 0x94, 0xC5, 0xF5, +0xCE, 0x36, 0xCE, 0x35, 0xC5, 0xF5, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0xD4, 0xCE, 0x35, 0xBD, 0xD4, +0x9C, 0xD0, 0xA4, 0xF1, 0xB5, 0x72, 0xBD, 0xB3, +0xC5, 0xD4, 0xC5, 0xF4, 0xBD, 0x93, 0xC5, 0xD4, +0xC5, 0xB4, 0xAD, 0x11, 0xBD, 0x73, 0xBD, 0x93, +0x8C, 0x4E, 0x9C, 0x90, 0xAC, 0xF1, 0x9C, 0x90, +0x73, 0x6C, 0x9C, 0xB0, 0xAD, 0x11, 0x94, 0x4E, +0xB5, 0x73, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x73, +0xAD, 0x52, 0xBD, 0x94, 0xAD, 0x32, 0xAD, 0x12, +0xAD, 0x12, 0xAD, 0x32, 0x9C, 0x90, 0x8C, 0x2E, +0x52, 0x89, 0x7B, 0xAD, 0x9C, 0xB0, 0x9C, 0xB0, +0x94, 0x6F, 0x94, 0x4E, 0x9C, 0xAF, 0xAD, 0x11, +0xC5, 0xB3, 0xB5, 0x52, 0xB5, 0x32, 0xE6, 0xD7, +0xD6, 0x34, 0xD6, 0x55, 0xDE, 0x96, 0xD6, 0x75, +0xD6, 0x56, 0xD6, 0x97, 0xDE, 0x97, 0xC5, 0xF5, +0x9D, 0x14, 0x9D, 0x14, 0x9D, 0x14, 0x94, 0xF4, +0x94, 0xB3, 0x5A, 0xCB, 0x52, 0x68, 0x5A, 0xA9, +0x5A, 0xC9, 0x62, 0xC9, 0x62, 0xEA, 0x6A, 0xEA, +0x73, 0x2A, 0x73, 0x2A, 0x7B, 0x4A, 0x7B, 0x8B, +0x83, 0xCC, 0x8C, 0x0D, 0x94, 0x2D, 0x94, 0x2E, +0x7B, 0x8B, 0x9C, 0x4E, 0x93, 0xEC, 0x7B, 0x6A, +0x83, 0xCC, 0x7B, 0x8B, 0xA4, 0xD1, 0x9C, 0xB0, +0xA4, 0xD0, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, +0xA4, 0xF1, 0xB5, 0x52, 0xBD, 0xD4, 0xB5, 0x73, +0xC5, 0xD5, 0xBD, 0x94, 0xB5, 0x94, 0xC5, 0xF5, +0x9C, 0x90, 0xC5, 0xD5, 0x94, 0x6F, 0x6B, 0x0A, +0x73, 0x4A, 0xA4, 0xB0, 0x9C, 0x4E, 0xB5, 0x11, +0xAC, 0xD0, 0xA4, 0x8F, 0xA4, 0xB0, 0xA4, 0xB1, +0xA4, 0xD1, 0x94, 0x70, 0xA5, 0x12, 0xB5, 0x73, +0x94, 0x70, 0x7B, 0xAD, 0x41, 0xE6, 0x29, 0x64, +0x29, 0x44, 0x39, 0xC6, 0x39, 0xE7, 0x39, 0xE7, +0x42, 0x07, 0x52, 0xAA, 0x63, 0x2C, 0x83, 0xEF, +0x9C, 0xF3, 0xA5, 0x14, 0xBD, 0xD8, 0xCE, 0x59, +0x9C, 0xB2, 0xB5, 0x94, 0xBD, 0xB4, 0xB5, 0x73, +0x9C, 0xB0, 0xA4, 0xD1, 0x9C, 0x90, 0xAD, 0x32, +0xBD, 0x73, 0xA4, 0xD0, 0xB5, 0x32, 0xBD, 0x93, +0xB5, 0x52, 0x62, 0xEA, 0x39, 0xC6, 0x42, 0x07, +0x4A, 0x69, 0x5A, 0xAA, 0x52, 0x8A, 0x6B, 0x2C, +0x84, 0x10, 0x52, 0x6A, 0x4A, 0x69, 0x9C, 0xB2, +0xBD, 0xB6, 0xBD, 0x96, 0xB5, 0x34, 0xD6, 0x59, +0x73, 0x6D, 0x9C, 0x70, 0xBD, 0x53, 0xAC, 0xCF, +0x9C, 0x6D, 0xA4, 0xAF, 0xE6, 0xD7, 0xE6, 0xB6, +0xE6, 0xB6, 0xCE, 0x14, 0xB5, 0x30, 0x9C, 0x4D, +0xA4, 0xD0, 0x73, 0x6B, 0x73, 0xAC, 0x83, 0xEE, +0x8C, 0x4F, 0x83, 0xCD, 0x83, 0xED, 0xBD, 0xD4, +0xDE, 0xD8, 0xCE, 0x76, 0x9C, 0xD1, 0x8C, 0x2F, +0x84, 0x0E, 0x9C, 0xB1, 0x8C, 0x2F, 0x94, 0x90, +0xBD, 0xD5, 0xC5, 0xF5, 0xCE, 0x15, 0xAD, 0x32, +0x83, 0xED, 0x9C, 0x8F, 0xAC, 0xF0, 0x83, 0x8B, +0x94, 0x4E, 0x94, 0x6F, 0x94, 0x4F, 0x94, 0x4F, +0x94, 0x90, 0x94, 0x70, 0xAD, 0x53, 0x9C, 0xD2, +0xCE, 0x59, 0xB5, 0xB7, 0xAD, 0x55, 0x9C, 0xF3, +0xC5, 0xF6, 0xB5, 0xB4, 0xAD, 0x53, 0xAD, 0x53, +0x94, 0x6F, 0x9C, 0xD1, 0xA5, 0x12, 0xCE, 0x57, +0xC5, 0xF5, 0x8C, 0x2E, 0xAD, 0x12, 0x94, 0x4F, +0x8C, 0x70, 0x94, 0xB1, 0x9C, 0xD1, 0xAD, 0x33, +0xA5, 0x12, 0x94, 0x90, 0x94, 0x6F, 0x94, 0x90, +0x94, 0x90, 0x7B, 0xCD, 0x83, 0xEE, 0x8C, 0x2F, +0x83, 0xEE, 0xA4, 0xD1, 0xB5, 0x52, 0xAD, 0x32, +0xB5, 0x73, 0xAD, 0x53, 0xAD, 0x12, 0xAD, 0x32, +0x9C, 0xD1, 0x94, 0x90, 0x94, 0x4F, 0x62, 0xEA, +0x73, 0x8C, 0x7B, 0xED, 0x84, 0x0E, 0x8C, 0x2F, +0x94, 0x90, 0x94, 0x70, 0x8C, 0x0E, 0x83, 0xED, +0x83, 0xED, 0x9C, 0xB0, 0x94, 0x70, 0x83, 0xEE, +0x8C, 0x4F, 0x94, 0x70, 0x7B, 0xCD, 0x7B, 0xAD, +0x7B, 0xAD, 0x83, 0xCE, 0x8C, 0x0F, 0x94, 0x4F, +0x9C, 0xB0, 0xA4, 0xB1, 0xB5, 0x74, 0xCE, 0x16, +0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x73, 0xB5, 0x53, +0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x73, 0xBD, 0x93, +0xBD, 0xB4, 0xC5, 0xD4, 0xBD, 0xB4, 0xB5, 0x73, +0xB5, 0x74, 0xC5, 0xD5, 0xCE, 0x37, 0xCE, 0x37, +0xCE, 0x16, 0xCE, 0x16, 0xCE, 0x16, 0xCD, 0xF6, +0xCD, 0xF5, 0xC5, 0xD5, 0xBD, 0xB5, 0xBD, 0x94, +0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x12, 0xAC, 0xF2, +0xA4, 0xB1, 0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0xB0, +0x9C, 0xB0, 0xA4, 0xD1, 0x9C, 0x90, 0x8C, 0x2E, +0xAD, 0x12, 0xB5, 0x73, 0x9C, 0x90, 0xA4, 0xD0, +0x94, 0x2E, 0x8C, 0x0E, 0x9C, 0x6F, 0x94, 0x6F, +0x94, 0x4E, 0x83, 0xCD, 0x94, 0x4F, 0x9C, 0xB0, +0xB5, 0x73, 0xB5, 0x53, 0xAD, 0x33, 0xBD, 0xB4, +0xCD, 0xF5, 0xCE, 0x36, 0xBD, 0xB4, 0xAD, 0x52, +0xB5, 0x52, 0xC6, 0x16, 0xCE, 0x56, 0xB5, 0x73, +0x94, 0x8F, 0xAD, 0x32, 0xBD, 0xB3, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x93, 0xAD, 0x31, 0xB5, 0x72, +0xBD, 0x93, 0xB5, 0x51, 0xC5, 0xD4, 0xBD, 0x73, +0xAD, 0x32, 0xBD, 0x93, 0xB5, 0x73, 0x83, 0xED, +0x6B, 0x2B, 0x9C, 0xB0, 0xB5, 0x52, 0x8C, 0x4F, +0xB5, 0x94, 0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xD5, +0xAD, 0x32, 0x8C, 0x4F, 0xBD, 0xD5, 0xB5, 0x94, +0xA4, 0xF2, 0xAD, 0x73, 0xA5, 0x12, 0x9C, 0xF2, +0x73, 0xAD, 0x6B, 0x2B, 0x9C, 0xD1, 0xA4, 0xF1, +0x94, 0x90, 0x8C, 0x2F, 0x9C, 0xB0, 0x9C, 0xAF, +0xAD, 0x10, 0xA4, 0xF0, 0xAD, 0x11, 0xDE, 0x96, +0xD6, 0x34, 0xD6, 0x34, 0xDE, 0x95, 0xDE, 0xB6, +0xDE, 0xB6, 0xDE, 0xB7, 0xD6, 0x76, 0xD6, 0x76, +0xA5, 0x35, 0xA5, 0x34, 0x9D, 0x14, 0x9C, 0xF4, +0x94, 0xB3, 0x5A, 0xCA, 0x5A, 0xA9, 0x62, 0xE9, +0x6B, 0x0A, 0x73, 0x2A, 0x7B, 0x6B, 0x7B, 0x6B, +0x83, 0xAC, 0x83, 0xAB, 0x83, 0x8B, 0x83, 0x8B, +0x83, 0xAB, 0x8B, 0xCC, 0x8B, 0xEC, 0x94, 0x2D, +0x9C, 0x6E, 0xAC, 0xCF, 0xB4, 0xF0, 0xAC, 0xD0, +0x9C, 0x4E, 0x8B, 0xEC, 0x94, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x2E, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4E, +0xA4, 0xB0, 0xAD, 0x11, 0xA4, 0xD0, 0xA4, 0xD0, +0x94, 0x4E, 0x9C, 0xAF, 0x83, 0xCC, 0x62, 0xC8, +0x94, 0x4E, 0x9C, 0x6E, 0x94, 0x0D, 0xB5, 0x11, +0xB5, 0x11, 0xAC, 0xB0, 0xAC, 0xF1, 0xAD, 0x12, +0xA4, 0xF1, 0x8C, 0x4F, 0xA4, 0xF2, 0xBD, 0xB4, +0x73, 0x8C, 0x5A, 0xCA, 0x4A, 0x28, 0x39, 0xC6, +0x3A, 0x07, 0x42, 0x07, 0x39, 0xE7, 0x39, 0xA6, +0x39, 0xE7, 0x4A, 0x49, 0x5A, 0xCA, 0x6B, 0x6D, +0x84, 0x0F, 0x9C, 0xF3, 0xB5, 0xB6, 0x73, 0x8E, +0x9C, 0xB3, 0xD6, 0x79, 0xB5, 0x53, 0xBD, 0x93, +0xB5, 0x52, 0xBD, 0x94, 0xB5, 0x73, 0xBD, 0x73, +0xC5, 0xB4, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x31, +0xB5, 0x32, 0x9C, 0x8F, 0x6B, 0x2A, 0x31, 0x85, +0x42, 0x07, 0x5A, 0xEB, 0x4A, 0x49, 0x73, 0x8D, +0x7B, 0x8E, 0x31, 0x86, 0x4A, 0x29, 0x62, 0xEB, +0x83, 0xF0, 0xB5, 0x55, 0xCD, 0xF7, 0xCE, 0x17, +0xCD, 0xF7, 0x6B, 0x0B, 0xAC, 0xD2, 0xBD, 0x73, +0x7B, 0x8A, 0xAC, 0xF0, 0xE6, 0xD7, 0xDE, 0xB6, +0xE6, 0xD6, 0xD6, 0x14, 0xB5, 0x30, 0x8B, 0xAB, +0x9C, 0x8F, 0x73, 0x6B, 0x5A, 0xCA, 0x6B, 0x4B, +0x8C, 0x2E, 0x73, 0x8C, 0x83, 0xED, 0xB5, 0x73, +0xD6, 0x76, 0xCE, 0x56, 0xA5, 0x12, 0x94, 0xB1, +0x8C, 0x4F, 0xA5, 0x12, 0x9C, 0xB0, 0xA5, 0x12, +0xC5, 0xF5, 0xC6, 0x15, 0xCE, 0x35, 0xB5, 0x52, +0x83, 0xEC, 0x94, 0x6E, 0xAD, 0x11, 0x83, 0x8B, +0x83, 0xED, 0x8C, 0x4E, 0x94, 0x4F, 0x8C, 0x4E, +0x8C, 0x4E, 0x8C, 0x2E, 0x94, 0x6F, 0xA4, 0xF2, +0xCE, 0x38, 0xB5, 0x96, 0xAD, 0x55, 0x94, 0x71, +0xB5, 0x74, 0xAD, 0x53, 0xB5, 0x94, 0xA5, 0x12, +0x8C, 0x4F, 0x9C, 0xD1, 0x9C, 0xD0, 0xA4, 0xF1, +0xB5, 0x94, 0x9C, 0xD1, 0xAD, 0x33, 0x8C, 0x4F, +0x94, 0x90, 0x94, 0x90, 0xA5, 0x12, 0xAD, 0x32, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xB0, 0x94, 0x90, +0x8C, 0x4F, 0x63, 0x2B, 0x5B, 0x0B, 0x6B, 0x6C, +0x73, 0x6C, 0x94, 0x90, 0xAD, 0x52, 0xBD, 0xB4, +0xA5, 0x11, 0xAD, 0x32, 0xB5, 0x93, 0xB5, 0x93, +0xB5, 0x73, 0x9C, 0xD1, 0x94, 0x90, 0x73, 0x6C, +0x73, 0x8D, 0x7B, 0xAD, 0x6B, 0x4C, 0x73, 0x6C, +0x6B, 0x4C, 0x6B, 0x4C, 0x6B, 0x2B, 0x6B, 0x2B, +0x73, 0x6C, 0x83, 0xCD, 0x94, 0x6F, 0x83, 0xCD, +0x83, 0xCD, 0x8C, 0x2F, 0x7B, 0xAD, 0x6B, 0x4C, +0x63, 0x0B, 0x6B, 0x2B, 0x6B, 0x2B, 0x6B, 0x4B, +0x83, 0xCD, 0x83, 0xCD, 0x83, 0xED, 0xAD, 0x12, +0x94, 0x6F, 0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xD0, +0x9C, 0xAF, 0xA4, 0xD0, 0x94, 0x6F, 0x7B, 0xCD, +0x7B, 0x8C, 0x7B, 0xAD, 0x7B, 0xAD, 0x7B, 0x8C, +0x83, 0xED, 0x83, 0xCD, 0x8B, 0xEE, 0x9C, 0xB0, +0xAD, 0x12, 0x9C, 0x70, 0x8C, 0x2F, 0x94, 0x4F, +0x9C, 0x70, 0x9C, 0x90, 0xB5, 0x74, 0xC5, 0xD5, +0xA4, 0xF1, 0xAD, 0x12, 0xA4, 0xF1, 0xAD, 0x32, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x53, 0xBD, 0x73, +0xC5, 0xB4, 0xBD, 0x94, 0xBD, 0x73, 0xBD, 0x73, +0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x73, 0xBD, 0x94, 0xC5, 0xB4, 0xC5, 0xB4, +0xBD, 0x73, 0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x12, +0xAD, 0x12, 0xA4, 0xF1, 0x9C, 0xB0, 0x94, 0x6F, +0x9C, 0x90, 0xAD, 0x12, 0xAD, 0x11, 0x94, 0x6F, +0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, 0x8C, 0x2E, +0x8C, 0x0E, 0x83, 0xCD, 0x8B, 0xED, 0x94, 0x4E, +0x9C, 0x6F, 0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xF1, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x52, 0x73, 0x6B, +0x6B, 0x2A, 0x9C, 0xB0, 0xA4, 0xF1, 0xA4, 0xD1, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xD4, 0xBD, 0xD5, +0xBD, 0xB4, 0xBD, 0xD5, 0xC5, 0xF5, 0xC6, 0x16, +0xBD, 0xD5, 0xAD, 0x74, 0xAD, 0x53, 0xAD, 0x73, +0x94, 0xB1, 0x84, 0x0F, 0xAD, 0x32, 0xB5, 0x94, +0xA5, 0x32, 0xA4, 0xF2, 0xA4, 0xF1, 0xA4, 0xF1, +0xA4, 0xF0, 0x9C, 0xAF, 0xA4, 0xB0, 0xD6, 0x55, +0xDE, 0x95, 0xD6, 0x54, 0xD6, 0x75, 0xDE, 0x75, +0xDE, 0x75, 0xD6, 0x96, 0xE6, 0xB7, 0xDE, 0x96, +0xA5, 0x35, 0xA5, 0x34, 0x9D, 0x14, 0x9C, 0xF4, +0x94, 0xD3, 0x52, 0xAA, 0x52, 0x68, 0x63, 0x0A, +0x6B, 0x2A, 0x6B, 0x09, 0x73, 0x2A, 0x73, 0x2A, +0x83, 0xCC, 0x8C, 0x0D, 0x94, 0x2D, 0x9C, 0x6F, +0x7B, 0xAB, 0x73, 0x6A, 0x7B, 0xAB, 0x8B, 0xEC, +0x94, 0x2D, 0x94, 0x0C, 0x93, 0xEC, 0x8B, 0xAB, +0x6A, 0xA8, 0x9C, 0x4D, 0xA4, 0xAF, 0xA4, 0x6E, +0x9C, 0x6E, 0x94, 0x2D, 0x9C, 0x8E, 0xA4, 0xCF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0x8F, 0x9C, 0x4E, 0xA4, 0x8E, 0x9C, 0x4D, +0x9C, 0x4D, 0x9C, 0x6E, 0x94, 0x4D, 0xA4, 0xCF, +0xAC, 0xF0, 0xA4, 0xAF, 0x83, 0xAB, 0x8B, 0xEC, +0x83, 0x8B, 0x62, 0xC9, 0x62, 0xC9, 0x62, 0xC9, +0x62, 0xE9, 0x62, 0xC9, 0x5A, 0x88, 0x5A, 0xA9, +0x62, 0xC9, 0x4A, 0x27, 0x4A, 0x28, 0x52, 0x89, +0x4A, 0x48, 0x4A, 0x28, 0x39, 0xA6, 0x31, 0xA6, +0x39, 0xE6, 0x4A, 0x48, 0x52, 0xAA, 0x73, 0xAE, +0x8C, 0x51, 0x9C, 0xD3, 0x9C, 0xD3, 0x6B, 0x6E, +0x8C, 0x72, 0xDE, 0xBA, 0xC6, 0x16, 0xA4, 0xD0, +0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x32, +0xB5, 0x52, 0xAC, 0xF1, 0x9C, 0xAF, 0xA4, 0xD0, +0x9C, 0x6F, 0x94, 0x2E, 0xB5, 0x31, 0x62, 0xEA, +0x39, 0xA6, 0x39, 0xA6, 0x52, 0x8A, 0x73, 0x8E, +0x52, 0x8A, 0x62, 0xEB, 0x63, 0x0C, 0x6B, 0x4D, +0x8C, 0x31, 0x5A, 0x8A, 0x9C, 0x92, 0x94, 0x31, +0xE6, 0x99, 0xDE, 0x79, 0x8B, 0xCF, 0xBD, 0x74, +0xAC, 0xF1, 0x9C, 0xB0, 0xDE, 0x97, 0xCE, 0x14, +0xE6, 0xF7, 0xCE, 0x14, 0xB4, 0xF0, 0x7B, 0x6A, +0x94, 0x6F, 0x7B, 0xAC, 0x5A, 0xCA, 0x6B, 0x4C, +0x8C, 0x4F, 0x8C, 0x2F, 0x9C, 0xB0, 0xBD, 0xB4, +0xDE, 0xB7, 0xD6, 0x77, 0xB5, 0x94, 0xA5, 0x33, +0xA5, 0x12, 0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x53, +0xCE, 0x36, 0xD6, 0x56, 0xCE, 0x36, 0xAD, 0x11, +0x94, 0x6F, 0x9C, 0xD0, 0xB5, 0x31, 0x83, 0x8B, +0x94, 0x4E, 0x9C, 0x90, 0x94, 0x4F, 0xA5, 0x12, +0xA5, 0x11, 0xA4, 0xD1, 0xAD, 0x53, 0xB5, 0x54, +0xC5, 0xF7, 0xAD, 0x55, 0xA5, 0x14, 0x9C, 0xB2, +0xAD, 0x33, 0xAD, 0x12, 0xB5, 0x73, 0xAD, 0x33, +0x94, 0x70, 0x9C, 0xB1, 0x94, 0x8F, 0x94, 0x90, +0xB5, 0x94, 0xBD, 0xB4, 0xAD, 0x33, 0x8C, 0x2F, +0x94, 0x70, 0x8C, 0x6F, 0xA5, 0x12, 0xA5, 0x12, +0xA4, 0xF2, 0xA5, 0x32, 0xA4, 0xF1, 0x9C, 0xB1, +0x84, 0x0E, 0x6B, 0x6C, 0x63, 0x4C, 0x6B, 0x8D, +0x6B, 0x6C, 0x84, 0x2F, 0xAD, 0x53, 0xBD, 0xB4, +0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x93, 0xAD, 0x53, +0xAD, 0x53, 0xA4, 0xD1, 0x94, 0x90, 0x83, 0xEE, +0x73, 0x6D, 0x7B, 0x8D, 0x7B, 0x8D, 0x7B, 0xCD, +0x8C, 0x2F, 0x94, 0x90, 0x8C, 0x2F, 0x83, 0xEE, +0x8C, 0x2F, 0x8C, 0x4F, 0x9C, 0xB1, 0x84, 0x0E, +0x94, 0x4F, 0x94, 0x4F, 0x84, 0x0E, 0x7B, 0x8D, +0x73, 0x8D, 0x73, 0x6C, 0x5A, 0xCA, 0x6B, 0x0B, +0x73, 0x6C, 0x73, 0x6C, 0x8C, 0x4F, 0xAD, 0x12, +0x9C, 0xB0, 0xA4, 0xF0, 0x9C, 0xB0, 0x9C, 0xD0, +0x94, 0x6E, 0x94, 0x4E, 0x8C, 0x2E, 0x84, 0x0E, +0x6B, 0x4B, 0x6B, 0x4B, 0x6B, 0x2B, 0x6B, 0x2B, +0x6B, 0x6B, 0x6B, 0x4B, 0x73, 0xAD, 0x8C, 0x2F, +0x94, 0x4F, 0x84, 0x0E, 0x94, 0x91, 0x84, 0x2F, +0x83, 0xCD, 0x6B, 0x0B, 0x73, 0x6D, 0xB5, 0x53, +0xD6, 0x77, 0xBD, 0xB4, 0xAD, 0x32, 0xB5, 0x53, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x94, 0xBD, 0x94, +0xBD, 0xB4, 0xBD, 0x94, 0xB5, 0x53, 0xA5, 0x12, +0xAD, 0x33, 0xAD, 0x12, 0xA4, 0xB0, 0xA4, 0xD0, +0xA4, 0xF1, 0x94, 0x4F, 0x8C, 0x0E, 0x94, 0x2E, +0x8C, 0x0E, 0x8C, 0x0E, 0x8C, 0x0E, 0xAD, 0x12, +0x9C, 0x90, 0x8C, 0x0E, 0x8C, 0x0D, 0x8C, 0x0E, +0xA4, 0xB0, 0x9C, 0x90, 0x9C, 0x8F, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xD1, 0xAD, 0x31, 0xAD, 0x11, +0xAD, 0x12, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x32, +0xB5, 0x53, 0xB5, 0x32, 0xAD, 0x11, 0xB5, 0x52, +0xB5, 0x32, 0xB5, 0x73, 0xB5, 0x52, 0xA4, 0xF1, +0x9C, 0x6F, 0x94, 0x4E, 0x83, 0xED, 0x7B, 0xAC, +0x7B, 0xAD, 0xA4, 0xD1, 0xAD, 0x11, 0xAD, 0x12, +0xB5, 0x53, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x12, 0x9C, 0xD1, 0x9C, 0xD1, 0xAD, 0x32, +0xAD, 0x52, 0xAD, 0x32, 0xA5, 0x12, 0xA5, 0x12, +0xA4, 0xF1, 0x9C, 0xB1, 0xA4, 0xF2, 0xA5, 0x12, +0x94, 0x6F, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x94, 0x6F, 0x94, 0x4F, 0x83, 0xAC, 0xC5, 0xB3, +0xE6, 0xB6, 0xDE, 0x95, 0xE6, 0xB6, 0xE6, 0xD6, +0xE6, 0xB6, 0xE6, 0xB6, 0xE6, 0xD7, 0xDE, 0x96, +0xA5, 0x35, 0xA5, 0x35, 0xA5, 0x34, 0x9C, 0xF4, +0x94, 0xB3, 0x5A, 0xCB, 0x5A, 0xA9, 0x73, 0x8B, +0x83, 0xCC, 0x83, 0xAC, 0x8C, 0x0D, 0x8C, 0x0D, +0x94, 0x4E, 0xA4, 0xF1, 0xA4, 0xD0, 0xAC, 0xF1, +0x9C, 0x6F, 0x94, 0x6F, 0x9C, 0x6F, 0xA4, 0xB0, +0xB5, 0x31, 0xAC, 0xF0, 0xAC, 0xD0, 0x7B, 0x4A, +0x52, 0x26, 0xA4, 0xAF, 0xAC, 0xF0, 0xAD, 0x11, +0xBD, 0xB3, 0xC5, 0xD4, 0x94, 0x6F, 0xA5, 0x11, +0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x31, 0xAD, 0x31, +0xB5, 0x72, 0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xD0, +0xA5, 0x11, 0xAD, 0x11, 0x8C, 0x2E, 0x73, 0x6A, +0x7B, 0xAB, 0x73, 0x4A, 0x6B, 0x09, 0x9C, 0x6F, +0xA4, 0xB0, 0x7B, 0xAB, 0x94, 0x4E, 0x94, 0x2D, +0x83, 0xAC, 0x83, 0xCC, 0x8B, 0xED, 0x8B, 0xEC, +0x83, 0xCB, 0x83, 0xAC, 0x41, 0xE6, 0x52, 0x89, +0x42, 0x07, 0x39, 0xE7, 0x39, 0xE6, 0x29, 0x65, +0x31, 0xA6, 0x42, 0x08, 0x4A, 0x48, 0x63, 0x2C, +0x63, 0x2C, 0x73, 0xAE, 0x6B, 0x2C, 0x8C, 0x72, +0xBD, 0xB7, 0xB5, 0x96, 0xDE, 0xBA, 0xA4, 0xF3, +0x83, 0xAD, 0x8C, 0x0D, 0x8B, 0xCC, 0x8B, 0xCC, +0x8B, 0xCC, 0x93, 0xED, 0x8B, 0xEC, 0x8B, 0xEC, +0x7B, 0x8B, 0x73, 0x29, 0x7B, 0x4A, 0x4A, 0x07, +0x42, 0x07, 0x42, 0x28, 0x52, 0x69, 0x31, 0x65, +0x42, 0x08, 0x4A, 0x69, 0x4A, 0x69, 0x62, 0xEB, +0x94, 0x72, 0x41, 0xE8, 0x6B, 0x2D, 0xAD, 0x14, +0xB5, 0x34, 0xCE, 0x17, 0xC5, 0x75, 0x8B, 0xAE, +0xD6, 0x58, 0xA4, 0xD1, 0xA4, 0xB0, 0x9C, 0x8F, +0xBD, 0xB3, 0xAC, 0xF0, 0xAC, 0xAE, 0x73, 0x4A, +0x62, 0xEA, 0x63, 0x0A, 0x6B, 0x4B, 0x73, 0x6C, +0x83, 0xEE, 0x84, 0x0E, 0x9C, 0xB0, 0xBD, 0xD4, +0xDE, 0xD8, 0xD6, 0x97, 0xBD, 0xD4, 0xA5, 0x12, +0xBD, 0xD5, 0xAD, 0x53, 0xA5, 0x12, 0xAD, 0x53, +0xCE, 0x56, 0xCE, 0x15, 0xD6, 0x56, 0x9C, 0xB0, +0x94, 0x4F, 0x9C, 0x6E, 0xB5, 0x31, 0x7B, 0x8B, +0x9C, 0x90, 0xAD, 0x52, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x93, 0xBD, 0xB5, +0xC6, 0x18, 0xAD, 0x35, 0x9C, 0xF4, 0xBD, 0xB5, +0xB5, 0x74, 0xB5, 0x73, 0xBD, 0x94, 0xC5, 0xD5, +0xA5, 0x12, 0xA4, 0xF2, 0xA5, 0x32, 0xAD, 0x33, +0xBD, 0xD5, 0xBD, 0xD5, 0xAD, 0x32, 0x8C, 0x2E, +0x8C, 0x4F, 0x8C, 0x6F, 0x9C, 0xD1, 0xA5, 0x12, +0xAD, 0x33, 0xA5, 0x32, 0x9C, 0xD1, 0x9C, 0xB0, +0x84, 0x2E, 0x7B, 0xEE, 0x7B, 0xCE, 0x7B, 0xEF, +0x84, 0x2F, 0xA5, 0x33, 0xBD, 0xD4, 0xBD, 0xD4, +0xAD, 0x53, 0xC5, 0xF5, 0xBD, 0xB4, 0xA5, 0x32, +0xAD, 0x32, 0x9C, 0xB1, 0x9C, 0x90, 0x7B, 0x8C, +0x6B, 0x4C, 0x6B, 0x6C, 0x7B, 0xAD, 0x7B, 0xCD, +0x8C, 0x4F, 0x9C, 0xD1, 0x9C, 0x90, 0x94, 0x90, +0x94, 0x90, 0x94, 0x90, 0x9C, 0xB1, 0x94, 0x70, +0x9C, 0xB1, 0x8C, 0x2F, 0x94, 0x70, 0x8C, 0x0F, +0x83, 0xEE, 0x7B, 0xAD, 0x62, 0xEA, 0x63, 0x2B, +0x73, 0x6C, 0x63, 0x0B, 0x94, 0x90, 0xAD, 0x32, +0xB5, 0x93, 0x9C, 0x8F, 0x9C, 0xB0, 0x94, 0x8F, +0x9C, 0xB0, 0xAD, 0x12, 0x9C, 0xB0, 0x8C, 0x6F, +0x73, 0xAD, 0x7B, 0xCD, 0x73, 0x8C, 0x6B, 0x4C, +0x6B, 0x4C, 0x7B, 0xEE, 0x94, 0xB1, 0xAD, 0x53, +0xA5, 0x12, 0xA5, 0x33, 0xAD, 0xB5, 0x94, 0xB2, +0x7B, 0xAE, 0x7B, 0xCE, 0x83, 0xEE, 0xB5, 0x73, +0xCE, 0x36, 0xB5, 0x94, 0xA4, 0xD1, 0x8C, 0x0E, +0x8C, 0x2E, 0x94, 0x6F, 0x94, 0x4F, 0x9C, 0xB1, +0xA5, 0x12, 0xA4, 0xD1, 0x9C, 0xB1, 0x94, 0x4F, +0x8C, 0x4F, 0x94, 0x4F, 0x94, 0x6F, 0x94, 0x6F, +0x9C, 0x90, 0x9C, 0x90, 0xA4, 0xD0, 0xA4, 0xF0, +0xA4, 0xF1, 0xA4, 0xF1, 0x94, 0x4F, 0xB5, 0x12, +0x7B, 0x8C, 0x73, 0x4B, 0x8C, 0x2E, 0x83, 0xCD, +0x94, 0x4E, 0x94, 0x6F, 0x8C, 0x2E, 0x94, 0x4E, +0x8C, 0x2E, 0x7B, 0xAC, 0x8C, 0x0D, 0x7B, 0xAC, +0x94, 0x6F, 0x94, 0x4E, 0x73, 0x6B, 0x73, 0x6B, +0x73, 0x4B, 0x73, 0x4B, 0x7B, 0x8C, 0x83, 0xED, +0x8B, 0xED, 0x8B, 0xED, 0x9C, 0x8F, 0xB5, 0x72, +0x8C, 0x0D, 0x9C, 0x6F, 0x94, 0x4F, 0x94, 0x90, +0x8C, 0x4F, 0x94, 0x4F, 0x9C, 0x90, 0xA4, 0xD1, +0xAD, 0x12, 0xAD, 0x33, 0xAD, 0x32, 0xB5, 0x32, +0xBD, 0x94, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, +0xB5, 0x73, 0xB5, 0x53, 0xB5, 0x73, 0xC5, 0xB4, +0xC5, 0xB4, 0xC5, 0xD5, 0xC5, 0xB4, 0xBD, 0xB4, +0xBD, 0x74, 0xBD, 0x94, 0xBD, 0x73, 0xBD, 0x94, +0xC5, 0xD5, 0xCD, 0xF5, 0xA4, 0xD1, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x31, 0xAC, 0xF0, 0xA4, 0xAF, +0xA4, 0xB0, 0xAD, 0x11, 0xAD, 0x31, 0xC5, 0xB3, +0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x34, 0x9C, 0xF4, +0x94, 0xB2, 0x6B, 0x4C, 0x6B, 0x4B, 0x7B, 0xAC, +0x8C, 0x0D, 0x8B, 0xED, 0x8C, 0x0D, 0x8C, 0x2D, +0x8C, 0x2E, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, +0xA4, 0xD0, 0xA4, 0xB0, 0xA4, 0xD0, 0xAC, 0xF1, +0xBD, 0x93, 0xAC, 0xF0, 0xA4, 0x6E, 0x73, 0x09, +0x73, 0x4A, 0x94, 0x0C, 0xB5, 0x31, 0xBD, 0x72, +0xBD, 0xD4, 0xCE, 0x36, 0xA5, 0x32, 0xAD, 0x53, +0xAD, 0x53, 0xB5, 0x94, 0xBD, 0xB4, 0xC5, 0xF5, +0xA5, 0x12, 0xB5, 0x73, 0xBD, 0xD4, 0xBD, 0xB4, +0xB5, 0x73, 0xB5, 0xB4, 0xAD, 0x52, 0x9C, 0xF1, +0xAD, 0x53, 0x94, 0x90, 0x73, 0x8C, 0x84, 0x0E, +0x83, 0xEE, 0x7B, 0xAC, 0x9C, 0x8E, 0xAD, 0x10, +0xCE, 0x14, 0xCE, 0x14, 0xDE, 0x96, 0xCE, 0x14, +0xC5, 0xD2, 0xCD, 0xF3, 0xB5, 0x51, 0x94, 0x4E, +0x39, 0xC5, 0x41, 0xE7, 0x42, 0x27, 0x29, 0x64, +0x29, 0x65, 0x42, 0x07, 0x4A, 0x69, 0x52, 0xAA, +0x5A, 0xCB, 0x5A, 0xEB, 0x62, 0xEB, 0xA4, 0xF4, +0xC5, 0xF8, 0x7B, 0xF0, 0xAD, 0x76, 0xDE, 0xBB, +0xA4, 0xF3, 0x94, 0x50, 0x83, 0xAC, 0x9C, 0x6E, +0x94, 0x2D, 0x94, 0x2E, 0x94, 0x0D, 0x7B, 0x6A, +0x83, 0xCC, 0x7B, 0x4A, 0x73, 0x2A, 0x29, 0x44, +0x52, 0xA9, 0x5A, 0xCA, 0x42, 0x07, 0x31, 0x65, +0x39, 0xC7, 0x4A, 0x49, 0x52, 0x6A, 0x62, 0xEC, +0x84, 0x10, 0x6B, 0x0D, 0x41, 0xC7, 0xAD, 0x34, +0xB5, 0x34, 0xC5, 0xB6, 0xE6, 0x99, 0xAC, 0xD2, +0x6B, 0x0B, 0xBD, 0xB6, 0x9C, 0x91, 0x7B, 0x8C, +0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0xAE, 0xAC, 0xAF, +0xA4, 0x8F, 0x94, 0x4E, 0x8B, 0xEC, 0x7B, 0xAC, +0x83, 0xCC, 0x8C, 0x0D, 0x8B, 0xEC, 0x8C, 0x2D, +0xA4, 0xD0, 0xAC, 0xF0, 0x9C, 0x8F, 0x83, 0xEC, +0x94, 0x6F, 0x8C, 0x2E, 0x83, 0xED, 0x8C, 0x4E, +0xB5, 0x52, 0xB5, 0x93, 0xB5, 0x93, 0x7B, 0xAC, +0x6B, 0x4B, 0x7B, 0xAB, 0xA4, 0xAF, 0x73, 0x2A, +0x9C, 0xB0, 0xBD, 0xD4, 0xC5, 0xF5, 0xC6, 0x15, +0xC6, 0x15, 0xC5, 0xF5, 0xAD, 0x73, 0xB5, 0x74, +0xC6, 0x38, 0xAD, 0x76, 0xA5, 0x34, 0xCE, 0x57, +0xC6, 0x16, 0xB5, 0x73, 0xBD, 0xF5, 0xCE, 0x56, +0xC5, 0xF5, 0xBD, 0xF5, 0xBD, 0xD5, 0xC5, 0xF6, +0xC6, 0x36, 0xBD, 0xD5, 0xA5, 0x12, 0x7B, 0xCD, +0x8C, 0x2E, 0x94, 0x90, 0xBD, 0xD5, 0xC5, 0xF6, +0xBD, 0xD5, 0xB5, 0x73, 0xAD, 0x53, 0x94, 0x90, +0x8C, 0x2E, 0x8C, 0x4F, 0x84, 0x4F, 0x8C, 0x90, +0x8C, 0x70, 0xA5, 0x12, 0xBD, 0xF5, 0xBD, 0xD5, +0xB5, 0x94, 0xC5, 0xF5, 0xBD, 0xD4, 0xB5, 0x73, +0xA4, 0xD1, 0xA4, 0xF2, 0x9C, 0xB0, 0x83, 0xEE, +0x73, 0x4C, 0x73, 0x6C, 0x7B, 0x8D, 0x7B, 0xAD, +0x7B, 0xAD, 0x83, 0xCD, 0x7B, 0xAD, 0x7B, 0xCD, +0x83, 0xEE, 0x8C, 0x0E, 0x83, 0xEE, 0x83, 0xCD, +0x7B, 0xAD, 0x7B, 0xCD, 0x7B, 0xAD, 0x7B, 0xAD, +0x73, 0x8D, 0x6B, 0x4C, 0x5A, 0xEA, 0x6B, 0x4C, +0x73, 0x8D, 0x6B, 0x6C, 0xA4, 0xF2, 0xB5, 0x73, +0xCE, 0x16, 0x8C, 0x0D, 0x94, 0x6F, 0x94, 0x8F, +0x9C, 0xD1, 0xA5, 0x32, 0x9C, 0xB0, 0xA4, 0xF1, +0x9C, 0xF2, 0x94, 0x90, 0x7C, 0x0E, 0x73, 0x8D, +0x84, 0x0F, 0x8C, 0x70, 0xA5, 0x33, 0xB5, 0x94, +0xBD, 0xF6, 0xB5, 0xD5, 0xBD, 0xF6, 0xA5, 0x54, +0x94, 0x91, 0xA5, 0x12, 0x8C, 0x4F, 0xB5, 0x94, +0xBD, 0x94, 0xBD, 0xB4, 0xA4, 0xD1, 0x94, 0x4F, +0x9C, 0x90, 0x9C, 0x90, 0x9C, 0xB1, 0x9C, 0xD1, +0x9C, 0xB1, 0x9C, 0x90, 0x9C, 0xD1, 0xA5, 0x12, +0x9C, 0xB1, 0x9C, 0xD1, 0xA4, 0xD1, 0x9C, 0xD1, +0xA4, 0xF1, 0xAD, 0x52, 0xC5, 0xD4, 0xB5, 0x52, +0xAD, 0x11, 0xBD, 0xB3, 0x9C, 0xB0, 0xAD, 0x32, +0x9C, 0xB0, 0x83, 0xEE, 0x8C, 0x2E, 0xA4, 0xD0, +0xAD, 0x11, 0x9C, 0xB0, 0xB5, 0x53, 0xB5, 0x93, +0xB5, 0x73, 0x9C, 0xD1, 0x94, 0x8F, 0x9C, 0x90, +0xA4, 0xD1, 0x9C, 0xD0, 0x9C, 0xB0, 0xA4, 0xF1, +0x9C, 0xD0, 0x9C, 0xD1, 0x9C, 0xB0, 0x94, 0x6E, +0x83, 0xED, 0x9C, 0x8F, 0x83, 0xCC, 0xB5, 0x73, +0x9C, 0xB0, 0xBD, 0x93, 0xAD, 0x52, 0xB5, 0x93, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xB4, 0xB5, 0x93, +0xB5, 0x93, 0xB5, 0x73, 0xAD, 0x53, 0xA4, 0xF1, +0x9C, 0xD1, 0x9C, 0x90, 0x94, 0x6F, 0x94, 0x90, +0xAD, 0x12, 0xAD, 0x33, 0x9C, 0x90, 0xA4, 0xD1, +0xA4, 0xD1, 0x94, 0x2E, 0xA4, 0xD1, 0xBD, 0x94, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0x8C, 0x83, 0xED, +0x94, 0x2E, 0x9C, 0x6F, 0x8C, 0x0E, 0x94, 0x4E, +0xA4, 0xB0, 0xAD, 0x11, 0xB5, 0x52, 0xAC, 0xF1, +0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x32, 0xAD, 0x11, +0xA5, 0x55, 0xA5, 0x55, 0xA5, 0x35, 0x9C, 0xF4, +0x8C, 0x92, 0x63, 0x0B, 0x6B, 0x4B, 0x7B, 0xAC, +0x8C, 0x0D, 0x8C, 0x2E, 0x8C, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x72, +0xA4, 0xD0, 0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x31, +0xBD, 0x72, 0x94, 0x2D, 0x8B, 0xCC, 0x8B, 0xCC, +0x9C, 0x2E, 0x8B, 0xCC, 0xB5, 0x10, 0xBD, 0x73, +0xCE, 0x56, 0xC6, 0x15, 0xAD, 0x73, 0xB5, 0x73, +0xB5, 0x94, 0xBD, 0xB5, 0xBD, 0xF5, 0xBD, 0xF5, +0x84, 0x0E, 0xC6, 0x16, 0xCE, 0x36, 0xC6, 0x16, +0xC6, 0x16, 0xBD, 0xD5, 0xAD, 0x32, 0xAD, 0x53, +0xB5, 0xD5, 0xAD, 0x33, 0x94, 0x90, 0x94, 0x70, +0x8C, 0x0E, 0x94, 0x6E, 0xB5, 0x51, 0xCE, 0x13, +0xCE, 0x55, 0xCE, 0x34, 0xDE, 0xB6, 0xDE, 0x74, +0xD6, 0x12, 0xD6, 0x33, 0xC5, 0xB1, 0xD6, 0x54, +0xAD, 0x31, 0x52, 0x88, 0x42, 0x27, 0x39, 0xE7, +0x29, 0x65, 0x29, 0x65, 0x4A, 0x69, 0x4A, 0x48, +0x52, 0x8A, 0x62, 0xEC, 0x7B, 0xCF, 0xA5, 0x35, +0xA4, 0xF4, 0xAD, 0x55, 0xB5, 0xB7, 0xC6, 0x39, +0xDE, 0xDB, 0x9C, 0xD2, 0x94, 0x4F, 0xA4, 0xAF, +0x9C, 0x8F, 0xA4, 0xD0, 0xAC, 0xF0, 0xA4, 0x6F, +0x9C, 0x4E, 0xA4, 0xAF, 0x83, 0xAC, 0x31, 0x65, +0x52, 0xAA, 0x4A, 0x48, 0x39, 0xA6, 0x42, 0x07, +0x42, 0x28, 0x4A, 0x49, 0x52, 0x6A, 0xA5, 0x34, +0xA5, 0x14, 0x94, 0x31, 0x5A, 0x6A, 0x62, 0xAA, +0xB5, 0x54, 0xBD, 0x95, 0xC5, 0x95, 0xDE, 0x78, +0xA4, 0xB2, 0x73, 0x4C, 0xB5, 0x33, 0xAC, 0xF1, +0xAC, 0xF1, 0x8C, 0x0C, 0x94, 0x0C, 0x8B, 0xEC, +0x9C, 0x4E, 0xA4, 0x8E, 0xAC, 0xCF, 0xB4, 0xF0, +0xAC, 0xD0, 0xAC, 0xCF, 0xAC, 0xCF, 0xB5, 0x10, +0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x30, +0xAC, 0xF0, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xD0, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAE, 0x94, 0x2D, +0x94, 0x2D, 0x9C, 0x6E, 0xB5, 0x10, 0xAC, 0xCF, +0x9C, 0x8E, 0x94, 0x4E, 0x94, 0x0D, 0x8C, 0x0D, +0x94, 0x4E, 0x94, 0x2D, 0x8C, 0x0D, 0x94, 0x6F, +0xCE, 0x59, 0xAD, 0x96, 0x9C, 0xD3, 0x83, 0xCD, +0x9C, 0x8F, 0x8C, 0x2E, 0x84, 0x0D, 0xAD, 0x11, +0xAD, 0x11, 0xB5, 0x72, 0xBD, 0xB4, 0xBD, 0xD5, +0xA5, 0x11, 0x7B, 0xAC, 0x9C, 0xF1, 0x7B, 0xCD, +0x83, 0xED, 0x8C, 0x2F, 0xA5, 0x12, 0xAD, 0x53, +0xAD, 0x32, 0x94, 0x6F, 0x7B, 0xCD, 0x94, 0x6F, +0x9C, 0xB0, 0x94, 0x70, 0x94, 0x90, 0x94, 0x90, +0x94, 0x90, 0x7B, 0xAD, 0xA5, 0x12, 0xBD, 0xD5, +0xAD, 0x52, 0xC5, 0xF5, 0xB5, 0x93, 0xBD, 0xD5, +0xAD, 0x53, 0xAD, 0x53, 0x9C, 0xD1, 0x7B, 0xAD, +0x6B, 0x0B, 0x63, 0x0B, 0x6B, 0x4C, 0x73, 0x6C, +0x73, 0x8C, 0x7B, 0xAC, 0x83, 0xCD, 0x6B, 0x2B, +0x84, 0x0E, 0x83, 0xEE, 0x84, 0x0E, 0x73, 0x8C, +0x7B, 0x8C, 0x7B, 0xAC, 0x7B, 0x8C, 0x73, 0x6C, +0x63, 0x2B, 0x5A, 0xCA, 0x52, 0xAA, 0x63, 0x2B, +0x6B, 0x4C, 0x6B, 0x4C, 0xAD, 0x33, 0xAD, 0x53, +0xCE, 0x56, 0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, +0xA4, 0xF1, 0xA5, 0x11, 0xA4, 0xF1, 0xA4, 0xF1, +0x94, 0x90, 0x9C, 0xD1, 0x94, 0xB0, 0x7B, 0xEE, +0x8C, 0x70, 0x9C, 0xD1, 0xA5, 0x53, 0xB5, 0x94, +0xBE, 0x16, 0xB5, 0xB5, 0xBD, 0xD5, 0x9D, 0x13, +0x9C, 0xD2, 0xAD, 0x74, 0x94, 0x70, 0xBD, 0x94, +0xBD, 0xB4, 0xB5, 0x53, 0x9C, 0x90, 0x9C, 0x90, +0xA4, 0xD1, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x53, +0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x73, 0xBD, 0xB5, +0xAD, 0x53, 0x9C, 0xB0, 0xA4, 0xD1, 0xAD, 0x53, +0xB5, 0x74, 0xBD, 0x94, 0xBD, 0x73, 0xAD, 0x11, +0xB5, 0x72, 0xCE, 0x15, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x72, 0x8C, 0x2E, 0x8C, 0x0D, 0xA4, 0xB0, +0x8C, 0x2E, 0x84, 0x0D, 0x9C, 0x90, 0xBD, 0xD4, +0xBD, 0xD4, 0xAD, 0x53, 0xA5, 0x11, 0xAD, 0x32, +0xAD, 0x52, 0xAD, 0x32, 0xAD, 0x32, 0xBD, 0xD4, +0xB5, 0x94, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, +0xAD, 0x11, 0xAD, 0x31, 0x94, 0x6F, 0xBD, 0x93, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x93, 0xB5, 0x93, +0xBD, 0x94, 0xCE, 0x36, 0xC6, 0x15, 0xC6, 0x36, +0xC6, 0x36, 0xC6, 0x36, 0xCE, 0x36, 0xC6, 0x36, +0xBD, 0xD5, 0xB5, 0xB4, 0xBD, 0xD5, 0xBD, 0xD5, +0xD6, 0x98, 0xD6, 0x77, 0xC6, 0x16, 0xCE, 0x57, +0xD6, 0x77, 0xAD, 0x52, 0x83, 0xED, 0xB5, 0x53, +0x83, 0xCD, 0x8C, 0x4E, 0x8C, 0x0E, 0x94, 0x70, +0xA4, 0xD0, 0xAD, 0x11, 0xC5, 0xB3, 0xCD, 0xF4, +0xCD, 0xF4, 0xD6, 0x35, 0xC5, 0xD4, 0x9C, 0x8F, +0xBD, 0x72, 0xD6, 0x54, 0xDE, 0x55, 0xDE, 0x75, +0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x35, 0x9C, 0xF4, +0x8C, 0x92, 0x62, 0xEB, 0x5A, 0xA9, 0x7B, 0xAC, +0x83, 0xEC, 0x94, 0x4E, 0x8C, 0x2D, 0x94, 0x4E, +0x94, 0x6F, 0xAD, 0x32, 0xAC, 0xF1, 0xAD, 0x11, +0xAC, 0xF1, 0xA4, 0xD0, 0xB5, 0x32, 0xB5, 0x52, +0xC5, 0xB3, 0x94, 0x2E, 0x8B, 0xCC, 0x9C, 0x4E, +0x9C, 0x2E, 0x83, 0x8B, 0xB5, 0x11, 0xB5, 0x52, +0xC5, 0xF5, 0xBD, 0xB5, 0xAD, 0x74, 0xAD, 0x73, +0xAD, 0x53, 0xB5, 0xB4, 0xC5, 0xF5, 0xC6, 0x36, +0xBD, 0xD5, 0xCE, 0x77, 0xC6, 0x16, 0xC6, 0x16, +0xB5, 0x94, 0xB5, 0x94, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x73, 0xA4, 0xF1, 0x9C, 0xB1, 0x9C, 0xB1, +0x94, 0x6F, 0xA4, 0xAF, 0xBD, 0x71, 0xC5, 0xD2, +0xBD, 0xB2, 0xC5, 0xF3, 0xCE, 0x34, 0xCD, 0xF2, +0xD6, 0x33, 0xCE, 0x13, 0xCD, 0xF2, 0xCD, 0xF3, +0xDE, 0x96, 0xB5, 0x72, 0x4A, 0x07, 0x4A, 0x48, +0x31, 0xA6, 0x31, 0xC6, 0x4A, 0x69, 0x4A, 0x69, +0x4A, 0x49, 0x63, 0x2C, 0x7B, 0xAE, 0x94, 0x92, +0x8C, 0x51, 0xBD, 0xD7, 0x9C, 0xB3, 0xA5, 0x35, +0xD6, 0xBB, 0xB5, 0x75, 0x83, 0xEE, 0x5A, 0xA9, +0x83, 0xCE, 0xAD, 0x32, 0xAC, 0xF1, 0x8B, 0xED, +0x9C, 0x6E, 0xCD, 0xD4, 0xBD, 0x73, 0x83, 0xEE, +0x31, 0x86, 0x29, 0x44, 0x52, 0xA9, 0x6B, 0x2C, +0x42, 0x08, 0x8C, 0x71, 0x7B, 0xCF, 0x9C, 0xD3, +0xB5, 0x96, 0xAD, 0x14, 0x7B, 0x8E, 0x4A, 0x08, +0x7B, 0x8D, 0xBD, 0x75, 0xB5, 0x13, 0xC5, 0x95, +0xCD, 0xF7, 0x94, 0x50, 0x6B, 0x0B, 0x7B, 0x6D, +0x8B, 0xEE, 0x83, 0xCD, 0x7B, 0xAD, 0x7B, 0x8C, +0x6B, 0x2A, 0x83, 0xAB, 0xAC, 0xF0, 0x7B, 0x6B, +0x73, 0x2A, 0x7B, 0x8B, 0x7B, 0x6B, 0x7B, 0x6B, +0x6A, 0xE9, 0x6B, 0x09, 0x7B, 0x8B, 0x83, 0xAB, +0x83, 0xAC, 0x83, 0xAB, 0x94, 0x0D, 0x94, 0x0D, +0x93, 0xEC, 0x9C, 0x2D, 0xAC, 0xEF, 0xA4, 0xAF, +0xA4, 0x8E, 0xA4, 0x8E, 0xB4, 0xEF, 0xAC, 0xCF, +0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x71, 0xAC, 0xCF, +0xA4, 0x6E, 0xA4, 0x6E, 0xA4, 0x8E, 0xAC, 0xF2, +0xCE, 0x59, 0xB5, 0xB7, 0xAD, 0x75, 0xA4, 0xD1, +0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xCF, 0xA4, 0xAE, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6F, +0x9C, 0x6E, 0x9C, 0x4E, 0xAD, 0x32, 0xB5, 0x32, +0xAD, 0x32, 0xA4, 0xF2, 0xA4, 0xF1, 0xA4, 0xD1, +0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0xB1, 0x9C, 0xD1, +0x9C, 0xB1, 0x94, 0x70, 0x94, 0x6F, 0x8C, 0x0E, +0x8C, 0x2E, 0x84, 0x0E, 0x8C, 0x2E, 0x8C, 0x2F, +0x83, 0xEE, 0x94, 0x6F, 0x9C, 0xB0, 0x94, 0x90, +0x83, 0xED, 0x73, 0x6C, 0x9C, 0xD1, 0x7B, 0xCD, +0x7B, 0x8D, 0x5A, 0xCA, 0x5A, 0xAA, 0x83, 0xEE, +0x94, 0x70, 0x8C, 0x2F, 0x83, 0xEE, 0x84, 0x0E, +0x8C, 0x4F, 0x94, 0xB0, 0x94, 0x90, 0x8C, 0x2F, +0x7B, 0xCD, 0x7B, 0xAD, 0x73, 0x6C, 0x6B, 0x4C, +0x6B, 0x4C, 0x6B, 0x4C, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x0B, 0x73, 0x6C, 0xAD, 0x53, 0xB5, 0x73, +0xD6, 0x77, 0x94, 0x8F, 0x94, 0x6F, 0x9C, 0x90, +0x9C, 0xD0, 0xA5, 0x11, 0xB5, 0x73, 0xAD, 0x52, +0x9C, 0xD1, 0xA5, 0x32, 0xAD, 0x53, 0x94, 0xB0, +0x9C, 0xF1, 0xA5, 0x32, 0xAD, 0x53, 0xC6, 0x36, +0xC6, 0x16, 0xBD, 0xD5, 0xC6, 0x16, 0xA5, 0x33, +0x9D, 0x13, 0xAD, 0x53, 0xA4, 0xD1, 0xB5, 0x94, +0xB5, 0x53, 0xA4, 0xD1, 0x9C, 0x90, 0xAD, 0x32, +0xBD, 0x93, 0xAD, 0x12, 0xB5, 0x53, 0xC5, 0xD5, +0xB5, 0x53, 0xA5, 0x12, 0xB5, 0x94, 0xC5, 0xD5, +0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x32, +0xB5, 0x94, 0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0x72, +0xAD, 0x11, 0xD6, 0x36, 0xA4, 0xB0, 0xAD, 0x11, +0xAD, 0x32, 0x83, 0xED, 0x83, 0xCC, 0xA4, 0xB0, +0x9C, 0x8F, 0x8C, 0x0D, 0x84, 0x0D, 0xAD, 0x11, +0xC5, 0xF5, 0x94, 0x8F, 0xAD, 0x32, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x94, 0xBD, 0xB4, 0xC5, 0xD5, +0xB5, 0x73, 0xB5, 0x94, 0xBD, 0xB4, 0xB5, 0x93, +0x9C, 0xB0, 0xA4, 0xF0, 0x94, 0x4E, 0xBD, 0x93, +0xB5, 0x73, 0xB5, 0x93, 0xBD, 0xB4, 0xBD, 0xB4, +0xBD, 0xB4, 0xD6, 0x77, 0xCE, 0x56, 0xCE, 0x56, +0xD6, 0x76, 0xC6, 0x15, 0xBD, 0xD5, 0xBD, 0xD5, +0xBD, 0xF5, 0xBD, 0xD5, 0xBD, 0xF5, 0xCE, 0x56, +0xCE, 0x36, 0xBD, 0xB4, 0xAD, 0x52, 0xAD, 0x32, +0xAD, 0x73, 0xAD, 0x32, 0x94, 0x6F, 0xB5, 0x53, +0xA4, 0xB1, 0xB5, 0x53, 0xAD, 0x53, 0xAD, 0x32, +0xAD, 0x32, 0xC5, 0xB4, 0xB5, 0x72, 0xC5, 0xD3, +0xC5, 0xD3, 0xC5, 0xD3, 0xC5, 0x93, 0xA4, 0xB0, +0xD6, 0x14, 0xE6, 0x95, 0xDE, 0x53, 0xDE, 0x53, +0xA5, 0x55, 0xA5, 0x35, 0xA5, 0x35, 0x9C, 0xF4, +0x8C, 0x92, 0x52, 0x89, 0x4A, 0x27, 0x7B, 0x8C, +0x8C, 0x0D, 0x8C, 0x0D, 0x8C, 0x0D, 0x94, 0x4E, +0x9C, 0x6F, 0xA4, 0xB0, 0x94, 0x2E, 0x83, 0xEC, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x52, 0xBD, 0x73, +0xCD, 0xD4, 0x9C, 0x6E, 0x83, 0xAC, 0x73, 0x2A, +0x52, 0x27, 0x52, 0x47, 0xAC, 0xF0, 0xA4, 0xD0, +0xB5, 0x94, 0xBD, 0xD5, 0xB5, 0x94, 0xAD, 0x73, +0xAD, 0x53, 0xBD, 0xD5, 0xBD, 0xF5, 0xBD, 0xF5, +0xB5, 0x73, 0xC6, 0x36, 0xB5, 0xB4, 0xBD, 0xF5, +0xB5, 0x94, 0xBD, 0xD5, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x53, 0xA5, 0x12, 0x94, 0xB1, 0x9C, 0xF2, +0x94, 0x90, 0xA4, 0xF0, 0xBD, 0x71, 0xB5, 0x71, +0x8C, 0x0C, 0x94, 0x6E, 0x8C, 0x2D, 0xBD, 0x91, +0xCE, 0x13, 0xCE, 0x13, 0xD6, 0x33, 0xCD, 0xD2, +0xCE, 0x13, 0xDE, 0x76, 0x94, 0x4E, 0x41, 0xE6, +0x39, 0xC6, 0x3A, 0x07, 0x42, 0x28, 0x4A, 0x48, +0x4A, 0x69, 0x52, 0x8A, 0x63, 0x0C, 0x63, 0x0C, +0x9C, 0xB3, 0xBD, 0xD7, 0xAD, 0x56, 0xA5, 0x15, +0xBD, 0xD7, 0xBD, 0xB6, 0x94, 0x92, 0x4A, 0x69, +0x6B, 0x2C, 0xCE, 0x16, 0xA4, 0xB0, 0x8B, 0xED, +0x9C, 0x6E, 0xB5, 0x32, 0xAC, 0xF0, 0xAD, 0x12, +0xA4, 0xF2, 0xA5, 0x12, 0xB5, 0x74, 0x6B, 0x4C, +0x42, 0x07, 0x94, 0xB2, 0x94, 0xB2, 0xA4, 0xF4, +0xB5, 0x96, 0xBD, 0xD7, 0xA4, 0xF3, 0x9C, 0x92, +0x41, 0xE8, 0x83, 0xCE, 0xB5, 0x33, 0xB5, 0x13, +0xA4, 0xB1, 0xC5, 0xB6, 0x8B, 0xCF, 0x7B, 0x4C, +0x94, 0x4F, 0x94, 0x70, 0x94, 0xB1, 0x9C, 0xB1, +0x84, 0x0E, 0x9C, 0x6F, 0xB5, 0x31, 0x83, 0xAC, +0x62, 0xE9, 0x84, 0x0E, 0x7B, 0xED, 0x7B, 0xCD, +0x63, 0x2B, 0x6B, 0x4B, 0x84, 0x4F, 0x9C, 0xD1, +0x94, 0xB1, 0x94, 0x90, 0x84, 0x2E, 0x6B, 0x2B, +0x5A, 0x89, 0x52, 0x68, 0x62, 0xEA, 0x5A, 0xA9, +0x63, 0x2A, 0x7B, 0xCC, 0x8C, 0x0E, 0x8C, 0x0D, +0x94, 0x4D, 0x9C, 0x6D, 0xBD, 0x51, 0x9C, 0x2D, +0x62, 0xA8, 0x62, 0xE9, 0x6B, 0x0A, 0x94, 0x91, +0xC6, 0x38, 0xBD, 0xF8, 0xCE, 0x59, 0x8B, 0xEE, +0x73, 0x4A, 0x83, 0x8C, 0x8B, 0xEC, 0x94, 0x0D, +0x94, 0x0D, 0x7B, 0x6B, 0x8B, 0xCC, 0x83, 0x8B, +0x7B, 0x6A, 0x83, 0xAC, 0x93, 0xED, 0x94, 0x0D, +0x8B, 0xEE, 0x94, 0x0E, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xD1, 0x94, 0x70, 0xA4, 0xD1, 0x9C, 0xB1, +0x94, 0x4F, 0xA4, 0xF2, 0xAD, 0x12, 0x9C, 0xB1, +0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x33, 0xB5, 0x53, +0xB5, 0x74, 0xAD, 0x33, 0xAD, 0x53, 0xB5, 0x53, +0xAD, 0x33, 0xAD, 0x33, 0xB5, 0x94, 0xAD, 0x12, +0x9C, 0xD1, 0x9C, 0xB1, 0xA4, 0xD2, 0x94, 0x90, +0x94, 0x6F, 0x94, 0x4F, 0x94, 0x90, 0x9C, 0x90, +0x84, 0x0E, 0x94, 0x6F, 0x94, 0x6F, 0x9C, 0x90, +0x94, 0x90, 0x94, 0x70, 0x7B, 0xCE, 0x7B, 0xAD, +0x73, 0x8C, 0x73, 0x6C, 0x6B, 0x4C, 0x6B, 0x2C, +0x63, 0x0B, 0x73, 0x6C, 0xAD, 0x53, 0x9C, 0xD1, +0xAD, 0x12, 0x8C, 0x4E, 0x83, 0xCD, 0x7B, 0xAC, +0x83, 0xED, 0x84, 0x0D, 0x84, 0x0E, 0xAD, 0x53, +0xBD, 0xD4, 0xB5, 0xB4, 0xB5, 0x94, 0xAD, 0x73, +0x94, 0x90, 0xA5, 0x12, 0xA5, 0x32, 0xBD, 0xD5, +0xA5, 0x33, 0x8C, 0x4F, 0xB5, 0x94, 0xAD, 0x53, +0xAD, 0x74, 0xA5, 0x33, 0xAD, 0x12, 0xB5, 0x73, +0xD6, 0x57, 0xAD, 0x53, 0xA4, 0xF1, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xF5, 0xC6, 0x15, 0xB5, 0x52, +0x9C, 0xB0, 0xA4, 0xF1, 0xBD, 0xB5, 0xBD, 0xD5, +0xB5, 0x94, 0xBD, 0xB5, 0xBD, 0xB5, 0xB5, 0x94, +0xB5, 0x73, 0xC5, 0xF4, 0xCE, 0x35, 0xD6, 0x35, +0xBD, 0x72, 0xC5, 0xB4, 0xA4, 0xD0, 0x94, 0x6F, +0xB5, 0x52, 0x94, 0x6F, 0x8C, 0x2E, 0xA4, 0xF1, +0x9C, 0xAF, 0x9C, 0xAF, 0x83, 0xCD, 0x9C, 0xD0, +0xC5, 0xF5, 0x9C, 0xD0, 0xAD, 0x52, 0xA4, 0xF1, +0xBD, 0xB4, 0xB5, 0xB4, 0xB5, 0x93, 0xC5, 0xD5, +0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x52, 0xAD, 0x53, +0x94, 0x4E, 0x9C, 0xB0, 0x8C, 0x2D, 0xAD, 0x32, +0xBD, 0xB4, 0xB5, 0x73, 0xB5, 0x73, 0xBD, 0xD4, +0xBD, 0xB4, 0xD6, 0x97, 0xD6, 0x76, 0xCE, 0x56, +0xCE, 0x56, 0xC6, 0x15, 0xC6, 0x15, 0xC6, 0x15, +0xAD, 0x53, 0x8C, 0x4F, 0xB5, 0x73, 0xD6, 0x77, +0xC5, 0xF5, 0xBD, 0xB4, 0xAD, 0x53, 0xA5, 0x12, +0x9C, 0xF1, 0x9C, 0xB0, 0x8C, 0x0D, 0xB5, 0x53, +0xA4, 0xF1, 0xBD, 0xB4, 0xC5, 0xD5, 0xB5, 0x94, +0xB5, 0x73, 0xC5, 0xD4, 0xAD, 0x10, 0xCD, 0xF4, +0xCE, 0x14, 0xC5, 0xD4, 0xBD, 0x72, 0xA4, 0x8F, +0xDE, 0x55, 0xDE, 0x33, 0xD5, 0xF2, 0xCD, 0x91, +0xA5, 0x35, 0xB5, 0xB7, 0xA5, 0x34, 0x9C, 0xF4, +0x8C, 0x92, 0x63, 0x0B, 0x62, 0xC9, 0x62, 0xC9, +0x6B, 0x09, 0x6B, 0x09, 0x73, 0x4A, 0x73, 0x4A, +0x73, 0x4A, 0x6B, 0x2A, 0x7B, 0x8B, 0x73, 0x29, +0x8C, 0x0D, 0x9C, 0x6F, 0x9C, 0x6E, 0xAD, 0x11, +0xBD, 0x73, 0x8B, 0xCC, 0xB4, 0xF1, 0x93, 0xED, +0x5A, 0x68, 0x62, 0x88, 0xAC, 0xF1, 0xB5, 0x52, +0xB5, 0x73, 0xB5, 0x93, 0xB5, 0xB4, 0xBD, 0xF5, +0xB5, 0xD5, 0xBD, 0xF5, 0xC6, 0x16, 0xBD, 0xF5, +0xBD, 0xD5, 0xC6, 0x57, 0xC6, 0x36, 0xBD, 0xF5, +0xB5, 0x94, 0xB5, 0xB5, 0xB5, 0xB4, 0xAD, 0x74, +0xB5, 0x94, 0xAD, 0x94, 0xA5, 0x13, 0xA5, 0x12, +0x9C, 0xD1, 0xAD, 0x10, 0xB5, 0x30, 0xCE, 0x14, +0xC5, 0xD4, 0x73, 0x8B, 0x7B, 0x8B, 0x84, 0x0C, +0xCE, 0x34, 0xCD, 0xF2, 0xCD, 0xF2, 0xBD, 0x91, +0xC5, 0xB2, 0xD6, 0x54, 0xD6, 0x35, 0x73, 0x4B, +0x39, 0xC6, 0x42, 0x07, 0x42, 0x07, 0x42, 0x28, +0x4A, 0x69, 0x52, 0xAA, 0x5A, 0xEB, 0x6B, 0x6D, +0x9C, 0xD3, 0xAD, 0x55, 0xB5, 0x96, 0x94, 0xB3, +0xBD, 0xD7, 0xA5, 0x14, 0xAD, 0x35, 0x73, 0x8E, +0x73, 0x8E, 0xC5, 0xF6, 0xBD, 0x74, 0xAC, 0xD0, +0xA4, 0xB0, 0xAC, 0xD0, 0xAC, 0xF1, 0xB5, 0x53, +0xCE, 0x15, 0xD6, 0x56, 0x94, 0x70, 0x31, 0x45, +0x29, 0x65, 0x42, 0x08, 0x4A, 0x49, 0x7B, 0xAF, +0x84, 0x10, 0xA4, 0xF3, 0x94, 0x92, 0xAD, 0x34, +0x94, 0x51, 0x4A, 0x28, 0x8B, 0xEE, 0xAC, 0xF2, +0xB5, 0x12, 0xBD, 0x54, 0xB5, 0x33, 0x94, 0x0F, +0x7B, 0x4C, 0x8C, 0x2F, 0xAD, 0x33, 0x94, 0x91, +0x94, 0x70, 0xA4, 0xD1, 0xB5, 0x31, 0x83, 0xAB, +0x62, 0xEA, 0x73, 0xAD, 0x73, 0xAD, 0x73, 0xAD, +0x6B, 0x6D, 0x73, 0x8D, 0x8C, 0x4F, 0xA5, 0x33, +0xB5, 0x95, 0xBD, 0xF6, 0xA5, 0x53, 0x7B, 0xCE, +0x6B, 0x6C, 0x52, 0xAA, 0x5A, 0xCA, 0x6B, 0x4C, +0x8C, 0x70, 0xB5, 0xB4, 0xB5, 0x74, 0xAD, 0x53, +0x94, 0x8F, 0x9C, 0x6D, 0xBD, 0x51, 0xAC, 0xCF, +0x83, 0xAC, 0x83, 0xCD, 0x83, 0xCD, 0xA5, 0x34, +0xBD, 0xF7, 0xB5, 0xB7, 0x84, 0x10, 0x83, 0xEF, +0x73, 0x4B, 0x8C, 0x0E, 0x8C, 0x0E, 0x8C, 0x0D, +0xA4, 0xD0, 0x94, 0x4E, 0x8B, 0xCC, 0x7B, 0x4B, +0x6B, 0x0A, 0x6A, 0xCA, 0x73, 0x0A, 0x7B, 0x0A, +0x73, 0x0A, 0x7B, 0x4B, 0xB5, 0x53, 0x8C, 0x2E, +0xA5, 0x12, 0xA4, 0xD1, 0x94, 0x70, 0x9C, 0xB1, +0xA5, 0x12, 0xAD, 0x53, 0xA5, 0x12, 0x7B, 0xCD, +0x83, 0xEE, 0xA5, 0x12, 0xA4, 0xF1, 0xA4, 0xD1, +0x94, 0x70, 0x73, 0x6C, 0x7B, 0xAD, 0xA4, 0xD1, +0xB5, 0x74, 0xAD, 0x13, 0xAD, 0x12, 0xAD, 0x33, +0xAD, 0x12, 0x8C, 0x4F, 0x9C, 0xD1, 0xAD, 0x33, +0xA4, 0xF2, 0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0xB1, +0x9C, 0xB1, 0xA4, 0xF1, 0x9C, 0xD1, 0x94, 0x90, +0xAD, 0x13, 0x9C, 0xB1, 0x9C, 0xD1, 0xA5, 0x12, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x12, 0xAD, 0x33, +0xAD, 0x33, 0xAD, 0x12, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x53, 0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x12, +0xAD, 0x12, 0xAD, 0x12, 0xA4, 0xD1, 0x9C, 0xD1, +0x94, 0x90, 0x94, 0x90, 0x8C, 0x4F, 0x8C, 0x4F, +0x83, 0xEE, 0x94, 0x4F, 0x83, 0xEE, 0x8C, 0x4F, +0x8C, 0x6F, 0x8C, 0x2E, 0x9C, 0xB0, 0x84, 0x0E, +0xA4, 0xF2, 0x8C, 0x2F, 0xA5, 0x12, 0xA4, 0xF1, +0xB5, 0x94, 0xB5, 0x73, 0xAD, 0x32, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x52, 0x8C, 0x2E, +0x94, 0x4F, 0x9C, 0xB0, 0x94, 0x6F, 0x9C, 0xD0, +0xB5, 0x73, 0xA5, 0x12, 0xB5, 0x53, 0xBD, 0xD5, +0xBD, 0xB4, 0xA4, 0xF1, 0xBD, 0x73, 0xCE, 0x15, +0xD6, 0x35, 0xC5, 0xD4, 0x94, 0x4E, 0xA4, 0xD0, +0xAD, 0x52, 0x7B, 0x8C, 0xB5, 0x52, 0x6B, 0x4B, +0x73, 0x6B, 0xA4, 0xF1, 0xA5, 0x11, 0xA5, 0x11, +0x9C, 0xB0, 0xAD, 0x52, 0xBD, 0xB4, 0xBD, 0xB4, +0xBD, 0xF5, 0x8C, 0x4F, 0xAD, 0x32, 0xC5, 0xF5, +0xC5, 0xF5, 0x94, 0x70, 0x6B, 0x4B, 0xBD, 0xD5, +0xBD, 0xB4, 0xAD, 0x32, 0x94, 0x6F, 0xAD, 0x11, +0xC5, 0xD5, 0xBD, 0xD4, 0xB5, 0x93, 0xBD, 0xD4, +0xC5, 0xF5, 0xCE, 0x15, 0xCE, 0x15, 0xBD, 0xD4, +0xC6, 0x15, 0xC6, 0x15, 0xD6, 0x56, 0xC6, 0x15, +0xB5, 0x94, 0x9C, 0xB1, 0x94, 0x70, 0xCE, 0x36, +0xCE, 0x57, 0xC6, 0x15, 0xBD, 0xD5, 0xBD, 0xF5, +0xB5, 0x94, 0xB5, 0x94, 0x94, 0x6F, 0xB5, 0x73, +0xAD, 0x12, 0xB5, 0x94, 0xB5, 0x94, 0xBD, 0x94, +0xBD, 0x93, 0xC5, 0xB3, 0xB5, 0x72, 0xC5, 0xD3, +0xCE, 0x14, 0xCE, 0x14, 0xC5, 0xB3, 0x9C, 0x8F, +0xDE, 0x55, 0xD6, 0x12, 0xBD, 0x50, 0xBD, 0x50, +0xA5, 0x35, 0xBD, 0xF8, 0xA5, 0x35, 0x9C, 0xF4, +0x8C, 0x72, 0x73, 0x6C, 0x7B, 0x8B, 0x83, 0xAC, +0x83, 0xCC, 0x8B, 0xCC, 0x8B, 0xEC, 0x94, 0x0C, +0x94, 0x4D, 0x94, 0x4D, 0x94, 0x2D, 0x94, 0x2D, +0xA4, 0x8E, 0xA4, 0x8F, 0xA4, 0x6E, 0x9C, 0x4D, +0x94, 0x2D, 0x8B, 0xEC, 0x94, 0x0C, 0x94, 0x0C, +0x94, 0x2D, 0xA4, 0x8F, 0xB5, 0x10, 0xAC, 0xEF, +0xAD, 0x10, 0xAD, 0x31, 0x9C, 0xAF, 0xA4, 0xF1, +0xAD, 0x52, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x93, +0xAD, 0x52, 0xB5, 0x73, 0xC5, 0xF5, 0xBD, 0xB4, +0xAD, 0x32, 0xBD, 0xB4, 0xC6, 0x16, 0xC5, 0xF5, +0xCE, 0x57, 0xCE, 0x77, 0xC6, 0x16, 0xC5, 0xF5, +0xB5, 0x93, 0xA4, 0xCF, 0xAC, 0xEF, 0xCE, 0x13, +0xCE, 0x34, 0xAC, 0xF1, 0x5A, 0xA8, 0x73, 0x6A, +0xCE, 0x14, 0xD6, 0x13, 0xCD, 0xF3, 0xCD, 0xF2, +0xD6, 0x13, 0xD6, 0x14, 0xD6, 0x34, 0xC5, 0x93, +0x4A, 0x07, 0x31, 0xA6, 0x42, 0x07, 0x42, 0x27, +0x42, 0x28, 0x52, 0x89, 0x5A, 0xCB, 0x63, 0x2C, +0x83, 0xF0, 0xA5, 0x14, 0xAD, 0x55, 0x9C, 0xB3, +0xAD, 0x76, 0xAD, 0x55, 0xA5, 0x35, 0x94, 0x92, +0x42, 0x08, 0x73, 0x6D, 0xC5, 0xD6, 0x94, 0x2F, +0x94, 0x2E, 0xA4, 0x8F, 0x94, 0x2E, 0xA4, 0xF0, +0xBD, 0xB4, 0xB5, 0x52, 0x8C, 0x0E, 0x29, 0x24, +0x29, 0x45, 0x29, 0x65, 0x41, 0xE7, 0x4A, 0x49, +0x7B, 0xCF, 0xAD, 0x34, 0xB5, 0x96, 0xBD, 0xB6, +0x83, 0xEF, 0x73, 0x4D, 0x39, 0x86, 0x62, 0xCB, +0xA4, 0x91, 0xAC, 0xD2, 0x9C, 0x50, 0x7B, 0x6C, +0x7B, 0x6D, 0x94, 0x50, 0xC5, 0xD6, 0xCD, 0xF7, +0x9C, 0xB2, 0xAC, 0xF1, 0xB5, 0x31, 0x7B, 0x6B, +0x84, 0x0F, 0x84, 0x50, 0x84, 0x2F, 0x7B, 0xEF, +0x73, 0xAE, 0x7B, 0xCE, 0x94, 0x90, 0xAD, 0x33, +0xC6, 0x16, 0xB5, 0xB4, 0x9C, 0xF2, 0x94, 0x91, +0x73, 0xAE, 0x6B, 0x6D, 0x6B, 0x6C, 0x84, 0x0F, +0xA5, 0x13, 0xC6, 0x16, 0xC5, 0xF6, 0xBD, 0xD5, +0xA5, 0x32, 0x9C, 0x6E, 0xBD, 0x51, 0xA4, 0x6E, +0x94, 0x2E, 0x83, 0xED, 0x7B, 0xAD, 0xB5, 0xB6, +0xB5, 0xB7, 0x94, 0x92, 0x63, 0x2C, 0x94, 0x71, +0x7B, 0x8C, 0x7B, 0x8C, 0x7B, 0xCC, 0x7B, 0xAC, +0x83, 0xED, 0x9C, 0x6F, 0x8B, 0xED, 0x7B, 0x8B, +0x7B, 0x8C, 0x7B, 0x6B, 0x73, 0x0A, 0x83, 0x4B, +0x83, 0x4B, 0x8B, 0xAD, 0xBD, 0x94, 0xA5, 0x12, +0xC6, 0x16, 0xB5, 0xB5, 0xAD, 0x74, 0xA5, 0x33, +0xAD, 0x74, 0xB5, 0xB5, 0xB5, 0x94, 0xAD, 0x74, +0xAD, 0x73, 0xB5, 0xB4, 0xB5, 0x94, 0xB5, 0x94, +0xB5, 0x74, 0x84, 0x0E, 0x73, 0x8C, 0x83, 0xED, +0xC6, 0x16, 0xCE, 0x36, 0xC5, 0xD5, 0xC5, 0xF5, +0xBD, 0xD5, 0x8C, 0x2F, 0x8C, 0x2F, 0x94, 0xB0, +0x94, 0x90, 0x7B, 0xED, 0x9C, 0xD1, 0x94, 0x90, +0x94, 0x4F, 0x9C, 0xD1, 0xA4, 0xF2, 0xA5, 0x12, +0xB5, 0x94, 0xAD, 0x53, 0x8C, 0x4F, 0x94, 0x90, +0xA4, 0xD1, 0xB5, 0x74, 0xB5, 0x53, 0xB5, 0x53, +0xA4, 0xD1, 0x9C, 0x90, 0x8C, 0x4F, 0x84, 0x0E, +0x94, 0x4F, 0x9C, 0x90, 0x7B, 0xCD, 0x8C, 0x2F, +0xAD, 0x32, 0xB5, 0x32, 0xBD, 0x94, 0xBD, 0xB4, +0x9C, 0xB0, 0x9C, 0x70, 0x9C, 0xB0, 0x9C, 0xB0, +0xA4, 0xD1, 0xA4, 0xF1, 0xB5, 0x32, 0xAD, 0x12, +0xA4, 0xD1, 0xAD, 0x12, 0xA4, 0xD0, 0x9C, 0xB0, +0x9C, 0xB0, 0x9C, 0x90, 0xAD, 0x32, 0xB5, 0x73, +0xB5, 0x32, 0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x53, +0xC5, 0xD5, 0xC5, 0xB4, 0xBD, 0x94, 0x94, 0x6F, +0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xF1, +0x9C, 0x90, 0xA4, 0xB1, 0xA4, 0xD1, 0xA4, 0xF1, +0xAC, 0xF2, 0xA4, 0xD1, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xB0, 0xAC, 0xD0, 0xAD, 0x12, 0xB5, 0x73, +0xAD, 0x12, 0x94, 0x8F, 0xA4, 0xF1, 0x73, 0x4C, +0x73, 0x6C, 0x8C, 0x4E, 0xA5, 0x11, 0xAD, 0x31, +0xAD, 0x11, 0xB5, 0x53, 0xB5, 0x93, 0xBD, 0xB4, +0xC5, 0xF5, 0xA5, 0x11, 0xAD, 0x32, 0xC6, 0x15, +0xC5, 0xF5, 0xAD, 0x32, 0xA5, 0x12, 0xC5, 0xD5, +0xC6, 0x15, 0xAD, 0x52, 0xA4, 0xD0, 0xB5, 0x73, +0xC5, 0xF5, 0xD6, 0x97, 0xCE, 0x36, 0xCE, 0x35, +0xCE, 0x56, 0xCE, 0x56, 0xD6, 0x76, 0xCE, 0x35, +0xCE, 0x36, 0xC5, 0xF4, 0xCE, 0x15, 0xC5, 0xF5, +0xC5, 0xF5, 0xC5, 0xF5, 0x9C, 0xB1, 0xA4, 0xF1, +0xDE, 0xD8, 0xD6, 0x77, 0xCE, 0x36, 0xCE, 0x56, +0xCE, 0x36, 0xBD, 0xD4, 0x9C, 0x8F, 0xB5, 0x73, +0x9C, 0x90, 0xB5, 0x53, 0xB5, 0x94, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD3, 0xBD, 0x72, 0xC5, 0xB3, +0xCE, 0x14, 0xD6, 0x35, 0xCE, 0x14, 0x9C, 0x8F, +0xDE, 0x35, 0xD5, 0xF2, 0xBD, 0x50, 0xBD, 0x30, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x94, 0xF3, +0x8C, 0x71, 0x62, 0xEA, 0x73, 0x4B, 0x6B, 0x2A, +0x6B, 0x2A, 0x83, 0xCC, 0x94, 0x2D, 0x83, 0xCB, +0x8C, 0x0D, 0x9C, 0xAF, 0xA4, 0xF0, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAF, 0xB5, 0x30, +0xB5, 0x10, 0xAC, 0xEF, 0xAC, 0xF0, 0xA4, 0x8E, +0xB5, 0x10, 0xB5, 0x10, 0x9C, 0x2D, 0xAC, 0xCF, +0xB5, 0x10, 0xB5, 0x31, 0xA4, 0xCF, 0xA4, 0xAF, +0xA4, 0x8F, 0xA4, 0xAF, 0xA4, 0x8E, 0x9C, 0x8E, +0x9C, 0x8E, 0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0xAC, 0xCF, 0xA4, 0xCF, 0xA4, 0xCF, 0xA4, 0xCF, +0x9C, 0x8E, 0x9C, 0x8E, 0x9C, 0x8E, 0xA4, 0xAF, +0xA4, 0xCF, 0xAC, 0xCF, 0xAD, 0x0F, 0xAC, 0xEF, +0xB5, 0x51, 0xAC, 0xEF, 0x83, 0xCB, 0x8B, 0xEC, +0xBD, 0x71, 0xBD, 0x71, 0xC5, 0x91, 0xC5, 0xB1, +0xC5, 0x91, 0xB5, 0x0F, 0xAD, 0x0F, 0xCD, 0xF3, +0x83, 0xCC, 0x39, 0xC6, 0x42, 0x27, 0x42, 0x07, +0x42, 0x28, 0x39, 0xC6, 0x4A, 0x28, 0x52, 0x8A, +0x63, 0x0C, 0x84, 0x31, 0x94, 0x92, 0x9C, 0xF4, +0xA5, 0x14, 0xB5, 0x96, 0xA5, 0x15, 0x94, 0x92, +0x63, 0x0C, 0x29, 0x45, 0x8C, 0x30, 0xC5, 0xD5, +0xB5, 0x11, 0xBD, 0x52, 0xB5, 0x32, 0xAD, 0x11, +0xBD, 0x73, 0xBD, 0x72, 0xBD, 0x73, 0x83, 0xCD, +0x52, 0x68, 0x29, 0x44, 0x29, 0x65, 0x41, 0xE7, +0x4A, 0x28, 0x62, 0xEB, 0x73, 0x4C, 0x52, 0x69, +0x39, 0xC7, 0x29, 0x45, 0x18, 0xC3, 0x4A, 0x07, +0x62, 0xCB, 0x7B, 0x4C, 0xA4, 0x71, 0x8B, 0xCF, +0xB5, 0x55, 0xC5, 0xD6, 0xAD, 0x13, 0xDE, 0x9A, +0xBD, 0x75, 0xA4, 0xB1, 0xB5, 0x10, 0x94, 0x2E, +0x84, 0x0F, 0x94, 0x91, 0x8C, 0x71, 0x84, 0x30, +0x7B, 0xEF, 0x84, 0x0F, 0x94, 0x90, 0x9C, 0xF2, +0xA5, 0x33, 0x9C, 0xD1, 0x8C, 0x6F, 0x73, 0xCD, +0x73, 0xAD, 0x73, 0xCE, 0x7B, 0xCE, 0x84, 0x0F, +0x9C, 0xF2, 0xC6, 0x16, 0xB5, 0xD5, 0xA5, 0x32, +0xAD, 0x53, 0x94, 0x4D, 0xB5, 0x10, 0x8B, 0xCB, +0xA4, 0xD0, 0xA4, 0xF0, 0x8C, 0x0E, 0xBD, 0xF7, +0xB5, 0x76, 0x9C, 0xD3, 0x73, 0xAE, 0x83, 0xEE, +0x8C, 0x2E, 0x83, 0xCD, 0x73, 0x6B, 0x84, 0x0D, +0x8C, 0x0D, 0xA4, 0xD0, 0x7B, 0x6B, 0x8B, 0xED, +0x8C, 0x0D, 0x94, 0x0E, 0x83, 0x6B, 0x8B, 0x6C, +0x8B, 0x8C, 0x94, 0x0E, 0xBD, 0x94, 0xAD, 0x53, +0xC6, 0x36, 0xBD, 0xB5, 0xAD, 0x74, 0xAD, 0x53, +0xB5, 0x74, 0xBD, 0xD5, 0xB5, 0x74, 0x8C, 0x4F, +0x9C, 0xF1, 0xA5, 0x12, 0xB5, 0x94, 0xBD, 0xF5, +0xBD, 0xB5, 0x94, 0x90, 0x8C, 0x4F, 0x62, 0xE9, +0xB5, 0x73, 0xCE, 0x77, 0xCE, 0x77, 0xCE, 0x36, +0xC6, 0x16, 0x8C, 0x2F, 0x94, 0x70, 0x9C, 0xD1, +0xA5, 0x32, 0x94, 0x90, 0xA5, 0x12, 0xA4, 0xF1, +0xA5, 0x12, 0xAD, 0x73, 0xAD, 0x74, 0xAD, 0x53, +0xB5, 0x74, 0xAD, 0x53, 0x8C, 0x2F, 0x9C, 0xB1, +0xA4, 0xD1, 0xA4, 0xF1, 0xAD, 0x32, 0x94, 0x6F, +0x94, 0x4F, 0xA4, 0xF1, 0x94, 0x6F, 0x84, 0x0E, +0x8C, 0x4F, 0x83, 0xED, 0x7B, 0xAC, 0x8C, 0x2E, +0xBD, 0x93, 0xC5, 0xF5, 0xDE, 0xD8, 0xDE, 0xB7, +0xB5, 0x53, 0x8C, 0x0E, 0x8C, 0x0D, 0x83, 0xED, +0x7B, 0xAC, 0x83, 0xAC, 0x83, 0xCC, 0x94, 0x4F, +0xAC, 0xF2, 0xCE, 0x16, 0xD6, 0x98, 0xBD, 0xB4, +0x8C, 0x0E, 0x8C, 0x0E, 0xA4, 0xB0, 0xBD, 0x52, +0xBD, 0x73, 0xBD, 0x73, 0xAC, 0xD0, 0x9C, 0x6F, +0xA4, 0xD0, 0x9C, 0x8F, 0x94, 0x4F, 0x9C, 0x6F, +0xA4, 0xB0, 0x9C, 0x6F, 0x9C, 0xB0, 0xA4, 0xB1, +0x94, 0x4F, 0x8C, 0x0E, 0x94, 0x4F, 0x94, 0x2F, +0x94, 0x4F, 0x9C, 0x90, 0xA4, 0xD1, 0xAC, 0xF1, +0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x73, 0xBD, 0x93, +0xC5, 0xB4, 0xC5, 0xD4, 0xC5, 0xF5, 0xC5, 0xF5, +0xCE, 0x16, 0xBD, 0x73, 0xAD, 0x12, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x52, 0xB5, 0x52, 0xA4, 0xD1, +0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, +0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xF1, 0xAC, 0xF1, +0xAD, 0x11, 0x9C, 0xB0, 0xB5, 0x53, 0xAD, 0x11, +0xA4, 0xF1, 0xB5, 0x52, 0xAD, 0x32, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x73, +0xAD, 0x32, 0x9C, 0x8F, 0x94, 0x6F, 0xAD, 0x32, +0xBD, 0xD5, 0xC5, 0xD5, 0xB5, 0x73, 0x9C, 0xB0, +0xCE, 0x56, 0xCE, 0x56, 0xCE, 0x56, 0xD6, 0x56, +0xC5, 0xF5, 0xBD, 0x93, 0x9C, 0x90, 0xB5, 0x73, +0xC5, 0xD5, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xCE, 0x35, 0xCE, 0x14, 0xC5, 0xF4, 0xD6, 0x55, +0xD6, 0x55, 0xD6, 0x55, 0xC5, 0xB3, 0x94, 0x4E, +0xDE, 0x35, 0xBD, 0x50, 0xA4, 0xAE, 0x94, 0x2D, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF3, +0x8C, 0x92, 0x7B, 0xEE, 0x84, 0x2F, 0x84, 0x0E, +0x7B, 0xED, 0x9C, 0xD0, 0xAD, 0x52, 0xA5, 0x11, +0x9C, 0xF0, 0xA5, 0x31, 0xB5, 0x93, 0xA4, 0xF1, +0xAD, 0x11, 0xAD, 0x31, 0xBD, 0xB3, 0xAC, 0xCF, +0xAC, 0xCF, 0xA4, 0xCF, 0x8C, 0x2D, 0x9C, 0x8F, +0xBD, 0x93, 0xAD, 0x31, 0x63, 0x0A, 0xAD, 0x32, +0x94, 0x6E, 0xAD, 0x32, 0xCE, 0x36, 0xB5, 0x73, +0xBD, 0x93, 0xC5, 0xF4, 0xA4, 0xF0, 0xAD, 0x31, +0x94, 0x6E, 0x94, 0x6F, 0x9C, 0x8F, 0x94, 0x6F, +0xA4, 0xAF, 0xB5, 0x51, 0xAC, 0xF0, 0xB5, 0x10, +0x94, 0x0C, 0x83, 0xCB, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x0C, 0x9C, 0x6E, 0xA4, 0xCE, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0xCF, 0xB5, 0x10, 0xAC, 0xEF, +0xAC, 0xEF, 0xB4, 0xEF, 0xAC, 0xCE, 0xAC, 0xCE, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xF0, 0x7B, 0x8B, 0x39, 0xA5, 0x39, 0xC6, +0x41, 0xE6, 0x42, 0x07, 0x4A, 0x48, 0x4A, 0x48, +0x63, 0x2C, 0x73, 0x8E, 0x94, 0x92, 0xA5, 0x14, +0x9C, 0xD3, 0xB5, 0x76, 0xAD, 0x55, 0x94, 0xB3, +0x73, 0x6E, 0x29, 0x25, 0x39, 0xE7, 0xA4, 0xF2, +0xBD, 0x73, 0xAC, 0xF0, 0xAC, 0xD0, 0xAC, 0xF1, +0xAD, 0x11, 0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x93, +0xB5, 0x32, 0x73, 0x4B, 0x29, 0x44, 0x39, 0xA6, +0x4A, 0x48, 0x29, 0x45, 0x31, 0x85, 0x31, 0x65, +0x39, 0xA6, 0x4A, 0x49, 0x39, 0xC7, 0x31, 0x45, +0x52, 0x28, 0x6A, 0xAA, 0x94, 0x0F, 0x9C, 0x51, +0xA4, 0xD3, 0x94, 0x51, 0xB5, 0x34, 0xA4, 0xD3, +0xCE, 0x18, 0xBD, 0x74, 0xB5, 0x31, 0xB5, 0x32, +0x84, 0x0F, 0xB5, 0x95, 0xAD, 0x94, 0xAD, 0x74, +0x94, 0x91, 0xA5, 0x13, 0xAD, 0x74, 0xB5, 0x94, +0xAD, 0x54, 0x73, 0xAD, 0x6B, 0x4C, 0x5A, 0xEA, +0x73, 0xAD, 0x7B, 0xEF, 0x8C, 0x50, 0x8C, 0x70, +0xB5, 0xB5, 0xC6, 0x37, 0xC6, 0x16, 0x83, 0xEE, +0x83, 0xEE, 0x9C, 0x6E, 0xB5, 0x10, 0x7B, 0x8A, +0xA4, 0xD0, 0xAC, 0xF1, 0xA5, 0x12, 0xC6, 0x18, +0xB5, 0x76, 0x9C, 0xF4, 0x73, 0x8D, 0x83, 0xAD, +0x9C, 0x90, 0x83, 0xED, 0x73, 0x4B, 0x8C, 0x2E, +0xA4, 0xB0, 0xAD, 0x11, 0xA4, 0xB0, 0xA4, 0xB0, +0x9C, 0x6F, 0xA4, 0x8F, 0x83, 0x6B, 0x93, 0xAC, +0x93, 0xAC, 0x94, 0x0E, 0xBD, 0x94, 0xB5, 0x94, +0xC6, 0x36, 0xB5, 0xB4, 0xB5, 0x74, 0xAD, 0x53, +0xB5, 0x94, 0xAD, 0x73, 0xAD, 0x32, 0x9C, 0xB1, +0xA5, 0x32, 0xB5, 0x94, 0xB5, 0x94, 0xBD, 0xD5, +0xBD, 0xD5, 0xBD, 0xD5, 0xBD, 0xF5, 0x9C, 0xD1, +0x94, 0x6F, 0xB5, 0x94, 0xCE, 0x36, 0xC6, 0x16, +0xC5, 0xF5, 0x84, 0x2E, 0x9C, 0xD1, 0xA5, 0x12, +0xA4, 0xF2, 0x9C, 0xB1, 0xA5, 0x12, 0xA5, 0x32, +0xA5, 0x33, 0xBD, 0xF5, 0xAD, 0x74, 0xA5, 0x33, +0xB5, 0x94, 0xAD, 0x73, 0x83, 0xEE, 0x9C, 0xD1, +0xA4, 0xF1, 0x9C, 0xD1, 0xA4, 0xF2, 0x84, 0x0E, +0x84, 0x0E, 0xA5, 0x12, 0x9C, 0xB0, 0x94, 0x4F, +0x94, 0x90, 0x8C, 0x2E, 0x94, 0x4F, 0x9C, 0x90, +0xBD, 0x93, 0xCE, 0x36, 0xDE, 0xB7, 0xD6, 0x76, +0xCE, 0x15, 0xA4, 0xD1, 0x94, 0x6F, 0x94, 0x4E, +0x7B, 0xAC, 0x7B, 0x8C, 0x7B, 0xAD, 0x94, 0x6F, +0xAD, 0x12, 0xB5, 0x53, 0xC5, 0xD5, 0xAD, 0x32, +0x83, 0xEE, 0x94, 0x4F, 0xB5, 0x12, 0xBD, 0x52, +0xC5, 0x93, 0xBD, 0x73, 0x9C, 0x2E, 0xA4, 0x6F, +0xA4, 0xB0, 0x94, 0x4F, 0x9C, 0x90, 0xAD, 0x32, +0xAD, 0x32, 0xAD, 0x12, 0x9C, 0xB0, 0x9C, 0x90, +0x94, 0x6F, 0xA4, 0xF1, 0x9C, 0xD1, 0x94, 0x6F, +0x8C, 0x2F, 0x94, 0x6F, 0x8C, 0x2E, 0xA4, 0xD1, +0x8C, 0x2E, 0x94, 0x70, 0x9C, 0xB0, 0x8C, 0x2E, +0x7B, 0xAC, 0x83, 0xCD, 0x83, 0xCD, 0x83, 0xCD, +0xB5, 0x53, 0x8C, 0x2E, 0x8C, 0x2E, 0x94, 0x6F, +0x9C, 0x70, 0x9C, 0x90, 0x9C, 0x90, 0x94, 0x2E, +0x94, 0x4F, 0x9C, 0x8F, 0x94, 0x6F, 0x9C, 0x6F, +0x9C, 0xB0, 0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x53, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x32, 0xAC, 0xF2, 0xAC, 0xD1, +0xA4, 0xD1, 0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xF1, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF2, 0xAD, 0x12, +0xAC, 0xF1, 0xA4, 0xF1, 0xA4, 0xB0, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x53, +0xA4, 0xD1, 0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xF1, +0xAC, 0xF0, 0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF0, +0xA4, 0xD0, 0xA4, 0xD0, 0x94, 0x2D, 0xA4, 0xB0, +0xCD, 0xB3, 0xC5, 0x91, 0xBD, 0x72, 0x9C, 0x6E, +0xA5, 0x35, 0xAD, 0x96, 0x9D, 0x14, 0x9C, 0xF4, +0x8C, 0x92, 0x84, 0x0F, 0x8C, 0x90, 0x8C, 0x70, +0x8C, 0x4F, 0xA5, 0x11, 0xB5, 0x73, 0xAD, 0x52, +0xA5, 0x11, 0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x73, +0xAD, 0x52, 0xA4, 0xF1, 0xC5, 0xF4, 0xA4, 0xAF, +0xAC, 0xEF, 0xBD, 0xD3, 0xA5, 0x11, 0xA5, 0x12, +0xB5, 0x93, 0xAD, 0x52, 0xAD, 0x53, 0xAD, 0x53, +0x9C, 0xD1, 0xBD, 0xD5, 0xBD, 0xB4, 0xC6, 0x15, +0xB5, 0x93, 0xB5, 0x94, 0xB5, 0x73, 0xB5, 0x93, +0xB5, 0x93, 0xAD, 0x73, 0xBD, 0xD5, 0xBD, 0xB4, +0xA4, 0xF1, 0xB5, 0x93, 0xAD, 0x11, 0xB5, 0x10, +0x9C, 0x4E, 0x9C, 0xB0, 0xAD, 0x32, 0xAD, 0x32, +0xA4, 0xF1, 0xAD, 0x52, 0xB5, 0x72, 0xBD, 0xB4, +0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x72, 0xB5, 0x52, +0x94, 0x6F, 0xB5, 0x52, 0xB5, 0x32, 0xA4, 0xF0, +0xBD, 0x73, 0xAC, 0xF0, 0x9C, 0x8F, 0x9C, 0x8F, +0xA4, 0xCF, 0x94, 0x2E, 0x52, 0x88, 0x31, 0xA5, +0x39, 0xE6, 0x41, 0xE6, 0x42, 0x07, 0x39, 0xC7, +0x4A, 0x69, 0x6B, 0x4D, 0x84, 0x10, 0x9C, 0xD3, +0x9C, 0xF3, 0xAD, 0x76, 0xB5, 0x97, 0xB5, 0x96, +0xA5, 0x35, 0x7B, 0xAF, 0x7B, 0xEE, 0xA4, 0xF1, +0xAC, 0xF1, 0xB4, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, +0xA4, 0xAF, 0xA4, 0xAF, 0xB5, 0x11, 0xAC, 0xF0, +0xAC, 0xCF, 0xAC, 0xD0, 0x8B, 0xED, 0x7B, 0xAC, +0x52, 0x48, 0x31, 0x85, 0x39, 0xC6, 0x39, 0xE7, +0x39, 0xC6, 0x6B, 0x0C, 0x6B, 0x2C, 0x5A, 0xAA, +0x41, 0xA6, 0x62, 0x8A, 0x83, 0x4C, 0x6A, 0xAA, +0x9C, 0x92, 0x8B, 0xF0, 0xC5, 0xD7, 0xA4, 0xD3, +0xAD, 0x34, 0xC5, 0xD6, 0xD5, 0xF5, 0xCD, 0x93, +0xAC, 0xD0, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xD1, +0x94, 0x70, 0x9C, 0xD1, 0xB5, 0x94, 0xBD, 0xD5, +0xB5, 0xB4, 0x94, 0xB0, 0x84, 0x0E, 0x73, 0xAE, +0x7B, 0xCE, 0x7C, 0x0F, 0x9C, 0xF2, 0xAD, 0x95, +0xDE, 0xDA, 0xCE, 0x79, 0xC6, 0x17, 0xB5, 0x95, +0xBD, 0x95, 0xB5, 0x32, 0xB5, 0x10, 0xA4, 0xAF, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB4, 0xC6, 0x18, +0xAD, 0x56, 0xA4, 0xF3, 0xA4, 0xF2, 0x9C, 0x90, +0x94, 0x2E, 0x7B, 0xAC, 0x7B, 0xAC, 0x94, 0x4F, +0xAD, 0x11, 0xB5, 0x72, 0xBD, 0x72, 0xAC, 0xD0, +0xAC, 0xD0, 0xA4, 0x8F, 0x7B, 0x0A, 0x83, 0x6B, +0x8B, 0x6B, 0x9C, 0x4F, 0xB5, 0x73, 0xBD, 0xF5, +0xC6, 0x36, 0xBD, 0xD5, 0xBD, 0xB5, 0xB5, 0x94, +0xBD, 0xD5, 0xB5, 0x94, 0xA4, 0xF2, 0xA5, 0x12, +0xA5, 0x32, 0xA5, 0x32, 0xAD, 0x53, 0xBD, 0xB5, +0xBD, 0xF5, 0xB5, 0xB4, 0xB5, 0xB4, 0xBD, 0xF5, +0xBD, 0xD5, 0xC6, 0x16, 0xC6, 0x36, 0xC6, 0x16, +0xBD, 0xD5, 0x84, 0x2E, 0xA5, 0x12, 0xAD, 0x33, +0xA4, 0xF2, 0x9C, 0xD1, 0x9C, 0xF1, 0x94, 0x90, +0x9C, 0xB1, 0xAD, 0x73, 0xAD, 0x53, 0xB5, 0xB5, +0xBD, 0xF6, 0xB5, 0xB5, 0x8C, 0x6F, 0xA5, 0x12, +0x9C, 0xD1, 0xAD, 0x12, 0xBD, 0xB5, 0xB5, 0x74, +0xA5, 0x12, 0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0xD1, +0x9C, 0xB0, 0x9C, 0x90, 0x9C, 0xB1, 0x9C, 0xB1, +0xBD, 0x73, 0xCE, 0x35, 0xC5, 0xF4, 0xCE, 0x15, +0xC5, 0xF4, 0xA4, 0xF0, 0xA4, 0xD0, 0xAD, 0x11, +0x8B, 0xED, 0xA4, 0xD1, 0x94, 0x6F, 0x9C, 0xB0, +0x9C, 0xB1, 0x94, 0x70, 0xB5, 0x74, 0x94, 0x90, +0x8C, 0x2F, 0xA4, 0xD1, 0xAC, 0xF2, 0xBD, 0x53, +0xCD, 0xB4, 0xC5, 0x73, 0x83, 0x8C, 0xA4, 0x6F, +0xA4, 0xF1, 0x9C, 0xB0, 0x94, 0x6F, 0xB5, 0x53, +0xB5, 0x73, 0xAD, 0x53, 0xA4, 0xF2, 0xA4, 0xD1, +0x9C, 0xB1, 0xB5, 0x73, 0xAD, 0x53, 0xA5, 0x12, +0xA4, 0xF1, 0x94, 0x90, 0x9C, 0x90, 0xA4, 0xF2, +0xA4, 0xF2, 0xAD, 0x53, 0xAD, 0x53, 0xA5, 0x12, +0x9C, 0xB1, 0x7B, 0xCD, 0x94, 0x70, 0x8C, 0x4F, +0xAD, 0x33, 0x83, 0xED, 0x9C, 0x90, 0xA4, 0xF1, +0x8C, 0x2E, 0x8B, 0xED, 0x9C, 0x6F, 0x94, 0x2E, +0x94, 0x4E, 0x83, 0xCD, 0x83, 0xED, 0x8B, 0xEE, +0xA4, 0xD1, 0x94, 0x4F, 0x94, 0x8F, 0x9C, 0x90, +0x94, 0x2E, 0x8B, 0xED, 0x8C, 0x0E, 0x9C, 0x90, +0xA4, 0xD1, 0x9C, 0xB0, 0xAD, 0x11, 0x9C, 0xB0, +0xA4, 0xD1, 0x9C, 0xB0, 0x8B, 0xED, 0x7B, 0x8C, +0x8C, 0x0E, 0xB5, 0x53, 0xB5, 0x53, 0x9C, 0x90, +0xA4, 0xD1, 0xA4, 0xB0, 0xAC, 0xF1, 0xA4, 0xF1, +0x9C, 0x90, 0xA4, 0xD1, 0xB5, 0x32, 0xB5, 0x32, +0xBD, 0x53, 0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x73, 0xC5, 0xB5, +0xC5, 0xB4, 0xCD, 0xD5, 0xBD, 0x94, 0xBD, 0x73, +0xBD, 0x93, 0xC5, 0x94, 0xC5, 0x94, 0xC5, 0xB4, +0xC5, 0x93, 0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x32, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF3, +0x8C, 0x92, 0x84, 0x0F, 0x8C, 0x91, 0x94, 0xB1, +0x8C, 0x4F, 0xA5, 0x12, 0xB5, 0x93, 0xAD, 0x31, +0xAD, 0x31, 0x9C, 0xF0, 0xBD, 0xD4, 0xB5, 0x94, +0xBD, 0xD4, 0xAD, 0x32, 0xC6, 0x14, 0xA4, 0xAF, +0xA4, 0xAE, 0xBD, 0xB3, 0xAD, 0x52, 0xA5, 0x32, +0xB5, 0x73, 0xAD, 0x32, 0xA5, 0x32, 0xA5, 0x32, +0xA5, 0x12, 0xBD, 0xD4, 0xC5, 0xF5, 0xBD, 0xF4, +0xB5, 0x73, 0xB5, 0xB4, 0xB5, 0x93, 0xBD, 0xB4, +0xC5, 0xD5, 0xB5, 0xB4, 0xB5, 0x93, 0xB5, 0x73, +0xB5, 0x52, 0xBD, 0x93, 0xB5, 0x72, 0xAD, 0x10, +0x83, 0xAB, 0xAD, 0x53, 0xAD, 0x53, 0xB5, 0xB4, +0x94, 0xB1, 0xB5, 0xB4, 0xB5, 0xB4, 0xC6, 0x16, +0xBD, 0xD5, 0xC6, 0x16, 0xC6, 0x36, 0xBD, 0xF6, +0xA5, 0x12, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x74, +0xBD, 0xF5, 0xBD, 0xF5, 0xBD, 0xF5, 0xC6, 0x16, +0xC6, 0x16, 0xA5, 0x32, 0x8C, 0x2E, 0x4A, 0x27, +0x39, 0xC6, 0x41, 0xE7, 0x42, 0x07, 0x4A, 0x28, +0x42, 0x28, 0x63, 0x2C, 0x7B, 0xCF, 0x7B, 0xCF, +0xA5, 0x35, 0x94, 0x92, 0x9C, 0xD3, 0xAD, 0x55, +0xAD, 0x75, 0xB5, 0xB6, 0xC5, 0xF7, 0xBD, 0xD5, +0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0x92, 0xB5, 0x51, +0xB5, 0x52, 0xCD, 0xF4, 0xB5, 0x10, 0x9C, 0x6E, +0x83, 0x8A, 0x83, 0xAB, 0x8B, 0xCC, 0x83, 0xED, +0x52, 0x68, 0x29, 0x44, 0x31, 0x85, 0x39, 0xA6, +0x41, 0xE7, 0x63, 0x0C, 0x5A, 0xAA, 0x5A, 0x8A, +0x83, 0xEF, 0x52, 0x6A, 0x62, 0x69, 0x93, 0xEF, +0xA4, 0x92, 0x9C, 0x71, 0xC5, 0xD7, 0xD6, 0x38, +0xBD, 0x75, 0xBD, 0x55, 0xB5, 0x33, 0xBD, 0x52, +0xBD, 0x31, 0xB5, 0x10, 0xA4, 0xAF, 0x9C, 0x6E, +0xA4, 0x8F, 0xAC, 0xD0, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x4F, +0x94, 0x6F, 0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xF1, +0x7B, 0xAD, 0x6B, 0x2B, 0x5A, 0x89, 0x52, 0x69, +0x8C, 0x30, 0xA4, 0xF2, 0xC5, 0xD5, 0xB5, 0x52, +0xBD, 0x93, 0xAD, 0x11, 0xC5, 0xB5, 0xC6, 0x38, +0xA5, 0x55, 0x94, 0x71, 0xBD, 0x73, 0xAD, 0x11, +0xA4, 0xB0, 0xA4, 0xB0, 0x8C, 0x2E, 0x94, 0x2E, +0x94, 0x4E, 0x8C, 0x0D, 0x9C, 0x6E, 0xAC, 0xF0, +0xB5, 0x11, 0x8B, 0xEC, 0x73, 0x0A, 0x72, 0xE9, +0x73, 0x0A, 0x9C, 0x6F, 0xAD, 0x12, 0xB5, 0x73, +0xBD, 0xD5, 0xBD, 0xD5, 0xBD, 0xD5, 0xB5, 0x74, +0xB5, 0x94, 0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x73, +0x94, 0x6F, 0xA4, 0xF1, 0xAD, 0x53, 0xC5, 0xF6, +0xBD, 0xD5, 0xBD, 0xD5, 0xB5, 0x94, 0xC5, 0xF5, +0xCE, 0x36, 0xCE, 0x36, 0xC6, 0x16, 0xC6, 0x16, +0xBD, 0xB4, 0x7B, 0xCD, 0x94, 0x90, 0xB5, 0x94, +0xB5, 0xB4, 0xAD, 0x53, 0xB5, 0xB4, 0x84, 0x0E, +0x94, 0x70, 0xA5, 0x12, 0xA5, 0x12, 0xB5, 0xB5, +0xBD, 0xD5, 0xBD, 0xD5, 0x9C, 0xB1, 0xAD, 0x33, +0x9C, 0xD1, 0xAD, 0x32, 0xDE, 0xB8, 0xC6, 0x16, +0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0x94, +0xBD, 0xD5, 0xBD, 0xD4, 0xC5, 0xF5, 0xA4, 0xF2, +0xBD, 0x94, 0xC5, 0xD4, 0xC6, 0x15, 0xC5, 0xF4, +0xC5, 0xD4, 0xAD, 0x11, 0xAC, 0xF0, 0xAD, 0x11, +0x9C, 0x8F, 0x9C, 0x90, 0x9C, 0x90, 0xA5, 0x12, +0xAD, 0x33, 0xAD, 0x54, 0xBD, 0xD5, 0xA4, 0xF2, +0x94, 0x70, 0xAC, 0xF1, 0xB5, 0x12, 0xC5, 0x94, +0xCD, 0xB3, 0xCD, 0x93, 0x8B, 0x8C, 0xA4, 0x90, +0x9C, 0x90, 0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xF1, +0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x73, 0xA4, 0xF2, +0xA5, 0x12, 0xAD, 0x32, 0xBD, 0xB4, 0xAD, 0x53, +0xBD, 0xD5, 0xAD, 0x53, 0xAD, 0x74, 0xB5, 0x74, +0xB5, 0x74, 0xBD, 0xD5, 0xBD, 0xD4, 0xBD, 0xF5, +0xBD, 0xB5, 0xAD, 0x32, 0x8C, 0x2E, 0x8C, 0x2E, +0xA4, 0xF1, 0x8C, 0x0E, 0xAD, 0x12, 0xA4, 0xD1, +0x8C, 0x0E, 0x7B, 0xCC, 0x9C, 0x8F, 0xAD, 0x11, +0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0x90, +0xBD, 0xB4, 0x9C, 0xB0, 0x8C, 0x2E, 0xA4, 0xD1, +0x8C, 0x2E, 0x8B, 0xED, 0x9C, 0x8F, 0xAD, 0x32, +0x94, 0x4E, 0xB5, 0x52, 0x9C, 0x8F, 0x9C, 0x8F, +0xAD, 0x12, 0x94, 0x8F, 0x83, 0xED, 0x6B, 0x0A, +0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x93, 0xA4, 0xD0, +0xA4, 0xF1, 0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xB0, +0x8C, 0x2F, 0x94, 0x90, 0xAD, 0x33, 0xA5, 0x32, +0xBD, 0xB4, 0x8C, 0x2F, 0x9C, 0xB0, 0xAD, 0x52, +0x9C, 0xD0, 0x9C, 0x90, 0x94, 0x6F, 0x8C, 0x0E, +0x8C, 0x2E, 0xB5, 0x52, 0xA4, 0xD1, 0xAD, 0x11, +0xAC, 0xF1, 0xA4, 0xD0, 0x9C, 0x6F, 0x9C, 0x90, +0x8C, 0x0E, 0xA4, 0xB0, 0xA4, 0xF1, 0xAD, 0x11, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF4, +0x8C, 0x71, 0x84, 0x50, 0x8C, 0x90, 0x94, 0xD1, +0x84, 0x2F, 0xA5, 0x11, 0xB5, 0x93, 0xB5, 0x73, +0xA5, 0x11, 0xAD, 0x72, 0xB5, 0xB4, 0xB5, 0x94, +0xBD, 0xB4, 0xAD, 0x52, 0xC5, 0xF4, 0xA4, 0x8E, +0x9C, 0x6E, 0xB5, 0x72, 0xB5, 0xB4, 0xAD, 0x73, +0xAD, 0x52, 0xAD, 0x53, 0xA5, 0x32, 0xB5, 0x74, +0xA5, 0x12, 0xBD, 0xF5, 0xC5, 0xF5, 0xC6, 0x15, +0xB5, 0xB4, 0xBD, 0xB4, 0xC6, 0x15, 0xBD, 0xD5, +0xB5, 0x94, 0xB5, 0x73, 0xB5, 0x73, 0xA5, 0x11, +0xB5, 0x72, 0xBD, 0xD4, 0xB5, 0x72, 0xAC, 0xEF, +0x8C, 0x0D, 0xB5, 0xB4, 0xB5, 0x94, 0xBD, 0xF6, +0xAD, 0x94, 0xC6, 0x16, 0xBD, 0xF6, 0xBD, 0xF6, +0xBD, 0xD5, 0xBE, 0x16, 0xC6, 0x37, 0xC6, 0x16, +0xC6, 0x16, 0xBD, 0xF6, 0xBD, 0xD5, 0xB5, 0xB5, +0xBD, 0xF6, 0xBD, 0xD5, 0xCE, 0x77, 0xCE, 0x57, +0xC6, 0x16, 0xB5, 0xB4, 0x9C, 0xB0, 0x94, 0x4F, +0x39, 0xA5, 0x31, 0x85, 0x39, 0xE7, 0x39, 0xA6, +0x31, 0x85, 0x41, 0xE7, 0x4A, 0x28, 0x73, 0x6D, +0x8C, 0x51, 0x8C, 0x51, 0xB5, 0x75, 0x9C, 0xB3, +0x8C, 0x51, 0x94, 0xB2, 0xC6, 0x38, 0xD6, 0x98, +0xC6, 0x15, 0xD6, 0x76, 0xCE, 0x55, 0xB5, 0x72, +0xAD, 0x31, 0xBD, 0x92, 0x9C, 0x8E, 0xAC, 0xF0, +0x83, 0xAB, 0x8C, 0x2D, 0x94, 0x4E, 0x9C, 0xD0, +0x9C, 0xD0, 0x7B, 0xCD, 0x39, 0xA5, 0x39, 0xA6, +0x4A, 0x48, 0x42, 0x07, 0x41, 0xE7, 0x83, 0xCF, +0x8C, 0x51, 0xC5, 0xF7, 0x52, 0x29, 0x6A, 0xCB, +0x72, 0xEB, 0x94, 0x31, 0xA4, 0xB3, 0xCD, 0xF7, +0xD6, 0x58, 0xAC, 0xD3, 0x6B, 0x0B, 0x83, 0x8D, +0xAC, 0xD1, 0x73, 0x2A, 0x83, 0x8A, 0x83, 0xAB, +0x7B, 0x6A, 0x94, 0x0D, 0x94, 0x2D, 0x94, 0x2D, +0x9C, 0x4E, 0x94, 0x2D, 0x94, 0x2E, 0x9C, 0x6E, +0xA4, 0xAF, 0xAC, 0xCF, 0xB5, 0x31, 0xB5, 0x10, +0xBD, 0x52, 0xBD, 0x52, 0xAC, 0xF0, 0x9C, 0x4F, +0x6B, 0x2B, 0x42, 0x07, 0x73, 0x6D, 0x94, 0x71, +0xB5, 0x74, 0xAC, 0xF2, 0xC5, 0xD6, 0xCE, 0x59, +0xAD, 0x76, 0x94, 0x71, 0xAC, 0xF1, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x52, 0xB5, 0x11, 0xAC, 0xD0, 0xAC, 0xF0, +0xAC, 0xD0, 0xAC, 0xF1, 0xA4, 0xB1, 0xA4, 0xB1, +0x9C, 0xB1, 0xAD, 0x12, 0xB5, 0x74, 0xA4, 0xF2, +0xA4, 0xD1, 0x94, 0x70, 0x8C, 0x4F, 0x94, 0x6F, +0x9C, 0xB0, 0x9C, 0xB1, 0x94, 0x70, 0x8C, 0x2E, +0x8C, 0x2E, 0x83, 0xED, 0x83, 0xED, 0x94, 0x90, +0x9C, 0xF1, 0xB5, 0x94, 0xAD, 0x52, 0xBD, 0xB4, +0xBD, 0xD5, 0xBD, 0xB4, 0xB5, 0x94, 0xBD, 0xB4, +0xAD, 0x52, 0x7B, 0xAC, 0x94, 0x90, 0xA4, 0xF1, +0xB5, 0x94, 0xAD, 0x33, 0xAD, 0x53, 0x8C, 0x2F, +0x84, 0x0E, 0x9C, 0xD0, 0xA5, 0x11, 0xB5, 0x94, +0xBD, 0xD5, 0xB5, 0xB4, 0x94, 0x6F, 0xB5, 0x73, +0xAD, 0x12, 0xAD, 0x32, 0xC5, 0xD5, 0xC5, 0xF5, +0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x56, +0xBD, 0xD4, 0xBD, 0xD5, 0xD6, 0x77, 0xAD, 0x11, +0xB5, 0x73, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xC5, 0xF4, 0xB5, 0x32, 0xA4, 0xD0, 0xA4, 0xF0, +0x9C, 0x8F, 0xBD, 0x73, 0xA4, 0xF1, 0x9C, 0xF1, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, 0xA5, 0x12, +0xA4, 0xF1, 0xB5, 0x32, 0xBD, 0x53, 0xCD, 0xD4, +0xD5, 0xF4, 0xCD, 0xB3, 0x8B, 0x8C, 0xA4, 0x90, +0x94, 0x4F, 0x9C, 0xB0, 0xA4, 0xD1, 0xA4, 0xD1, +0xC6, 0x15, 0xC5, 0xF5, 0xB5, 0xB4, 0x9C, 0xB0, +0xA5, 0x32, 0xAD, 0x33, 0xB5, 0x94, 0xAD, 0x53, +0xBD, 0xB4, 0xB5, 0x73, 0xA5, 0x12, 0xAD, 0x53, +0xB5, 0x74, 0xAD, 0x53, 0xB5, 0x74, 0xBD, 0xD5, +0xBD, 0xD5, 0xBD, 0xB4, 0xA4, 0xF1, 0x94, 0x4F, +0xA4, 0xF1, 0x9C, 0x90, 0xA4, 0xF1, 0x9C, 0xB0, +0x8C, 0x2E, 0x84, 0x0D, 0x94, 0x4F, 0x94, 0x8F, +0x8C, 0x2E, 0x8C, 0x2E, 0xAD, 0x32, 0x9C, 0x90, +0xB5, 0x53, 0x9C, 0x8F, 0x94, 0x6F, 0xA5, 0x11, +0x94, 0x6F, 0x94, 0x2E, 0xAD, 0x12, 0xBD, 0x72, +0xBD, 0x93, 0xC5, 0x93, 0x94, 0x4E, 0x9C, 0xB0, +0xB5, 0x53, 0x9C, 0x90, 0x8C, 0x4F, 0x73, 0x4B, +0xA4, 0xD1, 0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0x90, +0xA4, 0xD1, 0xB5, 0x53, 0xAD, 0x32, 0xA5, 0x32, +0xAD, 0x53, 0xAD, 0x53, 0xBD, 0xD5, 0xB5, 0x94, +0xC6, 0x16, 0x9C, 0xB0, 0xAD, 0x53, 0xC5, 0xF5, +0xB5, 0x93, 0xA4, 0xD1, 0xA4, 0xD1, 0xAC, 0xF2, +0x8C, 0x4F, 0xB5, 0x53, 0xB5, 0x52, 0xD6, 0x55, +0xBD, 0x93, 0xBD, 0x72, 0xBD, 0xD4, 0xC5, 0xF4, +0xB5, 0x52, 0x94, 0x6F, 0xB5, 0x73, 0xB5, 0x73, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF3, +0x8C, 0x91, 0x84, 0x70, 0x8C, 0x91, 0x94, 0xB1, +0x94, 0xB0, 0xA5, 0x52, 0xAD, 0x72, 0xAD, 0x52, +0xA5, 0x11, 0xBD, 0xB4, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xB4, 0xAD, 0x52, 0xCE, 0x15, 0x9C, 0x6E, +0x94, 0x4D, 0xAD, 0x31, 0xAD, 0x53, 0xB5, 0x94, +0xBD, 0xB4, 0x9C, 0xF1, 0xB5, 0xB5, 0xAD, 0x74, +0xA5, 0x12, 0xBD, 0xD4, 0xB5, 0x73, 0xBD, 0xF5, +0xBD, 0xF5, 0xBD, 0xD5, 0xC5, 0xF5, 0xB5, 0xB4, +0xB5, 0x73, 0xB5, 0x73, 0xA5, 0x11, 0x94, 0xAF, +0xA5, 0x31, 0xB5, 0x93, 0xAD, 0x11, 0xAC, 0xF0, +0x8C, 0x2D, 0xB5, 0xB4, 0xBD, 0xF6, 0xBD, 0xF6, +0xB5, 0xD5, 0xC6, 0x36, 0xC6, 0x16, 0xB5, 0xD5, +0xB5, 0xB4, 0xBD, 0xF6, 0xBD, 0xF6, 0xC6, 0x16, +0xC6, 0x37, 0xCE, 0x57, 0x9C, 0xD1, 0xAD, 0x94, +0xCE, 0x98, 0xCE, 0x57, 0xD6, 0x78, 0xCE, 0x57, +0xCE, 0x37, 0xB5, 0x94, 0xAD, 0x32, 0xB5, 0x52, +0x73, 0x6C, 0x31, 0xA6, 0x39, 0xC6, 0x42, 0x07, +0x42, 0x07, 0x42, 0x07, 0x52, 0x8A, 0x63, 0x2C, +0x7B, 0xCF, 0x9C, 0xD3, 0xBD, 0xF7, 0xA5, 0x14, +0x6B, 0x4D, 0x73, 0xAF, 0xBD, 0xD7, 0xDE, 0xBA, +0xB5, 0x54, 0x63, 0x0B, 0xA4, 0xF1, 0xBD, 0xD4, +0xAD, 0x31, 0xB5, 0x72, 0x94, 0x4D, 0xB5, 0x51, +0x94, 0x4E, 0xAD, 0x32, 0xAD, 0x53, 0xB5, 0x94, +0xB5, 0x73, 0xAD, 0x52, 0x7B, 0xAD, 0x29, 0x24, +0x29, 0x45, 0x39, 0xC6, 0x42, 0x07, 0x5A, 0xAA, +0x8C, 0x51, 0xC5, 0xF7, 0x94, 0x51, 0x83, 0xAF, +0x6A, 0xCB, 0x9C, 0x51, 0xAC, 0xD3, 0x8B, 0xEF, +0x7B, 0x8E, 0x83, 0x8E, 0x8B, 0xEF, 0x83, 0xAD, +0xAD, 0x13, 0xCE, 0x37, 0x94, 0x4F, 0x83, 0x8C, +0x83, 0xAC, 0x73, 0x4A, 0x6B, 0x0A, 0x7B, 0x6B, +0x7B, 0x4A, 0x6A, 0xE9, 0x62, 0xC9, 0x52, 0x27, +0x4A, 0x27, 0x5A, 0x67, 0x6A, 0xE9, 0x8B, 0xCC, +0xC5, 0x92, 0xA4, 0x6D, 0x94, 0x2D, 0xA4, 0x8E, +0xAC, 0xF0, 0x9C, 0x8F, 0x84, 0x0E, 0x5A, 0xCA, +0x4A, 0x48, 0x5A, 0xEB, 0x9C, 0xB2, 0xCE, 0x59, +0x9C, 0xD3, 0x7B, 0xAD, 0x8B, 0xEC, 0xB5, 0x11, +0x7B, 0x6B, 0x83, 0x8B, 0x83, 0xAB, 0x83, 0xAC, +0x83, 0x8B, 0x83, 0xAC, 0x8B, 0xCC, 0x94, 0x0D, +0xA4, 0xB0, 0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x32, +0xB5, 0x74, 0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x74, 0xBD, 0x94, 0xC5, 0xB5, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB5, 0xBD, 0x94, +0xB5, 0x74, 0xBD, 0xB4, 0xB5, 0x74, 0xB5, 0x74, +0xB5, 0x74, 0xA5, 0x12, 0x9C, 0x90, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0x90, 0x8C, 0x2F, 0x8C, 0x0E, +0x8C, 0x0E, 0x8C, 0x4F, 0x9C, 0xB1, 0x8C, 0x4F, +0x8C, 0x2E, 0x84, 0x0E, 0x7B, 0xCD, 0x83, 0xED, +0x84, 0x0E, 0x94, 0x6F, 0x94, 0x4F, 0x9C, 0xB0, +0xA5, 0x12, 0x9C, 0x90, 0x7B, 0x8C, 0xA5, 0x12, +0x9C, 0xD0, 0x9C, 0xB0, 0xAD, 0x32, 0xA5, 0x11, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x73, 0xBD, 0x93, +0xC5, 0xD4, 0xCE, 0x35, 0xBD, 0x93, 0x94, 0x6F, +0xB5, 0x73, 0xCE, 0x15, 0xBD, 0xB4, 0xC5, 0xB4, +0xBD, 0xB4, 0xAD, 0x11, 0x94, 0x6F, 0x9C, 0x8F, +0x8C, 0x2E, 0xAD, 0x11, 0xA4, 0xF1, 0xA5, 0x12, +0xB5, 0x94, 0xAD, 0x74, 0xBD, 0xD5, 0xB5, 0x94, +0xBD, 0x94, 0xC5, 0x93, 0xBD, 0x52, 0xBD, 0x52, +0xDE, 0x15, 0xCD, 0x93, 0x83, 0x6B, 0xAC, 0xD1, +0x8C, 0x0E, 0xA4, 0xD0, 0xBD, 0x94, 0xBD, 0xB4, +0xCE, 0x36, 0xCE, 0x15, 0xBD, 0xD4, 0xAD, 0x32, +0x9C, 0xD1, 0xA4, 0xF1, 0xB5, 0x74, 0xB5, 0x94, +0xBD, 0xB5, 0xAD, 0x53, 0xA5, 0x12, 0xAD, 0x33, +0xBD, 0xB4, 0xB5, 0xB4, 0xB5, 0x94, 0xBD, 0xF5, +0xB5, 0x73, 0xA4, 0xF1, 0xA5, 0x11, 0x94, 0x4F, +0xB5, 0x53, 0xA4, 0xD1, 0xB5, 0x53, 0xAD, 0x32, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x12, +0xAD, 0x12, 0x9C, 0xB0, 0xC5, 0xD5, 0xB5, 0x73, +0xC6, 0x15, 0xB5, 0x93, 0xA4, 0xF1, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x11, 0x9C, 0x6F, 0xBD, 0x72, +0xC5, 0xB3, 0xC5, 0xB3, 0x9C, 0x8F, 0xAD, 0x12, +0xAD, 0x11, 0x9C, 0xB0, 0x94, 0x4F, 0x73, 0x8C, +0x94, 0x6F, 0xC5, 0xD4, 0xBD, 0x73, 0xAD, 0x12, +0xAD, 0x33, 0xA4, 0xD1, 0x94, 0x6F, 0xAD, 0x32, +0xA5, 0x32, 0xAD, 0x94, 0xCE, 0x57, 0xBD, 0xD5, +0xBD, 0xB4, 0xAD, 0x33, 0xC6, 0x16, 0xC6, 0x35, +0xC6, 0x15, 0xAD, 0x32, 0x9C, 0x90, 0xB5, 0x73, +0xA5, 0x12, 0xBD, 0x93, 0xC5, 0xB3, 0xD6, 0x55, +0xCE, 0x14, 0xA4, 0xAF, 0xC5, 0xD4, 0xCE, 0x55, +0xC5, 0xF4, 0xAD, 0x31, 0xBD, 0xD4, 0xC6, 0x35, +0xA5, 0x35, 0xB5, 0x97, 0xA5, 0x34, 0x9C, 0xF4, +0x8C, 0x92, 0x8C, 0x90, 0x94, 0xB1, 0x9C, 0xF2, +0x9D, 0x12, 0xB5, 0x94, 0xB5, 0x93, 0xB5, 0x93, +0xB5, 0xB4, 0xC6, 0x36, 0xBD, 0xB4, 0xC6, 0x15, +0xC6, 0x15, 0xBD, 0xD4, 0xCE, 0x36, 0x9C, 0x4D, +0xB5, 0x31, 0xC5, 0xF4, 0xBD, 0xD4, 0xB5, 0xB4, +0xBD, 0xF5, 0xAD, 0x73, 0xC6, 0x37, 0xB5, 0xB5, +0x9D, 0x12, 0xC6, 0x36, 0xBD, 0xD5, 0xC6, 0x15, +0xC6, 0x16, 0xC6, 0x16, 0xC6, 0x36, 0xC6, 0x16, +0xC5, 0xF5, 0xC5, 0xF5, 0xAD, 0x32, 0xB5, 0x93, +0xBD, 0xF5, 0xCE, 0x35, 0x9C, 0x8F, 0xAC, 0xF0, +0x8C, 0x2D, 0xAD, 0x74, 0xB5, 0xB5, 0xBD, 0xF6, +0xC6, 0x16, 0xCE, 0x57, 0xBD, 0xF6, 0xBD, 0xF6, +0xB5, 0xD5, 0xB5, 0x94, 0xB5, 0xB5, 0xBD, 0xD5, +0xC6, 0x36, 0xBD, 0xF6, 0x9C, 0xF2, 0xBE, 0x16, +0xAD, 0x74, 0xCE, 0x57, 0xCE, 0x57, 0xCE, 0x57, +0xC6, 0x16, 0xBD, 0xB5, 0xAD, 0x32, 0xB5, 0x52, +0xAD, 0x32, 0x63, 0x2B, 0x42, 0x07, 0x42, 0x07, +0x4A, 0x48, 0x52, 0xAA, 0x63, 0x2C, 0x63, 0x0C, +0x6B, 0x2C, 0x84, 0x30, 0x9C, 0xD3, 0xA5, 0x14, +0x94, 0xB3, 0xAD, 0x56, 0xAD, 0x76, 0xCE, 0x59, +0xBD, 0xB7, 0x21, 0x05, 0x63, 0x2C, 0xC6, 0x36, +0xC5, 0xF4, 0xD6, 0x56, 0xA4, 0xAF, 0xB5, 0x51, +0xA4, 0xD0, 0xBD, 0xF5, 0xBD, 0xD5, 0xC5, 0xF5, +0xB5, 0x94, 0xAD, 0x52, 0xAD, 0x32, 0x73, 0x8C, +0x18, 0xC3, 0x39, 0xC6, 0x31, 0xA6, 0x6B, 0x4D, +0x9C, 0xD3, 0x7B, 0xAE, 0x94, 0x92, 0xD6, 0x59, +0xB5, 0x34, 0x72, 0xEC, 0x94, 0x30, 0x49, 0xE7, +0x52, 0x28, 0x83, 0x8D, 0xA4, 0xD2, 0xCD, 0xF6, +0x83, 0xCE, 0xAD, 0x13, 0xCE, 0x16, 0x9C, 0x90, +0x8C, 0x0E, 0x94, 0x2E, 0x8C, 0x2E, 0x8C, 0x2E, +0x94, 0x2E, 0x8C, 0x0E, 0x8C, 0x0E, 0x83, 0xEE, +0x83, 0xCD, 0x83, 0xAD, 0x6B, 0x0A, 0x6B, 0x0A, +0xBD, 0x72, 0x8B, 0xEB, 0x7B, 0xAB, 0x94, 0x4E, +0x9C, 0x4E, 0x8B, 0xEC, 0x94, 0x8F, 0x94, 0x6F, +0x6B, 0x4B, 0x39, 0xE7, 0x73, 0x8E, 0xA5, 0x35, +0x94, 0x92, 0x8C, 0x2E, 0x83, 0x8B, 0xB5, 0x31, +0x9C, 0x4E, 0x94, 0x4E, 0x94, 0x4E, 0x8B, 0xED, +0x7B, 0x8B, 0x8C, 0x0D, 0x94, 0x4E, 0x94, 0x4E, +0xA4, 0xD1, 0xB5, 0x53, 0x9C, 0x8F, 0xA4, 0xD0, +0xAD, 0x11, 0xBD, 0x93, 0xA4, 0xD1, 0xBD, 0xB4, +0xBD, 0xB4, 0x94, 0x70, 0x94, 0x4F, 0x9C, 0x90, +0xAD, 0x12, 0x9C, 0x90, 0x7B, 0x8D, 0x73, 0x6C, +0x83, 0xCD, 0x83, 0xEE, 0x9C, 0x90, 0xAD, 0x12, +0x94, 0x4F, 0xA4, 0xF1, 0x9C, 0xB0, 0x94, 0x6F, +0x9C, 0xD1, 0xAD, 0x12, 0xB5, 0x73, 0xBD, 0x94, +0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, +0xAD, 0x12, 0xB5, 0x53, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x32, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x53, +0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x94, +0xA4, 0xD1, 0xA4, 0xF1, 0xB5, 0x53, 0xAD, 0x12, +0xAD, 0x12, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x33, +0xAD, 0x32, 0xB5, 0x52, 0xAD, 0x32, 0xBD, 0xB4, +0xB5, 0x52, 0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x73, +0xB5, 0x32, 0xAD, 0x12, 0xAD, 0x32, 0xA4, 0xD1, +0x9C, 0x8F, 0xA4, 0xD0, 0x9C, 0x8F, 0xA4, 0xD1, +0x8C, 0x2F, 0x94, 0x91, 0x94, 0x70, 0x9C, 0xD1, +0x9C, 0x90, 0xAC, 0xD1, 0xAC, 0xF1, 0xAC, 0xD0, +0xAC, 0xF0, 0x9C, 0x2E, 0x7B, 0x2A, 0xAC, 0xF1, +0x83, 0xAC, 0x9C, 0xB0, 0xAD, 0x32, 0xC6, 0x15, +0xBD, 0xD4, 0xC5, 0xF4, 0xBD, 0xD4, 0xBD, 0xD5, +0xBD, 0xD4, 0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x94, +0xB5, 0xB4, 0xBD, 0xB5, 0xBD, 0xD5, 0xC5, 0xF5, +0xC6, 0x15, 0xC6, 0x15, 0xC6, 0x15, 0xC5, 0xF5, +0xAD, 0x32, 0xB5, 0x53, 0x9C, 0xD0, 0x8C, 0x2E, +0xAD, 0x52, 0x8C, 0x0E, 0xCE, 0x36, 0x9C, 0xB0, +0x94, 0x6F, 0x83, 0xED, 0xA4, 0xF1, 0xA4, 0xF1, +0x94, 0x6F, 0x9C, 0x90, 0xBD, 0xB4, 0xBD, 0xB4, +0xC5, 0xF4, 0xA5, 0x11, 0x8C, 0x2E, 0xA4, 0xF1, +0xAC, 0xF1, 0xB5, 0x52, 0xAC, 0xF0, 0xB5, 0x11, +0xBD, 0x72, 0xAC, 0xF0, 0xA4, 0xD0, 0xB5, 0x73, +0xB5, 0x53, 0x9C, 0xB0, 0x9C, 0xB1, 0x8C, 0x0E, +0x9C, 0xB0, 0xCE, 0x36, 0xC5, 0xF5, 0xB5, 0x73, +0xB5, 0x53, 0xB5, 0x73, 0xBD, 0xD5, 0xB5, 0x94, +0xA4, 0xF2, 0xA5, 0x33, 0xC6, 0x16, 0xC6, 0x16, +0xCE, 0x36, 0xA5, 0x32, 0xBD, 0xD5, 0xC6, 0x15, +0xCE, 0x15, 0xC5, 0xD5, 0xA4, 0xD1, 0xB5, 0xB4, +0xAD, 0x33, 0xB5, 0x73, 0xCD, 0xF4, 0xCE, 0x14, +0xBD, 0xB2, 0x9C, 0xAF, 0xCE, 0x14, 0xCE, 0x35, +0xB5, 0x52, 0xBD, 0xB3, 0xBD, 0xD4, 0xCE, 0x56, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x9C, 0xF4, +0x7B, 0xEF, 0x5A, 0xC9, 0x63, 0x09, 0x6B, 0x2A, +0x6B, 0x4A, 0x73, 0x8B, 0x73, 0x8B, 0x83, 0xCC, +0x83, 0xEC, 0x83, 0xED, 0x7B, 0x6B, 0x83, 0xED, +0x83, 0xED, 0x7B, 0x8C, 0x7B, 0x8C, 0x83, 0xAB, +0x7B, 0x8A, 0x7B, 0x8B, 0x8C, 0x0D, 0x7B, 0xAC, +0x7B, 0xAC, 0x94, 0x6F, 0xA4, 0xF1, 0x94, 0xB0, +0x94, 0xB0, 0xB5, 0x73, 0xAD, 0x73, 0xB5, 0xB4, +0xBD, 0xD4, 0xC5, 0xF5, 0xCE, 0x36, 0xD6, 0x77, +0xCE, 0x57, 0xCE, 0x57, 0xAD, 0x32, 0x9C, 0xB0, +0xBD, 0xB4, 0xC5, 0xD4, 0x83, 0xAC, 0xAC, 0xD0, +0x94, 0x8F, 0xBD, 0xF5, 0xC6, 0x16, 0xC6, 0x37, +0xC6, 0x16, 0xCE, 0x57, 0xCE, 0x57, 0xC6, 0x16, +0xC6, 0x16, 0xBD, 0xD5, 0xB5, 0xB4, 0xBD, 0xF6, +0xCE, 0x57, 0xCE, 0x98, 0xA5, 0x12, 0xCE, 0x57, +0xBD, 0xF6, 0xC6, 0x37, 0xD6, 0x78, 0xD6, 0x98, +0xCE, 0x77, 0xC5, 0xF5, 0xAD, 0x11, 0xBD, 0x92, +0x9C, 0xAF, 0x94, 0x70, 0x52, 0x89, 0x4A, 0x69, +0x52, 0x89, 0x84, 0x10, 0x7B, 0xAE, 0x52, 0x8A, +0x5A, 0xEB, 0x73, 0x8E, 0x94, 0x92, 0xB5, 0xB6, +0x9C, 0xD3, 0xB5, 0xB7, 0xB5, 0xB7, 0xB5, 0xB7, +0xC6, 0x18, 0x84, 0x10, 0x6B, 0x4D, 0xC6, 0x37, +0x9C, 0xD1, 0xC5, 0xF5, 0xA4, 0xF0, 0xB5, 0x31, +0xAD, 0x52, 0xC6, 0x16, 0xBD, 0xB5, 0xC5, 0xF5, +0xB5, 0x73, 0x8C, 0x4E, 0x8C, 0x2E, 0x94, 0x90, +0x31, 0x65, 0x21, 0x04, 0x31, 0x86, 0x42, 0x08, +0x4A, 0x28, 0x31, 0x86, 0x39, 0xA7, 0x84, 0x10, +0xDE, 0x9A, 0x8C, 0x10, 0x4A, 0x08, 0x41, 0xE7, +0x94, 0x2F, 0xAC, 0xF2, 0x94, 0x0F, 0xC5, 0xD6, +0xBD, 0x94, 0xBD, 0x74, 0x9C, 0x91, 0xCE, 0x16, +0xBD, 0x94, 0x9C, 0x90, 0xA4, 0xB0, 0xA4, 0xF1, +0xAD, 0x32, 0x9C, 0x90, 0x8B, 0xED, 0x8C, 0x0E, +0x94, 0x2E, 0x8C, 0x2F, 0x83, 0xCD, 0x8C, 0x0E, +0xBD, 0x31, 0xAC, 0xF0, 0xAD, 0x11, 0xBD, 0xB3, +0xB5, 0x72, 0xAD, 0x52, 0xAD, 0x52, 0xB5, 0x73, +0xAD, 0x32, 0x6B, 0x4C, 0x63, 0x0C, 0x8C, 0x51, +0x94, 0x71, 0x9C, 0x90, 0x83, 0xAB, 0xBD, 0x51, +0xAC, 0xCF, 0x8C, 0x0D, 0x7B, 0xAB, 0x7B, 0xAB, +0x6B, 0x09, 0x83, 0xEC, 0x7B, 0x8B, 0x8C, 0x0E, +0xA4, 0xF1, 0xA4, 0xF1, 0x7B, 0x8C, 0x9C, 0x90, +0xA4, 0xD0, 0x9C, 0xAF, 0xAD, 0x32, 0xC5, 0xF5, +0xCE, 0x36, 0xA5, 0x12, 0x83, 0xCD, 0x9C, 0xB0, +0x9C, 0xB0, 0x8C, 0x4F, 0x7B, 0xAD, 0x83, 0xEE, +0x83, 0xCD, 0x83, 0xEE, 0xB5, 0x73, 0xCE, 0x36, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x94, 0xB5, 0x53, +0x94, 0x4F, 0x94, 0x6F, 0x94, 0x6F, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xD0, 0xAD, 0x32, 0xB5, 0x53, +0xAD, 0x32, 0xB5, 0x32, 0xAD, 0x32, 0xB5, 0x52, +0xAD, 0x32, 0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0xB4, +0xB5, 0x74, 0xB5, 0x93, 0xB5, 0x53, 0xB5, 0x73, +0x9C, 0xB0, 0x94, 0x6F, 0x9C, 0xB1, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x32, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, 0xBD, 0x94, +0xC5, 0xB4, 0xBD, 0xB4, 0xBD, 0x94, 0xC5, 0xB4, +0xC5, 0xD5, 0xC5, 0xD5, 0xC5, 0xD5, 0xC5, 0xF5, +0xC5, 0xD5, 0xCE, 0x15, 0xC5, 0xD4, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x74, 0xBD, 0x74, +0xBD, 0x74, 0xC5, 0x94, 0xBD, 0x73, 0xBD, 0x72, +0xBD, 0x73, 0xB5, 0x32, 0xB5, 0x12, 0xBD, 0x94, +0x9C, 0x6F, 0x8C, 0x0E, 0x94, 0x6F, 0xA4, 0xD0, +0x94, 0x2E, 0x9C, 0x90, 0xA4, 0xD0, 0xA4, 0xD0, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x53, 0xA5, 0x12, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0xBD, 0x94, +0xB5, 0x73, 0xB5, 0x73, 0xC5, 0xD5, 0xBD, 0xB4, +0xBD, 0x93, 0xB5, 0x73, 0x94, 0x6F, 0x84, 0x0E, +0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x32, 0x94, 0x4F, +0x9C, 0xB1, 0x9C, 0x90, 0x83, 0xED, 0x9C, 0xB1, +0x8C, 0x2E, 0x8C, 0x2E, 0xB5, 0x53, 0xAC, 0xF1, +0xBD, 0x93, 0x83, 0xED, 0x5A, 0xA9, 0x94, 0x4F, +0x94, 0x4E, 0x9C, 0x6F, 0xA4, 0x8F, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x4E, 0xA4, 0xD0, 0xB5, 0x32, +0xB5, 0x53, 0x9C, 0x90, 0xB5, 0x53, 0x9C, 0xB0, +0x94, 0x6F, 0xCE, 0x36, 0xD6, 0x56, 0xBD, 0xB4, +0xB5, 0x53, 0xAD, 0x33, 0xBD, 0xB4, 0xB5, 0x94, +0xAD, 0x33, 0xAD, 0x73, 0xCE, 0x57, 0xD6, 0x77, +0xCE, 0x56, 0xAD, 0x53, 0xBD, 0xB4, 0xC5, 0xF5, +0xC5, 0xD4, 0xC5, 0xD4, 0xAD, 0x12, 0xBD, 0xD5, +0xAD, 0x32, 0xB5, 0x73, 0xC5, 0xB3, 0xD6, 0x14, +0xBD, 0x72, 0x9C, 0xAF, 0xCE, 0x55, 0xD6, 0x75, +0xAD, 0x31, 0xA4, 0xF0, 0xBD, 0xB3, 0xC5, 0xF4, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x94, 0xF3, +0x7C, 0x10, 0x62, 0xCA, 0x62, 0xE9, 0x6B, 0x0A, +0x73, 0x6B, 0x83, 0xAC, 0x8B, 0xEC, 0x8B, 0xCC, +0x94, 0x2E, 0x9C, 0x6E, 0xA4, 0x8F, 0x9C, 0x6E, +0xA4, 0x8F, 0xA4, 0xAF, 0xAC, 0xF0, 0xB5, 0x10, +0xAD, 0x10, 0xAC, 0xD0, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xD0, 0xA4, 0x8F, 0x9C, 0x6D, +0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x4E, 0x94, 0x0D, +0x94, 0x0C, 0x93, 0xEC, 0x8C, 0x0C, 0x94, 0x0D, +0x8B, 0xEC, 0x83, 0xCC, 0x83, 0xAB, 0x83, 0xAB, +0x7B, 0x8B, 0x7B, 0x6A, 0x94, 0x2D, 0xAC, 0xCF, +0x94, 0x4D, 0xAD, 0x32, 0xAD, 0x53, 0xAD, 0x32, +0xA4, 0xF1, 0xB5, 0x73, 0xB5, 0x93, 0xAD, 0x53, +0xA5, 0x11, 0xA4, 0xF1, 0x94, 0x4F, 0x94, 0x6F, +0xAD, 0x53, 0xCE, 0x77, 0xBD, 0xB4, 0xD6, 0x98, +0xD6, 0xB8, 0xD6, 0x98, 0xD6, 0x77, 0xCE, 0x77, +0xC6, 0x36, 0xCE, 0x16, 0x9C, 0x8F, 0xB5, 0x31, +0xBD, 0x93, 0xC5, 0xD5, 0x94, 0x70, 0x4A, 0x69, +0x39, 0xE7, 0x52, 0x89, 0x52, 0x69, 0x42, 0x07, +0x5A, 0xAA, 0x6B, 0x4C, 0x84, 0x10, 0x8C, 0x30, +0x9C, 0xF4, 0xAD, 0x56, 0xB5, 0x96, 0xA5, 0x35, +0xC6, 0x18, 0xD6, 0x7A, 0x9C, 0xD3, 0xC6, 0x17, +0x94, 0x70, 0x73, 0x8D, 0xA4, 0xD0, 0xB5, 0x52, +0xB5, 0x93, 0xBD, 0xD5, 0xBD, 0xD5, 0xC5, 0xF5, +0xBD, 0xB4, 0xA5, 0x12, 0xB5, 0x73, 0xB5, 0x73, +0x94, 0x90, 0x39, 0x85, 0x42, 0x07, 0x39, 0xC6, +0x4A, 0x28, 0x4A, 0x49, 0x42, 0x08, 0x4A, 0x29, +0xA4, 0xF4, 0xAD, 0x55, 0x83, 0xAE, 0x7B, 0x8D, +0xBD, 0x53, 0xCD, 0xB5, 0xD6, 0x37, 0xDE, 0x78, +0xDE, 0x58, 0xC5, 0x74, 0xB5, 0x33, 0x8C, 0x0F, +0xBD, 0x94, 0xAC, 0xF1, 0x9C, 0x8F, 0xA4, 0xD0, +0xB5, 0x52, 0xA4, 0xD1, 0x8C, 0x0E, 0x8B, 0xCE, +0x94, 0x4F, 0x8C, 0x0E, 0x83, 0xCD, 0xA4, 0xAF, +0xB5, 0x30, 0xB5, 0x11, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xD4, 0xBD, 0xB4, 0xBD, 0x93, +0xBD, 0xB4, 0xA4, 0xF2, 0x8C, 0x72, 0x8C, 0x51, +0x94, 0x71, 0x94, 0x2E, 0x73, 0x29, 0xBD, 0x51, +0x94, 0x0D, 0x83, 0xCC, 0x83, 0xCC, 0x8C, 0x0E, +0x7B, 0xAC, 0x8C, 0x4E, 0x84, 0x0D, 0x94, 0x6F, +0xA5, 0x11, 0x9C, 0xB0, 0x7B, 0xCD, 0x9C, 0x90, +0xAD, 0x11, 0x8C, 0x2E, 0xA4, 0xD1, 0xBD, 0xD5, +0xC5, 0xF5, 0x9C, 0xB1, 0x63, 0x0A, 0x9C, 0xD1, +0x8C, 0x2E, 0x6B, 0x4B, 0x83, 0xED, 0x83, 0xED, +0x83, 0xCD, 0x83, 0xED, 0x9C, 0x90, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x52, +0x94, 0x70, 0x9C, 0x90, 0x8C, 0x0E, 0x83, 0xED, +0x9C, 0x8F, 0x94, 0x6E, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x31, 0xAD, 0x11, +0x9C, 0xAF, 0xA4, 0xF1, 0xBD, 0x93, 0xBD, 0x93, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x31, 0xB5, 0x52, +0xB5, 0x52, 0xA5, 0x11, 0xAD, 0x32, 0x9C, 0x6F, +0x94, 0x6F, 0xB5, 0x53, 0xD6, 0x56, 0xCE, 0x15, +0xC5, 0xD4, 0xAD, 0x32, 0x94, 0x4F, 0x73, 0x6B, +0x73, 0x4B, 0x6B, 0x2B, 0x7B, 0x8C, 0x84, 0x0D, +0x9C, 0x90, 0x94, 0x6F, 0x84, 0x0D, 0x83, 0xCD, +0x8C, 0x0E, 0x8C, 0x0D, 0x8C, 0x0E, 0x94, 0x2E, +0x94, 0x4F, 0x8C, 0x0E, 0x94, 0x2F, 0x8C, 0x0E, +0xA4, 0xB0, 0xBD, 0x73, 0xAC, 0xF1, 0xAD, 0x11, +0xBD, 0x53, 0xBD, 0x73, 0xC5, 0xD4, 0xC5, 0xD4, +0xCD, 0xD5, 0xCD, 0xF5, 0xCD, 0xF5, 0xCD, 0xF6, +0xCE, 0x16, 0xCD, 0xF5, 0xC5, 0xD5, 0xCD, 0xF5, +0xC5, 0xD5, 0xC5, 0xB4, 0xC5, 0xD5, 0xB5, 0x53, +0xAC, 0xF1, 0xBD, 0x73, 0xB5, 0x53, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x73, 0xBD, 0x73, 0xC5, 0xB4, +0xAC, 0xF1, 0xA4, 0xD1, 0x9C, 0x90, 0xAD, 0x12, +0xB5, 0x33, 0xAC, 0xF2, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0xB0, 0xAD, 0x12, 0x9C, 0x90, 0xA4, 0xD1, +0x9C, 0x90, 0x94, 0x4F, 0xAD, 0x32, 0xB5, 0x52, +0xBD, 0x93, 0x73, 0x6C, 0x6B, 0x2B, 0x9C, 0xB0, +0xAD, 0x32, 0x94, 0x4E, 0x83, 0xAC, 0x94, 0x0E, +0x8C, 0x0D, 0x83, 0xAC, 0x9C, 0x6F, 0x94, 0x4E, +0xAD, 0x12, 0x9C, 0xD0, 0xAD, 0x32, 0x73, 0x8C, +0x6B, 0x0A, 0xA5, 0x11, 0xCE, 0x15, 0xCE, 0x15, +0xB5, 0x94, 0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0xD5, +0xB5, 0xB5, 0xB5, 0xB5, 0xCE, 0x57, 0xCE, 0x56, +0xCE, 0x36, 0xC5, 0xD4, 0xAD, 0x32, 0xBD, 0xD4, +0xBD, 0xD4, 0xBD, 0xB4, 0xAD, 0x32, 0xC5, 0xD5, +0xA5, 0x12, 0xB5, 0x53, 0xBD, 0x52, 0xCE, 0x14, +0xD6, 0x35, 0x9C, 0x8F, 0xC6, 0x14, 0xC5, 0xF4, +0xA4, 0xD0, 0x94, 0x8F, 0xC5, 0xF5, 0xC6, 0x15, +0xA5, 0x35, 0xB5, 0xB7, 0x9D, 0x14, 0x94, 0xD3, +0x73, 0xAE, 0x63, 0x0B, 0x63, 0x2B, 0x63, 0x0A, +0x52, 0x68, 0x5A, 0x88, 0x5A, 0xA8, 0x52, 0x68, +0x5A, 0xC9, 0x63, 0x0A, 0x5A, 0xA9, 0x52, 0x47, +0x73, 0x4B, 0x8B, 0xED, 0x94, 0x6E, 0x8B, 0xED, +0x83, 0xAB, 0x83, 0xAB, 0x8B, 0xCC, 0x94, 0x0D, +0x9C, 0x2D, 0x9C, 0x4D, 0xAC, 0xEF, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x4D, 0x8B, 0xCB, 0x8B, 0xAB, +0x94, 0x0D, 0xA4, 0x6E, 0x9C, 0x6D, 0xA4, 0x8E, +0xAC, 0xAF, 0xAC, 0xCF, 0xBD, 0x10, 0xBD, 0x30, +0xBD, 0x30, 0xBD, 0x51, 0xC5, 0x51, 0xBD, 0x50, +0xB5, 0x30, 0xB5, 0x10, 0xB4, 0xF0, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAE, +0xA4, 0xAE, 0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x8F, +0x9C, 0x6E, 0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0xAF, +0x9C, 0x8F, 0x94, 0x4D, 0x9C, 0x4D, 0xBD, 0x31, +0xA4, 0xAF, 0x9C, 0x8F, 0x7B, 0x8C, 0x52, 0x68, +0x29, 0x45, 0x29, 0x45, 0x39, 0xA6, 0x42, 0x08, +0x52, 0x69, 0x5A, 0xCB, 0x4A, 0x49, 0x5A, 0xCB, +0x8C, 0x71, 0xAD, 0x35, 0xA5, 0x35, 0x9C, 0xF4, +0xBD, 0xB7, 0xD6, 0x9A, 0xB5, 0xB6, 0xBD, 0xF7, +0xAD, 0x54, 0x5A, 0x8A, 0x94, 0x6F, 0xB5, 0x73, +0xC6, 0x16, 0xC6, 0x16, 0xC6, 0x16, 0xC5, 0xF5, +0xBD, 0xD4, 0xCE, 0x76, 0xD6, 0x97, 0xD6, 0x76, +0xC5, 0xD4, 0xA4, 0xD1, 0x39, 0xC6, 0x21, 0x03, +0x39, 0xA6, 0x52, 0xAA, 0x31, 0x86, 0x21, 0x24, +0x4A, 0x49, 0x4A, 0x49, 0x73, 0x6D, 0x9C, 0x50, +0x83, 0xAD, 0xAC, 0xD2, 0xBD, 0x54, 0xD6, 0x17, +0xDE, 0x58, 0xD6, 0x37, 0xBD, 0x74, 0x7B, 0x8D, +0x94, 0x50, 0xC5, 0xB5, 0xC5, 0xD5, 0xA4, 0xB0, +0xA4, 0xD0, 0xAD, 0x11, 0x9C, 0x6F, 0x9C, 0x6F, +0x9C, 0x6F, 0x9C, 0x6F, 0x8B, 0xED, 0xA4, 0x8F, +0xBD, 0x51, 0xB5, 0x51, 0xC5, 0xD3, 0xC5, 0xF4, +0xCE, 0x14, 0xCE, 0x55, 0xC6, 0x15, 0xBD, 0xF4, +0xBD, 0xD4, 0xB5, 0x95, 0xA5, 0x35, 0x9C, 0xD3, +0x8C, 0x50, 0x6B, 0x2B, 0x73, 0x0A, 0xBD, 0x51, +0x8B, 0xCC, 0x7B, 0x8B, 0x7B, 0xAC, 0x8C, 0x0D, +0x8C, 0x0D, 0x94, 0x4F, 0x94, 0x6F, 0x9C, 0x8F, +0xA5, 0x12, 0x9C, 0xB0, 0x83, 0xEE, 0x94, 0x8F, +0xAD, 0x32, 0x8C, 0x2E, 0xA4, 0xF1, 0xB5, 0x94, +0xBD, 0xD4, 0xA4, 0xF2, 0x63, 0x0A, 0xAD, 0x53, +0x94, 0x90, 0x83, 0xEE, 0x94, 0x70, 0x94, 0x70, +0x83, 0xED, 0x84, 0x0E, 0x94, 0x6F, 0xA4, 0xD0, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x72, 0xB5, 0x52, +0x94, 0x70, 0x9C, 0x90, 0x7B, 0xAC, 0x73, 0x6C, +0x9C, 0x8F, 0x94, 0x2D, 0xA4, 0xB0, 0xB5, 0x52, +0x9C, 0x6E, 0x94, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, +0x8C, 0x2E, 0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x52, +0xAD, 0x11, 0x9C, 0x6F, 0xA4, 0xD0, 0x94, 0x2D, +0x8C, 0x0D, 0x8C, 0x2D, 0x83, 0xEC, 0x8C, 0x0D, +0x94, 0x4F, 0xAD, 0x32, 0xAD, 0x32, 0x83, 0xED, +0xA4, 0xD1, 0xBD, 0x94, 0xAD, 0x32, 0x8C, 0x4F, +0x63, 0x2B, 0x6B, 0x4C, 0x8C, 0x2E, 0x9C, 0xD1, +0xAD, 0x32, 0x9C, 0xB0, 0xAD, 0x53, 0xA5, 0x12, +0x9C, 0xB0, 0x7B, 0xCD, 0x7B, 0xAC, 0x94, 0x4F, +0x9C, 0xB0, 0x94, 0x4F, 0x6B, 0x0A, 0x7B, 0x8C, +0x94, 0x2E, 0xBD, 0x73, 0xB5, 0x32, 0xBD, 0x73, +0x8C, 0x0E, 0x7B, 0x6B, 0x83, 0xCD, 0xA4, 0xD1, +0x8C, 0x0E, 0x8B, 0xED, 0x8C, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x2E, 0x94, 0x4F, 0x9C, 0x90, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xD1, 0xA4, 0xB0, +0x9C, 0x6F, 0xA4, 0xD0, 0xA4, 0xD1, 0x9C, 0x90, +0xA4, 0xB0, 0xBD, 0x53, 0xB5, 0x32, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x32, 0xB5, 0x32, +0xBD, 0x94, 0xC5, 0xB4, 0xC5, 0xB4, 0xC5, 0xD4, +0xC5, 0xB4, 0xCD, 0xF5, 0xC5, 0xF5, 0xC5, 0xD5, +0xCE, 0x15, 0xC5, 0xD4, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0xB4, 0xB5, 0x53, 0xBD, 0xB4, 0xB5, 0x73, +0xA4, 0xF1, 0xA4, 0xB0, 0x9C, 0xB0, 0x94, 0x6F, +0x94, 0x4F, 0x8C, 0x0E, 0x8C, 0x2E, 0x94, 0x2E, +0xA4, 0xD1, 0x9C, 0x90, 0x9C, 0x90, 0x94, 0x70, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xF0, 0xAD, 0x32, +0xB5, 0x53, 0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0xD5, +0xB5, 0x94, 0xBD, 0xD5, 0xBD, 0xD5, 0xCE, 0x77, +0xD6, 0x76, 0xC5, 0xF5, 0xC5, 0xF5, 0xCE, 0x35, +0xCE, 0x35, 0xC5, 0xD5, 0xC5, 0xD5, 0xC6, 0x15, +0x9C, 0x90, 0xB5, 0x73, 0xC5, 0xB3, 0xDE, 0x55, +0xDE, 0x76, 0x9C, 0x8F, 0xC5, 0xD4, 0xB5, 0x92, +0x9C, 0xAF, 0x9C, 0x8F, 0xCE, 0x35, 0xCE, 0x35, +0xA5, 0x55, 0xAD, 0x96, 0x9D, 0x14, 0x94, 0xD3, +0x7B, 0xEF, 0x84, 0x0F, 0x94, 0x90, 0x8C, 0x4F, +0x52, 0x88, 0x6B, 0x4B, 0x73, 0x8C, 0x6B, 0x2B, +0x73, 0x8C, 0x6B, 0x4B, 0x52, 0x88, 0x6B, 0x4B, +0x73, 0x6C, 0x8C, 0x4F, 0x9C, 0xD0, 0x73, 0x8C, +0x6B, 0x0A, 0x62, 0xC9, 0x73, 0x8C, 0xAD, 0x32, +0xB5, 0x32, 0xA4, 0x8F, 0xAC, 0xAF, 0xA4, 0x6E, +0xB4, 0xF0, 0xC5, 0x72, 0xBD, 0x92, 0xB5, 0x51, +0xAC, 0xF0, 0x94, 0x4E, 0x83, 0xCC, 0x8B, 0xCC, +0x8B, 0xEC, 0x8B, 0xCB, 0x8B, 0xCB, 0x8B, 0xEB, +0x8B, 0xCB, 0x83, 0xAA, 0x83, 0x6A, 0x7B, 0x6A, +0x83, 0x8A, 0x9C, 0x4E, 0xB5, 0x10, 0xAC, 0xEF, +0xB5, 0x10, 0xB4, 0xF0, 0xAC, 0xCF, 0xB5, 0x10, +0xAC, 0xCF, 0xA4, 0x8E, 0xAC, 0xCF, 0xAC, 0xAF, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0xAF, +0xB4, 0xEF, 0xB4, 0xF0, 0xB4, 0xEF, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xEF, 0xBD, 0x30, 0xBD, 0x51, +0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xEF, 0x94, 0x2E, +0x52, 0x68, 0x31, 0xA6, 0x39, 0xE7, 0x42, 0x07, +0x4A, 0x48, 0x4A, 0x69, 0x42, 0x08, 0x63, 0x0C, +0x7B, 0xCF, 0xAD, 0x35, 0xAD, 0x55, 0xAD, 0x56, +0xAD, 0x76, 0xBD, 0xD7, 0xBD, 0xD7, 0xC6, 0x38, +0xD6, 0x79, 0xA4, 0xD3, 0x6B, 0x2B, 0x7B, 0x8D, +0xA4, 0xF1, 0xAD, 0x31, 0xAC, 0xF1, 0xA4, 0xF0, +0x9C, 0xAF, 0xA4, 0xCF, 0xA4, 0xF0, 0x9C, 0x6E, +0x7B, 0x8B, 0xA4, 0xB0, 0x7B, 0x8C, 0x31, 0x64, +0x18, 0xE3, 0x31, 0xA5, 0x39, 0xA6, 0x31, 0xA6, +0x39, 0xC7, 0x6B, 0x4D, 0xAD, 0x55, 0xAD, 0x14, +0x9C, 0x71, 0x9C, 0x70, 0xBD, 0x74, 0xAC, 0xF2, +0xBD, 0x53, 0xD6, 0x17, 0x9C, 0x50, 0x7B, 0x8D, +0xA4, 0xD3, 0xBD, 0x75, 0xAD, 0x13, 0xAC, 0xF2, +0xAC, 0xF1, 0xAD, 0x12, 0xA4, 0xD1, 0xC5, 0xF5, +0xC5, 0xB4, 0xC5, 0xB4, 0x8C, 0x0D, 0x9C, 0x6E, +0xBD, 0x51, 0xBD, 0xB2, 0xC6, 0x14, 0xC5, 0xD3, +0xC5, 0xD3, 0xC6, 0x34, 0xC6, 0x15, 0xC6, 0x15, +0xC6, 0x15, 0xB5, 0xB6, 0xAD, 0x56, 0x9C, 0xD3, +0x83, 0xEF, 0x6B, 0x2B, 0x7B, 0x6B, 0xB5, 0x31, +0x83, 0xCB, 0x7B, 0xAC, 0x7B, 0xAC, 0x83, 0xCC, +0x7B, 0xAC, 0x83, 0xED, 0x94, 0x6F, 0x8C, 0x2E, +0xAD, 0x32, 0xA4, 0xD1, 0x83, 0xCD, 0x9C, 0xB0, +0x9C, 0xB0, 0x83, 0xEC, 0xA4, 0xF1, 0xBD, 0xB4, +0xBD, 0xD5, 0xB5, 0x53, 0x7B, 0x8C, 0xAD, 0x53, +0x9C, 0xB0, 0x9C, 0x90, 0xAD, 0x32, 0x9C, 0xB1, +0xA5, 0x12, 0x9C, 0x90, 0x94, 0x90, 0xB5, 0x53, +0xC5, 0xF5, 0xC5, 0xD4, 0xCE, 0x15, 0xB5, 0x73, +0x94, 0x6F, 0x8C, 0x0E, 0x73, 0x6C, 0x7B, 0x8C, +0x94, 0x4F, 0x8B, 0xED, 0xA4, 0xD0, 0xAD, 0x31, +0x94, 0x2D, 0x8C, 0x0C, 0x8B, 0xEC, 0x94, 0x4E, +0x83, 0xED, 0x9C, 0x8F, 0x94, 0x4E, 0xAD, 0x11, +0xA4, 0xD0, 0x8C, 0x2D, 0x8C, 0x2E, 0x83, 0xCC, +0x94, 0x4E, 0x8C, 0x2D, 0x9C, 0x8F, 0xA4, 0xF1, +0x94, 0x4F, 0xAD, 0x32, 0xAD, 0x11, 0x7B, 0xAD, +0x83, 0xEE, 0xB5, 0x94, 0xB5, 0x73, 0xA5, 0x12, +0x8C, 0x2F, 0x7B, 0xAD, 0x9C, 0xD0, 0xBD, 0xD4, +0xA5, 0x11, 0x9C, 0xD0, 0xAD, 0x52, 0xB5, 0x74, +0xB5, 0x73, 0x8C, 0x2E, 0x83, 0xEE, 0x7B, 0xCD, +0x83, 0xED, 0x83, 0xEE, 0x63, 0x0A, 0x7B, 0xAD, +0x94, 0x6F, 0xB5, 0x53, 0x9C, 0x90, 0xAD, 0x32, +0xA4, 0xD1, 0x83, 0xEE, 0x83, 0xEE, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0x90, 0x9C, 0xB0, 0x9C, 0xB0, +0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0xB0, 0x94, 0x4F, +0x9C, 0xB0, 0xA4, 0xD1, 0x9C, 0x90, 0x94, 0x6F, +0x8C, 0x2E, 0x8C, 0x0E, 0x83, 0xEE, 0x7B, 0x8C, +0x94, 0x4F, 0xB5, 0x52, 0xC5, 0xB4, 0xBD, 0x92, +0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x31, 0xB5, 0x52, +0xC5, 0xB4, 0xAC, 0xF1, 0x9C, 0x6E, 0x8B, 0xED, +0x94, 0x2E, 0x9C, 0x8F, 0x94, 0x2E, 0x9C, 0x8F, +0xAD, 0x11, 0xAC, 0xF1, 0xA4, 0xF0, 0xAD, 0x11, +0x94, 0x4E, 0xAD, 0x32, 0xAD, 0x12, 0xB5, 0x32, +0xBD, 0x93, 0xCE, 0x15, 0xAD, 0x12, 0x94, 0x50, +0x9C, 0xB0, 0xA4, 0xB1, 0xAC, 0xF1, 0xB5, 0x32, +0xC5, 0xB5, 0xC5, 0xB5, 0xC5, 0xB4, 0xCD, 0xF5, +0xCD, 0xF5, 0xC5, 0xF5, 0xC5, 0xD5, 0xBD, 0xB4, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, +0xBD, 0xB4, 0xBD, 0x94, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x52, 0xA4, 0xD1, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x8F, +0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x31, 0xBD, 0x92, +0xB5, 0x52, 0x9C, 0x8F, 0xA4, 0xD1, 0xA4, 0xD0, +0x94, 0x6F, 0x9C, 0x8F, 0xAD, 0x11, 0xA4, 0xF0, +0xA5, 0x75, 0xAD, 0x76, 0x9D, 0x14, 0x94, 0xD3, +0x7B, 0xCF, 0x8C, 0x50, 0x94, 0xB0, 0x8C, 0x2F, +0x73, 0x6C, 0x9C, 0xB1, 0x7B, 0xCD, 0x7B, 0xCD, +0x6B, 0x4B, 0x4A, 0x68, 0x6B, 0x4C, 0x7B, 0xEE, +0x84, 0x0F, 0x94, 0x90, 0x7B, 0xCD, 0x83, 0xED, +0x8C, 0x4F, 0xA4, 0xF2, 0xB5, 0x73, 0xAD, 0x53, +0xAD, 0x32, 0x9C, 0x8F, 0xB4, 0xF0, 0xA4, 0x8E, +0xD6, 0x14, 0xD5, 0xF3, 0xD6, 0x13, 0xD6, 0x54, +0xD6, 0x34, 0xD6, 0x35, 0xC5, 0xF4, 0xBD, 0x93, +0xB5, 0x52, 0xA4, 0xAF, 0xBD, 0x93, 0xBD, 0x93, +0xAD, 0x11, 0xA4, 0xD0, 0x8C, 0x2E, 0x83, 0xCD, +0x94, 0x6F, 0x9C, 0x90, 0xAD, 0x10, 0xB5, 0x10, +0xBD, 0x71, 0xDE, 0x55, 0xB5, 0x10, 0xB4, 0xCF, +0x7B, 0x6A, 0x7B, 0x6B, 0x5A, 0x88, 0x4A, 0x06, +0x49, 0xE6, 0x4A, 0x27, 0x4A, 0x27, 0x62, 0xA9, +0x62, 0xA8, 0x6B, 0x0A, 0x73, 0x2A, 0x73, 0x4A, +0x7B, 0x4A, 0x73, 0x2A, 0x7B, 0x6A, 0x7B, 0x8A, +0x73, 0x09, 0x7B, 0x4A, 0x83, 0xAB, 0x9C, 0x4E, +0x8C, 0x0E, 0x4A, 0x48, 0x39, 0xE7, 0x42, 0x07, +0x31, 0xA6, 0x42, 0x07, 0x42, 0x08, 0x5A, 0xCB, +0x6B, 0x4D, 0x94, 0x92, 0xA5, 0x35, 0xB5, 0x96, +0xAD, 0x56, 0xA5, 0x35, 0xAD, 0x55, 0xC6, 0x38, +0xDE, 0xBA, 0x94, 0x50, 0x41, 0xE7, 0x7B, 0xAE, +0x94, 0x2E, 0xBD, 0x72, 0xBD, 0x51, 0xBD, 0x30, +0xBD, 0x51, 0xC5, 0x71, 0xC5, 0x91, 0xBD, 0x71, +0xC5, 0x72, 0xB5, 0x10, 0xB5, 0x10, 0x8B, 0xED, +0x21, 0x03, 0x21, 0x03, 0x63, 0x0B, 0x42, 0x07, +0x31, 0xA6, 0x4A, 0x48, 0x9C, 0xB2, 0x9C, 0x92, +0x9C, 0x71, 0x8B, 0xEF, 0xAC, 0xF2, 0xAC, 0xD2, +0x9C, 0x2F, 0x9C, 0x2F, 0x73, 0x0B, 0x94, 0x10, +0x83, 0xCF, 0x7B, 0x8E, 0xB5, 0x34, 0xBD, 0x75, +0xB5, 0x55, 0xCE, 0x38, 0xA4, 0xD2, 0xA5, 0x12, +0xBD, 0xB4, 0xBD, 0x93, 0x8C, 0x0D, 0xAC, 0xCF, +0xAC, 0xEF, 0xA4, 0xCF, 0xA4, 0xF0, 0x94, 0x4E, +0x83, 0xCC, 0x8C, 0x2D, 0x9C, 0xD0, 0xB5, 0x73, +0xAD, 0x52, 0xB5, 0xB5, 0xAD, 0x76, 0x9C, 0xF4, +0x83, 0xEF, 0x7B, 0x8C, 0x8B, 0xED, 0xB4, 0xF0, +0x94, 0x0D, 0x7B, 0xAC, 0x7B, 0xAC, 0x8C, 0x0D, +0x73, 0x6B, 0x73, 0x6B, 0x7B, 0xAC, 0x73, 0x4B, +0xA4, 0xF1, 0x8C, 0x0E, 0x94, 0x6F, 0xAD, 0x52, +0xA4, 0xD1, 0x83, 0xED, 0xAD, 0x53, 0xCE, 0x16, +0xC5, 0xD5, 0xC5, 0xF5, 0xB5, 0x74, 0xCE, 0x36, +0xBD, 0xD4, 0xA4, 0xF1, 0x9C, 0x90, 0x94, 0x6F, +0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x32, 0xCE, 0x36, +0xD6, 0x76, 0xCE, 0x36, 0xCE, 0x15, 0xA4, 0xD1, +0x8C, 0x2E, 0x7B, 0xAD, 0x73, 0x4B, 0x7B, 0x8C, +0x8B, 0xCD, 0x94, 0x0D, 0xA4, 0xF0, 0xAD, 0x10, +0x94, 0x2D, 0x8B, 0xEC, 0x94, 0x2D, 0x9C, 0x8F, +0x8C, 0x0D, 0x9C, 0x8F, 0x94, 0x8F, 0xA5, 0x11, +0x94, 0x4E, 0x7B, 0xCB, 0x8C, 0x0D, 0x8B, 0xED, +0x83, 0xEC, 0x7B, 0x8B, 0x94, 0x6E, 0xA4, 0xF0, +0x9C, 0xD0, 0xB5, 0x53, 0xA4, 0xF1, 0x7B, 0xAD, +0xA4, 0xF1, 0xBD, 0xD4, 0xBD, 0xD5, 0xAD, 0x53, +0x9C, 0xD1, 0x8C, 0x4F, 0x8C, 0x4F, 0xA4, 0xD1, +0x8C, 0x0E, 0x94, 0x6F, 0xA4, 0xF1, 0xB5, 0x73, +0xBD, 0xB4, 0x94, 0x90, 0x94, 0x90, 0x9C, 0xF1, +0x94, 0xB0, 0x9C, 0xB1, 0x7B, 0xCD, 0x83, 0xEE, +0x9C, 0xB0, 0xAD, 0x32, 0x73, 0x8C, 0x7B, 0xCD, +0x84, 0x0E, 0x9C, 0xF2, 0xA5, 0x12, 0xAD, 0x53, +0xAD, 0x53, 0xAD, 0x73, 0xB5, 0x74, 0xAD, 0x53, +0xAD, 0x33, 0xA4, 0xF1, 0xA4, 0xF2, 0x94, 0x70, +0x8C, 0x4F, 0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xF1, +0x94, 0x6F, 0x8C, 0x4F, 0x9C, 0xB1, 0x83, 0xEE, +0x8C, 0x2E, 0xAD, 0x12, 0x9C, 0xAF, 0xAD, 0x10, +0xAD, 0x10, 0x9C, 0x8F, 0xAC, 0xF1, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0x93, 0xAD, 0x31, 0x94, 0x4E, +0x8C, 0x4E, 0x8C, 0x2E, 0x7B, 0xAC, 0x8C, 0x2E, +0x9C, 0xD0, 0x9C, 0xB0, 0xB5, 0x73, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x52, 0xAD, 0x11, 0xAD, 0x32, +0x9C, 0xB0, 0xB5, 0x52, 0x73, 0x4B, 0x5A, 0xA9, +0x73, 0x4B, 0x83, 0x8C, 0x7B, 0x8C, 0x83, 0xCD, +0x9C, 0x6F, 0xA4, 0xB0, 0xA4, 0xD1, 0xB5, 0x53, +0xB5, 0x53, 0xA4, 0xD1, 0x9C, 0xB0, 0x9C, 0xB0, +0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x70, 0x9C, 0x90, +0xA4, 0xB1, 0xA4, 0xD1, 0xAC, 0xF1, 0xAD, 0x12, +0xA4, 0xF1, 0xB5, 0x32, 0xB5, 0x32, 0x94, 0x4F, +0x83, 0xED, 0x9C, 0x8F, 0xA4, 0xF1, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x32, 0xB5, 0x32, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x73, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0x73, 0xBD, 0x94, +0xAD, 0x76, 0xB5, 0xD7, 0x9D, 0x14, 0x94, 0xD3, +0x7B, 0xCF, 0x84, 0x50, 0x84, 0x4F, 0x84, 0x2E, +0x9C, 0xD1, 0x84, 0x2F, 0x6B, 0x8C, 0x94, 0x90, +0x7B, 0xEE, 0x73, 0xAE, 0x8C, 0x70, 0x94, 0x91, +0x94, 0xB2, 0xA4, 0xF2, 0x94, 0x70, 0x9C, 0xD1, +0x7B, 0xEE, 0x9C, 0xB1, 0xBD, 0xD5, 0xAD, 0x53, +0xBD, 0x94, 0xA4, 0xAF, 0xB4, 0xF0, 0xAC, 0xCF, +0xDE, 0x55, 0xB4, 0xEF, 0xBD, 0x50, 0xC5, 0x91, +0xC5, 0xB2, 0xCD, 0xD3, 0xCD, 0xD3, 0xC5, 0xD3, +0xBD, 0x92, 0xC5, 0xD4, 0xCE, 0x35, 0xD6, 0x35, +0xC5, 0xD4, 0xCE, 0x15, 0xBD, 0x93, 0xAD, 0x32, +0xBD, 0xB4, 0xC5, 0xD4, 0xCD, 0xF4, 0xD6, 0x35, +0xCD, 0xF3, 0xDE, 0x75, 0xBD, 0x30, 0xB5, 0x10, +0xA4, 0xB0, 0x94, 0x6F, 0x7B, 0xCD, 0x7B, 0xAD, +0x84, 0x0F, 0x8C, 0x4F, 0x83, 0xEE, 0x8C, 0x2F, +0x7B, 0xCD, 0x83, 0xCD, 0x7B, 0x8C, 0x7B, 0xAD, +0x8C, 0x2E, 0x7B, 0x8C, 0x6B, 0x0A, 0x73, 0x6B, +0x7B, 0x8C, 0x8C, 0x0D, 0x9C, 0xB0, 0xA4, 0xD1, +0xAD, 0x12, 0x73, 0x4B, 0x4A, 0x27, 0x4A, 0x28, +0x4A, 0x48, 0x4A, 0x48, 0x39, 0xC6, 0x42, 0x28, +0x5A, 0xCB, 0x7B, 0xCF, 0x9C, 0xF4, 0xAD, 0x76, +0xAD, 0x55, 0x9C, 0xD3, 0x9C, 0xD4, 0xB5, 0xB7, +0xCE, 0x79, 0x7B, 0xAE, 0x42, 0x08, 0x39, 0xA6, +0x62, 0xCA, 0x83, 0xAC, 0x83, 0xAB, 0x94, 0x0D, +0xAC, 0xD0, 0xAC, 0xCF, 0xAC, 0xCF, 0x83, 0xAA, +0x94, 0x2C, 0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0x8F, +0x41, 0xE6, 0x5A, 0xCA, 0x7B, 0x8C, 0x31, 0x65, +0x39, 0xA6, 0x31, 0xA5, 0x42, 0x08, 0xA4, 0xF3, +0x7B, 0x6D, 0xAC, 0xF4, 0xA4, 0xF3, 0xA4, 0xB2, +0x7B, 0x6D, 0x39, 0x86, 0x4A, 0x28, 0x7B, 0xAE, +0x4A, 0x29, 0x5A, 0x8B, 0xBD, 0x96, 0xB5, 0x96, +0xCE, 0x59, 0xBD, 0xF8, 0xF7, 0x7D, 0xBD, 0xF7, +0x73, 0x6D, 0xBD, 0x94, 0xAD, 0x11, 0xBD, 0x30, +0xB5, 0x10, 0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xEF, +0xB4, 0xCF, 0xB4, 0xEF, 0xAC, 0xCF, 0xA4, 0xAF, +0x9C, 0x6F, 0xBD, 0xB6, 0xBD, 0xD7, 0xA5, 0x14, +0xAC, 0xF2, 0xA4, 0xAF, 0xB5, 0x10, 0xB4, 0xEF, +0x94, 0x0D, 0x8B, 0xEC, 0x83, 0xEC, 0x8C, 0x0D, +0x7B, 0x8B, 0x7B, 0xAC, 0x7B, 0x8B, 0x94, 0x2E, +0xB5, 0x53, 0x73, 0x6C, 0x83, 0xCD, 0x9C, 0x90, +0x9C, 0xB0, 0x8C, 0x0E, 0xA4, 0xF1, 0xBD, 0xB4, +0xAD, 0x32, 0x94, 0x90, 0xA4, 0xD1, 0xCE, 0x16, +0xA5, 0x12, 0x83, 0xED, 0x8C, 0x0E, 0x8C, 0x2E, +0xA4, 0xD1, 0xB5, 0x53, 0xCE, 0x16, 0xC6, 0x15, +0xDE, 0x97, 0xD6, 0x76, 0xC5, 0xF5, 0x73, 0x6B, +0x83, 0xCD, 0x7B, 0x8D, 0x4A, 0x07, 0x6B, 0x2B, +0x83, 0x8C, 0x94, 0x4E, 0xAD, 0x11, 0xAC, 0xF0, +0xAC, 0xD0, 0xAD, 0x10, 0xB5, 0x72, 0xB5, 0x72, +0xAD, 0x31, 0xAD, 0x31, 0xAD, 0x32, 0xAD, 0x11, +0x94, 0x6E, 0x94, 0x4E, 0x94, 0x4E, 0x9C, 0x8F, +0x94, 0x2E, 0x83, 0xED, 0x7B, 0xAC, 0xA4, 0xF0, +0xA4, 0xD1, 0xAD, 0x12, 0x9C, 0x90, 0x63, 0x2B, +0xA5, 0x33, 0xBD, 0xD4, 0xBD, 0xB5, 0xAD, 0x53, +0xA5, 0x33, 0x94, 0x70, 0x94, 0x6F, 0x8C, 0x2F, +0x84, 0x0E, 0xA5, 0x12, 0xB5, 0xB4, 0xC5, 0xF5, +0xBD, 0xD4, 0xA5, 0x32, 0xAD, 0x53, 0xAD, 0x53, +0xA5, 0x32, 0xA5, 0x12, 0x94, 0x90, 0x8C, 0x70, +0x9C, 0x6F, 0xA4, 0xF1, 0x7B, 0xEE, 0x94, 0x90, +0x9C, 0xF2, 0xAD, 0x53, 0xAD, 0x53, 0xB5, 0xB4, +0xB5, 0xB4, 0xB5, 0xB4, 0xBD, 0xB5, 0xB5, 0xB4, +0xAD, 0x73, 0xB5, 0x73, 0xB5, 0x94, 0xA5, 0x12, +0x94, 0xB0, 0xAD, 0x33, 0xB5, 0x74, 0xBD, 0xD5, +0xAD, 0x33, 0x94, 0x90, 0x9C, 0xB1, 0x8C, 0x4F, +0x94, 0x6F, 0xAD, 0x32, 0xAD, 0x31, 0xAD, 0x31, +0xA4, 0xCF, 0x94, 0x6E, 0xB5, 0x72, 0xB5, 0x93, +0xBD, 0xD4, 0xBD, 0xD4, 0xBD, 0xB4, 0xA4, 0xF1, +0xAD, 0x53, 0xA5, 0x12, 0x8C, 0x6F, 0x94, 0x70, +0x9C, 0xD1, 0xA4, 0xF1, 0xC5, 0xD5, 0xCE, 0x36, +0xBD, 0xB4, 0xC5, 0xF4, 0xBD, 0x93, 0xB5, 0x73, +0x9C, 0xB0, 0xA4, 0xB0, 0x6A, 0xEA, 0x83, 0xCE, +0x7B, 0x8C, 0x8B, 0xED, 0x83, 0xED, 0x7B, 0xAC, +0x83, 0xAC, 0x9C, 0x6F, 0xA4, 0xF1, 0xB5, 0x73, +0xB5, 0x73, 0xBD, 0x94, 0xB5, 0x73, 0xB5, 0x53, +0xB5, 0x73, 0xBD, 0x93, 0xAD, 0x12, 0xA4, 0xF1, +0x94, 0x2F, 0x83, 0xCD, 0x94, 0x4F, 0x73, 0x6C, +0x62, 0xCA, 0x7B, 0xAD, 0x7B, 0x8C, 0x6B, 0x0B, +0x62, 0xA9, 0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xD1, +0xAD, 0x12, 0x9C, 0x90, 0x9C, 0xB0, 0x9C, 0x8F, +0x83, 0xED, 0x94, 0x4F, 0x94, 0x6F, 0x94, 0x4F, +0x8C, 0x0E, 0xB5, 0x53, 0xAC, 0xF1, 0xA4, 0xF1, +0xA5, 0x55, 0xAD, 0x76, 0x9D, 0x14, 0x94, 0xD3, +0x73, 0xCF, 0x84, 0x2F, 0x94, 0xB1, 0x9C, 0xD1, +0x9C, 0xF2, 0x84, 0x0E, 0x8C, 0x50, 0x63, 0x2B, +0x6B, 0x4C, 0x9C, 0xD2, 0x9C, 0xD2, 0x8C, 0x50, +0x7C, 0x0F, 0xAD, 0x33, 0x94, 0x91, 0xA4, 0xF2, +0x83, 0xEE, 0xB5, 0x94, 0xB5, 0x94, 0xA4, 0xF1, +0xBD, 0x93, 0x9C, 0x8F, 0xB5, 0x10, 0xAC, 0xCF, +0xD6, 0x13, 0xAC, 0xEF, 0x9C, 0x4D, 0xAC, 0xEF, +0xBD, 0x71, 0xC5, 0x92, 0xBD, 0x71, 0xC5, 0xB2, +0xB5, 0x51, 0xCE, 0x35, 0xCE, 0x35, 0xD6, 0x35, +0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xF5, 0xAD, 0x12, +0xBD, 0x93, 0xCE, 0x14, 0xB5, 0x31, 0xAC, 0xCF, +0xB5, 0x10, 0xD6, 0x34, 0xAC, 0xCF, 0xB5, 0x10, +0xB5, 0x52, 0x84, 0x0E, 0x8C, 0x4F, 0xA4, 0xF2, +0xA4, 0xD1, 0xAD, 0x32, 0x7B, 0xCD, 0x94, 0x90, +0x94, 0x90, 0xA4, 0xF2, 0x8C, 0x50, 0x8C, 0x70, +0x8C, 0x4F, 0x8C, 0x2F, 0x8C, 0x4F, 0x9C, 0xB0, +0x8C, 0x2E, 0x9C, 0xB0, 0xB5, 0x93, 0xB5, 0x73, +0xB5, 0x73, 0xA4, 0xD1, 0x52, 0x68, 0x42, 0x07, +0x41, 0xE7, 0x41, 0xE7, 0x39, 0xC6, 0x31, 0xA6, +0x42, 0x49, 0x63, 0x2C, 0x8C, 0x51, 0xAD, 0x76, +0xAD, 0x76, 0x9C, 0xB3, 0x8C, 0x72, 0xB5, 0x96, +0xD6, 0x9A, 0xB5, 0x96, 0x6B, 0x4E, 0x4A, 0x29, +0x5A, 0x8A, 0x7B, 0x8D, 0x83, 0xCD, 0x7B, 0xCD, +0x7B, 0xAC, 0x8B, 0xED, 0xAC, 0xF0, 0x9C, 0x8F, +0x9C, 0xAF, 0xAD, 0x10, 0xAC, 0xCF, 0x9C, 0x4E, +0x7B, 0xAC, 0x73, 0x8C, 0x21, 0x03, 0x21, 0x03, +0x31, 0x85, 0x31, 0xA6, 0x29, 0x45, 0x5A, 0xCA, +0xA4, 0xD3, 0xAC, 0xF4, 0xCE, 0x38, 0x7B, 0x8D, +0x41, 0xE7, 0x29, 0x04, 0x29, 0x45, 0x6B, 0x2C, +0x7B, 0xCF, 0x7B, 0x8F, 0xB5, 0x76, 0xC5, 0xF8, +0xCE, 0x39, 0xB5, 0xB7, 0xCE, 0x9A, 0xEF, 0x7D, +0xA4, 0xF4, 0xBD, 0xB5, 0xE6, 0xF9, 0xD5, 0xF3, +0xDE, 0x54, 0xE6, 0x75, 0xDE, 0x54, 0xC5, 0x71, +0xCD, 0xB2, 0xDE, 0x34, 0xC5, 0x71, 0xBD, 0x30, +0xA4, 0xD0, 0xCE, 0x38, 0xA5, 0x14, 0xA5, 0x13, +0xA4, 0xB0, 0xAC, 0xCF, 0xB4, 0xEF, 0xB5, 0x10, +0xB5, 0x30, 0xBD, 0x51, 0xC5, 0x71, 0xCD, 0x92, +0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x51, 0xC5, 0x93, +0xC5, 0xF5, 0xC5, 0xF6, 0xBD, 0xB5, 0xB5, 0x74, +0xAD, 0x33, 0xAD, 0x12, 0xA4, 0xF2, 0x9C, 0x90, +0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0x90, 0x94, 0x90, 0x94, 0x70, 0x8C, 0x2F, +0x8C, 0x2F, 0x83, 0xEE, 0x8C, 0x2E, 0x8C, 0x0E, +0x9C, 0x90, 0x94, 0x4F, 0x83, 0xED, 0x7B, 0x8C, +0x8C, 0x2F, 0x9C, 0x91, 0x94, 0x50, 0x83, 0xCE, +0x7B, 0x8D, 0x73, 0x6B, 0x7B, 0x8B, 0x7B, 0xAB, +0x8C, 0x0D, 0x9C, 0x8F, 0xA4, 0xCF, 0xA4, 0xD0, +0xB5, 0x52, 0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0x93, +0xB5, 0x72, 0xAD, 0x10, 0xAD, 0x10, 0xBD, 0x52, +0xAD, 0x10, 0xAD, 0x11, 0x94, 0x6E, 0x9C, 0xB0, +0xAD, 0x32, 0xAD, 0x12, 0x84, 0x0E, 0x63, 0x2B, +0xBD, 0xF5, 0xBD, 0xD4, 0xCE, 0x56, 0xBD, 0xD4, +0xAD, 0x73, 0x8C, 0x2F, 0x73, 0x8C, 0x7B, 0xAC, +0x8C, 0x2E, 0xA5, 0x12, 0xC5, 0xF5, 0xBD, 0xB4, +0xBD, 0xB4, 0xA5, 0x12, 0x9C, 0xF2, 0xB5, 0xB5, +0xAD, 0x73, 0xAD, 0x74, 0xAD, 0x53, 0xA4, 0xF1, +0x9C, 0x90, 0xA4, 0xD1, 0x8C, 0x4F, 0x9C, 0xD1, +0xA5, 0x12, 0xA5, 0x12, 0xA5, 0x32, 0xB5, 0x94, +0xC5, 0xF6, 0xBD, 0xD5, 0xBD, 0xB4, 0xBD, 0xD5, +0xBD, 0xD5, 0xBD, 0xF5, 0xC6, 0x16, 0xB5, 0x94, +0xB5, 0x94, 0xBD, 0xD5, 0xBD, 0xD5, 0xC6, 0x36, +0xBD, 0xF5, 0x9C, 0xF2, 0xA4, 0xF1, 0x94, 0x6F, +0x9C, 0xB0, 0xB5, 0x73, 0xB5, 0x52, 0xAD, 0x11, +0xAD, 0x32, 0xAD, 0x52, 0xC5, 0xF5, 0xC5, 0xD4, +0xBD, 0x93, 0xAD, 0x52, 0xBD, 0xB4, 0xAD, 0x12, +0xA4, 0xF1, 0x9C, 0xF1, 0x94, 0xB1, 0x9C, 0xD1, +0xAD, 0x74, 0xAD, 0x53, 0xC6, 0x36, 0xCE, 0x35, +0xBD, 0xD4, 0xC6, 0x15, 0xC5, 0xF5, 0xBD, 0xD4, +0x94, 0x90, 0xA4, 0xD1, 0x73, 0x4B, 0x8C, 0x2F, +0x83, 0xCD, 0x94, 0x4E, 0x83, 0xCD, 0x83, 0xCD, +0x94, 0x4F, 0x9C, 0xB0, 0xA4, 0xD0, 0xA4, 0xF1, +0x94, 0x6F, 0x83, 0xED, 0x83, 0xCD, 0x7B, 0xCC, +0x83, 0xED, 0x94, 0x4F, 0x94, 0x6F, 0x8C, 0x2E, +0x8C, 0x2E, 0x94, 0x4F, 0xA4, 0xD1, 0x8C, 0x2F, +0x73, 0x6C, 0x73, 0x4C, 0x4A, 0x28, 0x52, 0x48, +0x73, 0x4C, 0xAD, 0x12, 0x94, 0x6F, 0xAD, 0x12, +0xB5, 0x53, 0x9C, 0x90, 0xA4, 0xF1, 0xA4, 0xF1, +0x94, 0x6F, 0xAD, 0x11, 0xA4, 0xF1, 0xAD, 0x32, +0x94, 0x6F, 0xB5, 0x53, 0xB5, 0x73, 0x9C, 0xB0, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xD3, +0x73, 0xCE, 0x84, 0x50, 0x94, 0x90, 0x94, 0x90, +0x9C, 0xD1, 0x9C, 0xB1, 0x94, 0x90, 0x84, 0x0E, +0x6B, 0x6C, 0x9C, 0xD2, 0x94, 0x71, 0x94, 0x90, +0x8C, 0x70, 0xAD, 0x54, 0x9C, 0xD1, 0xAD, 0x33, +0xBD, 0xB4, 0xBD, 0xD4, 0xB5, 0x73, 0xB5, 0x93, +0xC5, 0xD5, 0x9C, 0x6F, 0xB4, 0xF0, 0xA4, 0x8E, +0xD5, 0xF3, 0xBD, 0x51, 0xB4, 0xEF, 0x8B, 0xAA, +0x9C, 0x6E, 0xAC, 0xCF, 0xB5, 0x51, 0xC5, 0xB3, +0xC5, 0xB3, 0xD6, 0x35, 0xCE, 0x35, 0xCE, 0x15, +0xCD, 0xF4, 0xD6, 0x36, 0xCD, 0xF5, 0xBD, 0x72, +0xC5, 0xD4, 0xD6, 0x35, 0xC5, 0x92, 0xA4, 0xAE, +0x9C, 0x2D, 0xD5, 0xF3, 0xAC, 0xCE, 0xBD, 0x92, +0xBD, 0x93, 0xAD, 0x12, 0xAD, 0x32, 0xBD, 0xB5, +0xB5, 0x73, 0xBD, 0xB5, 0xB5, 0x53, 0xAD, 0x33, +0xB5, 0x73, 0xB5, 0x73, 0x9C, 0xD1, 0xA4, 0xF2, +0xB5, 0x53, 0xB5, 0x73, 0x7B, 0xCD, 0x9C, 0xD1, +0xAD, 0x32, 0xAD, 0x12, 0xBD, 0x93, 0xB5, 0x52, +0xC5, 0xD4, 0xA4, 0xD1, 0x7B, 0xCD, 0x42, 0x06, +0x39, 0xA6, 0x42, 0x07, 0x4A, 0x68, 0x42, 0x08, +0x4A, 0x49, 0x5A, 0xCB, 0x73, 0x8E, 0x8C, 0x71, +0x94, 0xB3, 0x84, 0x10, 0xA5, 0x34, 0xB5, 0x96, +0xA5, 0x14, 0xBD, 0xF7, 0xA5, 0x14, 0x94, 0x71, +0x9C, 0xB1, 0xA4, 0xD2, 0xAD, 0x33, 0xA5, 0x12, +0x7B, 0xCD, 0x6B, 0x4B, 0xAD, 0x11, 0xB5, 0x51, +0xA4, 0xCF, 0xBD, 0x92, 0xB5, 0x31, 0x9C, 0x6E, +0x94, 0x2E, 0x9C, 0x90, 0x6B, 0x4B, 0x5A, 0xAA, +0x6B, 0x2B, 0x41, 0xE7, 0x39, 0xE7, 0x29, 0x24, +0x4A, 0x28, 0x8C, 0x30, 0xAD, 0x13, 0x41, 0xE6, +0x18, 0xC2, 0x29, 0x45, 0x39, 0xA6, 0x4A, 0x49, +0x7B, 0xAE, 0x52, 0x8A, 0x6B, 0x2D, 0x84, 0x11, +0xAD, 0x56, 0xD6, 0x9B, 0xCE, 0x7A, 0xBD, 0xB7, +0x94, 0x71, 0x8C, 0x50, 0xCE, 0x17, 0xA4, 0xB0, +0xB5, 0x51, 0xC5, 0xB2, 0xBD, 0x51, 0xB4, 0xEF, +0x9C, 0x4C, 0xA4, 0xAE, 0xB5, 0x0F, 0xAC, 0xAF, +0x83, 0xEE, 0xB5, 0x95, 0x5A, 0xCB, 0x84, 0x10, +0x5A, 0xA9, 0x5A, 0x88, 0x62, 0xE9, 0x6B, 0x0A, +0x7B, 0x6B, 0x83, 0xAB, 0x94, 0x0D, 0xA4, 0x8F, +0xB5, 0x10, 0xAD, 0x0F, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xD0, 0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x12, +0xB5, 0x33, 0xB5, 0x74, 0xBD, 0x94, 0xB5, 0x33, +0xB5, 0x73, 0xAD, 0x12, 0xB5, 0x33, 0xBD, 0xB4, +0xC5, 0xD5, 0xC5, 0xD5, 0xB5, 0x73, 0xB5, 0x94, +0xBD, 0xB5, 0xBD, 0x94, 0xBD, 0x93, 0xBD, 0x94, +0xBD, 0xB5, 0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xD5, +0xC5, 0xB5, 0xC5, 0xD5, 0xC5, 0xF6, 0xC5, 0xF6, +0xBD, 0xD5, 0xB5, 0x53, 0xAD, 0x12, 0x9C, 0xB0, +0x94, 0x6F, 0x8C, 0x0E, 0x83, 0xEE, 0x8B, 0xEE, +0x83, 0xED, 0x83, 0xED, 0x8C, 0x0D, 0x8B, 0xED, +0x83, 0xCD, 0x7B, 0xAC, 0x83, 0xCC, 0x83, 0xCC, +0x7B, 0xAB, 0x8B, 0xED, 0x83, 0xCC, 0x83, 0xAC, +0xAD, 0x32, 0x9C, 0xB0, 0x8C, 0x4F, 0x84, 0x2E, +0x9C, 0xF1, 0xA4, 0xF1, 0xBD, 0xD4, 0xA4, 0xF1, +0xB5, 0x73, 0x7B, 0xAD, 0x6B, 0x6C, 0x73, 0x6C, +0x8C, 0x4F, 0xAD, 0x53, 0xCE, 0x36, 0xCE, 0x36, +0xC6, 0x16, 0xB5, 0x94, 0xB5, 0xB4, 0xBD, 0xF5, +0xC5, 0xF5, 0xBD, 0xD5, 0xA5, 0x32, 0x9C, 0xB0, +0x94, 0x6F, 0xA4, 0xD1, 0x9C, 0xB1, 0xA5, 0x12, +0xAD, 0x53, 0xAD, 0x53, 0x9C, 0xF2, 0xB5, 0x73, +0xB5, 0x94, 0xBD, 0xD5, 0xB5, 0x73, 0xB5, 0x74, +0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0xD5, 0xB5, 0x94, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD5, 0xC5, 0xF5, +0xBD, 0xB5, 0xA4, 0xF2, 0xA5, 0x32, 0x9C, 0xD1, +0x8C, 0x2F, 0xB5, 0x73, 0xAD, 0x31, 0xAD, 0x11, +0xAD, 0x52, 0xB5, 0x93, 0xBD, 0xB4, 0xBD, 0x93, +0xB5, 0x73, 0xAD, 0x52, 0xBD, 0xB4, 0xAD, 0x32, +0x9C, 0xB0, 0x8C, 0x4E, 0x7B, 0xCD, 0x94, 0x90, +0xB5, 0x94, 0xAD, 0x53, 0xC6, 0x36, 0xC6, 0x35, +0xBD, 0xB4, 0xC6, 0x15, 0xC5, 0xF4, 0xAD, 0x32, +0x94, 0x8F, 0xA5, 0x11, 0x8C, 0x0E, 0x94, 0x4F, +0x8C, 0x0E, 0x94, 0x4F, 0x8C, 0x2F, 0x94, 0x2F, +0x9C, 0x90, 0xA4, 0xF1, 0xA5, 0x11, 0xBD, 0xB4, +0xA4, 0xF1, 0x7B, 0xCC, 0x84, 0x0D, 0x83, 0xCD, +0x94, 0x6F, 0xA4, 0xD1, 0xB5, 0x93, 0x9C, 0xB0, +0x9C, 0xB0, 0xA4, 0xD1, 0xB5, 0x53, 0xA4, 0xF1, +0x7B, 0x8C, 0x7B, 0xAE, 0x6B, 0x0C, 0x7B, 0x8D, +0x94, 0x71, 0xB5, 0x94, 0x9C, 0xB1, 0xB5, 0x73, +0xB5, 0x52, 0xAC, 0xF1, 0xB5, 0x73, 0xBD, 0xB3, +0xA4, 0xD0, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x93, +0xA4, 0xD0, 0xBD, 0x94, 0xAD, 0x12, 0xA4, 0xD0, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x9C, 0xD3, +0x5A, 0xEB, 0x5A, 0xC9, 0x6B, 0x2B, 0x6B, 0x4B, +0x73, 0x8C, 0x7B, 0xCD, 0x84, 0x0E, 0x84, 0x0E, +0x84, 0x0E, 0x94, 0x90, 0x8C, 0x50, 0x94, 0x70, +0x94, 0x90, 0x9C, 0xD1, 0x9C, 0xF2, 0xA5, 0x12, +0xAD, 0x73, 0xB5, 0x93, 0xB5, 0x73, 0xBD, 0xB4, +0xA4, 0xD0, 0x94, 0x4D, 0xAC, 0xEF, 0x93, 0xEC, +0xCD, 0xB3, 0x9C, 0x4D, 0x94, 0x0C, 0x7B, 0x6A, +0x9C, 0x6F, 0x83, 0x8B, 0x73, 0x2A, 0x7B, 0x8B, +0xAC, 0xF0, 0xD6, 0x35, 0xD6, 0x56, 0xD6, 0x35, +0xD6, 0x55, 0xD6, 0x56, 0xC5, 0xB3, 0xC5, 0xB3, +0xC5, 0x92, 0xC5, 0xB3, 0xC5, 0xB3, 0xB5, 0x10, +0x83, 0x8A, 0xAC, 0xEF, 0xA4, 0x8E, 0xCD, 0xF4, +0xC5, 0xF4, 0xAD, 0x52, 0xA5, 0x12, 0xBD, 0x94, +0xBD, 0xB4, 0xBD, 0xB4, 0xA4, 0xF1, 0xBD, 0x94, +0xBD, 0xB4, 0xB5, 0x73, 0xA4, 0xD1, 0xA4, 0xF1, +0xB5, 0x74, 0x8C, 0x4F, 0x7B, 0xCD, 0xB5, 0x73, +0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0x94, 0xBD, 0x93, +0xBD, 0xB4, 0x9C, 0x6F, 0xB5, 0x52, 0x62, 0xC9, +0x41, 0xE7, 0x39, 0xA6, 0x39, 0xE7, 0x42, 0x07, +0x42, 0x28, 0x4A, 0x48, 0x52, 0x89, 0x6B, 0x4D, +0x73, 0x6D, 0x94, 0x92, 0xA5, 0x34, 0xAD, 0x75, +0x9C, 0xD3, 0xCE, 0x59, 0xDE, 0xBB, 0xAD, 0x14, +0xB5, 0x54, 0xB5, 0x53, 0xB5, 0x74, 0xAD, 0x33, +0x83, 0xCE, 0x6B, 0x0B, 0xAD, 0x11, 0xB5, 0x31, +0xA4, 0xCF, 0xB5, 0x71, 0xBD, 0x72, 0xA4, 0x6E, +0xA4, 0xD0, 0xAC, 0xF1, 0xA4, 0xB0, 0x8C, 0x0E, +0x8B, 0xEE, 0x73, 0x2B, 0x39, 0xA6, 0x31, 0x85, +0x31, 0x85, 0x39, 0xA6, 0x62, 0xEA, 0x39, 0xA5, +0x29, 0x65, 0x39, 0xA6, 0x39, 0xE7, 0x4A, 0x69, +0x41, 0xE8, 0x52, 0x8A, 0x5A, 0xAB, 0x6B, 0x6E, +0xAD, 0x55, 0xCE, 0x59, 0x8C, 0x51, 0x6B, 0x2D, +0x7B, 0xAE, 0x8C, 0x30, 0x94, 0x71, 0xC5, 0xF7, +0xBD, 0x73, 0xCD, 0xF4, 0xC5, 0xB2, 0xC5, 0xB2, +0xA4, 0xAE, 0x9C, 0x4C, 0xAC, 0xEF, 0xA4, 0x8E, +0x8C, 0x2F, 0xB5, 0x96, 0x8C, 0x51, 0x8C, 0x51, +0x42, 0x07, 0x42, 0x07, 0x4A, 0x48, 0x4A, 0x48, +0x4A, 0x48, 0x52, 0x68, 0x52, 0x68, 0x5A, 0x89, +0x62, 0xEA, 0x73, 0x4B, 0x5A, 0xA8, 0x63, 0x0A, +0x62, 0xEA, 0x52, 0x88, 0x5A, 0xC9, 0x62, 0xEA, +0x83, 0xCD, 0x84, 0x0E, 0x94, 0x6F, 0x9C, 0x8F, +0x8C, 0x2E, 0x83, 0xAC, 0x83, 0xCD, 0x94, 0x70, +0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xF2, 0xB5, 0x53, +0x9C, 0xD1, 0x94, 0x6F, 0x8C, 0x2E, 0x9C, 0x90, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x12, +0xB5, 0x33, 0x94, 0x2F, 0x8C, 0x2E, 0x8C, 0x0E, +0x94, 0x8F, 0xA4, 0xF1, 0xA4, 0xF2, 0xB5, 0x73, +0xAD, 0x12, 0xAD, 0x33, 0xBD, 0x94, 0xBD, 0x94, +0xBD, 0x94, 0xB5, 0x94, 0xBD, 0x94, 0xBD, 0xB5, +0xC5, 0xD5, 0xBD, 0xB5, 0xBD, 0x94, 0xBD, 0x94, +0xAD, 0x32, 0x73, 0x8C, 0xB5, 0x74, 0xBD, 0xB5, +0xBD, 0xD5, 0xC5, 0xD5, 0xBD, 0xB4, 0xB5, 0x73, +0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD1, +0xA5, 0x12, 0xA4, 0xF2, 0xA5, 0x12, 0xAD, 0x12, +0xA5, 0x12, 0xAD, 0x33, 0xAD, 0x32, 0xA4, 0xF1, +0xA5, 0x11, 0xA5, 0x12, 0xA4, 0xF1, 0xA4, 0xF1, +0xA4, 0xF1, 0xAD, 0x53, 0x8C, 0x2E, 0x7B, 0xAD, +0x8C, 0x4F, 0x8C, 0x2E, 0x9C, 0xD1, 0xB5, 0x94, +0xC5, 0xF6, 0xCE, 0x37, 0xC5, 0xF6, 0xBD, 0xB4, +0xB5, 0x93, 0xCE, 0x57, 0xCE, 0x36, 0xC6, 0x36, +0xC6, 0x16, 0xBD, 0xD5, 0xBD, 0xD5, 0xBD, 0xB4, +0xB5, 0x94, 0xAD, 0x53, 0xB5, 0x74, 0xBD, 0xB4, +0xA5, 0x12, 0xB5, 0x94, 0xBD, 0xB5, 0xA4, 0xF1, +0x7B, 0xAD, 0xA4, 0xF1, 0x9C, 0x8F, 0xA5, 0x11, +0xAD, 0x12, 0xCE, 0x36, 0xC6, 0x15, 0xBD, 0xB4, +0xB5, 0x93, 0xB5, 0x93, 0xBD, 0xD5, 0xAD, 0x53, +0xB5, 0x94, 0xAD, 0x32, 0x94, 0x6F, 0xAD, 0x53, +0xB5, 0x94, 0xAD, 0x53, 0xC6, 0x35, 0xC6, 0x35, +0xBD, 0xD4, 0xBD, 0xD4, 0xB5, 0x73, 0x9C, 0xB0, +0x94, 0x8F, 0xAD, 0x32, 0x94, 0x6F, 0x84, 0x0E, +0x9C, 0xD0, 0x9C, 0xB1, 0x94, 0x6F, 0xA4, 0xD1, +0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, 0xBD, 0xB4, +0xBD, 0xB4, 0xAD, 0x12, 0xA4, 0xD1, 0x9C, 0xD1, +0xAD, 0x12, 0xBD, 0xB4, 0xBD, 0xB4, 0xAD, 0x32, +0x9C, 0xD1, 0xA4, 0xD1, 0xB5, 0x52, 0xBD, 0x93, +0x7B, 0x8D, 0x62, 0xEB, 0x62, 0xEB, 0x73, 0x8D, +0x94, 0x71, 0xBD, 0xD6, 0xA4, 0xF2, 0xB5, 0x52, +0xB5, 0x32, 0xAC, 0xF1, 0xBD, 0x93, 0xC5, 0xB4, +0xAC, 0xF1, 0xC5, 0xB3, 0xCD, 0xF4, 0xC5, 0xF4, +0xAD, 0x11, 0xB5, 0x52, 0xAD, 0x32, 0xB5, 0x53, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xD3, +0x73, 0xAD, 0x7B, 0x8B, 0x83, 0xCC, 0x8C, 0x0D, +0x94, 0x2D, 0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, +0x9C, 0x8F, 0xA4, 0x8F, 0xA4, 0x8F, 0xA4, 0x8F, +0x9C, 0x6E, 0x94, 0x2D, 0x94, 0x4E, 0x9C, 0x6F, +0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0xAF, +0x9C, 0x8E, 0xA4, 0x8E, 0xAC, 0xAE, 0x83, 0x8A, +0xA4, 0x6E, 0xA4, 0x6E, 0x8B, 0xCB, 0x8B, 0xCC, +0xA4, 0xAF, 0x73, 0x4A, 0x7B, 0x8C, 0x8C, 0x0D, +0xAC, 0xF0, 0xC5, 0xB3, 0xCD, 0xF4, 0xBD, 0x72, +0xBD, 0x72, 0xA4, 0xF0, 0xA4, 0xAF, 0xBD, 0x72, +0xC5, 0x92, 0xBD, 0x72, 0xB5, 0x31, 0xA4, 0x8E, +0x83, 0x8B, 0xAC, 0xEF, 0xAC, 0xAE, 0xBD, 0x72, +0xC5, 0xD4, 0xA4, 0xF1, 0x9C, 0xB0, 0x94, 0x6F, +0xA4, 0xD1, 0xAD, 0x32, 0x9C, 0xB0, 0xBD, 0xD4, +0xBD, 0x93, 0x9C, 0xB0, 0xBD, 0xB5, 0x9C, 0x90, +0xB5, 0x74, 0x9C, 0x90, 0x9C, 0xB0, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xF5, +0xCE, 0x35, 0xAC, 0xD0, 0xC5, 0x72, 0x94, 0x4E, +0x52, 0x88, 0x39, 0xA6, 0x31, 0x85, 0x39, 0xC6, +0x39, 0xC6, 0x39, 0xC6, 0x4A, 0x69, 0x63, 0x2C, +0x84, 0x10, 0x9C, 0xD3, 0x9C, 0xD3, 0x94, 0x72, +0x84, 0x10, 0xBD, 0xD7, 0xD6, 0xBA, 0xCE, 0x58, +0xA4, 0xD2, 0xC5, 0xB5, 0xC5, 0xD6, 0xAD, 0x33, +0x83, 0xCE, 0x63, 0x0B, 0xA4, 0xD0, 0xB5, 0x31, +0xAD, 0x10, 0xB5, 0x51, 0xB5, 0x30, 0x9C, 0x6D, +0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xD0, 0x9C, 0x6F, +0x73, 0x0A, 0x94, 0x0E, 0x9C, 0x90, 0x62, 0xCA, +0x31, 0x85, 0x31, 0x65, 0x31, 0x85, 0x29, 0x44, +0x31, 0xA6, 0x31, 0xA6, 0x39, 0xE7, 0x39, 0xE7, +0x42, 0x28, 0x6B, 0x2D, 0x63, 0x2D, 0x7B, 0xCF, +0x8C, 0x72, 0xA5, 0x35, 0x63, 0x2C, 0x52, 0x8A, +0x62, 0xCB, 0x7B, 0x6D, 0x7B, 0xAE, 0xD6, 0x9A, +0xCE, 0x37, 0xAD, 0x12, 0xA4, 0xD0, 0x94, 0x2D, +0x83, 0xEC, 0x94, 0x4D, 0xB5, 0x10, 0xA4, 0x8E, +0x94, 0x92, 0xB5, 0x96, 0x9C, 0xF4, 0x8C, 0x71, +0x42, 0x28, 0x4A, 0x49, 0x52, 0x89, 0x5A, 0xAA, +0x5A, 0xAA, 0x5A, 0xAA, 0x52, 0x69, 0x52, 0x69, +0x52, 0x89, 0x5A, 0xCA, 0x52, 0x89, 0x5A, 0xCA, +0x5A, 0xCA, 0x5A, 0xCA, 0x63, 0x0B, 0x62, 0xEB, +0x52, 0xA9, 0x5A, 0xEA, 0x94, 0x70, 0xA4, 0xF1, +0x94, 0x4F, 0x83, 0xED, 0x7B, 0xAD, 0x73, 0x8C, +0x83, 0xEE, 0x7B, 0xCD, 0x73, 0x8C, 0x7B, 0xAD, +0x83, 0xCD, 0x7B, 0xAD, 0x7B, 0x8C, 0x7B, 0x8C, +0x7B, 0xAC, 0x73, 0x4B, 0xA4, 0xD1, 0x9C, 0xB1, +0x7B, 0xAD, 0x6B, 0x0A, 0x7B, 0x8C, 0x8C, 0x2E, +0x83, 0xAD, 0x83, 0xEE, 0x8C, 0x0E, 0x94, 0x90, +0x94, 0x6F, 0x9C, 0x90, 0x8C, 0x4E, 0x94, 0x6F, +0x9C, 0xD0, 0x9C, 0xD1, 0x9C, 0xB1, 0xA4, 0xF1, +0x94, 0x70, 0xAD, 0x32, 0xAD, 0x12, 0x9C, 0xB1, +0x62, 0xEB, 0x4A, 0x49, 0x8C, 0x70, 0x94, 0x6F, +0x9C, 0x90, 0x9C, 0x90, 0xAD, 0x12, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0xB5, 0x53, 0xB5, 0x73, +0xC5, 0xF5, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x73, +0xBD, 0x73, 0xBD, 0xB4, 0xBD, 0x94, 0xB5, 0x52, +0xB5, 0x73, 0xBD, 0x73, 0xC5, 0xB4, 0xC5, 0xB4, +0xBD, 0x94, 0xBD, 0x94, 0xC5, 0xD5, 0xC5, 0xF5, +0xCE, 0x16, 0xC5, 0xB4, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xB1, 0xA4, 0xB1, 0xA4, 0xD0, 0x9C, 0xB0, +0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, 0xA4, 0xD1, +0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x32, +0xA4, 0xF1, 0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0x90, +0x9C, 0xB1, 0xAD, 0x33, 0xB5, 0x53, 0x84, 0x0E, +0x83, 0xEE, 0xBD, 0xB5, 0xAD, 0x32, 0x9C, 0xB0, +0x8C, 0x2E, 0xAD, 0x32, 0x83, 0xED, 0x9C, 0xD0, +0xBD, 0xD4, 0xCE, 0x36, 0xC6, 0x15, 0xAD, 0x52, +0xCE, 0x36, 0xCE, 0x36, 0xB5, 0x94, 0xC6, 0x16, +0xC5, 0xF6, 0xC5, 0xF5, 0xD6, 0x97, 0xC6, 0x15, +0xC6, 0x15, 0xCE, 0x36, 0xBD, 0xB4, 0x94, 0x8F, +0x9C, 0xB0, 0xA4, 0xF1, 0x94, 0x6F, 0xA4, 0xF1, +0x9C, 0xD1, 0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x94, 0xC5, 0xF5, 0xBD, 0xD5, 0xC5, 0xF5, +0xCE, 0x36, 0xC5, 0xF5, 0xBD, 0xB4, 0xB5, 0x73, +0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xF5, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0x94, 0xC5, 0xD4, 0xC5, 0xD4, +0x83, 0xCD, 0x8C, 0x0F, 0x62, 0xEB, 0x6B, 0x6D, +0x94, 0x91, 0xC6, 0x17, 0xB5, 0x54, 0xAD, 0x32, +0xB5, 0x32, 0xB5, 0x32, 0xBD, 0x93, 0xC5, 0x93, +0xBD, 0x73, 0xD6, 0x35, 0xCE, 0x14, 0xC5, 0xF4, +0xA4, 0xF1, 0xAC, 0xF1, 0xAD, 0x32, 0xB5, 0x52, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xB3, +0x6B, 0x4C, 0x5A, 0x67, 0x5A, 0x67, 0x6A, 0xC8, +0x72, 0xE9, 0x7B, 0x29, 0x7B, 0x4A, 0x7B, 0x4A, +0x83, 0xAB, 0x8B, 0xCC, 0x94, 0x0C, 0x9C, 0x2D, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8F, 0xA4, 0x6E, +0x9C, 0x4E, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAF, +0xAC, 0xAF, 0xA4, 0x8E, 0xAC, 0xCF, 0xB5, 0x10, +0xB4, 0xEF, 0xB4, 0xCF, 0xB4, 0xF0, 0xAC, 0xEF, +0xAC, 0xCF, 0xB4, 0xF0, 0xB4, 0xEF, 0xAC, 0xAE, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x6D, 0x9C, 0x2C, +0x94, 0x2C, 0x93, 0xEC, 0x8B, 0xEC, 0x94, 0x2D, +0x8B, 0xCC, 0x83, 0x8B, 0x83, 0x6A, 0x8B, 0xAA, +0x72, 0xE8, 0x94, 0x0D, 0xAC, 0xCF, 0x9C, 0x2D, +0x8B, 0xEC, 0x73, 0x2A, 0x8B, 0xED, 0x73, 0x2A, +0x62, 0xA9, 0x62, 0xC9, 0x73, 0x4B, 0x7B, 0x6B, +0x73, 0x2A, 0x62, 0xC9, 0x83, 0xEE, 0x73, 0x4A, +0x83, 0xCC, 0x83, 0xCC, 0x9C, 0x6F, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x31, 0xB5, 0x52, +0xAD, 0x11, 0xAC, 0xCF, 0xC5, 0x71, 0x9C, 0x4D, +0x8C, 0x0E, 0x42, 0x07, 0x39, 0xA6, 0x42, 0x07, +0x42, 0x28, 0x42, 0x28, 0x4A, 0x69, 0x52, 0x89, +0x63, 0x0C, 0x7B, 0xAE, 0x9C, 0xB2, 0x83, 0xEF, +0x9C, 0xD3, 0xB5, 0x96, 0xBD, 0xB7, 0xCE, 0x59, +0x94, 0x51, 0xA4, 0xF3, 0xEF, 0x3C, 0xDE, 0xDB, +0xBD, 0xB6, 0x7B, 0xCE, 0xA4, 0xD1, 0xBD, 0x93, +0xC5, 0xD3, 0xBD, 0xB3, 0xB5, 0x10, 0x9C, 0x2C, +0xB5, 0x10, 0xB5, 0x11, 0xAC, 0xF0, 0xB4, 0xF1, +0x94, 0x0E, 0x8B, 0xED, 0x94, 0x2E, 0x73, 0x4B, +0x31, 0xA5, 0x39, 0xC6, 0x31, 0x85, 0x29, 0x64, +0x31, 0x85, 0x39, 0xC6, 0x39, 0xE7, 0x42, 0x28, +0x62, 0xEB, 0x6B, 0x6D, 0x7B, 0xCF, 0x63, 0x0C, +0x63, 0x2D, 0x8C, 0x72, 0x6B, 0x2D, 0x39, 0x86, +0x41, 0xE7, 0x52, 0x49, 0x73, 0x6D, 0xAD, 0x35, +0xDE, 0xBA, 0xE6, 0xDB, 0xCE, 0x38, 0x83, 0xEE, +0x83, 0xED, 0x9C, 0x8F, 0xBD, 0x30, 0xA4, 0x8F, +0xB5, 0x75, 0xAD, 0x76, 0x9C, 0xF4, 0x8C, 0x51, +0x6B, 0x4D, 0x6B, 0x2C, 0x62, 0xEB, 0x63, 0x0B, +0x63, 0x2B, 0x63, 0x0B, 0x62, 0xEA, 0x6B, 0x4B, +0x6B, 0x6C, 0x73, 0x8D, 0x63, 0x2B, 0x6B, 0x4C, +0x6B, 0x6C, 0x73, 0x8D, 0x73, 0xAE, 0x7B, 0xCE, +0x83, 0xEE, 0x83, 0xEE, 0x9C, 0xD1, 0xAD, 0x12, +0xB5, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, 0xA5, 0x12, +0xB5, 0x93, 0xB5, 0x94, 0x9C, 0xD1, 0xAD, 0x12, +0xA4, 0xF1, 0x94, 0x2E, 0x9C, 0x8F, 0xA4, 0xD1, +0xA4, 0xB1, 0x83, 0xEE, 0xCE, 0x57, 0xDE, 0xB8, +0xCD, 0xF5, 0xBD, 0x94, 0xA4, 0xD0, 0xB5, 0x52, +0xA4, 0xB0, 0xAC, 0xF1, 0x9C, 0xB0, 0xB5, 0x53, +0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x12, +0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xF2, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0x8C, 0x2E, 0x5A, 0xCB, +0x4A, 0x6A, 0x52, 0xAB, 0x94, 0x91, 0xA5, 0x12, +0x9C, 0x90, 0xAD, 0x12, 0xC5, 0xD5, 0xBD, 0x94, +0xB5, 0x52, 0xB5, 0x53, 0xAD, 0x32, 0xA4, 0xD1, +0x9C, 0x90, 0x8C, 0x0D, 0x94, 0x4E, 0x9C, 0x8F, +0xA4, 0xD0, 0x94, 0x4E, 0x94, 0x6F, 0x83, 0xEC, +0x94, 0x6E, 0xA4, 0xD0, 0xAC, 0xF0, 0xB5, 0x10, +0xAD, 0x10, 0xA4, 0xCF, 0x8C, 0x2D, 0x94, 0x2E, +0x8C, 0x2E, 0x8C, 0x0E, 0x8C, 0x0E, 0x94, 0x4F, +0x9C, 0x90, 0x9C, 0x90, 0x9C, 0xB0, 0xB5, 0x53, +0xBD, 0x73, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x52, +0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x53, 0xB5, 0x53, +0xAD, 0x12, 0xB5, 0x53, 0xA5, 0x12, 0xB5, 0x53, +0xC5, 0xB4, 0xBD, 0x94, 0xB5, 0x53, 0xBD, 0xB4, +0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, +0xA4, 0xD1, 0xA4, 0xF2, 0x94, 0x70, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xD0, 0x9C, 0xD0, +0xA4, 0xD1, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, +0xA5, 0x11, 0xA5, 0x11, 0xA4, 0xD0, 0x94, 0x4F, +0x94, 0x6F, 0x9C, 0x90, 0x83, 0xED, 0x6B, 0x2A, +0x94, 0x6F, 0xA5, 0x12, 0xB5, 0x73, 0xA4, 0xF1, +0x94, 0x90, 0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0x94, +0xC6, 0x16, 0xCE, 0x57, 0xCE, 0x36, 0xCE, 0x36, +0xCE, 0x36, 0xCE, 0x36, 0xCE, 0x36, 0xCE, 0x36, +0xCE, 0x36, 0xD6, 0x56, 0xD6, 0x57, 0xCE, 0x36, +0xCE, 0x56, 0xD6, 0x76, 0xD6, 0x77, 0xCE, 0x15, +0x83, 0xCD, 0xA4, 0xF2, 0x7B, 0xAE, 0x8C, 0x51, +0xAD, 0x55, 0xCE, 0x79, 0xC5, 0xD5, 0xBD, 0x94, +0xB5, 0x32, 0xBD, 0x73, 0xD6, 0x15, 0xD6, 0x35, +0xCD, 0xD3, 0xD6, 0x55, 0xD6, 0x35, 0xCD, 0xF4, +0xA4, 0xF0, 0xAD, 0x11, 0xC5, 0xF4, 0xBD, 0x93, +0xA5, 0x55, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xB2, +0x8C, 0x0F, 0x7B, 0x6B, 0x7B, 0x6B, 0x83, 0xAC, +0x94, 0x2D, 0x8B, 0xCC, 0x7B, 0x4B, 0x83, 0x6B, +0x8B, 0xCC, 0x83, 0x6B, 0x83, 0xAC, 0x83, 0xAC, +0x8B, 0xEC, 0x9C, 0x2D, 0x9C, 0x4D, 0x9C, 0x4D, +0x7B, 0x6A, 0x83, 0xCC, 0x7B, 0x8B, 0x6B, 0x09, +0x6A, 0xE9, 0x6A, 0xE9, 0x7B, 0x6A, 0x73, 0x09, +0x7B, 0x4A, 0x83, 0x6A, 0x8B, 0xCB, 0x94, 0x0C, +0x9C, 0x2C, 0xA4, 0x6D, 0x9C, 0x2C, 0x9C, 0x2C, +0xA4, 0x6D, 0xA4, 0x8E, 0x9C, 0x2D, 0xA4, 0x8E, +0xB4, 0xCF, 0xB4, 0xEF, 0xB4, 0xEF, 0xA4, 0x8E, +0x9C, 0x4D, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x6D, +0x9C, 0x4D, 0x9C, 0x2D, 0xA4, 0x8E, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x6F, 0x9C, 0x6E, 0x9C, 0x4E, +0x9C, 0x6F, 0x9C, 0x4F, 0x9C, 0x6E, 0x9C, 0x6E, +0xA4, 0xCF, 0xA4, 0xB0, 0x9C, 0x6E, 0xA4, 0x6F, +0x94, 0x0D, 0x94, 0x0D, 0x9C, 0x6E, 0x9C, 0x6E, +0x94, 0x0D, 0x8B, 0xEC, 0x83, 0xAB, 0x73, 0x4A, +0x73, 0x29, 0x7B, 0x6A, 0xAC, 0xCF, 0x94, 0x0D, +0x83, 0xAC, 0x62, 0xEA, 0x42, 0x07, 0x4A, 0x48, +0x4A, 0x48, 0x42, 0x07, 0x4A, 0x69, 0x52, 0xAA, +0x5A, 0xAA, 0x7B, 0xCF, 0x73, 0x6D, 0x84, 0x30, +0x9C, 0xF3, 0xAD, 0x55, 0xB5, 0x96, 0xBD, 0xB7, +0x8C, 0x51, 0x62, 0xEC, 0xA5, 0x14, 0xBD, 0xB7, +0xBD, 0x96, 0x94, 0x50, 0xBD, 0xB4, 0xCE, 0x34, +0xC5, 0xF4, 0xBD, 0xB3, 0xB5, 0x10, 0xA4, 0x6D, +0xCD, 0xD3, 0xD5, 0xD3, 0xCD, 0xB3, 0xCD, 0xB3, +0x9C, 0x2E, 0x83, 0xAC, 0x7B, 0x6B, 0x6B, 0x0A, +0x5A, 0xA9, 0x39, 0xC6, 0x41, 0xE7, 0x31, 0x85, +0x31, 0xA6, 0x39, 0xC6, 0x42, 0x07, 0x52, 0x89, +0x73, 0x8D, 0x52, 0xAA, 0x5A, 0xEB, 0x39, 0xE7, +0x6B, 0x4D, 0x84, 0x31, 0x6B, 0x4D, 0x31, 0x85, +0x41, 0xE7, 0x42, 0x08, 0x4A, 0x28, 0x39, 0xA7, +0x52, 0x8A, 0x6B, 0x2D, 0xDE, 0xBB, 0xD6, 0x79, +0x94, 0x70, 0x9C, 0x6F, 0xBD, 0x51, 0xA4, 0xAF, +0xBD, 0xF6, 0xA5, 0x35, 0x8C, 0x72, 0x9C, 0xB1, +0xAD, 0x32, 0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0xB0, +0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x4F, 0x8C, 0x2E, +0x8C, 0x2E, 0x9C, 0xB0, 0x8C, 0x4F, 0x83, 0xED, +0x83, 0xEE, 0x83, 0xEE, 0x8C, 0x0E, 0x8C, 0x4F, +0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x11, +0xC5, 0xB3, 0xC5, 0xB3, 0xB5, 0x72, 0xA5, 0x11, +0xA4, 0xF1, 0xB5, 0x73, 0xA4, 0xD1, 0xBD, 0x93, +0xCD, 0xD4, 0xCD, 0xD3, 0xBD, 0x72, 0xBD, 0x52, +0xAC, 0xF1, 0x41, 0xE7, 0x6B, 0x6C, 0x9C, 0xB1, +0xBD, 0xB4, 0xCE, 0x36, 0xB5, 0x51, 0xA4, 0xD0, +0xB5, 0x11, 0xC5, 0x93, 0x9C, 0x90, 0xB5, 0x73, +0xB5, 0x53, 0xA4, 0xF1, 0xAD, 0x52, 0xB5, 0x94, +0xB5, 0x74, 0xB5, 0x74, 0xBD, 0x94, 0xBD, 0x94, +0xB5, 0x73, 0x9C, 0xB1, 0x5A, 0xCA, 0x4A, 0x4A, +0x4A, 0x6A, 0x4A, 0x6A, 0x8C, 0x50, 0x9C, 0xB1, +0x8C, 0x4F, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x32, +0xB5, 0x52, 0xAD, 0x32, 0xBD, 0xB4, 0xB5, 0x52, +0xA4, 0xD1, 0xAD, 0x11, 0xBD, 0xB3, 0xB5, 0x72, +0xBD, 0x93, 0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0xB0, +0xB5, 0x52, 0xAC, 0xF0, 0xB5, 0x30, 0xBD, 0x71, +0xAD, 0x30, 0xB5, 0x51, 0xB5, 0x72, 0xB5, 0x72, +0xA4, 0xF0, 0x94, 0x6E, 0x94, 0x6E, 0x8C, 0x2D, +0x94, 0x6F, 0x83, 0xCC, 0x73, 0x4B, 0xA4, 0xD1, +0xB5, 0x53, 0xBD, 0x94, 0x83, 0xCD, 0x9C, 0x90, +0xAD, 0x12, 0x94, 0x70, 0x94, 0x2F, 0x94, 0x6F, +0x8C, 0x2F, 0x94, 0x4F, 0x83, 0xED, 0x8C, 0x0E, +0x94, 0x2F, 0x9C, 0x90, 0x9C, 0x70, 0x8C, 0x2F, +0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xD1, +0xAC, 0xF1, 0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x32, +0xA4, 0xB0, 0x94, 0x4F, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x8F, +0x94, 0x6F, 0x94, 0x4E, 0x9C, 0x90, 0xA4, 0xF1, +0xA4, 0xD0, 0xAD, 0x12, 0xAD, 0x11, 0xAD, 0x11, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x32, +0x9C, 0xB0, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x32, +0xAD, 0x32, 0xAD, 0x32, 0xAC, 0xF1, 0xA4, 0xD1, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF2, 0xCE, 0x16, 0xDE, 0x99, 0xDE, 0x99, +0xAD, 0x33, 0xAD, 0x32, 0xB5, 0x73, 0xAD, 0x53, +0x83, 0xCE, 0xAD, 0x54, 0x94, 0x71, 0x73, 0x8E, +0x63, 0x2D, 0x8C, 0x51, 0xCE, 0x17, 0xC5, 0xD4, +0xC5, 0x94, 0xBD, 0x73, 0xCD, 0xF5, 0xC5, 0xB4, +0xBD, 0x72, 0xC5, 0xB3, 0xC5, 0x72, 0xAC, 0xD0, +0xA4, 0x8F, 0xB5, 0x52, 0xCD, 0xF5, 0xB5, 0x73, +0xA5, 0x55, 0xA5, 0x34, 0x9D, 0x14, 0x94, 0xB2, +0x94, 0x70, 0x8B, 0xED, 0x94, 0x2E, 0xAC, 0xF1, +0x83, 0x8B, 0x94, 0x4E, 0xAC, 0xF0, 0xAD, 0x11, +0xB5, 0x11, 0xAD, 0x11, 0xB5, 0x32, 0xA4, 0xAF, +0xB5, 0x31, 0xB5, 0x10, 0xAC, 0xAE, 0xA4, 0x6E, +0x94, 0x4E, 0x9C, 0xB0, 0x94, 0x90, 0xA4, 0xF1, +0x9C, 0xB1, 0x8C, 0x2E, 0x8C, 0x0D, 0x8C, 0x2E, +0x8C, 0x2E, 0x8C, 0x2E, 0x9C, 0x8F, 0x94, 0x4E, +0x9C, 0x4E, 0xA4, 0xAF, 0x9C, 0x4D, 0xA4, 0xAE, +0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xD0, 0x9C, 0x6E, 0xA4, 0x8E, 0xAC, 0xCF, +0xC5, 0x92, 0xBD, 0x31, 0xB5, 0x10, 0xBD, 0x51, +0xA4, 0x8E, 0x94, 0x0D, 0x94, 0x0C, 0xA4, 0x6D, +0x9C, 0x2D, 0xA4, 0x6E, 0xA4, 0x8E, 0x94, 0x0D, +0x8B, 0xAB, 0x83, 0xAC, 0x8B, 0xCC, 0x94, 0x0D, +0x9C, 0x4D, 0xA4, 0x8F, 0x9C, 0x4D, 0x8B, 0xAB, +0x93, 0xEC, 0x9C, 0x4D, 0xB5, 0x10, 0xB5, 0x10, +0xA4, 0xAF, 0xA4, 0x6E, 0x9C, 0x6E, 0x9C, 0x2D, +0x94, 0x2D, 0x9C, 0x6E, 0xAC, 0xAE, 0xAC, 0xCF, +0xA4, 0x8E, 0x8C, 0x0D, 0x4A, 0x48, 0x39, 0xC6, +0x39, 0xA6, 0x39, 0xC6, 0x4A, 0x28, 0x52, 0x89, +0x52, 0x8A, 0x5A, 0xCA, 0x5A, 0xCB, 0x9C, 0xB2, +0x9C, 0xB2, 0xA5, 0x14, 0xAD, 0x76, 0xB5, 0x76, +0x84, 0x30, 0x41, 0xE8, 0x5A, 0x8A, 0x5A, 0xAB, +0x4A, 0x49, 0x63, 0x0B, 0xB5, 0x73, 0x8C, 0x2D, +0x7B, 0xAB, 0x7B, 0x8A, 0x9C, 0x4D, 0x8B, 0xEB, +0x9C, 0x4D, 0xA4, 0x8E, 0x9C, 0x6E, 0x83, 0x8B, +0x62, 0xA8, 0x83, 0xAC, 0x73, 0x4B, 0x6A, 0xEA, +0x8C, 0x0E, 0x9C, 0x6F, 0xA4, 0x8F, 0x73, 0x6B, +0x39, 0xC6, 0x29, 0x65, 0x39, 0xC7, 0x42, 0x07, +0x52, 0x69, 0x31, 0xA6, 0x39, 0xC7, 0x52, 0xAA, +0x73, 0x8E, 0x7B, 0xEF, 0x7B, 0xAE, 0x39, 0xA6, +0x52, 0x8A, 0x52, 0xAA, 0x7B, 0xCF, 0x73, 0xAE, +0x5A, 0xCB, 0x39, 0xC8, 0x63, 0x0D, 0xBD, 0xF7, +0xDE, 0xDA, 0xAD, 0x11, 0xB5, 0x30, 0xB5, 0x11, +0xCE, 0x58, 0xAD, 0x55, 0x8C, 0x72, 0xBD, 0x94, +0xD6, 0x75, 0xDE, 0x75, 0xD6, 0x55, 0xDE, 0x96, +0xD6, 0x55, 0xCD, 0xF4, 0xD6, 0x55, 0xDE, 0x75, +0xD6, 0x34, 0xCD, 0xF4, 0xB5, 0x52, 0xA4, 0xF1, +0x7B, 0x8C, 0x94, 0x6F, 0xB5, 0x53, 0xBD, 0x93, +0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x53, 0xAD, 0x11, +0xC5, 0xB3, 0xBD, 0x93, 0xBD, 0x73, 0xB5, 0x73, +0xAD, 0x52, 0xC5, 0xF5, 0xB5, 0x53, 0xB5, 0x31, +0xAC, 0xCF, 0xCD, 0xB3, 0xCD, 0x92, 0xCD, 0xB3, +0xCD, 0xD4, 0x52, 0x69, 0x39, 0xE8, 0x4A, 0x49, +0x73, 0x6D, 0xA4, 0xF1, 0x94, 0x4E, 0xAC, 0xF0, +0xC5, 0x73, 0xC5, 0x73, 0xA4, 0xB0, 0xAD, 0x32, +0xBD, 0xD5, 0xC5, 0xD5, 0xC5, 0xF5, 0xCE, 0x36, +0xC6, 0x16, 0xBD, 0xD5, 0xAD, 0x32, 0x94, 0x4F, +0x73, 0x8D, 0x52, 0x8A, 0x39, 0xE8, 0x41, 0xE9, +0x42, 0x09, 0x3A, 0x08, 0x83, 0xEF, 0x9C, 0xD1, +0x8C, 0x2F, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0x90, +0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xF1, 0xB5, 0x73, +0x9C, 0xD0, 0xAD, 0x11, 0xB5, 0x93, 0xBD, 0xB3, +0xC5, 0xF5, 0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x52, +0xB5, 0x51, 0xAD, 0x10, 0xB5, 0x30, 0xAD, 0x0F, +0xA4, 0xCF, 0xAD, 0x30, 0xB5, 0x72, 0xB5, 0x92, +0xBD, 0xB3, 0x9C, 0xAF, 0xB5, 0x51, 0xB5, 0x51, +0xBD, 0x93, 0xAD, 0x11, 0x8C, 0x0D, 0xB5, 0x53, +0xBD, 0x74, 0x9C, 0xB0, 0x94, 0x4F, 0x94, 0x4F, +0x83, 0xCD, 0x7B, 0x8C, 0x83, 0xAD, 0x94, 0x4F, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0x8C, 0x7B, 0x6C, +0x6B, 0x2B, 0x83, 0xEE, 0x9C, 0xB0, 0x9C, 0x90, +0x94, 0x70, 0x94, 0x4F, 0x8C, 0x0E, 0x7B, 0xAC, +0x7B, 0x8C, 0x8C, 0x2E, 0x83, 0xCD, 0x83, 0xCD, +0xA4, 0xD1, 0x9C, 0xB1, 0x8C, 0x0E, 0x94, 0x4F, +0x5A, 0xA8, 0x83, 0xCD, 0x8C, 0x2E, 0xA4, 0xD0, +0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x32, 0xAD, 0x11, +0xA4, 0xF0, 0xB5, 0x32, 0xAC, 0xF1, 0xAD, 0x32, +0x9C, 0x6F, 0x9C, 0x6F, 0xA4, 0xD0, 0xB5, 0x32, +0xBD, 0x93, 0xAD, 0x31, 0xAC, 0xF1, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x32, 0xB5, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xBD, 0x94, 0xBD, 0x94, 0xAD, 0x33, +0xCE, 0x58, 0xCE, 0x18, 0xC6, 0x38, 0xDE, 0xDB, +0xBD, 0xB6, 0xA4, 0xF2, 0xA4, 0xD1, 0x9C, 0xD1, +0xAD, 0x33, 0xC5, 0xD6, 0x8C, 0x50, 0x41, 0xE8, +0x39, 0xE8, 0x63, 0x2D, 0xB5, 0x75, 0xAD, 0x12, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x6E, 0x94, 0x4E, +0xA4, 0xD1, 0xAC, 0xF1, 0x9C, 0x90, 0x94, 0x6F, +0xA5, 0x75, 0xA5, 0x35, 0x9D, 0x14, 0x94, 0xB2, +0x9C, 0x90, 0x8C, 0x0D, 0x9C, 0x8F, 0xA4, 0xD0, +0x94, 0x2D, 0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x51, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x52, 0xBD, 0x92, +0xC5, 0xB3, 0xBD, 0x72, 0xAC, 0xCF, 0xA4, 0x8E, +0xA4, 0xD0, 0x9C, 0xB0, 0x8C, 0x4F, 0x94, 0x6F, +0x9C, 0xB1, 0x9C, 0xD0, 0x94, 0x4E, 0xA4, 0xD1, +0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xF0, 0x94, 0x6F, +0x9C, 0x8F, 0xAC, 0xF1, 0xAD, 0x31, 0xBD, 0x93, +0xB5, 0x72, 0xBD, 0x73, 0xAD, 0x11, 0xB5, 0x73, +0xBD, 0x73, 0xA4, 0xD0, 0x9C, 0x6D, 0xAC, 0xAE, +0xC5, 0xB2, 0xAC, 0xEF, 0xC5, 0x92, 0xBD, 0x31, +0xB5, 0x10, 0xAC, 0xF0, 0xA4, 0x8E, 0xA4, 0x8E, +0x94, 0x0C, 0x94, 0x0D, 0x94, 0x2D, 0x94, 0x2D, +0x8B, 0xCC, 0x83, 0xAC, 0x94, 0x2E, 0x9C, 0x6E, +0x9C, 0x8E, 0xAC, 0xF0, 0xAC, 0xF0, 0x9C, 0x8E, +0x8B, 0xEC, 0x93, 0xEC, 0x94, 0x0C, 0xA4, 0x6D, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xA4, 0xAF, +0x83, 0x8B, 0x7B, 0x6A, 0x94, 0x0C, 0x94, 0x0C, +0x94, 0x2D, 0x9C, 0x8F, 0x7B, 0xAD, 0x4A, 0x28, +0x39, 0xE7, 0x31, 0x85, 0x41, 0xE7, 0x41, 0xE7, +0x41, 0xE7, 0x4A, 0x48, 0x6B, 0x2C, 0x83, 0xEF, +0x7B, 0xEF, 0x9C, 0xD3, 0x8C, 0x71, 0x9C, 0xD3, +0xA4, 0xF3, 0x5A, 0xAB, 0x6B, 0x2D, 0x6B, 0x4D, +0x31, 0x66, 0x42, 0x28, 0xAD, 0x13, 0xAD, 0x12, +0xAC, 0xF0, 0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xAE, +0x9C, 0x4D, 0x9C, 0x2D, 0x93, 0xEC, 0x8B, 0xED, +0x9C, 0x4E, 0xA4, 0x8F, 0x9C, 0x6E, 0xB5, 0x11, +0xC5, 0x92, 0xC5, 0x71, 0xC5, 0x71, 0xB4, 0xF0, +0xA4, 0x8F, 0x6B, 0x0B, 0x5A, 0xEB, 0x39, 0xE7, +0x31, 0x86, 0x31, 0xA6, 0x42, 0x07, 0x4A, 0x49, +0x63, 0x0C, 0x39, 0xE7, 0x31, 0x86, 0x5A, 0xAB, +0x6B, 0x4D, 0x6B, 0x6D, 0x94, 0xD2, 0xA5, 0x34, +0x73, 0x6E, 0x52, 0x8A, 0x42, 0x29, 0x94, 0x92, +0x8C, 0x30, 0xBD, 0x94, 0xB5, 0x31, 0xA4, 0xD0, +0xCE, 0x38, 0xAD, 0x35, 0x94, 0x92, 0xB5, 0x73, +0xCD, 0xF4, 0xC5, 0xD3, 0xBD, 0x92, 0xCD, 0xF3, +0xD6, 0x34, 0xD6, 0x55, 0xE6, 0xB6, 0xDE, 0x96, +0xDE, 0x75, 0xDE, 0x96, 0xD6, 0x15, 0xB5, 0x31, +0xAD, 0x31, 0xB5, 0x32, 0xCD, 0xF4, 0xD6, 0x35, +0xCE, 0x36, 0xBD, 0x93, 0xBD, 0x94, 0xB5, 0x52, +0xC5, 0xB3, 0xBD, 0x92, 0xBD, 0xB3, 0xBD, 0xB4, +0xC5, 0xD4, 0xBD, 0xD4, 0xB5, 0x72, 0xC5, 0xB3, +0xCD, 0xD3, 0xCD, 0x92, 0xCD, 0xB3, 0xCD, 0xB3, +0xC5, 0x93, 0x83, 0xCE, 0x42, 0x08, 0x42, 0x09, +0x42, 0x08, 0x4A, 0x49, 0x73, 0x6C, 0xA4, 0xB0, +0xBD, 0x52, 0xBD, 0x51, 0xA4, 0xF0, 0x9C, 0x8F, +0xAD, 0x32, 0xA4, 0xF2, 0x9C, 0xD1, 0x94, 0x90, +0x7B, 0xCE, 0x52, 0x69, 0x39, 0xE7, 0x39, 0xC7, +0x31, 0x87, 0x29, 0x46, 0x29, 0x46, 0x31, 0x87, +0x39, 0xA7, 0x39, 0xC7, 0x7B, 0xCE, 0x8C, 0x6F, +0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x2E, +0x8C, 0x4E, 0x9C, 0xB0, 0xA5, 0x11, 0xB5, 0x73, +0xA4, 0xF1, 0xB5, 0x52, 0xC5, 0xF4, 0xC5, 0xD4, +0xBD, 0xD4, 0xB5, 0x52, 0xB5, 0x52, 0xAD, 0x32, +0xBD, 0xB3, 0xB5, 0x71, 0xBD, 0x71, 0xAD, 0x10, +0xB5, 0x71, 0xB5, 0x72, 0xB5, 0x52, 0xC5, 0xD4, +0xCE, 0x15, 0xAD, 0x31, 0xB5, 0x71, 0xB5, 0x51, +0xC5, 0xD3, 0xBD, 0xB3, 0xA4, 0xF0, 0xBD, 0x94, +0xBD, 0x73, 0x9C, 0xB0, 0xBD, 0x94, 0xBD, 0xB4, +0xB5, 0x53, 0xAD, 0x33, 0x9C, 0xB0, 0xA4, 0xF1, +0xAD, 0x53, 0xAD, 0x52, 0xA4, 0xF1, 0x8C, 0x2F, +0x83, 0xCE, 0xA4, 0xF1, 0xAD, 0x32, 0xBD, 0x93, +0xAD, 0x32, 0x9C, 0x90, 0x9C, 0xB0, 0x94, 0x6F, +0x6B, 0x2A, 0x8C, 0x2E, 0x73, 0x6B, 0x9C, 0xB1, +0xAD, 0x53, 0x94, 0x70, 0xA4, 0xD1, 0xA4, 0xD1, +0x6B, 0x2B, 0x83, 0xCD, 0x7B, 0x8B, 0x7B, 0xAC, +0x8C, 0x0D, 0x83, 0xED, 0x83, 0xEC, 0x83, 0xCC, +0x83, 0xCC, 0x83, 0xED, 0x8C, 0x2E, 0xA4, 0xF0, +0x8C, 0x0D, 0x83, 0xCD, 0x8B, 0xED, 0x8C, 0x0D, +0x83, 0xCC, 0x83, 0xCC, 0xAC, 0xF0, 0xBD, 0x72, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, 0x94, 0x4E, +0xA4, 0xF1, 0xAD, 0x32, 0xBD, 0x73, 0xB5, 0x54, +0xC6, 0x18, 0xC5, 0xF8, 0xE7, 0x1C, 0xE7, 0x3C, +0xC6, 0x38, 0xBD, 0xD6, 0xB5, 0x54, 0xB5, 0x73, +0xB5, 0x74, 0xB5, 0x74, 0x94, 0x91, 0x52, 0x8A, +0x5A, 0xCB, 0x73, 0xAF, 0xAD, 0x54, 0xB5, 0x74, +0xBD, 0x73, 0xB5, 0x52, 0xB5, 0x53, 0xB5, 0x53, +0xB5, 0x53, 0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x73, 0xBD, 0x73, 0xB5, 0x53, 0xB5, 0x52, +0xB5, 0xD5, 0xA5, 0x55, 0x9D, 0x14, 0x94, 0xD2, +0x94, 0x70, 0x7B, 0x6B, 0x9C, 0x8F, 0xA4, 0xAF, +0xA4, 0xF0, 0xB5, 0x31, 0x8C, 0x0D, 0xA4, 0xCF, +0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x31, 0xBD, 0x72, +0xBD, 0x93, 0xC5, 0x93, 0xAC, 0xCF, 0xA4, 0x8E, +0xB5, 0x31, 0xA5, 0x11, 0x9C, 0xB0, 0x94, 0x70, +0xA4, 0xD1, 0x9C, 0xB0, 0x94, 0x8F, 0xBD, 0x93, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x52, 0xA4, 0xD0, +0x9C, 0x8F, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, +0x9C, 0xAF, 0xAD, 0x31, 0xC5, 0xD4, 0xBD, 0x93, +0xC5, 0xD4, 0xAD, 0x11, 0xA4, 0x8E, 0xAC, 0xCF, +0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xB2, +0xCD, 0xD3, 0xBD, 0x72, 0xBD, 0x51, 0xB5, 0x30, +0xA4, 0xCF, 0xA4, 0xAF, 0xAC, 0xF0, 0xBD, 0x51, +0xBD, 0x72, 0xBD, 0x52, 0xB5, 0x11, 0xA4, 0xAF, +0xB5, 0x10, 0xB5, 0x31, 0xBD, 0x51, 0xB5, 0x30, +0xBD, 0x51, 0xA4, 0x6E, 0x83, 0x8A, 0x9C, 0x4D, +0xAC, 0xD0, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xF0, +0x94, 0x0D, 0x9C, 0x4D, 0x9C, 0x4E, 0xA4, 0x6E, +0x94, 0x0D, 0xA4, 0x8F, 0x94, 0x2F, 0x52, 0x68, +0x39, 0xA6, 0x29, 0x44, 0x41, 0xE7, 0x52, 0x69, +0x5A, 0xAA, 0x52, 0x8A, 0x62, 0xEB, 0x73, 0x8D, +0x94, 0x92, 0x94, 0xB2, 0x83, 0xF0, 0xA5, 0x14, +0xA4, 0xF4, 0x8C, 0x51, 0x8C, 0x52, 0x84, 0x10, +0x4A, 0x49, 0x29, 0x25, 0x52, 0x8A, 0x5A, 0xAA, +0x73, 0x2B, 0x6B, 0x0A, 0x73, 0x2A, 0x73, 0x4B, +0x7B, 0x6B, 0x73, 0x4B, 0x6B, 0x0A, 0x7B, 0x6B, +0x94, 0x0D, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x4D, +0x94, 0x0D, 0x6B, 0x2B, 0x42, 0x07, 0x21, 0x24, +0x19, 0x04, 0x21, 0x24, 0x39, 0xE7, 0x4A, 0x48, +0x3A, 0x07, 0x29, 0x65, 0x39, 0xE7, 0x5A, 0xCB, +0x73, 0x8E, 0x8C, 0x71, 0xC6, 0x38, 0x9C, 0xD2, +0x63, 0x2D, 0x8C, 0x72, 0x73, 0x8F, 0x63, 0x0C, +0x84, 0x10, 0x8C, 0x30, 0xCD, 0xF6, 0xBD, 0x95, +0xC6, 0x18, 0xA5, 0x35, 0x94, 0x71, 0x94, 0x4F, +0x9C, 0x4E, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0x6D, +0x9C, 0x6D, 0x9C, 0x2C, 0x93, 0xEC, 0x94, 0x0D, +0xA4, 0x8E, 0xAC, 0xCF, 0xBD, 0x31, 0xAC, 0xD0, +0xA4, 0xD0, 0xB5, 0x52, 0xAD, 0x11, 0xAC, 0xF0, +0xCD, 0xF5, 0xBD, 0x73, 0xB5, 0x73, 0x9C, 0x8F, +0x9C, 0xB0, 0xB5, 0x52, 0xAD, 0x11, 0xBD, 0xB4, +0xB5, 0x73, 0xC5, 0xF5, 0xBD, 0x72, 0xDE, 0x55, +0xD5, 0xF4, 0xCD, 0xB3, 0xE6, 0x55, 0xDE, 0x55, +0xD6, 0x14, 0xB5, 0x53, 0x52, 0x69, 0x39, 0xC8, +0x39, 0xC7, 0x41, 0xE8, 0x39, 0xC8, 0x41, 0xC7, +0x5A, 0x89, 0x5A, 0x88, 0x4A, 0x07, 0x39, 0xC6, +0x39, 0x86, 0x31, 0x65, 0x29, 0x45, 0x29, 0x45, +0x29, 0x66, 0x31, 0x87, 0x29, 0x66, 0x29, 0x25, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x29, 0x26, +0x29, 0x46, 0x31, 0x86, 0x52, 0x89, 0x7B, 0xAD, +0x8C, 0x0E, 0x94, 0x4F, 0x7B, 0xCC, 0x84, 0x0D, +0xA4, 0xF1, 0xAD, 0x32, 0x8C, 0x2E, 0xBD, 0x94, +0xA4, 0xF1, 0xAD, 0x52, 0xC5, 0xF4, 0xBD, 0xD4, +0xC6, 0x15, 0xC5, 0xD4, 0xBD, 0x93, 0xB5, 0x52, +0xBD, 0xB3, 0xB5, 0x92, 0xBD, 0x92, 0xBD, 0x92, +0xC5, 0xD3, 0xC5, 0xF4, 0xCE, 0x15, 0xBD, 0x93, +0xC5, 0xF4, 0xBD, 0x93, 0xBD, 0x92, 0xBD, 0xB3, +0xB5, 0x72, 0xC5, 0xF4, 0xA4, 0xF0, 0xC5, 0xB4, +0xB5, 0x53, 0xAD, 0x11, 0xBD, 0xB4, 0xC5, 0xF5, +0xCE, 0x15, 0xC6, 0x15, 0xAD, 0x32, 0xAD, 0x52, +0xC5, 0xF5, 0xAD, 0x32, 0xBD, 0xB4, 0x94, 0x4F, +0xAD, 0x12, 0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x93, +0xBD, 0xB4, 0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x32, +0x7B, 0x8C, 0x8C, 0x2E, 0x94, 0x70, 0x94, 0x6F, +0xAD, 0x33, 0x9C, 0x90, 0x83, 0xEE, 0xB5, 0x53, +0x7B, 0xCD, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x90, +0xA4, 0xF1, 0x8C, 0x2E, 0x8C, 0x2E, 0x94, 0x8F, +0x94, 0x8F, 0x7B, 0xCD, 0x8C, 0x0E, 0x94, 0x6F, +0x9C, 0x8F, 0xA4, 0xF1, 0x94, 0x4E, 0x83, 0xED, +0x9C, 0x8F, 0x9C, 0xB0, 0xAC, 0xF0, 0xC5, 0x93, +0xA4, 0xD0, 0xBD, 0x94, 0xB5, 0x53, 0x94, 0x6F, +0xAD, 0x53, 0xB5, 0x94, 0xCE, 0x36, 0xBD, 0xD6, +0xBD, 0xD7, 0xD6, 0xBB, 0xCE, 0x7A, 0xB5, 0x56, +0xB5, 0x76, 0xEF, 0x3C, 0xCE, 0x37, 0xCE, 0x36, +0xCD, 0xF6, 0xC5, 0xD5, 0xAD, 0x53, 0x73, 0x6D, +0x63, 0x2D, 0x7B, 0xAF, 0x8C, 0x30, 0xB5, 0x94, +0x94, 0x4F, 0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xB0, +0xBD, 0x93, 0xAD, 0x12, 0xAD, 0x11, 0x9C, 0x6F, +0x8C, 0x0D, 0xB5, 0x32, 0xBD, 0x73, 0xAD, 0x11, +0x95, 0x2F, 0xA5, 0x94, 0x9D, 0x34, 0x94, 0xB2, +0x94, 0x4F, 0x83, 0xAB, 0xA4, 0x8F, 0xA4, 0xAF, +0xB5, 0x52, 0xB5, 0x32, 0x8C, 0x0D, 0x94, 0x2D, +0xB5, 0x52, 0xB5, 0x31, 0xAD, 0x11, 0xBD, 0x72, +0xC5, 0x93, 0xC5, 0x92, 0xA4, 0x6E, 0xA4, 0x8E, +0xAD, 0x31, 0xB5, 0x73, 0xAD, 0x12, 0x94, 0x70, +0x94, 0x70, 0x9C, 0x90, 0xAD, 0x32, 0xB5, 0x73, +0xB5, 0x72, 0xCD, 0xF5, 0xB5, 0x52, 0xB5, 0x32, +0xAD, 0x12, 0xA4, 0xF1, 0x9C, 0xB0, 0x9C, 0xD0, +0x9C, 0x8F, 0xB5, 0x52, 0xAD, 0x11, 0xBD, 0xB4, +0xB5, 0x72, 0xA4, 0x8F, 0xAC, 0xAE, 0xAC, 0xAE, +0xDE, 0x35, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xD2, +0xCD, 0xF3, 0xD5, 0xF3, 0xC5, 0xB2, 0xC5, 0x71, +0xC5, 0xB2, 0xD5, 0xF3, 0xCD, 0xB2, 0xD6, 0x34, +0xCD, 0xD3, 0xCD, 0xB3, 0xCD, 0xB3, 0xC5, 0x92, +0xCD, 0xD2, 0xCD, 0xB2, 0xCD, 0x92, 0xCD, 0xB2, +0xC5, 0x71, 0xBD, 0x31, 0x9C, 0x2C, 0xA4, 0x6D, +0xC5, 0x72, 0xAC, 0xCF, 0x93, 0xEB, 0xB5, 0x30, +0xBD, 0x51, 0xA4, 0x8E, 0x9C, 0x2D, 0x94, 0x0C, +0xA4, 0xCF, 0x8B, 0xED, 0x7B, 0x8C, 0x52, 0x89, +0x31, 0xA6, 0x29, 0x44, 0x42, 0x07, 0x52, 0x89, +0x4A, 0x28, 0x42, 0x07, 0x5A, 0xAA, 0x6B, 0x4C, +0x84, 0x10, 0x8C, 0x71, 0x8C, 0x31, 0x94, 0x72, +0xAD, 0x35, 0xB5, 0x97, 0xA4, 0xF4, 0x94, 0x71, +0x6B, 0x4D, 0x42, 0x08, 0x52, 0x69, 0x4A, 0x28, +0x7B, 0xAD, 0x73, 0x8D, 0x5A, 0xCA, 0x5A, 0xCA, +0x52, 0xA9, 0x52, 0x89, 0x52, 0x89, 0x7B, 0xAC, +0x8C, 0x0D, 0x8C, 0x0D, 0x6B, 0x2A, 0x5A, 0x88, +0x52, 0x68, 0x52, 0x48, 0x52, 0x89, 0x52, 0x88, +0x52, 0x48, 0x52, 0x69, 0x62, 0xEB, 0x5A, 0xCA, +0x39, 0xE7, 0x29, 0x44, 0x39, 0xC7, 0x39, 0xE7, +0x29, 0x65, 0x42, 0x28, 0x4A, 0x48, 0x52, 0x69, +0x63, 0x2C, 0x8C, 0x50, 0x8C, 0x50, 0x8C, 0x71, +0x8C, 0x51, 0x9D, 0x15, 0xA5, 0x35, 0xAD, 0x56, +0xAD, 0x35, 0xBD, 0xB6, 0xCE, 0x17, 0xC5, 0xD7, +0xC6, 0x38, 0xAD, 0x35, 0x8C, 0x71, 0x9C, 0x6F, +0xA4, 0xAF, 0x94, 0x0C, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x6D, 0x9C, 0x4D, 0x9C, 0x6D, 0xA4, 0x8E, +0xB4, 0xF0, 0xBD, 0x51, 0xBD, 0x50, 0xC5, 0x92, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, 0xB5, 0x52, +0xBD, 0x72, 0xC5, 0xD4, 0xC5, 0xD5, 0xBD, 0x94, +0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x12, +0xAC, 0xF1, 0xAD, 0x11, 0xA4, 0xD1, 0xA4, 0xF1, +0xA4, 0xD0, 0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x90, +0x9C, 0x6F, 0x8C, 0x2F, 0x62, 0xEB, 0x29, 0x46, +0x31, 0x87, 0x31, 0x87, 0x39, 0xA7, 0x29, 0x45, +0x21, 0x04, 0x21, 0x04, 0x21, 0x05, 0x21, 0x05, +0x21, 0x25, 0x29, 0x25, 0x21, 0x25, 0x20, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x29, 0x26, 0x31, 0x66, 0x42, 0x08, +0x6B, 0x2B, 0x8C, 0x2E, 0x84, 0x0D, 0x9C, 0xB0, +0xB5, 0x73, 0xAD, 0x52, 0x8C, 0x4E, 0xBD, 0xD4, +0xA4, 0xD0, 0xBD, 0xB3, 0xC5, 0xF4, 0xBD, 0xD4, +0xCE, 0x35, 0xC5, 0xF4, 0xC6, 0x15, 0xBD, 0x93, +0xC5, 0xF4, 0xBD, 0xB2, 0xC5, 0xB3, 0xC5, 0xD3, +0xCE, 0x14, 0x9C, 0xD0, 0xAD, 0x32, 0xB5, 0x53, +0xC5, 0xF4, 0xB5, 0x93, 0xB5, 0x72, 0xCE, 0x34, +0xB5, 0x72, 0xC5, 0xF4, 0xA4, 0xD0, 0xC5, 0xB5, +0xB5, 0x53, 0xA4, 0xF1, 0xC5, 0xD4, 0xCE, 0x36, +0xBD, 0xB4, 0xC5, 0xD4, 0xB5, 0x73, 0xC5, 0xF5, +0xCE, 0x16, 0xC5, 0xF5, 0xC5, 0xF5, 0xAD, 0x12, +0xBD, 0xB4, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x93, 0xAD, 0x52, 0xBD, 0x93, 0xBD, 0x94, +0x7B, 0xAD, 0x9C, 0x90, 0x9C, 0xB1, 0x9C, 0x90, +0xAD, 0x32, 0x94, 0x90, 0x52, 0x68, 0x8C, 0x2E, +0x5A, 0xC9, 0x5A, 0xC9, 0x62, 0xEA, 0x62, 0xEA, +0x94, 0x6F, 0xA4, 0xD1, 0x94, 0x8F, 0xA4, 0xD1, +0x9C, 0x90, 0x83, 0xED, 0x9C, 0xB0, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x52, 0xA4, 0xD0, 0x8C, 0x0E, +0xAD, 0x32, 0xA4, 0xD1, 0x9C, 0x6F, 0xB5, 0x52, +0xAD, 0x11, 0xB5, 0x53, 0xB5, 0x32, 0xA4, 0xF1, +0xB5, 0x94, 0xB5, 0x94, 0xC5, 0xF6, 0xCE, 0x38, +0xD6, 0x9A, 0xC6, 0x39, 0x8C, 0x72, 0xBD, 0xF8, +0xE6, 0xFC, 0xD6, 0xBA, 0xBD, 0xF7, 0x9C, 0xD2, +0x9C, 0xB1, 0xCE, 0x36, 0xC6, 0x16, 0x7B, 0xCE, +0x62, 0xEB, 0x73, 0x8E, 0x8C, 0x30, 0xBD, 0xD6, +0xAD, 0x12, 0xB5, 0x52, 0x9C, 0x8F, 0xAD, 0x11, +0xBD, 0xB4, 0xA4, 0xF1, 0xA4, 0xF0, 0xAD, 0x10, +0xA4, 0xD0, 0xD6, 0x56, 0xD6, 0x35, 0xBD, 0xB3, +0xA5, 0xB2, 0x9D, 0x54, 0x9D, 0x14, 0x94, 0xB2, +0x7B, 0xAC, 0x7B, 0x6A, 0x83, 0xAC, 0x94, 0x4E, +0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x11, 0xA4, 0xD0, +0xAD, 0x11, 0xBD, 0x72, 0xBD, 0x73, 0xC5, 0xD4, +0xBD, 0x72, 0xCD, 0xD3, 0xAC, 0xCF, 0xAC, 0xCF, +0x83, 0xAB, 0xB5, 0x52, 0xA5, 0x11, 0x8C, 0x0E, +0x94, 0x90, 0xAD, 0x12, 0xA4, 0xD1, 0x9C, 0xAF, +0xC5, 0xD4, 0xC5, 0xD4, 0xA4, 0xD0, 0xC5, 0xF5, +0xBD, 0x93, 0xAD, 0x32, 0xA4, 0xF1, 0xA4, 0xF1, +0x9C, 0xD0, 0xBD, 0x94, 0xB5, 0x73, 0xBD, 0x93, +0xC5, 0xB4, 0x94, 0x2D, 0xBD, 0x30, 0xAC, 0xCE, +0xC5, 0x92, 0xBD, 0x10, 0xCD, 0xD2, 0xCD, 0xB2, +0xCD, 0xD2, 0xD5, 0xF3, 0xD6, 0x13, 0xCD, 0xD2, +0xCD, 0xD2, 0xD5, 0xD3, 0xCD, 0xB2, 0xD6, 0x13, +0xCD, 0xB2, 0xD5, 0xF3, 0xD5, 0xF3, 0xD5, 0xF3, +0xCD, 0xB2, 0xCD, 0x92, 0xCD, 0x91, 0xCD, 0x92, +0xC5, 0x51, 0xC5, 0x30, 0xAC, 0x8E, 0xAC, 0x8D, +0xBD, 0x51, 0xB5, 0x10, 0xBD, 0x31, 0xBD, 0x51, +0x94, 0x2D, 0xBD, 0x31, 0xAC, 0xAF, 0xA4, 0x8F, +0xAC, 0xF0, 0x94, 0x4E, 0x94, 0x6F, 0x8C, 0x0E, +0x52, 0x48, 0x31, 0xA6, 0x39, 0xC6, 0x31, 0x65, +0x39, 0xC6, 0x4A, 0x48, 0x52, 0x89, 0x52, 0x89, +0x6B, 0x4D, 0x73, 0xAE, 0x94, 0x71, 0x94, 0x92, +0xA5, 0x35, 0xA4, 0xF4, 0x7B, 0x8E, 0x83, 0xCF, +0x73, 0x8E, 0x62, 0xEB, 0x4A, 0x69, 0x4A, 0x49, +0x7B, 0xAE, 0xAD, 0x13, 0x84, 0x0F, 0x73, 0x8D, +0x6B, 0x4C, 0x6B, 0x6D, 0x73, 0x6D, 0x8C, 0x4F, +0x94, 0x4E, 0x8C, 0x0D, 0x83, 0xCD, 0x7B, 0xAD, +0x73, 0xAD, 0x73, 0xAD, 0x83, 0xEE, 0x73, 0x6C, +0x6B, 0x4C, 0x73, 0x6C, 0x8C, 0x2F, 0x94, 0x90, +0x8C, 0x4F, 0x4A, 0x68, 0x31, 0xA6, 0x39, 0xE7, +0x31, 0x85, 0x39, 0xE7, 0x42, 0x07, 0x4A, 0x49, +0x5A, 0xCA, 0x5A, 0xCA, 0x6B, 0x6D, 0x7B, 0xEF, +0x94, 0xB3, 0x9C, 0xD4, 0xAD, 0x55, 0x8C, 0x52, +0x7B, 0xAF, 0x73, 0x6E, 0xA5, 0x14, 0xBD, 0xD7, +0xCE, 0x39, 0xB5, 0x96, 0x94, 0x72, 0x8C, 0x0E, +0x9C, 0x8F, 0x8B, 0xEC, 0xAD, 0x10, 0x7B, 0x8B, +0x6B, 0x29, 0x83, 0xEC, 0x8C, 0x0C, 0x8B, 0xED, +0x8B, 0xEC, 0xAC, 0xCF, 0xB5, 0x30, 0xBD, 0x52, +0xC5, 0xB4, 0x94, 0x4F, 0x94, 0x4E, 0x9C, 0xB0, +0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xD1, +0xA4, 0xD1, 0xA4, 0xB0, 0xA4, 0xD1, 0xAC, 0xF1, +0xAC, 0xF1, 0xA4, 0xF1, 0xAD, 0x32, 0xAD, 0x12, +0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x32, 0xB5, 0x33, +0xB5, 0x53, 0xAC, 0xF2, 0x83, 0xCE, 0x31, 0x66, +0x29, 0x46, 0x29, 0x66, 0x29, 0x66, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x20, 0xE5, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x25, 0x29, 0x45, +0x4A, 0x49, 0x83, 0xEE, 0x84, 0x0D, 0x8C, 0x2E, +0x94, 0x6F, 0x94, 0x6F, 0x8C, 0x0E, 0xAD, 0x32, +0x8C, 0x2E, 0xA4, 0xD1, 0xB5, 0x73, 0xA4, 0xF1, +0x94, 0x6F, 0x94, 0x6F, 0xC5, 0xF5, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD3, 0xBD, 0xB3, 0xBD, 0xB2, +0xBD, 0xB3, 0x8C, 0x2F, 0xAD, 0x74, 0xB5, 0x94, +0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0xB3, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x72, 0xA4, 0xF1, 0xC5, 0xD4, +0xA4, 0xD1, 0xA4, 0xF1, 0xB5, 0x73, 0xD6, 0x56, +0xC5, 0xD5, 0xBD, 0xB4, 0xCE, 0x36, 0xCE, 0x36, +0xC5, 0xF5, 0xCE, 0x36, 0xB5, 0x73, 0xAD, 0x11, +0xBD, 0xB4, 0xCE, 0x15, 0xBD, 0xB3, 0xCE, 0x15, +0xDE, 0x97, 0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xD5, +0x83, 0xEE, 0x9C, 0xB0, 0x9C, 0x90, 0xA4, 0xD1, +0xAD, 0x32, 0x8C, 0x2E, 0x5A, 0xC9, 0xAD, 0x33, +0xA4, 0xF1, 0x52, 0x89, 0x4A, 0x48, 0x73, 0x8D, +0x9C, 0xB0, 0x9C, 0xD1, 0xA4, 0xF1, 0x94, 0x8F, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, 0xCE, 0x15, +0xB5, 0x53, 0xCE, 0x36, 0xBD, 0x94, 0xA4, 0xD1, +0xBD, 0xB4, 0x6B, 0x2B, 0x4A, 0x27, 0x6B, 0x2B, +0x9C, 0xB0, 0xB5, 0x32, 0xAD, 0x12, 0xA4, 0xF1, +0xBD, 0xD4, 0x9C, 0xB1, 0x73, 0x8E, 0xA5, 0x14, +0xCE, 0x3A, 0xCE, 0x7A, 0xCE, 0x7A, 0xDE, 0xDB, +0xCE, 0x7A, 0x8C, 0x31, 0xAD, 0x35, 0xB5, 0x96, +0xBD, 0xD6, 0xCE, 0x37, 0xB5, 0x74, 0x73, 0x8D, +0x4A, 0x49, 0x52, 0x8A, 0x7B, 0xCF, 0x94, 0x91, +0xAD, 0x12, 0xAD, 0x32, 0x9C, 0xB0, 0xB5, 0x53, +0xC5, 0xD4, 0xCE, 0x35, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xF4, 0xD6, 0x76, 0xCE, 0x55, 0xBD, 0xB3, +0xA5, 0x93, 0xA5, 0x54, 0x9C, 0xF3, 0x94, 0x71, +0x62, 0xC9, 0x6A, 0xE9, 0x73, 0x2A, 0x7B, 0x6B, +0x8B, 0xCB, 0x94, 0x2C, 0x94, 0x2D, 0x9C, 0x4E, +0xA4, 0x8E, 0xA4, 0xCF, 0x9C, 0x4D, 0xAC, 0xCF, +0x9C, 0x6E, 0xAC, 0xCF, 0xB4, 0xEF, 0xB5, 0x10, +0x94, 0x2D, 0x94, 0x4E, 0x9C, 0xB0, 0x84, 0x0E, +0x8C, 0x2E, 0x9C, 0xB0, 0x9C, 0xB0, 0xBD, 0xD4, +0xD6, 0x56, 0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0xB3, +0xBD, 0xD4, 0xBD, 0xB3, 0xAD, 0x32, 0xAD, 0x11, +0xAD, 0x32, 0xBD, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xB4, 0x73, 0x2A, 0xAC, 0xCF, 0xA4, 0x6D, +0xC5, 0x70, 0xB5, 0x0F, 0xCD, 0x92, 0xAC, 0x8E, +0xAC, 0x8E, 0xB5, 0x0F, 0xBD, 0x30, 0xCD, 0xB2, +0xCD, 0xB2, 0xCD, 0x92, 0xC5, 0x71, 0xCD, 0x92, +0xC5, 0x71, 0xC5, 0x51, 0xBD, 0x30, 0xBD, 0x30, +0xC5, 0x71, 0xC5, 0x30, 0xC5, 0x30, 0xBD, 0x10, +0xC5, 0x30, 0xBD, 0x10, 0xBC, 0xEF, 0xAC, 0xAE, +0x94, 0x0C, 0xC5, 0x91, 0xCD, 0xD3, 0xBD, 0x71, +0xBD, 0x31, 0xCD, 0xB2, 0xBD, 0x51, 0xBD, 0x51, +0xB5, 0x11, 0xB5, 0x11, 0xAD, 0x10, 0xC5, 0xB3, +0x8B, 0xEE, 0x52, 0x48, 0x41, 0xE7, 0x31, 0xA5, +0x39, 0xC6, 0x39, 0xC6, 0x41, 0xE7, 0x52, 0x69, +0x62, 0xEB, 0x7B, 0xEF, 0x84, 0x30, 0x8C, 0x71, +0x8C, 0x31, 0xAD, 0x14, 0x94, 0x51, 0x73, 0x6D, +0x73, 0x6D, 0x63, 0x0C, 0x4A, 0x49, 0x39, 0xE7, +0x7B, 0x8D, 0xAD, 0x33, 0xAD, 0x34, 0x7B, 0xCE, +0x73, 0xAE, 0x7B, 0xCE, 0x6B, 0x6D, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0xB0, 0x94, 0x90, 0x94, 0x70, +0x8C, 0x70, 0x8C, 0x4F, 0x83, 0xCE, 0x7B, 0xCE, +0x7B, 0xCE, 0x73, 0x8C, 0x73, 0x8C, 0x7B, 0xCD, +0x7B, 0xEE, 0x63, 0x2B, 0x63, 0x0B, 0x42, 0x07, +0x42, 0x07, 0x4A, 0x28, 0x42, 0x07, 0x42, 0x28, +0x52, 0xAA, 0x5A, 0xEB, 0x63, 0x0C, 0x8C, 0x71, +0x94, 0xB3, 0x94, 0x92, 0x73, 0xAF, 0x63, 0x0C, +0x84, 0x10, 0x52, 0x6A, 0x63, 0x0D, 0xB5, 0xB7, +0xD6, 0xBB, 0xCE, 0x59, 0xC6, 0x18, 0xBD, 0x95, +0x83, 0xED, 0x9C, 0xB0, 0xAD, 0x52, 0xA4, 0xD1, +0x8C, 0x4E, 0x94, 0x4E, 0x94, 0x6E, 0x8C, 0x2E, +0x8C, 0x0E, 0x83, 0xED, 0xAD, 0x31, 0xB5, 0x52, +0xB5, 0x32, 0x94, 0x2E, 0x8C, 0x0D, 0xA4, 0xF1, +0x8C, 0x2E, 0x83, 0xED, 0x83, 0xED, 0x94, 0x4E, +0x9C, 0x8F, 0x8C, 0x2E, 0x9C, 0x6F, 0x94, 0x4E, +0x8C, 0x2E, 0x7B, 0x8C, 0x83, 0xAD, 0x83, 0xCC, +0x7B, 0xAC, 0x7B, 0xAC, 0x83, 0xAC, 0x83, 0xED, +0x94, 0x6F, 0x8C, 0x0E, 0x83, 0xEE, 0x52, 0x69, +0x21, 0x25, 0x29, 0x46, 0x29, 0x46, 0x29, 0x25, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x4A, 0x49, 0x6B, 0x4D, +0x41, 0xE8, 0x5A, 0xAA, 0x84, 0x0E, 0x7B, 0x8C, +0x5A, 0x89, 0x52, 0x68, 0x62, 0xEA, 0x83, 0xED, +0xA4, 0xD1, 0xAD, 0x53, 0xAD, 0x54, 0xB5, 0x74, +0xB5, 0x74, 0xAD, 0x33, 0xA4, 0xF1, 0xA4, 0xB0, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0xAF, 0xA4, 0xB0, +0xA4, 0xF0, 0x9C, 0x90, 0x9C, 0xD1, 0xA5, 0x11, +0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x11, 0xAD, 0x11, +0x9C, 0xB0, 0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x8F, +0x8C, 0x2E, 0x7B, 0x8C, 0x6B, 0x4B, 0x84, 0x0E, +0xAD, 0x12, 0xBD, 0x73, 0xD6, 0x36, 0xCD, 0xF5, +0xC5, 0xD4, 0xCE, 0x15, 0xC5, 0xB4, 0xB5, 0x73, +0xC5, 0xD4, 0xCE, 0x15, 0xB5, 0x72, 0xBD, 0xB3, +0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x35, 0xAD, 0x11, +0x7B, 0x8C, 0x94, 0x6F, 0x94, 0x6F, 0x9C, 0xB0, +0xAD, 0x12, 0x83, 0xCD, 0x9C, 0xD1, 0xC5, 0xF5, +0xC5, 0xD4, 0xBD, 0xB4, 0xAD, 0x32, 0xAD, 0x12, +0xA4, 0xD1, 0x94, 0x4F, 0xA4, 0xD1, 0x8C, 0x2E, +0x94, 0x4F, 0x9C, 0x8F, 0xAD, 0x11, 0xBD, 0x73, +0xBD, 0x73, 0xC5, 0xB4, 0xB5, 0x73, 0xAD, 0x32, +0xB5, 0x53, 0x52, 0x69, 0x4A, 0x69, 0x6B, 0x2B, +0x9C, 0xB1, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x53, +0xB5, 0x73, 0x9C, 0xB1, 0x4A, 0x49, 0x73, 0x8E, +0xA5, 0x35, 0xB5, 0x76, 0xBD, 0xB8, 0xD6, 0x7B, +0xDE, 0xDC, 0xDE, 0xDC, 0xD6, 0x9A, 0xBD, 0xD7, +0xBD, 0xD6, 0xCE, 0x57, 0xCE, 0x56, 0x8C, 0x4F, +0x52, 0x8A, 0x63, 0x2C, 0x7B, 0xCF, 0x7B, 0xCF, +0x8C, 0x2F, 0xB5, 0x52, 0xA4, 0xB0, 0xB5, 0x53, +0xBD, 0xB4, 0xCE, 0x35, 0xCE, 0x15, 0xAD, 0x31, +0xAD, 0x31, 0xC5, 0xF4, 0xCE, 0x55, 0xBD, 0xD4, +0xAD, 0xD5, 0xAE, 0x16, 0xB6, 0x16, 0xB5, 0xF6, +0x9D, 0x12, 0x7B, 0x8C, 0x7B, 0x4B, 0x83, 0xCC, +0x8B, 0xCB, 0x83, 0xAB, 0x94, 0x0C, 0x93, 0xEC, +0x9C, 0x2D, 0x9C, 0x4D, 0xA4, 0x8E, 0xA4, 0x8E, +0xAC, 0xCF, 0xB4, 0xF0, 0xBD, 0x30, 0xBD, 0x51, +0xBD, 0x30, 0xB5, 0x10, 0xAC, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xCF, +0xA4, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xCF, +0xAC, 0xF0, 0xA4, 0xD0, 0x9C, 0xAF, 0x9C, 0x8F, +0xA4, 0xF0, 0xB5, 0x52, 0xBD, 0x93, 0xB5, 0x52, +0x94, 0x4E, 0x9C, 0x4D, 0xB5, 0x10, 0xAC, 0x8D, +0x94, 0x0C, 0x9C, 0x4C, 0xB4, 0xCF, 0xAC, 0xAE, +0xB4, 0xCE, 0xB4, 0xCE, 0xAC, 0x8E, 0xB4, 0xEF, +0xC5, 0x71, 0xAC, 0xAE, 0x9C, 0x0C, 0xAC, 0x8E, +0x9C, 0x4D, 0xB4, 0xEF, 0xC5, 0x71, 0xAC, 0x8E, +0xC5, 0x31, 0xAC, 0x8E, 0xAC, 0x6D, 0xAC, 0x6D, +0xB4, 0xCF, 0x93, 0xAB, 0xAC, 0x8E, 0xB4, 0xCF, +0x83, 0x8A, 0x83, 0xCB, 0xBD, 0x72, 0xD5, 0xF3, +0xD5, 0xF4, 0xC5, 0x71, 0xBD, 0x51, 0xC5, 0x92, +0xB5, 0x11, 0xB5, 0x31, 0xC5, 0x92, 0xC5, 0xB4, +0xCD, 0xD5, 0x83, 0xCD, 0x31, 0x85, 0x31, 0x65, +0x39, 0xC6, 0x39, 0xC6, 0x42, 0x07, 0x4A, 0x48, +0x52, 0x8A, 0x5A, 0xCB, 0x7B, 0xEF, 0x83, 0xEF, +0x83, 0xEF, 0x9C, 0x71, 0x8B, 0xEF, 0x83, 0xEF, +0x6B, 0x2D, 0x6B, 0x4D, 0x4A, 0x69, 0x31, 0xA6, +0x5A, 0xAA, 0x8C, 0x30, 0xB5, 0x74, 0x84, 0x2F, +0x7B, 0xEE, 0x7B, 0xCF, 0x63, 0x0B, 0x9C, 0x90, +0x94, 0x6F, 0xB5, 0x52, 0xAD, 0x12, 0x9C, 0xB1, +0x9C, 0xB0, 0x9C, 0xD1, 0x94, 0x70, 0x9C, 0xB1, +0x94, 0x90, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x84, 0x0E, 0x83, 0xEE, 0x84, 0x0F, 0x73, 0xAE, +0x5A, 0xAA, 0x42, 0x07, 0x42, 0x28, 0x42, 0x07, +0x52, 0x89, 0x5A, 0xCA, 0x4A, 0x69, 0x6B, 0x6D, +0x7B, 0xCF, 0x7B, 0xAF, 0x52, 0x8A, 0x4A, 0x29, +0x5A, 0xCB, 0x6B, 0x4D, 0x94, 0xB3, 0xC6, 0x19, +0xC6, 0x39, 0x7B, 0xF0, 0x9C, 0xB2, 0xB5, 0x33, +0x83, 0xCD, 0x9C, 0xB0, 0xA5, 0x11, 0xAD, 0x32, +0x8C, 0x2E, 0x8C, 0x2E, 0xA4, 0xD0, 0x94, 0x4E, +0x94, 0x4F, 0x83, 0xCD, 0xB5, 0x73, 0xBD, 0x73, +0xB5, 0x52, 0x7B, 0x6B, 0x8C, 0x2E, 0xB5, 0x52, +0xAD, 0x31, 0x9C, 0x8F, 0x8C, 0x4D, 0xAD, 0x10, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x52, 0xBD, 0xB3, +0xB5, 0x52, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x90, +0xB5, 0x53, 0x9C, 0x6F, 0xB5, 0x32, 0x9C, 0xB0, +0xA4, 0xD0, 0x9C, 0x90, 0x73, 0x6C, 0x7B, 0xAE, +0x21, 0x05, 0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xA3, 0x18, 0xA3, 0x21, 0x05, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC3, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, +0x20, 0xE5, 0x18, 0xC4, 0x62, 0xEC, 0xB5, 0x55, +0x94, 0x71, 0x4A, 0x29, 0x31, 0x86, 0x31, 0x66, +0x29, 0x46, 0x29, 0x25, 0x29, 0x25, 0x31, 0x66, +0x5A, 0xA9, 0x7B, 0xAE, 0x94, 0x71, 0xA4, 0xF2, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x32, 0xB5, 0x53, +0xBD, 0x94, 0xC5, 0xD4, 0xC5, 0x94, 0xC5, 0xB4, +0xCD, 0xF5, 0xCE, 0x16, 0xCD, 0xF5, 0xBD, 0xB4, +0xBD, 0x94, 0x9C, 0xD1, 0xA4, 0xD1, 0x9C, 0xB0, +0x8C, 0x0E, 0x7B, 0xAD, 0x83, 0xED, 0x83, 0xCD, +0xA4, 0xD0, 0xA4, 0xD1, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0x90, 0x94, 0x4F, 0x8C, 0x2E, 0x8C, 0x0E, +0x83, 0xED, 0x83, 0xED, 0x8B, 0xEE, 0x7B, 0xAD, +0x83, 0xED, 0x8C, 0x2E, 0x8C, 0x0E, 0x94, 0x4E, +0xA4, 0xD0, 0xA4, 0xF1, 0x9C, 0x90, 0x8C, 0x2E, +0x8C, 0x2E, 0x94, 0x4F, 0x8C, 0x2E, 0x94, 0x6F, +0x94, 0x90, 0x73, 0x4B, 0xAD, 0x12, 0xAD, 0x11, +0xB5, 0x52, 0xB5, 0x72, 0xAD, 0x32, 0x9C, 0xB0, +0x94, 0x6F, 0x8C, 0x2E, 0x7B, 0xAC, 0x83, 0xED, +0x94, 0x4E, 0x9C, 0xB0, 0xB5, 0x52, 0xC5, 0xB3, +0xC5, 0xB4, 0xC5, 0xB4, 0xB5, 0x52, 0xA4, 0xD0, +0xA4, 0xD0, 0x6B, 0x2B, 0x73, 0x6C, 0x83, 0xCE, +0xA4, 0xD1, 0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x93, +0xC6, 0x15, 0xCE, 0x77, 0xA5, 0x33, 0x63, 0x2C, +0x84, 0x10, 0xAD, 0x56, 0xA4, 0xF5, 0xC6, 0x19, +0xDE, 0xDC, 0xA4, 0xF4, 0x9C, 0xB3, 0x9C, 0xB3, +0x9C, 0x92, 0xC5, 0xD6, 0xCE, 0x36, 0x7B, 0xAD, +0x4A, 0x69, 0x5A, 0xCB, 0x73, 0x8D, 0x6B, 0x4C, +0x8C, 0x2F, 0xB5, 0x32, 0xA4, 0xF1, 0xB5, 0x73, +0xB5, 0x73, 0xC5, 0xF4, 0xCE, 0x15, 0xBD, 0xB3, +0xBD, 0xB3, 0xCE, 0x35, 0xD6, 0x55, 0xBD, 0xD4, +0xB6, 0x55, 0xBE, 0xD8, 0xC6, 0xF8, 0xCE, 0xF8, +0xC6, 0xB8, 0xB5, 0xD5, 0x83, 0xED, 0x6B, 0x29, +0x6B, 0x2A, 0x73, 0x4A, 0x7B, 0x8B, 0x6B, 0x09, +0x73, 0x2A, 0x83, 0xCC, 0x7B, 0x6A, 0x73, 0x4A, +0x62, 0xC8, 0x5A, 0x87, 0x6A, 0xE9, 0x73, 0x4A, +0x8B, 0xEC, 0x93, 0xEC, 0x8B, 0xEC, 0x9C, 0x4E, +0x9C, 0x4E, 0xA4, 0x8F, 0xAC, 0xAF, 0xAC, 0xAF, +0xB5, 0x10, 0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xCF, +0xAC, 0xCF, 0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xCF, +0xAC, 0xAF, 0xA4, 0x8F, 0xA4, 0x8E, 0xA4, 0x8E, +0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x0F, 0xAC, 0xCE, +0xAC, 0xCF, 0xAC, 0xAE, 0xA4, 0x6D, 0xA4, 0x4D, +0x9C, 0x0C, 0x93, 0xEB, 0x93, 0xCB, 0x94, 0x0C, +0x9C, 0x2C, 0xA4, 0x4D, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x2C, 0xA4, 0x4D, 0xA4, 0x6D, 0xA4, 0x4C, +0xA4, 0x6D, 0x9B, 0xEB, 0xAC, 0x8D, 0xAC, 0xAE, +0xB4, 0xAE, 0xA4, 0x4D, 0xA4, 0x2C, 0xBD, 0x0F, +0xB4, 0xCF, 0x7B, 0x4A, 0x73, 0x09, 0x83, 0x8A, +0x94, 0x0C, 0x8B, 0xCB, 0x9C, 0x2D, 0xAC, 0xAF, +0xA4, 0xAF, 0xC5, 0x93, 0xB5, 0x31, 0xC5, 0xD3, +0xCE, 0x14, 0xA4, 0xD0, 0x63, 0x0A, 0x31, 0xA5, +0x39, 0xA6, 0x39, 0xC6, 0x42, 0x07, 0x41, 0xE7, +0x39, 0xC7, 0x52, 0x8A, 0x6B, 0x4D, 0x5A, 0xCB, +0x4A, 0x28, 0x4A, 0x08, 0x41, 0xC7, 0x5A, 0xCB, +0x4A, 0x49, 0x63, 0x0C, 0x52, 0x6A, 0x29, 0x65, +0x31, 0x66, 0x7B, 0xAE, 0x8C, 0x0F, 0x84, 0x0F, +0x7B, 0xEF, 0x73, 0xAE, 0x63, 0x0B, 0xA4, 0xF2, +0x94, 0x4E, 0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x93, +0xB5, 0x32, 0xAD, 0x11, 0xAD, 0x12, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x11, 0xB5, 0x73, 0xB5, 0x32, +0xA4, 0xD1, 0xA5, 0x11, 0x9C, 0x90, 0x9C, 0xB0, +0x7B, 0x8D, 0x73, 0x8D, 0x39, 0xA6, 0x39, 0xE6, +0x42, 0x27, 0x42, 0x28, 0x4A, 0x68, 0x63, 0x0B, +0x5A, 0xCA, 0x63, 0x0B, 0x52, 0x69, 0x41, 0xE8, +0x42, 0x08, 0x8C, 0x51, 0xA4, 0xF4, 0xC6, 0x19, +0x9C, 0xB4, 0x5A, 0xAC, 0xA5, 0x14, 0xB5, 0x75, +0xC5, 0xB5, 0xA4, 0xB1, 0x94, 0x4F, 0xAD, 0x12, +0x94, 0x2E, 0x8C, 0x2E, 0x9C, 0x90, 0x94, 0x4E, +0x94, 0x6F, 0x7B, 0xAC, 0x94, 0x6F, 0xB5, 0x72, +0xB5, 0x52, 0x6B, 0x0A, 0x8C, 0x2E, 0xA4, 0xD0, +0x94, 0x6F, 0x94, 0x2E, 0x94, 0x6F, 0x94, 0x6E, +0xA4, 0xAF, 0xAC, 0xF1, 0x9C, 0xAF, 0x9C, 0x8F, +0x9C, 0x8F, 0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xD0, +0xB5, 0x73, 0x94, 0x4F, 0x9C, 0x90, 0xAC, 0xF1, +0xB5, 0x72, 0xA4, 0xF1, 0x7B, 0xAD, 0x8C, 0x30, +0x21, 0x04, 0x18, 0xE4, 0x20, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x10, 0x83, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xA4, +0x18, 0xC4, 0x18, 0xC3, 0x18, 0xC4, 0x18, 0xC3, +0x10, 0xA4, 0x10, 0xA3, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xA4, 0x10, 0xA3, 0x29, 0x45, +0x42, 0x08, 0x21, 0x05, 0x21, 0x05, 0x21, 0x04, +0x20, 0xE4, 0x18, 0xC4, 0x18, 0xC3, 0x20, 0xE4, +0x29, 0x45, 0x31, 0x87, 0x42, 0x08, 0x52, 0x8A, +0x7B, 0xAE, 0x94, 0x50, 0x9C, 0xB1, 0x83, 0xEE, +0x8B, 0xEE, 0x83, 0xEE, 0x7B, 0xAD, 0x7B, 0xAD, +0x73, 0x8D, 0x83, 0xEE, 0x94, 0x50, 0x94, 0x90, +0x94, 0x50, 0x7B, 0xCE, 0x73, 0x6D, 0x6B, 0x4D, +0x63, 0x0C, 0x5A, 0xCB, 0x5A, 0xAA, 0x62, 0xEB, +0x7B, 0x8D, 0x73, 0x4C, 0x7B, 0x6C, 0x94, 0x2F, +0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x33, 0xB5, 0x33, +0xB5, 0x33, 0xB5, 0x33, 0xAD, 0x32, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x32, 0xA4, 0xF1, +0xA4, 0xD1, 0xB5, 0x73, 0xBD, 0x73, 0xBD, 0x94, +0xBD, 0x94, 0xC5, 0xB4, 0xB5, 0x32, 0xBD, 0x94, +0xA4, 0xD1, 0x83, 0xEE, 0x8C, 0x0E, 0x83, 0xED, +0x83, 0xED, 0x8C, 0x0E, 0x8C, 0x0E, 0x83, 0xEE, +0x8B, 0xEE, 0x94, 0x6F, 0xA4, 0xB1, 0x94, 0x6F, +0x8C, 0x0E, 0x7B, 0xCC, 0x83, 0xAC, 0x83, 0xCD, +0x94, 0x0F, 0x9C, 0x6F, 0x94, 0x4F, 0x94, 0x4F, +0x83, 0xED, 0x94, 0x4F, 0x7B, 0x8C, 0x7B, 0x8C, +0xAD, 0x32, 0xA4, 0xF1, 0xB5, 0x52, 0xBD, 0xD4, +0xBD, 0xB4, 0xBD, 0xD4, 0xC6, 0x15, 0x8C, 0x4F, +0x6B, 0x4D, 0x84, 0x31, 0x83, 0xF0, 0xBD, 0xF8, +0xA4, 0xF4, 0x7B, 0xAF, 0xA4, 0xD3, 0xBD, 0x76, +0x7B, 0x8E, 0xC6, 0x17, 0xCE, 0x78, 0x63, 0x2C, +0x5A, 0xCA, 0x63, 0x0C, 0x63, 0x0B, 0x52, 0xAA, +0x5A, 0xAA, 0x8C, 0x2F, 0x94, 0x4E, 0xAD, 0x32, +0xAD, 0x11, 0xC5, 0xF4, 0xC5, 0xF4, 0xA4, 0xD0, +0xA4, 0xF0, 0xCE, 0x14, 0xD6, 0x55, 0xC5, 0xF4, +0xA5, 0xF1, 0xA5, 0xB4, 0x95, 0x32, 0x84, 0x50, +0x3A, 0x07, 0x5A, 0xC9, 0x6B, 0x29, 0x73, 0x6A, +0x83, 0xCC, 0x94, 0x4E, 0x94, 0x6E, 0x8C, 0x2D, +0x8C, 0x0D, 0x9C, 0x8F, 0xA4, 0xD0, 0x9C, 0x8F, +0x94, 0x6F, 0x7B, 0x8C, 0x7B, 0xAC, 0x73, 0x4B, +0x7B, 0xAB, 0x83, 0xAB, 0x83, 0xCC, 0x94, 0x0D, +0x8B, 0xCC, 0x83, 0xAB, 0xA4, 0x8F, 0x9C, 0x2D, +0x9C, 0x4D, 0xA4, 0x6D, 0x9C, 0x4D, 0x83, 0xAB, +0x7B, 0x6A, 0x94, 0x0C, 0x83, 0xCB, 0x73, 0x2A, +0x73, 0x29, 0x83, 0xCB, 0x94, 0x0D, 0x9C, 0x2D, +0x8B, 0xCC, 0x9C, 0x4D, 0xB4, 0xEF, 0xB5, 0x10, +0xAC, 0xAE, 0xA4, 0x8E, 0xAC, 0xAE, 0xA4, 0x4D, +0xAC, 0x8E, 0xAC, 0xCF, 0xB4, 0xF0, 0x8B, 0xEC, +0x93, 0xEC, 0x9C, 0x2D, 0x9C, 0x2C, 0xAC, 0xAF, +0xAC, 0xCF, 0xAC, 0xAE, 0xAC, 0xCF, 0xAC, 0x8E, +0xAC, 0x8E, 0xAC, 0x8E, 0xA4, 0x8E, 0xAC, 0x8E, +0xAC, 0x8E, 0xAC, 0xAE, 0xB4, 0xCF, 0xBD, 0x30, +0xBD, 0x10, 0xB4, 0xF0, 0xB4, 0xF0, 0x9C, 0x4E, +0x94, 0x2D, 0x94, 0x2D, 0x8B, 0xEC, 0x8B, 0xEC, +0x94, 0x0D, 0xA4, 0x6E, 0xAC, 0xAE, 0x94, 0x0C, +0x9C, 0x4D, 0xA4, 0x8F, 0x94, 0x2E, 0x4A, 0x28, +0x39, 0xA6, 0x39, 0xC6, 0x39, 0xA6, 0x39, 0xC6, +0x4A, 0x28, 0x52, 0x69, 0x52, 0x8A, 0x42, 0x08, +0x39, 0xC7, 0x39, 0xC7, 0x31, 0x86, 0x39, 0xA6, +0x31, 0x86, 0x6B, 0x2D, 0x5A, 0xCB, 0x42, 0x08, +0x4A, 0x28, 0xAD, 0x34, 0xA4, 0xD2, 0x9C, 0xB1, +0x9C, 0xB1, 0x94, 0x71, 0x8C, 0x4F, 0xB5, 0x53, +0x94, 0x2D, 0xAD, 0x11, 0xBD, 0x52, 0xC5, 0xB3, +0xC5, 0xB3, 0xC5, 0x92, 0xBD, 0x51, 0xBD, 0x52, +0xBD, 0x52, 0xBD, 0x51, 0xB5, 0x11, 0xAC, 0xF1, +0xA4, 0xAF, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xA4, 0xD0, 0xAD, 0x11, 0x6B, 0x2A, 0x39, 0xA5, +0x39, 0xC6, 0x39, 0xE6, 0x4A, 0x48, 0x42, 0x07, +0x41, 0xE7, 0x52, 0x69, 0x4A, 0x48, 0x31, 0xA6, +0x4A, 0x69, 0x84, 0x10, 0x9C, 0xD4, 0xC6, 0x39, +0xA5, 0x35, 0x7B, 0xD0, 0xBD, 0xD7, 0xAD, 0x55, +0xC5, 0xB6, 0xCD, 0xB5, 0xB5, 0x33, 0x8C, 0x0E, +0xA4, 0xF1, 0xBD, 0xF6, 0xB5, 0x53, 0x94, 0x70, +0xA4, 0xF1, 0x7B, 0xAC, 0x8C, 0x0D, 0xB5, 0x52, +0xAD, 0x12, 0x5A, 0xA9, 0x9C, 0x6F, 0xAC, 0xF0, +0x9C, 0xAF, 0x9C, 0x8F, 0x94, 0x6E, 0x9C, 0x6F, +0xA4, 0xF0, 0xAD, 0x10, 0xA4, 0xD0, 0x9C, 0xAF, +0x94, 0x6E, 0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x4E, +0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x0D, 0xA4, 0xF0, +0x94, 0x4E, 0x8C, 0x2E, 0x7B, 0xCD, 0x94, 0x91, +0x29, 0x66, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xA4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x20, 0xE4, 0x20, 0xE5, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x21, 0x04, 0x29, 0x25, 0x29, 0x66, 0x29, 0x66, +0x39, 0xC7, 0x52, 0x6A, 0x6B, 0x4D, 0x7B, 0xAE, +0x9C, 0xB2, 0xA4, 0xF2, 0x8C, 0x2F, 0x8C, 0x50, +0x7B, 0xCE, 0x7B, 0xAE, 0x73, 0x8D, 0x6B, 0x2C, +0x63, 0x0C, 0x5A, 0xAB, 0x52, 0x6A, 0x52, 0x6A, +0x52, 0x6A, 0x5A, 0x8B, 0x5A, 0xAB, 0x5A, 0x8B, +0x5A, 0xAB, 0x5A, 0xAA, 0x5A, 0xCB, 0x73, 0x6D, +0x8C, 0x2F, 0x8C, 0x0E, 0x94, 0x2F, 0x9C, 0xB0, +0x94, 0x70, 0x94, 0x2F, 0x83, 0xED, 0x8C, 0x2E, +0xA4, 0xD1, 0x9C, 0x70, 0x94, 0x4F, 0x9C, 0x90, +0x9C, 0x70, 0xAD, 0x11, 0xBD, 0x72, 0xBD, 0x73, +0xB5, 0x11, 0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x94, +0xB5, 0x53, 0xA4, 0xD1, 0x9C, 0xB0, 0xA4, 0xF1, +0xBD, 0x94, 0xBD, 0x73, 0xC5, 0xD5, 0xCD, 0xF6, +0xCE, 0x16, 0xCE, 0x16, 0xD6, 0x57, 0xC5, 0xD5, +0xC5, 0xD5, 0xBD, 0x94, 0xC5, 0xD5, 0xC5, 0xD5, +0xC5, 0xD4, 0xC5, 0xB4, 0xC5, 0xD5, 0xC5, 0xD5, +0xC5, 0xD4, 0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x32, 0xAC, 0xF1, 0xA4, 0xB0, +0x94, 0x6F, 0xA4, 0xB0, 0x9C, 0xB0, 0x94, 0x70, +0x7B, 0xAD, 0x6B, 0x4D, 0x8C, 0x51, 0xBD, 0xF7, +0x84, 0x10, 0xAD, 0x35, 0x8C, 0x51, 0xBD, 0x96, +0x94, 0x51, 0xCE, 0x59, 0xD6, 0xBA, 0x73, 0xAF, +0x4A, 0x49, 0x5A, 0xCA, 0x52, 0xAA, 0x5A, 0xEB, +0x6B, 0x2C, 0xAD, 0x13, 0x8C, 0x2E, 0x9C, 0xB0, +0xB5, 0x73, 0xB5, 0x93, 0xB5, 0x72, 0x9C, 0x8F, +0x94, 0x4E, 0xC5, 0xD4, 0xC5, 0xF4, 0xC5, 0xD4, +0x9D, 0xD0, 0x9D, 0x72, 0x9D, 0x73, 0x84, 0x50, +0x7C, 0x2F, 0x94, 0xD0, 0x6B, 0x4A, 0x83, 0xCC, +0x94, 0x6F, 0x94, 0x6F, 0x9C, 0x8F, 0x83, 0xED, +0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xF0, 0xA4, 0xD0, +0x9C, 0xAF, 0x9C, 0x8F, 0x9C, 0xAF, 0x94, 0x2E, +0x94, 0x6E, 0x94, 0x4E, 0xA4, 0xD0, 0x9C, 0x6F, +0x94, 0x6F, 0x83, 0xCC, 0xA4, 0xCF, 0xA4, 0xAF, +0x9C, 0x8E, 0xAD, 0x10, 0xAC, 0xF0, 0xAD, 0x11, +0x9C, 0x8F, 0x94, 0x4E, 0x9C, 0xB0, 0x94, 0x6F, +0x73, 0x6B, 0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x0D, +0x7B, 0x6B, 0x73, 0x29, 0x83, 0x6A, 0x83, 0x6A, +0x83, 0x8A, 0x83, 0x8A, 0x83, 0xAB, 0x9C, 0x6E, +0x83, 0x8B, 0x8B, 0xEC, 0xB5, 0x10, 0x9C, 0x8E, +0x9C, 0xD0, 0xA4, 0xD0, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xF0, 0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xCF, +0x9C, 0x8E, 0x9C, 0x4D, 0xA4, 0x8E, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x4E, 0x8B, 0xEC, 0x94, 0x0C, +0x8B, 0xCB, 0x8B, 0xCB, 0x8B, 0xCC, 0x8B, 0xCB, +0x9C, 0x4D, 0xAC, 0xEF, 0xC5, 0x92, 0xCD, 0xB3, +0xC5, 0x71, 0xB4, 0xF0, 0xBD, 0x10, 0xAC, 0xCF, +0xB4, 0xEF, 0xB5, 0x10, 0xAC, 0xD0, 0x73, 0x4B, +0x31, 0x85, 0x41, 0xE7, 0x41, 0xE7, 0x42, 0x08, +0x4A, 0x48, 0x42, 0x08, 0x4A, 0x48, 0x39, 0xA6, +0x29, 0x44, 0x29, 0x24, 0x31, 0x65, 0x4A, 0x28, +0x6B, 0x4D, 0x94, 0x72, 0x73, 0x8E, 0x52, 0x8A, +0x7B, 0x8D, 0x73, 0x4C, 0x62, 0xCA, 0x6B, 0x2B, +0x84, 0x0F, 0x9C, 0x90, 0xB5, 0x52, 0xC5, 0x93, +0xA4, 0x8E, 0x9C, 0x6E, 0x9C, 0x4E, 0x9C, 0x6E, +0xAC, 0xCF, 0xBD, 0x30, 0xC5, 0x71, 0xCD, 0xD2, +0xCD, 0x92, 0xC5, 0x51, 0xBD, 0x50, 0xBD, 0x51, +0xCD, 0xB2, 0xCD, 0xB3, 0xC5, 0x72, 0xAC, 0xF0, +0xAD, 0x11, 0xB5, 0x51, 0xAC, 0xF0, 0x6A, 0xE9, +0x29, 0x64, 0x31, 0xA5, 0x42, 0x07, 0x39, 0xA5, +0x39, 0xA6, 0x42, 0x07, 0x42, 0x07, 0x39, 0xC7, +0x5A, 0xAA, 0x73, 0xAE, 0x94, 0xB3, 0xC6, 0x19, +0x94, 0x93, 0x84, 0x10, 0xBD, 0xF8, 0xAD, 0x56, +0xAD, 0x35, 0xA4, 0xD3, 0xD6, 0x38, 0x9C, 0x50, +0x52, 0x8A, 0x8C, 0x51, 0xB5, 0x95, 0x8C, 0x4F, +0xB5, 0x53, 0x8C, 0x4E, 0x94, 0x4F, 0xB5, 0x73, +0xB5, 0x53, 0x52, 0x68, 0xA4, 0xD1, 0xA4, 0xF0, +0xAD, 0x31, 0xAC, 0xF0, 0x9C, 0xAF, 0x9C, 0x8F, +0xAD, 0x31, 0xB5, 0x51, 0xB5, 0x52, 0xA4, 0xD0, +0xA4, 0xB0, 0xA4, 0xD0, 0xA4, 0xD1, 0x8C, 0x4E, +0x94, 0x6F, 0x84, 0x0E, 0x8C, 0x4E, 0xAD, 0x11, +0x9C, 0x6F, 0x94, 0x2F, 0x94, 0x2F, 0x94, 0x50, +0x39, 0xA7, 0x21, 0x05, 0x18, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC3, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x20, 0xE5, 0x49, 0x46, 0x71, 0xA8, +0x59, 0x86, 0x21, 0x04, 0x21, 0x05, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x21, 0x25, 0x29, 0x46, 0x29, 0x66, +0x39, 0xA7, 0x31, 0xA7, 0x39, 0xE8, 0x4A, 0x29, +0x62, 0xEC, 0x7B, 0xAE, 0x6B, 0x4D, 0x62, 0xEC, +0x5A, 0xAB, 0x52, 0x6A, 0x52, 0x4A, 0x4A, 0x29, +0x4A, 0x09, 0x41, 0xE8, 0x41, 0xC8, 0x41, 0xC8, +0x41, 0xC8, 0x4A, 0x09, 0x52, 0x8B, 0x5A, 0xAB, +0x52, 0x8B, 0x52, 0x8B, 0x5A, 0xAB, 0x73, 0x6D, +0x9C, 0xD2, 0xB5, 0x74, 0xB5, 0x74, 0xBD, 0xB4, +0xA4, 0xF2, 0x94, 0x70, 0xA4, 0xF2, 0x9C, 0xD1, +0x9C, 0xD1, 0xA4, 0xF2, 0x8C, 0x2F, 0x83, 0xEE, +0xAD, 0x32, 0xBD, 0xB3, 0xC5, 0xD3, 0xC5, 0xB3, +0xAD, 0x11, 0xA4, 0xF0, 0x9C, 0xAF, 0x9C, 0x8F, +0xAD, 0x11, 0xB5, 0x52, 0x9C, 0xB0, 0xA4, 0xD0, +0xAD, 0x11, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x8F, +0xAD, 0x32, 0xA4, 0xD0, 0x94, 0x6F, 0x94, 0x4E, +0x8C, 0x0E, 0xAC, 0xF1, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x11, 0xAC, 0xF1, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xB0, 0xAC, 0xD0, 0xAC, 0xD0, 0xB5, 0x32, +0xAC, 0xD0, 0xAC, 0xF1, 0xA4, 0xB0, 0xB5, 0x11, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x33, 0x6B, 0x2C, 0x73, 0xAF, 0x8C, 0x72, +0xB5, 0x96, 0xB5, 0x56, 0x83, 0xEF, 0xB5, 0x55, +0xCE, 0x7A, 0xD6, 0xDB, 0xEF, 0x5D, 0xD6, 0xBA, +0x73, 0x8E, 0x52, 0xAA, 0x52, 0xAA, 0x63, 0x2C, +0x7B, 0xEF, 0xB5, 0x54, 0xAD, 0x33, 0xA4, 0xD1, +0x94, 0x6F, 0x9C, 0x6F, 0x94, 0x6F, 0x8C, 0x2E, +0x8C, 0x2E, 0x94, 0x4F, 0x94, 0x4F, 0x8C, 0x0E, +0x95, 0xAE, 0x9D, 0x70, 0x9D, 0x52, 0x9D, 0x52, +0x9D, 0x32, 0x6B, 0x6B, 0x94, 0x8F, 0xBD, 0xF4, +0xCE, 0x95, 0xBD, 0xF4, 0x9C, 0x8F, 0x6B, 0x2A, +0xAD, 0x52, 0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x31, +0xAD, 0x31, 0xAD, 0x31, 0xB5, 0x52, 0xAD, 0x11, +0xAD, 0x11, 0xA4, 0xD0, 0xBD, 0x93, 0xAD, 0x31, +0xAC, 0xF0, 0x94, 0x2D, 0xA4, 0xAF, 0xAD, 0x10, +0xB5, 0x31, 0xBD, 0x72, 0xB5, 0x72, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x73, 0xAD, 0x12, +0x94, 0x4F, 0x9C, 0x90, 0x9C, 0xD0, 0x9C, 0x90, +0xAD, 0x11, 0x7B, 0x8C, 0x7B, 0x6B, 0x62, 0xC8, +0x83, 0xAC, 0xA4, 0xB0, 0x8B, 0xED, 0x94, 0x4E, +0x94, 0x2E, 0x83, 0xAB, 0xB5, 0x10, 0xAD, 0x11, +0xB5, 0x93, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x73, +0xBD, 0xB4, 0xB5, 0x53, 0xA5, 0x11, 0xAD, 0x32, +0x9C, 0xD0, 0x9C, 0xD0, 0xA4, 0xF1, 0x9C, 0xB0, +0xA4, 0xF1, 0xAD, 0x52, 0x9C, 0xB0, 0x8C, 0x0D, +0x9C, 0x8F, 0xA4, 0xD0, 0xA4, 0xF1, 0x9C, 0x8F, +0xA4, 0xD0, 0xA4, 0x8E, 0xB4, 0xF0, 0xAC, 0xCF, +0xBD, 0x51, 0xBD, 0x51, 0xB5, 0x30, 0xAC, 0xEF, +0xA4, 0xAF, 0xBD, 0x52, 0x8C, 0x0D, 0x8C, 0x2E, +0x4A, 0x48, 0x41, 0xE7, 0x39, 0xC6, 0x39, 0xA6, +0x41, 0xE7, 0x52, 0x69, 0x4A, 0x48, 0x41, 0xE7, +0x29, 0x45, 0x31, 0x65, 0x39, 0xA6, 0x52, 0x69, +0x84, 0x10, 0xAD, 0x55, 0x83, 0xEF, 0x4A, 0x48, +0x5A, 0xAA, 0x31, 0x45, 0x29, 0x45, 0x41, 0xE7, +0x5A, 0x89, 0xA4, 0xB0, 0xBD, 0x31, 0xBD, 0x50, +0xCD, 0x92, 0xCD, 0xB2, 0xCD, 0xB2, 0xCD, 0xB2, +0xCD, 0xB2, 0xC5, 0x92, 0xC5, 0x51, 0xBD, 0x30, +0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x10, 0xBD, 0x30, +0xBD, 0x31, 0xBD, 0x10, 0xB4, 0xEF, 0xB4, 0xEF, +0xAC, 0xEF, 0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xF0, +0x62, 0xC9, 0x29, 0x64, 0x39, 0xA5, 0x39, 0xA5, +0x39, 0xC6, 0x41, 0xE7, 0x42, 0x28, 0x42, 0x08, +0x52, 0x8A, 0x6B, 0x4D, 0xA5, 0x35, 0xBD, 0xD7, +0x84, 0x11, 0x7B, 0xD0, 0xA5, 0x35, 0xBD, 0xF8, +0x94, 0x93, 0x73, 0x6D, 0xBD, 0x95, 0x9C, 0x71, +0xB5, 0x35, 0x9C, 0xB2, 0x9C, 0xF3, 0x5A, 0xCB, +0x94, 0x70, 0x8C, 0x4E, 0x9C, 0xB0, 0xBD, 0x94, +0xB5, 0x32, 0x8B, 0xEE, 0xA4, 0xF1, 0xAC, 0xF0, +0xB5, 0x52, 0xBD, 0x72, 0xBD, 0x93, 0xB5, 0x31, +0xBD, 0x72, 0xB5, 0x51, 0xB5, 0x52, 0xBD, 0x72, +0xBD, 0x93, 0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x73, +0xAD, 0x11, 0x9C, 0xB0, 0xA5, 0x12, 0xAD, 0x32, +0xA4, 0xB0, 0x94, 0x4F, 0x83, 0xCD, 0x6B, 0x2B, +0x21, 0x04, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xC4, 0x30, 0xE5, 0x71, 0x87, 0xA1, 0xE9, +0xA2, 0x8A, 0x31, 0x04, 0x20, 0xE5, 0x21, 0x05, +0x20, 0xE4, 0x18, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC3, +0x18, 0xC4, 0x21, 0x04, 0x29, 0x45, 0x29, 0x66, +0x29, 0x66, 0x31, 0x67, 0x31, 0x87, 0x39, 0xA7, +0x41, 0xE8, 0x4A, 0x29, 0x52, 0x6A, 0x52, 0x8B, +0x4A, 0x4A, 0x4A, 0x09, 0x41, 0xE8, 0x39, 0xC8, +0x39, 0x87, 0x39, 0x87, 0x31, 0x66, 0x31, 0x66, +0x31, 0x86, 0x31, 0x87, 0x39, 0xC8, 0x41, 0xE8, +0x4A, 0x4A, 0x52, 0x8B, 0x52, 0xAB, 0x5A, 0xCC, +0x62, 0xEC, 0x73, 0x8E, 0x94, 0x91, 0xB5, 0x74, +0xBD, 0x94, 0xB5, 0x74, 0xB5, 0x74, 0xAD, 0x33, +0xAD, 0x53, 0xAD, 0x53, 0x9C, 0x90, 0x84, 0x2E, +0xB5, 0x93, 0xBD, 0xB3, 0xBD, 0x72, 0xCD, 0xF4, +0xBD, 0xB4, 0xBD, 0xD4, 0xAD, 0x12, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x93, 0xBD, 0x92, 0xBD, 0x72, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x73, 0xA4, 0xF1, +0xAD, 0x52, 0xAD, 0x52, 0xA5, 0x11, 0x94, 0x6F, +0x7B, 0x6C, 0xCD, 0xF5, 0xCE, 0x15, 0xCD, 0xF4, +0xAC, 0xD0, 0xBD, 0x52, 0x8C, 0x0D, 0xA4, 0x8F, +0xA4, 0xAF, 0xAC, 0xF0, 0xBD, 0x52, 0xBD, 0x72, +0xB5, 0x52, 0xC5, 0xB3, 0xBD, 0x72, 0xAC, 0xF1, +0x7B, 0x6B, 0x8C, 0x2E, 0xA4, 0xD0, 0xA4, 0xB0, +0xC5, 0xB4, 0xA4, 0xF2, 0x52, 0xAA, 0x7B, 0xF0, +0xB5, 0x76, 0x73, 0x8E, 0x94, 0x92, 0xCE, 0x39, +0xDE, 0xDB, 0xC6, 0x18, 0x94, 0xB3, 0xB5, 0x96, +0xBD, 0xD7, 0x73, 0xAE, 0x5A, 0xEB, 0x6B, 0x4D, +0x7B, 0xEF, 0xA5, 0x13, 0xAD, 0x33, 0xAD, 0x12, +0xB5, 0x73, 0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x53, +0xC5, 0xB4, 0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x94, +0x85, 0x0A, 0x9D, 0xAF, 0x95, 0x30, 0x8C, 0xCF, +0x4A, 0x87, 0x6B, 0x4A, 0x84, 0x2D, 0x9D, 0x2E, +0x9D, 0xAD, 0xC6, 0x93, 0xB5, 0x92, 0xA4, 0xCF, +0xAD, 0x30, 0x84, 0x0C, 0xB5, 0x52, 0xB5, 0x52, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x52, 0xB5, 0x32, +0xB5, 0x32, 0xAD, 0x31, 0xC5, 0xD4, 0xB5, 0x51, +0xB5, 0x31, 0xAD, 0x11, 0xAC, 0xF0, 0xB5, 0x31, +0xC5, 0x92, 0xCD, 0xF4, 0xBD, 0x93, 0xB5, 0x53, +0xBD, 0x73, 0xBD, 0xB4, 0xAD, 0x12, 0xAD, 0x32, +0xB5, 0x32, 0x8C, 0x2E, 0x94, 0x6F, 0xAD, 0x52, +0xB5, 0x52, 0x9C, 0xB0, 0x94, 0x4E, 0x6A, 0xE9, +0x83, 0xED, 0x73, 0x6A, 0x9C, 0x8F, 0x9C, 0x6F, +0x9C, 0xB0, 0x9C, 0x8F, 0xB5, 0x31, 0xB5, 0x73, +0xC5, 0xF5, 0xBD, 0xB4, 0xAD, 0x53, 0xB5, 0x94, +0xBD, 0xB4, 0xAD, 0x53, 0xB5, 0x94, 0xAD, 0x52, +0xA5, 0x11, 0xAD, 0x32, 0xAD, 0x53, 0xA5, 0x11, +0xAD, 0x53, 0xB5, 0x94, 0xB5, 0x73, 0xA4, 0xF1, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x93, 0xAD, 0x52, +0xC5, 0xF5, 0xA4, 0xAF, 0xA4, 0x8E, 0xAC, 0xD0, +0xBD, 0x72, 0xD6, 0x14, 0xCD, 0xF4, 0xCD, 0xF4, +0xCD, 0xD3, 0xCD, 0xF4, 0x9C, 0x90, 0x9C, 0xB0, +0x7B, 0xCE, 0x4A, 0x48, 0x41, 0xE7, 0x39, 0xC7, +0x39, 0xC7, 0x4A, 0x28, 0x42, 0x08, 0x41, 0xE7, +0x4A, 0x28, 0x5A, 0xAA, 0x52, 0x8A, 0x62, 0xEB, +0x94, 0x71, 0xB5, 0x75, 0x7B, 0xCF, 0x5A, 0xCB, +0x4A, 0x48, 0x39, 0x86, 0x4A, 0x49, 0x5A, 0xCA, +0x41, 0xC6, 0x83, 0xCD, 0x94, 0x2D, 0x8B, 0xCB, +0x9C, 0x6D, 0x9C, 0x4D, 0xA4, 0x6E, 0xBD, 0x10, +0xC5, 0x71, 0x94, 0x0C, 0xA4, 0x8E, 0x94, 0x0C, +0x94, 0x2D, 0x94, 0x2C, 0x94, 0x0C, 0x94, 0x2D, +0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0x8E, 0x94, 0x2D, +0x9C, 0x4D, 0xA4, 0x8E, 0xB5, 0x10, 0xAC, 0xF0, +0x5A, 0xA8, 0x21, 0x03, 0x21, 0x23, 0x39, 0xA5, +0x42, 0x07, 0x39, 0xC6, 0x42, 0x07, 0x41, 0xE7, +0x42, 0x08, 0x5A, 0xEB, 0xC6, 0x18, 0xB5, 0x76, +0x8C, 0x72, 0x73, 0x8F, 0x9C, 0xF4, 0xB5, 0x96, +0x84, 0x10, 0x7B, 0xCF, 0x6B, 0x0C, 0x39, 0xA6, +0xC5, 0xF7, 0xD6, 0x79, 0xAD, 0x34, 0x7B, 0xEF, +0x73, 0x6C, 0x8B, 0xED, 0x94, 0x2E, 0xAD, 0x11, +0xAC, 0xF1, 0x9C, 0xB0, 0x9C, 0x90, 0x9C, 0xB0, +0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x11, 0x9C, 0x8E, +0x9C, 0x8F, 0x9C, 0x6F, 0x9C, 0x8F, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xAF, 0x9C, 0x8F, 0xAC, 0xF1, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x73, +0xA4, 0xF1, 0x94, 0x6F, 0x7B, 0x8D, 0x52, 0x49, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xA3, 0x49, 0x26, 0x79, 0x47, 0xAA, 0x4A, +0x79, 0xA8, 0x28, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x20, 0xE5, 0x21, 0x05, 0x21, 0x25, +0x29, 0x46, 0x29, 0x66, 0x31, 0x87, 0x39, 0xA7, +0x39, 0xC8, 0x39, 0xC8, 0x39, 0xE8, 0x4A, 0x09, +0x42, 0x09, 0x41, 0xC8, 0x39, 0xC8, 0x31, 0x87, +0x31, 0x87, 0x31, 0x87, 0x29, 0x66, 0x29, 0x46, +0x29, 0x46, 0x29, 0x46, 0x29, 0x66, 0x31, 0x87, +0x39, 0xA7, 0x39, 0xC8, 0x42, 0x29, 0x4A, 0x4A, +0x4A, 0x2A, 0x4A, 0x4A, 0x52, 0x8B, 0x63, 0x2D, +0x83, 0xEF, 0x9C, 0xD2, 0xB5, 0x74, 0xB5, 0x94, +0xB5, 0xB5, 0xAD, 0x53, 0x94, 0x70, 0x94, 0x6F, +0xBD, 0xB4, 0xCD, 0xF4, 0xBD, 0x92, 0xC5, 0xF4, +0xB5, 0x52, 0xB5, 0x73, 0xAD, 0x53, 0xBD, 0xB4, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x51, 0xBD, 0x92, +0xBD, 0x72, 0xB5, 0x51, 0xB5, 0x93, 0xAD, 0x32, +0xC6, 0x16, 0xBD, 0xD5, 0xBD, 0xF5, 0xB5, 0x73, +0x9C, 0xD0, 0xCD, 0xF4, 0xCE, 0x35, 0xCE, 0x15, +0xA4, 0xB0, 0xBD, 0x73, 0x94, 0x6F, 0x94, 0x0D, +0x9C, 0x4E, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xBD, 0xB3, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0x8C, 0x0D, 0xA4, 0xF0, 0xAD, 0x11, 0xAD, 0x11, +0xBD, 0x93, 0xC5, 0xB4, 0x94, 0x70, 0x5A, 0xCB, +0x8C, 0x51, 0x73, 0xAF, 0x7B, 0xCF, 0xB5, 0x96, +0x83, 0xF0, 0x5A, 0xCC, 0x73, 0x6E, 0x84, 0x30, +0x94, 0xB2, 0x8C, 0x51, 0x62, 0xEC, 0x6B, 0x4D, +0x7B, 0xEF, 0x9C, 0xF3, 0xC5, 0xF6, 0xC5, 0xF4, +0xC5, 0xF4, 0xC5, 0xF4, 0xB5, 0x73, 0xBD, 0xB3, +0xC5, 0xB4, 0xBD, 0x72, 0xBD, 0x93, 0xAD, 0x11, +0x74, 0xE9, 0x7C, 0xEC, 0x85, 0x0F, 0x84, 0x8F, +0x39, 0xE6, 0x52, 0x88, 0x73, 0xAB, 0x7C, 0x2A, +0x74, 0x47, 0x9D, 0x8B, 0xBE, 0x30, 0xB5, 0xB0, +0x94, 0x8C, 0x94, 0x6D, 0xA4, 0xAF, 0xB5, 0x52, +0xAD, 0x31, 0xAD, 0x11, 0xB5, 0x31, 0xB5, 0x52, +0xB5, 0x32, 0xBD, 0x73, 0xC5, 0xB3, 0xB5, 0x51, +0xAD, 0x31, 0x9C, 0x6E, 0xAC, 0xF0, 0xB5, 0x10, +0xBD, 0x92, 0xC5, 0xB3, 0xC5, 0xB4, 0xC5, 0xB4, +0xC5, 0xD4, 0xC5, 0xD5, 0xBD, 0xB4, 0xBD, 0xD5, +0xA4, 0xD1, 0x94, 0x4F, 0xAD, 0x32, 0xBD, 0xB4, +0xAD, 0x11, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, +0xA4, 0xD0, 0x8C, 0x2E, 0xA4, 0xF1, 0x9C, 0x6F, +0x9C, 0xB0, 0x9C, 0xAF, 0xB5, 0x10, 0xBD, 0xB3, +0xBD, 0xD5, 0xB5, 0x94, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xD5, 0xB5, 0x74, 0xC5, 0xF5, 0xBD, 0xB4, +0xB5, 0x73, 0xBD, 0xD5, 0xBD, 0xD5, 0xB5, 0x94, +0xB5, 0xB4, 0xBD, 0xD5, 0xBD, 0xB4, 0xA5, 0x11, +0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x73, +0xC5, 0xF5, 0xA4, 0xCF, 0xA4, 0x8E, 0xB5, 0x52, +0xBD, 0x93, 0xCD, 0xF4, 0xCD, 0xF4, 0xCD, 0xD3, +0xCD, 0xD3, 0xCD, 0xF4, 0x9C, 0xB0, 0x8C, 0x4F, +0x84, 0x0E, 0x73, 0x6D, 0x41, 0xE7, 0x39, 0xA6, +0x29, 0x44, 0x39, 0xC6, 0x39, 0xC6, 0x52, 0x69, +0x52, 0x89, 0x5A, 0xAA, 0x63, 0x0C, 0x73, 0x8D, +0x94, 0x91, 0x8C, 0x30, 0x7B, 0xAE, 0x6B, 0x2C, +0x42, 0x07, 0x39, 0xA6, 0x39, 0xC7, 0x42, 0x08, +0x4A, 0x28, 0xA4, 0xF1, 0xB5, 0x31, 0x9C, 0x6E, +0xAC, 0xF0, 0xB5, 0x31, 0xA4, 0xAF, 0xAC, 0xF0, +0xC5, 0x72, 0x94, 0x0C, 0xA4, 0xAF, 0xAC, 0xF0, +0xAD, 0x31, 0xA4, 0xAF, 0xAD, 0x11, 0xAD, 0x11, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF0, 0x9C, 0xB0, +0x84, 0x0D, 0x94, 0x6F, 0xA4, 0xF0, 0xAD, 0x11, +0xB5, 0x73, 0x73, 0x6C, 0x4A, 0x48, 0x63, 0x2B, +0x29, 0x64, 0x42, 0x27, 0x42, 0x07, 0x39, 0xC6, +0x84, 0x10, 0x94, 0xB3, 0xD6, 0x7A, 0xA5, 0x35, +0x8C, 0x51, 0x8C, 0x52, 0x9C, 0xF4, 0x8C, 0x52, +0x7B, 0xAF, 0x84, 0x10, 0xC5, 0xD7, 0x62, 0xCB, +0x62, 0xEC, 0x84, 0x10, 0x9C, 0xD3, 0xAD, 0x34, +0xA4, 0xD2, 0xAC, 0xD0, 0xA4, 0xB0, 0xB5, 0x53, +0xB5, 0x73, 0xC5, 0xB4, 0xC5, 0xD5, 0xC5, 0xD5, +0xC5, 0xB4, 0xBD, 0x94, 0xB5, 0x52, 0xB5, 0x53, +0xC5, 0xD5, 0xC5, 0xB4, 0xC5, 0xB4, 0xBD, 0x93, +0xBD, 0x94, 0xC5, 0xB4, 0xBD, 0x94, 0xBD, 0x94, +0xB5, 0x53, 0xB5, 0x32, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x12, 0xAD, 0x53, 0x9C, 0x90, 0x41, 0xE7, +0x20, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x20, 0xA3, 0x61, 0x87, 0x71, 0x26, 0x89, 0xE9, +0x30, 0x83, 0x20, 0xC4, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x29, 0x25, +0x29, 0x46, 0x29, 0x66, 0x31, 0x87, 0x31, 0xA7, +0x39, 0xC8, 0x39, 0xC8, 0x31, 0xA7, 0x39, 0xA8, +0x39, 0xC8, 0x39, 0xC8, 0x31, 0x87, 0x31, 0x87, +0x31, 0x66, 0x29, 0x66, 0x29, 0x66, 0x29, 0x66, +0x29, 0x66, 0x29, 0x46, 0x29, 0x46, 0x21, 0x25, +0x29, 0x46, 0x29, 0x46, 0x31, 0x87, 0x31, 0xA7, +0x39, 0xC8, 0x4A, 0x4A, 0x4A, 0x6A, 0x52, 0x6B, +0x5A, 0xAB, 0x63, 0x0C, 0x7B, 0xCF, 0xA4, 0xF3, +0xBD, 0xB5, 0xBD, 0xD5, 0xA5, 0x12, 0x94, 0x90, +0xBD, 0x94, 0xCE, 0x14, 0xBD, 0x72, 0xC5, 0xD4, +0xAD, 0x52, 0xAD, 0x32, 0xB5, 0x94, 0xBD, 0xD5, +0xBD, 0xD5, 0xBD, 0xB4, 0xB5, 0x52, 0xBD, 0xB3, +0xB5, 0x51, 0xB5, 0x31, 0xAD, 0x31, 0xAD, 0x52, +0xC6, 0x15, 0xBD, 0xB5, 0xB5, 0xB4, 0xB5, 0x93, +0xA4, 0xF1, 0xC5, 0xF4, 0xCE, 0x14, 0xC5, 0xD4, +0xA4, 0xB0, 0xBD, 0x93, 0x94, 0x4F, 0xAC, 0xD0, +0xAC, 0xF0, 0xBD, 0x93, 0xAD, 0x31, 0xBD, 0x73, +0xCE, 0x15, 0xA4, 0xF0, 0xAD, 0x11, 0xB5, 0x52, +0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xD0, 0xAD, 0x32, +0xC5, 0xF5, 0xC5, 0xD4, 0xC5, 0xF5, 0x6B, 0x4C, +0x62, 0xEC, 0x4A, 0x29, 0x52, 0x69, 0x63, 0x0C, +0x6B, 0x4D, 0x5A, 0xCB, 0x6B, 0x2D, 0x73, 0x8E, +0x84, 0x10, 0xAD, 0x76, 0x6B, 0x6E, 0x73, 0xAF, +0x84, 0x10, 0x9C, 0xF3, 0xBD, 0xB5, 0xC5, 0xD4, +0xC6, 0x14, 0xBD, 0xB3, 0xAD, 0x11, 0xC5, 0xD3, +0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x35, 0xC5, 0xF4, +0x74, 0xAA, 0x8D, 0x4F, 0x9D, 0x71, 0x7C, 0x4D, +0x63, 0x49, 0x52, 0xE8, 0x5A, 0xC8, 0x63, 0x29, +0x5B, 0x26, 0x7C, 0x68, 0x84, 0x87, 0x95, 0x2B, +0xAD, 0xB0, 0xAD, 0x90, 0x8C, 0x6C, 0x9C, 0x8F, +0x9C, 0x8F, 0x9C, 0x8E, 0x9C, 0xAF, 0xAD, 0x11, +0xB5, 0x32, 0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x52, 0x83, 0xCB, 0xB5, 0x10, 0xB5, 0x30, +0xC5, 0xD3, 0xCE, 0x15, 0xD6, 0x35, 0xCE, 0x15, +0xCE, 0x35, 0xCE, 0x35, 0xC5, 0xF5, 0xCE, 0x16, +0x8C, 0x0E, 0xC5, 0xD5, 0xC5, 0xD5, 0xBD, 0xB4, +0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x73, 0xBD, 0x94, +0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xF0, 0xB5, 0x31, 0xC5, 0xF4, +0xC5, 0xF6, 0xB5, 0x94, 0xC6, 0x16, 0xBD, 0xD5, +0xBD, 0xD5, 0xC5, 0xF6, 0xC6, 0x16, 0xC6, 0x36, +0xC6, 0x15, 0xC5, 0xF5, 0xBD, 0xD5, 0xB5, 0xB4, +0xC6, 0x16, 0xBD, 0xD5, 0xBD, 0xD5, 0xBD, 0xD5, +0xC6, 0x16, 0xC6, 0x15, 0xB5, 0x73, 0xBD, 0xB4, +0xBD, 0x93, 0xB5, 0x10, 0xA4, 0x8E, 0xAD, 0x11, +0xC5, 0xD4, 0xCD, 0xF4, 0xD5, 0xF4, 0xCD, 0xD3, +0xCD, 0xF3, 0xD6, 0x15, 0xA4, 0xD1, 0x9C, 0xD1, +0x8C, 0x2F, 0x94, 0x71, 0x52, 0x89, 0x41, 0xE7, +0x39, 0xC6, 0x39, 0xA6, 0x41, 0xE7, 0x4A, 0x28, +0x4A, 0x49, 0x63, 0x0B, 0x6B, 0x4C, 0x6B, 0x4C, +0x73, 0x8E, 0x7B, 0xCE, 0x8C, 0x51, 0x73, 0x8E, +0x5A, 0xAA, 0x52, 0x69, 0x8C, 0x71, 0x7B, 0xAE, +0x52, 0x69, 0xA4, 0xF1, 0xC5, 0xD4, 0xAC, 0xF0, +0x9C, 0xAF, 0xAD, 0x31, 0xCD, 0xF5, 0xA4, 0xAF, +0xBD, 0x51, 0x94, 0x4D, 0xAC, 0xF0, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x52, +0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x11, 0xB5, 0x73, +0xAD, 0x52, 0xB5, 0x73, 0xAD, 0x52, 0xB5, 0x73, +0xBD, 0xB4, 0xB5, 0x73, 0xA5, 0x12, 0x63, 0x0B, +0x18, 0xE3, 0x29, 0x64, 0x31, 0xA5, 0x4A, 0x69, +0x94, 0xB2, 0xC6, 0x39, 0xC5, 0xF8, 0xA4, 0xF4, +0x84, 0x11, 0x84, 0x31, 0x7B, 0xCF, 0x7B, 0xD0, +0x73, 0x6E, 0x94, 0x72, 0xCE, 0x38, 0xB5, 0x55, +0x52, 0x49, 0x4A, 0x28, 0x5A, 0xAA, 0x5A, 0x8A, +0xA4, 0xF2, 0xBD, 0x52, 0x9C, 0x6E, 0xAD, 0x11, +0xB5, 0x52, 0xB5, 0x52, 0xA4, 0xD0, 0xA4, 0xB0, +0xBD, 0x73, 0x9C, 0x8F, 0xA4, 0xD0, 0xB5, 0x31, +0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xD0, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x12, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x73, 0x94, 0x4F, 0x31, 0x86, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xA3, +0x38, 0xE4, 0x71, 0x46, 0x89, 0xA8, 0x61, 0x46, +0x20, 0xA3, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x21, 0x25, +0x21, 0x05, 0x21, 0x25, 0x21, 0x25, 0x29, 0x46, +0x31, 0xA7, 0x39, 0xC8, 0x39, 0xC8, 0x31, 0x87, +0x31, 0x87, 0x31, 0x87, 0x31, 0x66, 0x29, 0x46, +0x31, 0x66, 0x31, 0x87, 0x31, 0x66, 0x29, 0x66, +0x29, 0x46, 0x29, 0x46, 0x29, 0x46, 0x29, 0x46, +0x21, 0x25, 0x21, 0x05, 0x29, 0x46, 0x31, 0x87, +0x39, 0xC8, 0x39, 0xC8, 0x41, 0xE9, 0x4A, 0x29, +0x52, 0x8B, 0x52, 0x8B, 0x52, 0x8B, 0x5A, 0xCC, +0x73, 0x8E, 0x94, 0x91, 0x94, 0x91, 0x94, 0x90, +0xBD, 0x73, 0xC5, 0xF4, 0xBD, 0x92, 0xC5, 0xD4, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xD4, +0xC6, 0x16, 0xBD, 0xB4, 0xB5, 0x93, 0xC5, 0xB3, +0xC5, 0xD3, 0xC5, 0xF4, 0xB5, 0x93, 0xB5, 0x73, +0xC5, 0xF5, 0xC5, 0xF5, 0xB5, 0x94, 0xBD, 0xB4, +0xB5, 0x52, 0xC5, 0xD4, 0xCE, 0x35, 0xBD, 0xD3, +0xAD, 0x11, 0xC5, 0xB4, 0x94, 0x2E, 0xA4, 0xAF, +0xB5, 0x51, 0xC5, 0xD4, 0xCE, 0x15, 0xD6, 0x35, +0xCE, 0x15, 0xB5, 0x72, 0xBD, 0xB3, 0xCE, 0x15, +0xC5, 0xF4, 0xBD, 0xB4, 0xB5, 0x53, 0xAD, 0x52, +0xC5, 0xF4, 0xC5, 0xD4, 0xC5, 0xB4, 0xAD, 0x32, +0x6B, 0x0B, 0x52, 0x8A, 0x5A, 0xAA, 0x84, 0x10, +0x8C, 0x51, 0x39, 0xC7, 0x4A, 0x4A, 0x8C, 0x31, +0x84, 0x10, 0xC5, 0xF8, 0x9C, 0xB3, 0x84, 0x31, +0x8C, 0x51, 0x6B, 0x4D, 0xAD, 0x13, 0xCE, 0x15, +0xCE, 0x35, 0xBD, 0xD3, 0xB5, 0x72, 0xC5, 0xD4, +0xCE, 0x34, 0xD6, 0x55, 0xC5, 0xF3, 0xC5, 0xF4, +0x7D, 0x0C, 0x7C, 0xEC, 0x6C, 0x4B, 0x7C, 0x8B, +0x84, 0x8C, 0x8C, 0x8C, 0x84, 0x0B, 0x8C, 0x0C, +0x94, 0x6D, 0x94, 0xCC, 0x7C, 0x68, 0x5B, 0x84, +0x63, 0xE5, 0x7C, 0x68, 0x9C, 0xEC, 0x9C, 0x6D, +0x94, 0x2D, 0x94, 0x2D, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x2D, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, +0x8B, 0xEC, 0x7B, 0x6A, 0xB5, 0x10, 0x8B, 0xCB, +0x94, 0x4D, 0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0x8F, +0xA4, 0xB0, 0xAD, 0x11, 0xB5, 0x32, 0xB5, 0x73, +0xB5, 0x53, 0xB5, 0x93, 0xB5, 0x73, 0xBD, 0x94, +0xC5, 0xF5, 0xCE, 0x15, 0xCE, 0x16, 0xCE, 0x36, +0xC5, 0xD5, 0xC5, 0xD5, 0xB5, 0x73, 0xA4, 0xF1, +0xA4, 0xF1, 0xB5, 0x31, 0xBD, 0x51, 0xBD, 0xB4, +0xCE, 0x57, 0xBD, 0xF5, 0xC6, 0x16, 0xCE, 0x57, +0xCE, 0x36, 0xC6, 0x36, 0xCE, 0x36, 0xC6, 0x16, +0xC6, 0x16, 0xC6, 0x16, 0xC5, 0xF5, 0xBD, 0xF5, +0xC6, 0x16, 0xBD, 0xD5, 0xC5, 0xF5, 0xBD, 0xD5, +0xBD, 0xB4, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0x73, +0xBD, 0xB4, 0xAD, 0x10, 0x9C, 0x6E, 0x94, 0x4E, +0xC5, 0xD4, 0xCD, 0xD3, 0xDE, 0x35, 0xCD, 0xF4, +0xCD, 0xB3, 0xD6, 0x15, 0xAD, 0x12, 0xAD, 0x33, +0x9C, 0xF2, 0x9C, 0xF2, 0x8C, 0x50, 0x4A, 0x28, +0x42, 0x07, 0x4A, 0x28, 0x41, 0xE7, 0x4A, 0x48, +0x5A, 0xCA, 0x5A, 0xEB, 0x5A, 0xCA, 0x5A, 0xCB, +0x62, 0xEB, 0x83, 0xEF, 0x94, 0x92, 0x8C, 0x30, +0x7B, 0xCF, 0x6B, 0x2D, 0x9C, 0xB3, 0x83, 0xF0, +0x62, 0xEB, 0x83, 0xEE, 0xCE, 0x35, 0xC5, 0xD4, +0xA5, 0x11, 0xBD, 0xB3, 0xCE, 0x15, 0x9C, 0x8F, +0xB5, 0x51, 0x7B, 0x6A, 0x94, 0x6F, 0xAD, 0x11, +0xAD, 0x11, 0xC5, 0xD4, 0xC6, 0x15, 0xC5, 0xF5, +0xCE, 0x36, 0xBD, 0xD4, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xB4, 0xBD, 0xB4, 0xCE, 0x56, 0xC5, 0xD5, +0xBD, 0xD4, 0xBD, 0xD4, 0xB5, 0x94, 0x8C, 0x50, +0x4A, 0x49, 0x42, 0x28, 0x29, 0x44, 0x39, 0xE7, +0x7B, 0xCF, 0xB5, 0x96, 0xAD, 0x55, 0x9C, 0xD4, +0x73, 0x8F, 0x52, 0xAB, 0x63, 0x2D, 0x73, 0x6E, +0x73, 0x6E, 0x73, 0x6E, 0xB5, 0x96, 0xBD, 0x96, +0x7B, 0xAE, 0x62, 0xEB, 0x39, 0xA6, 0x62, 0xEB, +0x9C, 0x91, 0xB5, 0x52, 0xA4, 0xB0, 0xC5, 0xB3, +0xC5, 0xD3, 0xC5, 0xB3, 0xB5, 0x52, 0x9C, 0x90, +0xB5, 0x52, 0xC5, 0xB3, 0xC5, 0xD3, 0xCD, 0xD3, +0xDE, 0x75, 0xC5, 0xB3, 0xBD, 0x72, 0xBD, 0x92, +0xD6, 0x14, 0xC5, 0x93, 0xA4, 0xB0, 0xA4, 0xF0, +0xAC, 0xF0, 0x9C, 0x8F, 0x9C, 0x6F, 0xBD, 0x73, +0xB5, 0x53, 0xAD, 0x12, 0x7B, 0xAD, 0x29, 0x45, +0x21, 0x04, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x08, 0x83, 0x10, 0xA3, 0x18, 0xC4, +0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x20, 0x83, +0x61, 0x26, 0x81, 0x67, 0x91, 0xE9, 0x38, 0xA3, +0x18, 0xA3, 0x18, 0xA3, 0x18, 0xA3, 0x18, 0xA3, +0x18, 0xA3, 0x10, 0xA3, 0x18, 0xA3, 0x18, 0xA3, +0x18, 0xA3, 0x18, 0xC3, 0x18, 0xC3, 0x18, 0xE4, +0x20, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x21, 0x25, +0x29, 0x25, 0x29, 0x46, 0x29, 0x46, 0x31, 0x66, +0x31, 0x87, 0x39, 0xA7, 0x31, 0xA7, 0x31, 0x87, +0x31, 0x66, 0x29, 0x25, 0x21, 0x25, 0x21, 0x05, +0x21, 0x25, 0x29, 0x46, 0x29, 0x46, 0x21, 0x25, +0x29, 0x46, 0x29, 0x25, 0x29, 0x25, 0x29, 0x25, +0x29, 0x25, 0x29, 0x46, 0x29, 0x46, 0x29, 0x46, +0x31, 0x87, 0x31, 0xA7, 0x31, 0x87, 0x31, 0xA7, +0x41, 0xE8, 0x4A, 0x29, 0x4A, 0x4A, 0x4A, 0x4A, +0x4A, 0x6A, 0x52, 0xAB, 0x63, 0x2C, 0x84, 0x0F, +0xB5, 0x53, 0xC5, 0xF4, 0xCE, 0x14, 0xCE, 0x15, +0xCE, 0x36, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0xB4, +0xC6, 0x36, 0xBD, 0xB4, 0xC6, 0x15, 0xCE, 0x55, +0xCE, 0x35, 0xD6, 0x76, 0xBD, 0xB4, 0xB5, 0x94, +0xBD, 0xD5, 0xBD, 0xD4, 0xB5, 0x94, 0xB5, 0x94, +0xBD, 0x93, 0xBD, 0x93, 0xD6, 0x76, 0xC5, 0xD4, +0xB5, 0x52, 0xC5, 0xB3, 0x94, 0x0E, 0x7B, 0x6B, +0x94, 0x4E, 0xBD, 0xB3, 0xB5, 0x92, 0xC5, 0xD3, +0xAD, 0x11, 0xAC, 0xF0, 0xB5, 0x52, 0xC5, 0xD3, +0xC5, 0xF4, 0xBD, 0xD4, 0xB5, 0x73, 0xB5, 0x53, +0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x15, 0xB5, 0x73, +0x9C, 0xB0, 0x5A, 0xEB, 0x62, 0xEB, 0x7B, 0xCF, +0x73, 0xAE, 0x52, 0x6A, 0x52, 0x6A, 0x6B, 0x4D, +0x63, 0x0D, 0x84, 0x10, 0x8C, 0x31, 0x63, 0x0C, +0x42, 0x08, 0x31, 0x87, 0xAD, 0x34, 0xCE, 0x36, +0xC5, 0xF4, 0xC5, 0xF4, 0xC6, 0x14, 0xC5, 0xD4, +0xCE, 0x55, 0xC6, 0x14, 0xC5, 0xF4, 0xBD, 0xD3, +0x5B, 0xE7, 0x6C, 0x4A, 0x8D, 0x0E, 0x7C, 0x4C, +0x63, 0x89, 0x8C, 0x6C, 0x7B, 0xCB, 0x84, 0x0C, +0xAD, 0x31, 0x9C, 0xEF, 0x73, 0xE7, 0x6C, 0x06, +0x64, 0x26, 0x84, 0xA9, 0xAD, 0x2E, 0xAD, 0x10, +0xA4, 0x8E, 0x9C, 0x6D, 0x9C, 0x6D, 0xAC, 0xEF, +0xB5, 0x10, 0xAC, 0xEF, 0xB5, 0x10, 0xB5, 0x30, +0xBD, 0x31, 0xB5, 0x30, 0xB5, 0x30, 0xAC, 0xAF, +0xAC, 0xAF, 0xA4, 0x8E, 0xA4, 0x8E, 0xB4, 0xF0, +0xB4, 0xF0, 0xAC, 0xAF, 0xA4, 0x8F, 0xA4, 0x8E, +0x9C, 0x6E, 0x9C, 0x4D, 0x94, 0x0D, 0x94, 0x2D, +0x93, 0xEC, 0x8B, 0xEC, 0x9C, 0x4E, 0x9C, 0x8E, +0x9C, 0x8F, 0xA4, 0xD0, 0xAC, 0xF0, 0xA4, 0xF0, +0xAD, 0x11, 0xBD, 0x51, 0xC5, 0x71, 0xBD, 0x51, +0xBD, 0x72, 0xB5, 0x72, 0xAD, 0x31, 0xB5, 0x72, +0xB5, 0x52, 0xB5, 0x52, 0xC5, 0xD4, 0xC6, 0x15, +0xCE, 0x36, 0xCE, 0x56, 0xCE, 0x57, 0xD6, 0x77, +0xD6, 0x77, 0xCE, 0x56, 0xD6, 0x77, 0xCE, 0x36, +0xCE, 0x16, 0xCE, 0x36, 0xC5, 0xF5, 0xC5, 0xD4, +0xB5, 0x73, 0xB5, 0x10, 0xAC, 0xEF, 0x8C, 0x0D, +0xCD, 0xF4, 0xD6, 0x55, 0xCE, 0x14, 0xCD, 0xF4, +0xD6, 0x35, 0xDE, 0x56, 0xBD, 0x73, 0xA4, 0xF2, +0x9C, 0xF2, 0x9C, 0xF2, 0xAD, 0x33, 0x73, 0x8D, +0x41, 0xE7, 0x41, 0xE7, 0x41, 0xE7, 0x52, 0x69, +0x41, 0xE7, 0x4A, 0x28, 0x52, 0x69, 0x4A, 0x49, +0x52, 0x8A, 0x73, 0x6D, 0x94, 0x72, 0x9C, 0xB2, +0x94, 0x92, 0x84, 0x10, 0xAD, 0x55, 0xA4, 0xF3, +0x6B, 0x2C, 0x62, 0xEA, 0xCE, 0x36, 0xCE, 0x35, +0xC5, 0xF4, 0xC5, 0xF4, 0xCE, 0x15, 0xB5, 0x31, +0xB5, 0x30, 0x7B, 0x8B, 0x94, 0x6F, 0xA4, 0xD0, +0xA4, 0xD0, 0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x72, 0xA4, 0xF1, 0xBD, 0xB4, 0xB5, 0x73, +0x9C, 0xD1, 0xBD, 0xD5, 0xC5, 0xF5, 0xBD, 0x94, +0xC5, 0xF5, 0xC5, 0xF5, 0xC6, 0x15, 0xCE, 0x57, +0xA5, 0x33, 0x52, 0xA9, 0x39, 0xC7, 0x21, 0x03, +0x52, 0xAB, 0xBD, 0xF8, 0xA5, 0x14, 0x8C, 0x72, +0x63, 0x2D, 0x42, 0x08, 0x62, 0xEC, 0x6B, 0x4D, +0x6B, 0x2D, 0x5A, 0xCB, 0x63, 0x2D, 0x7B, 0xAF, +0x73, 0x6D, 0x83, 0xF0, 0x7B, 0x6E, 0x62, 0xEC, +0x94, 0x70, 0xBD, 0x94, 0xAD, 0x12, 0xC5, 0xB3, +0xC5, 0xB3, 0xC5, 0xB3, 0xC5, 0xB3, 0xA4, 0xB0, +0xB5, 0x52, 0xCD, 0xD4, 0xBD, 0x71, 0xCD, 0xD3, +0xCD, 0xD3, 0xC5, 0x72, 0xC5, 0x92, 0xC5, 0xB2, +0xDE, 0x35, 0xCD, 0xD3, 0xB5, 0x11, 0xB5, 0x31, +0xBD, 0x72, 0xBD, 0x72, 0xAC, 0xF1, 0xAD, 0x11, +0x94, 0x6F, 0x94, 0x6F, 0x73, 0x6C, 0x29, 0x25, +0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, 0x10, 0xA3, +0x10, 0xC3, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x40, 0xE4, +0x79, 0x46, 0x91, 0x87, 0x69, 0x46, 0x20, 0xA3, +0x18, 0xC4, 0x18, 0xA3, 0x18, 0xA3, 0x18, 0xC3, +0x18, 0xA3, 0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xA3, 0x18, 0xC3, 0x18, 0xC4, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x25, 0x21, 0x05, 0x21, 0x05, 0x21, 0x25, +0x29, 0x46, 0x29, 0x25, 0x21, 0x25, 0x29, 0x25, +0x29, 0x66, 0x29, 0x46, 0x21, 0x25, 0x21, 0x05, +0x20, 0xE4, 0x21, 0x05, 0x29, 0x46, 0x29, 0x46, +0x21, 0x25, 0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x25, 0x29, 0x25, 0x29, 0x46, 0x29, 0x46, +0x29, 0x46, 0x29, 0x46, 0x31, 0x67, 0x31, 0xA7, +0x39, 0xA7, 0x39, 0xC8, 0x41, 0xE9, 0x42, 0x09, +0x4A, 0x2A, 0x4A, 0x4A, 0x4A, 0x4A, 0x52, 0x8A, +0x6B, 0x0C, 0x8C, 0x2F, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD0, 0xAD, 0x12, +0xBD, 0xD4, 0xBD, 0xD4, 0xCE, 0x35, 0xD6, 0x96, +0xD6, 0x96, 0xD6, 0x76, 0xBD, 0xB4, 0xC5, 0xF5, +0xC6, 0x16, 0xC6, 0x16, 0xBD, 0xD4, 0xBD, 0xB4, +0xB5, 0x52, 0xCE, 0x35, 0xDE, 0x96, 0xBD, 0xB3, +0xB5, 0x52, 0xBD, 0x73, 0xAD, 0x12, 0x94, 0x4F, +0x8C, 0x0D, 0xA4, 0xAF, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x31, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x73, +0xBD, 0xB4, 0xC5, 0xF4, 0xBD, 0xB3, 0xAD, 0x11, +0xAD, 0x52, 0x7B, 0xCD, 0x5A, 0xCA, 0x63, 0x0C, +0x63, 0x0C, 0x84, 0x10, 0x9C, 0xD3, 0x9C, 0xD3, +0x6B, 0x2D, 0x42, 0x29, 0x5A, 0xCB, 0x39, 0xE7, +0x39, 0xA6, 0x39, 0x87, 0xB5, 0x75, 0xDE, 0xDA, +0xAD, 0x32, 0xC5, 0xF4, 0xC6, 0x15, 0xBD, 0xD3, +0xC6, 0x14, 0xB5, 0x92, 0xC6, 0x14, 0xBD, 0xD4, +0x8D, 0x6E, 0x9D, 0xD0, 0x8D, 0x2E, 0x74, 0x4C, +0x7C, 0x2C, 0x94, 0xCF, 0x8C, 0x4E, 0x94, 0x4E, +0xAD, 0x31, 0xBD, 0xD3, 0xA5, 0x4E, 0x74, 0x47, +0x84, 0xCA, 0x9D, 0x4E, 0xBD, 0xD2, 0xC5, 0xF4, +0xC5, 0xD4, 0xD6, 0x76, 0xBD, 0x72, 0xAC, 0xCF, +0xA4, 0x8E, 0x93, 0xCC, 0x93, 0xEC, 0x83, 0x6A, +0x83, 0x8B, 0x83, 0x8A, 0x83, 0x8A, 0x83, 0xAB, +0x83, 0xAB, 0x83, 0x8A, 0x94, 0x0C, 0x94, 0x0C, +0x93, 0xEC, 0x9C, 0x2D, 0x9C, 0x4D, 0xA4, 0x8E, +0xAC, 0xAF, 0xAC, 0xAF, 0xBD, 0x30, 0xBD, 0x31, +0xB5, 0x10, 0xBD, 0x51, 0xBD, 0x30, 0xBD, 0x30, +0xB5, 0x10, 0xB4, 0xF0, 0xAC, 0xCF, 0xAC, 0xF0, +0xB5, 0x10, 0xBD, 0x30, 0xBD, 0x50, 0xB5, 0x10, +0xBD, 0x30, 0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x51, +0xB5, 0x30, 0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x10, +0xAD, 0x0F, 0xAC, 0xEF, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xD0, 0xAC, 0xD0, 0xAD, 0x11, +0xBD, 0x72, 0xBD, 0x93, 0xBD, 0x72, 0xB5, 0x52, +0xB5, 0x10, 0xC5, 0x71, 0xBD, 0x31, 0x7B, 0x6A, +0xAD, 0x10, 0xC5, 0xB3, 0xBD, 0x72, 0xC5, 0x92, +0xCD, 0xF4, 0xD6, 0x35, 0xB5, 0x32, 0x9C, 0xB0, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xF1, 0xB5, 0x73, +0x5A, 0xC9, 0x41, 0xE7, 0x39, 0xC6, 0x39, 0xC7, +0x41, 0xE7, 0x52, 0x8A, 0x5A, 0xCB, 0x62, 0xEB, +0x63, 0x0C, 0x6B, 0x6D, 0x94, 0x71, 0xA4, 0xF4, +0x9C, 0xF4, 0x9C, 0xD3, 0xC6, 0x18, 0xAD, 0x34, +0x7B, 0xAF, 0x8C, 0x50, 0xBD, 0xD5, 0xD6, 0x56, +0xCE, 0x35, 0xCE, 0x35, 0xD6, 0x56, 0xA4, 0xD0, +0xB5, 0x30, 0x83, 0xCC, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x52, 0xA5, 0x11, 0xA4, 0xF1, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x93, 0xB5, 0x93, 0xB5, 0x53, +0x9C, 0xD0, 0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x53, +0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xF5, 0xCE, 0x36, +0xCE, 0x76, 0xBD, 0xD5, 0x5A, 0xCA, 0x29, 0x65, +0x5A, 0xEC, 0xCE, 0x59, 0xAD, 0x76, 0x8C, 0x52, +0x52, 0x8A, 0x42, 0x08, 0x52, 0xAA, 0x5A, 0xEB, +0x63, 0x2C, 0x5A, 0xEC, 0x52, 0x8A, 0x4A, 0x49, +0x52, 0x69, 0x6B, 0x2D, 0xA4, 0xF3, 0x7B, 0x8E, +0x73, 0x4D, 0x9C, 0x71, 0xCE, 0x16, 0xC5, 0xD4, +0xBD, 0x92, 0xC5, 0xB2, 0xC5, 0xD3, 0xA4, 0xD0, +0xB5, 0x31, 0xC5, 0x92, 0xB5, 0x0F, 0xC5, 0x92, +0xD6, 0x34, 0xC5, 0xB2, 0xC5, 0x92, 0xBD, 0x51, +0xC5, 0x92, 0xB5, 0x10, 0xAC, 0xD0, 0xBD, 0x72, +0xCD, 0xB3, 0xBD, 0x71, 0x9C, 0xAF, 0x9C, 0xB0, +0xA4, 0xF1, 0xA4, 0xD1, 0x6B, 0x4C, 0x29, 0x25, +0x20, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x19, 0x04, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xA3, 0x59, 0x46, +0x89, 0x67, 0x89, 0x67, 0x38, 0xC3, 0x18, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xA3, 0x18, 0xA3, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xA3, 0x18, 0xC3, 0x18, 0xC4, 0x18, 0xE4, +0x20, 0xE4, 0x21, 0x05, 0x20, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x25, 0x21, 0x25, 0x21, 0x05, 0x21, 0x25, +0x29, 0x25, 0x29, 0x46, 0x21, 0x25, 0x21, 0x05, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x25, 0x29, 0x26, +0x29, 0x25, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x05, 0x21, 0x05, 0x21, 0x25, 0x21, 0x25, +0x21, 0x05, 0x21, 0x25, 0x29, 0x46, 0x31, 0xA7, +0x39, 0xC8, 0x31, 0xA7, 0x39, 0xA8, 0x39, 0xC8, +0x41, 0xE9, 0x42, 0x09, 0x42, 0x2A, 0x4A, 0x2A, +0x42, 0x29, 0x4A, 0x29, 0x63, 0x0C, 0x94, 0x50, +0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x53, 0xAC, 0xF1, +0xA4, 0xB0, 0x9C, 0x6F, 0x94, 0x2E, 0x8B, 0xED, +0x83, 0xED, 0x83, 0xCD, 0x83, 0xCD, 0x84, 0x0E, +0x9C, 0x70, 0x94, 0x6F, 0x83, 0xEE, 0x9C, 0xB0, +0xA4, 0xD0, 0xB5, 0x32, 0xAD, 0x11, 0x94, 0x6E, +0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x90, 0xA4, 0xF1, +0xA4, 0xD1, 0xAD, 0x31, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x52, 0xAD, 0x12, 0x9C, 0x8F, +0xBD, 0x93, 0xC5, 0xD3, 0xA4, 0xD0, 0xB5, 0x73, +0x9C, 0x8F, 0x73, 0x8C, 0x73, 0x8D, 0x62, 0xEB, +0x5A, 0xEB, 0x84, 0x10, 0xBD, 0xB6, 0x9C, 0xF3, +0x73, 0x6E, 0x4A, 0x49, 0x63, 0x2D, 0x4A, 0x49, +0x39, 0xC7, 0x39, 0xA7, 0xAD, 0x55, 0xAD, 0x34, +0x83, 0xCF, 0xAD, 0x33, 0xCE, 0x15, 0xCE, 0x35, +0xC6, 0x14, 0xBD, 0xD3, 0xC6, 0x14, 0xC6, 0x14, +0x74, 0xA9, 0x6C, 0x68, 0x6C, 0x49, 0x74, 0x4B, +0x94, 0xCF, 0xC6, 0x55, 0xBD, 0xF5, 0xB5, 0x72, +0xBD, 0xB3, 0xB5, 0x71, 0x8C, 0xAB, 0x84, 0xAA, +0xB6, 0x11, 0xAD, 0x91, 0xC5, 0xF3, 0xBD, 0x93, +0xC5, 0xD4, 0xDE, 0x96, 0xBD, 0x72, 0xB4, 0xCF, +0x93, 0xEB, 0xB4, 0x6E, 0xBC, 0xCF, 0x8B, 0x8B, +0x7B, 0x4A, 0x9C, 0x6E, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xA4, 0xAF, 0xA4, 0xAF, 0xAC, 0xCF, +0xA4, 0x8E, 0x94, 0x2D, 0x94, 0x0C, 0x94, 0x2D, +0x94, 0x2D, 0x9C, 0x4E, 0xAC, 0xF0, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x6D, 0xB4, 0xEF, 0x9C, 0x2C, +0x8B, 0xEC, 0xA4, 0x8E, 0x8B, 0xCB, 0x8B, 0xEC, +0x9C, 0x4D, 0x94, 0x2D, 0x9C, 0x4D, 0xA4, 0x8E, +0x8B, 0xCB, 0x9C, 0x4D, 0xA4, 0x8E, 0xA4, 0x6D, +0xAC, 0xCE, 0xAC, 0xAE, 0xA4, 0x8E, 0x9C, 0x4D, +0x94, 0x0C, 0x9C, 0x2D, 0x94, 0x0C, 0x9C, 0x2D, +0xA4, 0x8E, 0xBD, 0x51, 0xC5, 0x71, 0xCD, 0xB2, +0xC5, 0x51, 0xC5, 0x71, 0xC5, 0x91, 0xC5, 0x71, +0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x30, +0xAC, 0xCE, 0xAC, 0xAE, 0xA4, 0xAE, 0xA4, 0x8D, +0xA4, 0x8E, 0xAC, 0xAE, 0xA4, 0x8E, 0x9C, 0x6E, +0x9C, 0x8F, 0x9C, 0x6F, 0x9C, 0x6E, 0xB5, 0x10, +0x8C, 0x2E, 0x4A, 0x07, 0x39, 0xC6, 0x39, 0xA6, +0x42, 0x08, 0x52, 0x8A, 0x5A, 0xAA, 0x6B, 0x4C, +0x63, 0x2C, 0x63, 0x2C, 0x8C, 0x31, 0x9C, 0xB3, +0x9C, 0xB3, 0xAD, 0x55, 0xC6, 0x18, 0xAD, 0x35, +0x7B, 0xCF, 0x5A, 0xCB, 0x7B, 0xAE, 0xD6, 0x77, +0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x56, 0xA4, 0xCF, +0xA4, 0xCF, 0x83, 0xCC, 0x9C, 0xD0, 0xA4, 0xD0, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xB4, +0xC5, 0xD5, 0xC6, 0x15, 0xC6, 0x15, 0xBD, 0xD4, +0xB5, 0x73, 0xB5, 0x94, 0xBD, 0xD4, 0xB5, 0x73, +0xB5, 0x93, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xD4, +0xB5, 0x93, 0xBD, 0xB4, 0x83, 0xED, 0x7B, 0xCE, +0x9C, 0xB2, 0xC6, 0x18, 0xAD, 0x56, 0x8C, 0x52, +0x31, 0xA7, 0x31, 0xA6, 0x42, 0x08, 0x4A, 0x69, +0x63, 0x0B, 0x6B, 0x4D, 0x6B, 0x4D, 0x63, 0x0C, +0x63, 0x0C, 0x7B, 0xCF, 0xD6, 0x79, 0xA4, 0xF3, +0x6B, 0x0C, 0x94, 0x71, 0x9C, 0xB2, 0xCE, 0x17, +0xBD, 0x73, 0xBD, 0x92, 0xB5, 0x52, 0xA4, 0xD0, +0xB5, 0x31, 0xC5, 0x92, 0xBD, 0x51, 0xCD, 0xF3, +0xD6, 0x34, 0xD5, 0xF4, 0xC5, 0xB3, 0xC5, 0xB2, +0xC5, 0xB2, 0xC5, 0xB2, 0xB5, 0x10, 0xB5, 0x31, +0xC5, 0xB3, 0xB5, 0x31, 0x9C, 0x8F, 0xAD, 0x32, +0xBD, 0x73, 0xAD, 0x32, 0x7B, 0xCD, 0x39, 0xA7, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xC4, 0x28, 0xC4, 0x71, 0x46, +0x89, 0x67, 0x69, 0x25, 0x20, 0x62, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x20, 0xE4, +0x20, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x05, 0x29, 0x46, 0x29, 0x46, 0x21, 0x25, +0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x20, 0xE4, 0x20, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x20, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x31, 0x67, +0x31, 0xA7, 0x31, 0x87, 0x31, 0x87, 0x31, 0xA8, +0x39, 0xC8, 0x39, 0xE9, 0x42, 0x09, 0x42, 0x09, +0x4A, 0x2A, 0x42, 0x2A, 0x4A, 0x2A, 0x52, 0x8B, +0x7B, 0x8E, 0xA4, 0xD2, 0xAC, 0xF2, 0xB5, 0x53, +0xAD, 0x12, 0xA4, 0xD1, 0xAC, 0xF1, 0xAC, 0xF1, +0xA4, 0xB0, 0xAC, 0xF2, 0xAC, 0xF1, 0xAD, 0x12, +0xAC, 0xF1, 0xAD, 0x12, 0xB5, 0x12, 0xB5, 0x12, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x53, +0xBD, 0x73, 0xB5, 0x52, 0xAD, 0x12, 0xAD, 0x12, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x32, 0xAC, 0xD0, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xD0, 0xAC, 0xF1, 0x94, 0x4F, +0x9C, 0xB0, 0xA4, 0xD1, 0x94, 0x6F, 0xA4, 0xF1, +0x9C, 0x90, 0x8C, 0x2E, 0x94, 0x4F, 0x73, 0x6C, +0x5A, 0xCB, 0x7B, 0xAF, 0x94, 0x71, 0x73, 0x6E, +0x4A, 0x49, 0x63, 0x0C, 0x84, 0x10, 0x5A, 0xCB, +0x4A, 0x29, 0x31, 0x66, 0x7B, 0xAF, 0x83, 0xCF, +0x94, 0x31, 0x73, 0x4D, 0x83, 0xCE, 0xC5, 0xF5, +0xC6, 0x14, 0xCE, 0x55, 0xDE, 0x97, 0xBD, 0xB4, +0x5C, 0x04, 0x4B, 0xA4, 0x7C, 0xAC, 0x84, 0x8E, +0xA5, 0x91, 0xA5, 0x91, 0xD6, 0xD8, 0xBD, 0xD4, +0xBD, 0xB3, 0x84, 0x2B, 0x6B, 0xE6, 0x9D, 0x6D, +0xBE, 0x12, 0x9C, 0xEE, 0xBD, 0xB2, 0xBD, 0x92, +0xC5, 0xD3, 0xDE, 0x76, 0xB5, 0x31, 0xA4, 0x8E, +0x8B, 0x69, 0x93, 0x8A, 0x8B, 0x6A, 0x93, 0xCC, +0xA4, 0x6E, 0xB5, 0x10, 0xB5, 0x11, 0xA4, 0xAF, +0xAC, 0xF0, 0xA4, 0xAF, 0xA4, 0x8F, 0xAC, 0xCF, +0xAC, 0xF0, 0xA4, 0xD0, 0x94, 0x2D, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x52, 0xBD, 0x72, 0xB5, 0x31, +0xB5, 0x31, 0xA4, 0xAF, 0xB5, 0x30, 0x94, 0x0D, +0x83, 0xCC, 0x9C, 0x8F, 0x83, 0xCC, 0x83, 0xCC, +0x83, 0xED, 0x94, 0x6F, 0x8C, 0x0D, 0x8C, 0x2D, +0x7B, 0x8B, 0x94, 0x4E, 0x9C, 0x6E, 0xA4, 0xAF, +0xA4, 0x8E, 0xA4, 0xCF, 0xA4, 0xAE, 0xA4, 0xCF, +0xA4, 0xAF, 0xB5, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xBD, 0x31, 0xB4, 0xEF, 0xC5, 0x72, +0xBD, 0x71, 0xCD, 0xB3, 0xC5, 0x92, 0xD5, 0xF4, +0xCD, 0xD3, 0xD6, 0x14, 0xD6, 0x34, 0xD6, 0x14, +0xC5, 0x92, 0xB5, 0x30, 0xBD, 0x72, 0xBD, 0x72, +0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x51, 0xAC, 0xEF, +0xA4, 0xAF, 0xBD, 0x52, 0xBD, 0x31, 0xBD, 0x31, +0xAC, 0xF0, 0x6B, 0x0A, 0x39, 0xA6, 0x39, 0xA6, +0x39, 0xC7, 0x4A, 0x28, 0x5A, 0xAA, 0x5A, 0xAA, +0x5A, 0xAA, 0x52, 0x8A, 0x6B, 0x4D, 0x7B, 0xAF, +0x7B, 0xAF, 0xAD, 0x76, 0x9C, 0xD3, 0xC5, 0xF8, +0x8C, 0x31, 0x5A, 0xCB, 0x52, 0x89, 0xA4, 0xF1, +0xA4, 0x8F, 0x8B, 0xEC, 0x8B, 0xCB, 0x83, 0x6A, +0x9C, 0x4D, 0x8C, 0x0D, 0x8B, 0xED, 0x83, 0xAC, +0x73, 0x4A, 0x7B, 0x8B, 0x83, 0xAC, 0x83, 0xCC, +0x7B, 0xAC, 0x7B, 0x8C, 0x73, 0x8B, 0x7B, 0xAC, +0x7B, 0xAC, 0x83, 0xED, 0x8C, 0x2E, 0x8C, 0x0E, +0x8C, 0x4F, 0x84, 0x0D, 0x83, 0xED, 0x7B, 0xAC, +0x83, 0xCC, 0x8C, 0x4E, 0x63, 0x0A, 0x8C, 0x2F, +0xB5, 0x75, 0xBD, 0xF7, 0xB5, 0x76, 0x8C, 0x72, +0x39, 0xC7, 0x39, 0xE7, 0x31, 0xA6, 0x39, 0xC6, +0x4A, 0x69, 0x52, 0x8A, 0x63, 0x0C, 0x63, 0x0C, +0x63, 0x0C, 0x52, 0xAB, 0x6B, 0x4D, 0x83, 0xF0, +0x42, 0x08, 0x73, 0x8E, 0x94, 0x51, 0x94, 0x51, +0xC5, 0xB6, 0xB5, 0x32, 0x9C, 0x8F, 0xA4, 0xB0, +0xAD, 0x11, 0xC5, 0x92, 0xC5, 0x71, 0xC5, 0xB2, +0xCD, 0xD3, 0xCD, 0xB2, 0xCD, 0xF3, 0xD6, 0x35, +0xD6, 0x14, 0xD5, 0xF3, 0xCD, 0xB3, 0xBD, 0x51, +0xC5, 0x92, 0xBD, 0x52, 0xAD, 0x11, 0xB5, 0x52, +0xBD, 0x92, 0xB5, 0x31, 0x8C, 0x2F, 0x52, 0x8A, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, 0x19, 0x04, +0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, 0x18, 0xC4, +0x10, 0x83, 0x10, 0xA3, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x38, 0xE4, 0x69, 0x25, +0x71, 0x25, 0x40, 0xE4, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xA3, 0x18, 0xC3, 0x18, 0xC4, 0x21, 0x04, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x20, 0xE4, 0x21, 0x25, 0x21, 0x25, +0x21, 0x05, 0x18, 0xC4, 0x18, 0xC3, 0x18, 0xC3, +0x18, 0xC4, 0x18, 0xA4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x29, 0x46, 0x29, 0x25, +0x20, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x29, 0x66, +0x31, 0x87, 0x29, 0x67, 0x31, 0x67, 0x31, 0x87, +0x31, 0x67, 0x31, 0x87, 0x39, 0xC8, 0x39, 0xC8, +0x41, 0xE9, 0x4A, 0x2A, 0x4A, 0x29, 0x42, 0x2A, +0x4A, 0x4A, 0x5A, 0xAB, 0x73, 0x6D, 0x8C, 0x2F, +0x7B, 0x6C, 0x7B, 0xAD, 0x83, 0xCD, 0x9C, 0x70, +0x94, 0x0E, 0x73, 0x4B, 0x7B, 0x6C, 0x83, 0xAC, +0x83, 0xAD, 0x73, 0x4B, 0x73, 0x2B, 0x62, 0xC9, +0x6A, 0xEA, 0x83, 0xAD, 0x6B, 0x0A, 0x73, 0x2B, +0x83, 0x8C, 0x83, 0xCD, 0xA4, 0xB0, 0x9C, 0x6F, +0x94, 0x2E, 0xA4, 0xB0, 0xAC, 0xD0, 0xB5, 0x32, +0xC5, 0xD4, 0xCD, 0xB4, 0xCD, 0xD4, 0xB5, 0x32, +0xCD, 0xB4, 0xCD, 0xF5, 0xCE, 0x15, 0xC5, 0xF5, +0xC5, 0xF5, 0xCD, 0xF5, 0xC5, 0xD5, 0xC5, 0xD4, +0xB5, 0x53, 0xBD, 0x94, 0xBD, 0x52, 0xBD, 0x73, +0x7B, 0xAD, 0x6B, 0x4D, 0x5A, 0xEB, 0x4A, 0x49, +0x39, 0xA7, 0x5A, 0xCB, 0x63, 0x0C, 0x73, 0x8E, +0x63, 0x0C, 0x21, 0x05, 0x62, 0xEC, 0x83, 0xCF, +0xCE, 0x17, 0xCE, 0x18, 0xAD, 0x14, 0xCE, 0x17, +0xC5, 0xD5, 0xCE, 0x36, 0xC5, 0xB5, 0x94, 0x4F, +0x53, 0xA6, 0x8D, 0x0F, 0x9D, 0x72, 0x84, 0x4E, +0x9D, 0x4F, 0x95, 0x2E, 0xAD, 0xD3, 0xCE, 0xB7, +0xC6, 0x34, 0x84, 0xA9, 0x8D, 0x08, 0x8D, 0x0B, +0x9D, 0x4F, 0x8C, 0x8D, 0xBD, 0xF3, 0xBD, 0xD3, +0xC5, 0xF4, 0xDE, 0x76, 0xCD, 0xB3, 0xA4, 0x4D, +0x9B, 0xCB, 0x8B, 0x6B, 0x72, 0xC9, 0x62, 0xA9, +0x73, 0x0A, 0x9C, 0x4E, 0xA4, 0x8F, 0x83, 0xCC, +0x7B, 0x8B, 0x8B, 0xED, 0x94, 0x2E, 0x83, 0xCC, +0x9C, 0x6E, 0xA4, 0xF0, 0x94, 0x4E, 0xAD, 0x31, +0xB5, 0x52, 0xBD, 0x72, 0xBD, 0x52, 0xBD, 0x72, +0xBD, 0x72, 0xAC, 0xAF, 0xBD, 0x30, 0xA4, 0xAF, +0x8C, 0x2E, 0x94, 0x4E, 0xA4, 0xD1, 0xA4, 0xD1, +0x94, 0x6F, 0x8C, 0x0D, 0x83, 0xED, 0x94, 0x6F, +0x8C, 0x2E, 0x94, 0x6F, 0x94, 0x6E, 0xA4, 0xD0, +0x94, 0x4E, 0x8C, 0x2D, 0x9C, 0xAF, 0x9C, 0xAF, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x92, +0xB5, 0x10, 0xBD, 0x30, 0xA4, 0xAE, 0x94, 0x2D, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0x8C, 0x7B, 0x8B, +0x7B, 0xAB, 0x7B, 0xAC, 0x83, 0xEC, 0x83, 0xCC, +0x62, 0xE9, 0x6B, 0x0A, 0x83, 0xCD, 0x8C, 0x0E, +0x83, 0xED, 0x73, 0x6B, 0x8C, 0x0D, 0x62, 0xE9, +0x6B, 0x2B, 0x7B, 0x8C, 0x7B, 0x8C, 0x73, 0x2A, +0x7B, 0xAC, 0x94, 0x90, 0x52, 0x69, 0x39, 0xC6, +0x31, 0xA6, 0x42, 0x08, 0x5A, 0x8A, 0x5A, 0xAA, +0x6B, 0x2C, 0x5A, 0xAA, 0x52, 0x8A, 0x5A, 0xCB, +0x8C, 0x51, 0x94, 0x92, 0xB5, 0x96, 0xD6, 0xBB, +0xAD, 0x35, 0x63, 0x2D, 0x42, 0x08, 0x62, 0xEA, +0x9C, 0x6F, 0xA4, 0x6E, 0x94, 0x0C, 0x9C, 0x4D, +0xA4, 0xAF, 0xA4, 0x8E, 0xA4, 0x8F, 0xA4, 0x8E, +0x9C, 0x6E, 0xA4, 0x8F, 0xAC, 0xD0, 0xAC, 0xF0, +0xB5, 0x11, 0xB5, 0x11, 0xAC, 0xF0, 0xAD, 0x10, +0xB5, 0x51, 0xB5, 0x51, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, +0x9C, 0x8F, 0x8C, 0x2E, 0x83, 0xED, 0x9C, 0x90, +0xC5, 0xF6, 0xB5, 0x96, 0xAD, 0x35, 0x7B, 0xF0, +0x31, 0x86, 0x31, 0xA6, 0x39, 0xE7, 0x31, 0x85, +0x31, 0xC6, 0x42, 0x08, 0x5A, 0xEB, 0x5A, 0xCB, +0x5A, 0xCB, 0x5A, 0xCB, 0x5A, 0xEB, 0x63, 0x0C, +0x52, 0x8A, 0x7B, 0xAF, 0x62, 0xCB, 0x73, 0x4E, +0x83, 0xEF, 0xAD, 0x13, 0x9C, 0x90, 0xA4, 0xB0, +0xA4, 0x8F, 0xC5, 0x92, 0xBD, 0x71, 0xC5, 0x92, +0xCD, 0xD3, 0xBD, 0x72, 0xAC, 0xF0, 0xB5, 0x10, +0xBD, 0x51, 0xD6, 0x34, 0xDE, 0x34, 0xCD, 0xB3, +0xCD, 0xB3, 0xBD, 0x51, 0xB5, 0x52, 0xAD, 0x31, +0xB5, 0x51, 0xB5, 0x52, 0x94, 0x6F, 0x83, 0xEE, +0x39, 0xC7, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x41, 0x05, 0x61, 0x25, +0x59, 0x04, 0x30, 0xC3, 0x20, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xC4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xA3, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x21, 0x05, +0x20, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, +0x31, 0x87, 0x31, 0x87, 0x29, 0x46, 0x29, 0x46, +0x29, 0x67, 0x31, 0x67, 0x31, 0x87, 0x39, 0xA8, +0x39, 0xC8, 0x41, 0xE9, 0x42, 0x09, 0x4A, 0x2A, +0x42, 0x09, 0x42, 0x09, 0x4A, 0x6A, 0x63, 0x0C, +0x7B, 0xAE, 0x94, 0x4F, 0x94, 0x2F, 0x9C, 0x90, +0x94, 0x70, 0x83, 0xCE, 0x94, 0x4F, 0x8C, 0x0E, +0x83, 0xCD, 0x83, 0xEE, 0x73, 0x4B, 0x6B, 0x2B, +0x6B, 0x2B, 0x6A, 0xEA, 0x5A, 0x88, 0x62, 0xCA, +0x83, 0xAD, 0x7B, 0xAD, 0x7B, 0xAC, 0x7B, 0xAC, +0x83, 0xED, 0x9C, 0x90, 0xA4, 0xB0, 0xAC, 0xD1, +0xBD, 0x93, 0xB5, 0x11, 0xBD, 0x52, 0xC5, 0x93, +0xC5, 0x72, 0xB5, 0x31, 0x9C, 0x4E, 0x94, 0x0E, +0xA4, 0xB0, 0xAC, 0xF1, 0xAD, 0x11, 0xBD, 0xB3, +0xAD, 0x11, 0xAC, 0xD0, 0x9C, 0x6E, 0xA4, 0xD1, +0x9C, 0x91, 0x73, 0x8D, 0x4A, 0x49, 0x4A, 0x29, +0x31, 0x86, 0x4A, 0x29, 0x73, 0x8E, 0x83, 0xCF, +0x6B, 0x4D, 0x29, 0x46, 0x4A, 0x29, 0x73, 0x6D, +0xB5, 0x34, 0xC5, 0x95, 0xCD, 0xD6, 0xBD, 0x74, +0x8B, 0xEF, 0xA4, 0xB2, 0x9C, 0x71, 0xA4, 0xB1, +0x9D, 0x91, 0xA5, 0xB3, 0xB6, 0x35, 0x7C, 0x4E, +0x8C, 0xCC, 0x84, 0xCA, 0x9D, 0x90, 0xA5, 0xD1, +0x9D, 0x6C, 0x95, 0x47, 0x7C, 0x85, 0x7C, 0x88, +0xB5, 0xD1, 0xB5, 0xB2, 0xC6, 0x14, 0xC6, 0x14, +0xBD, 0xB2, 0xCE, 0x34, 0xC5, 0x92, 0xA4, 0x6D, +0x93, 0xAB, 0x83, 0x4B, 0x5A, 0x68, 0x52, 0x68, +0x52, 0x48, 0x62, 0xC9, 0x62, 0xC9, 0x6B, 0x2B, +0x5A, 0xA9, 0x6B, 0x4B, 0x94, 0x4F, 0x94, 0x4F, +0x83, 0xCD, 0x9C, 0xB0, 0x73, 0x6B, 0xAD, 0x31, +0xBD, 0x72, 0xB5, 0x31, 0xB5, 0x31, 0xAC, 0xF0, +0xC5, 0x93, 0x9C, 0x6E, 0xB5, 0x10, 0x9C, 0x6E, +0x7B, 0xAC, 0x94, 0x6F, 0x9C, 0xD1, 0x9C, 0xD1, +0xBD, 0xB4, 0x9C, 0xB0, 0x8C, 0x4F, 0x94, 0x6F, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD0, 0x94, 0x4E, 0x9C, 0x8F, +0xAC, 0xF1, 0xB5, 0x52, 0xB5, 0x52, 0x7B, 0x6B, +0x73, 0x49, 0xBD, 0x30, 0xAC, 0xCF, 0xAD, 0x11, +0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x53, 0xA4, 0xF1, +0xA4, 0xD1, 0x9C, 0xB0, 0x8C, 0x2E, 0x94, 0x8F, +0x94, 0x90, 0x94, 0xB0, 0x8C, 0x4F, 0x8C, 0x2E, +0x8C, 0x0E, 0x84, 0x0E, 0x83, 0xEE, 0x84, 0x0E, +0x7B, 0xEE, 0x7B, 0xEE, 0x73, 0x8D, 0x63, 0x0B, +0x7B, 0xAD, 0x8C, 0x2F, 0x83, 0xCE, 0x4A, 0x48, +0x39, 0xC7, 0x41, 0xE7, 0x5A, 0x8A, 0x5A, 0xCB, +0x52, 0x8A, 0x41, 0xE7, 0x52, 0x8A, 0x73, 0xAE, +0x94, 0xB2, 0xA5, 0x35, 0xBD, 0xD7, 0xCE, 0x59, +0xB5, 0xB7, 0x8C, 0x31, 0x73, 0x8F, 0x5A, 0xCB, +0x62, 0xEA, 0xBD, 0x93, 0xB5, 0x31, 0xBD, 0x72, +0xB5, 0x31, 0x8B, 0xCC, 0x83, 0x8A, 0x83, 0xAB, +0x7B, 0x8A, 0x7B, 0x6A, 0x8B, 0xCC, 0x7B, 0x6A, +0x83, 0xCC, 0x7B, 0x8A, 0x8B, 0xCB, 0xA4, 0xAF, +0xBD, 0x72, 0xB5, 0x10, 0xB5, 0x10, 0xB4, 0xEF, +0xA4, 0x8E, 0xAC, 0xAE, 0x9C, 0x6D, 0x83, 0xCB, +0xA4, 0xD0, 0xB5, 0x52, 0x9C, 0x6F, 0x8B, 0xED, +0xBD, 0xD6, 0xAD, 0x76, 0xA5, 0x14, 0x7B, 0xAF, +0x39, 0xC7, 0x29, 0x44, 0x31, 0xA6, 0x42, 0x08, +0x39, 0xC7, 0x39, 0xE7, 0x5A, 0xCB, 0x4A, 0x69, +0x52, 0x89, 0x52, 0xAA, 0x5A, 0xEC, 0x6B, 0x4E, +0x73, 0x6E, 0xCE, 0x39, 0xCE, 0x59, 0x6B, 0x2D, +0x62, 0xEC, 0x7B, 0x8D, 0xAD, 0x33, 0x9C, 0x6F, +0xAD, 0x12, 0x9C, 0x6F, 0x8C, 0x0D, 0x94, 0x2D, +0x94, 0x2D, 0x8B, 0xED, 0x8B, 0xED, 0x94, 0x2D, +0x94, 0x2D, 0x9C, 0x6E, 0xA4, 0xAF, 0xA4, 0xAF, +0xAC, 0xF0, 0xA4, 0xD0, 0xAC, 0xF0, 0xAC, 0xF0, +0xBD, 0x72, 0xBD, 0x72, 0xAD, 0x11, 0x9C, 0xB1, +0x52, 0x8A, 0x29, 0x25, 0x19, 0x04, 0x21, 0x04, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC3, 0x18, 0xC3, +0x18, 0xE5, 0x18, 0xE4, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x41, 0x05, 0x58, 0xE4, +0x48, 0xE4, 0x30, 0xE4, 0x20, 0xE4, 0x21, 0x04, +0x21, 0x05, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x20, 0xE4, 0x20, 0xE5, 0x20, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x20, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x20, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x21, 0x25, 0x29, 0x66, 0x29, 0x46, 0x29, 0x46, +0x29, 0x46, 0x29, 0x46, 0x29, 0x67, 0x31, 0x87, +0x31, 0x87, 0x31, 0xA8, 0x41, 0xE9, 0x42, 0x0A, +0x42, 0x2A, 0x42, 0x09, 0x42, 0x09, 0x4A, 0x4A, +0x5A, 0xAB, 0x7B, 0x8E, 0x94, 0x2F, 0x94, 0x4F, +0x94, 0x4F, 0xA4, 0x90, 0x9C, 0x70, 0x9C, 0x70, +0x94, 0x0E, 0xA4, 0xB0, 0x94, 0x2E, 0x7B, 0x8C, +0x94, 0x0E, 0x94, 0x0F, 0x73, 0x2B, 0x73, 0x4C, +0x8B, 0xEE, 0x8C, 0x2F, 0x83, 0xCD, 0x83, 0xAD, +0x83, 0xCD, 0x8C, 0x2E, 0xAC, 0xF1, 0xB5, 0x12, +0xB5, 0x31, 0xA4, 0x8F, 0xA4, 0x8F, 0xAC, 0xF0, +0xBD, 0x51, 0xC5, 0x72, 0x9C, 0x6E, 0x94, 0x2E, +0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x32, 0xAC, 0xF0, +0x9C, 0x4E, 0x94, 0x0D, 0x94, 0x2E, 0x94, 0x4E, +0x94, 0x2F, 0x8C, 0x0F, 0x5A, 0xCB, 0x62, 0xEC, +0x39, 0xA7, 0x39, 0xE8, 0x7B, 0xCF, 0x7B, 0xCF, +0x84, 0x10, 0x5A, 0xCB, 0x6B, 0x2D, 0x83, 0xCF, +0x73, 0x4D, 0x8B, 0xCF, 0x9C, 0x71, 0x83, 0xCE, +0xA4, 0xD2, 0xAD, 0x13, 0xA4, 0xD2, 0xBD, 0x52, +0xA5, 0xB4, 0x9D, 0x71, 0x9D, 0x70, 0xA5, 0xD2, +0x84, 0xCB, 0x74, 0x88, 0x8D, 0x6D, 0x9D, 0xAD, +0x85, 0x06, 0x8D, 0x47, 0x84, 0xC7, 0x74, 0x47, +0x84, 0x2B, 0x94, 0xCE, 0xA5, 0x2F, 0x8C, 0xAD, +0x9D, 0x2F, 0xCE, 0x34, 0xAC, 0xEF, 0xA4, 0x6D, +0xBD, 0x30, 0x9C, 0x4E, 0x62, 0xA9, 0x6B, 0x4C, +0x73, 0x8D, 0x62, 0xEB, 0x52, 0x89, 0x6B, 0x6C, +0x62, 0xCA, 0x52, 0x69, 0x6B, 0x4B, 0x6B, 0x4C, +0x5A, 0xA9, 0x5A, 0xCA, 0x5A, 0xA9, 0x94, 0x6F, +0xA4, 0xF0, 0xAD, 0x11, 0xB5, 0x31, 0xA4, 0xD0, +0xBD, 0x73, 0x8C, 0x0C, 0xB5, 0x10, 0xB5, 0x31, +0x9C, 0xB0, 0x94, 0x8F, 0x8C, 0x2F, 0x5A, 0xEA, +0x9C, 0xB0, 0xC6, 0x16, 0xB5, 0x53, 0x94, 0x6F, +0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x32, +0xB5, 0x73, 0xB5, 0x73, 0xA4, 0xF1, 0x9C, 0xB0, +0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x31, 0x94, 0x6F, +0x83, 0xEC, 0xBD, 0x51, 0xAC, 0xCE, 0xB5, 0x52, +0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0xD5, 0xBD, 0xB4, +0xBD, 0xD4, 0xC5, 0xF5, 0xB5, 0x73, 0xAD, 0x52, +0xB5, 0x94, 0xB5, 0x93, 0xAD, 0x32, 0xA5, 0x12, +0xAD, 0x33, 0xA5, 0x12, 0xAD, 0x53, 0xB5, 0x74, +0xAD, 0x53, 0xAD, 0x53, 0xB5, 0x74, 0xAD, 0x33, +0xA4, 0xD1, 0xA4, 0xB0, 0xAC, 0xF1, 0x5A, 0xA9, +0x4A, 0x48, 0x4A, 0x28, 0x4A, 0x28, 0x39, 0xA6, +0x52, 0x69, 0x6B, 0x4D, 0x62, 0xEC, 0x6B, 0x6E, +0x8C, 0x51, 0x9C, 0xF4, 0xB5, 0x97, 0xBD, 0xD7, +0xA5, 0x35, 0xC5, 0xF8, 0x94, 0xB3, 0x6B, 0x6D, +0x6B, 0x2B, 0xB5, 0x93, 0xA4, 0xCF, 0x83, 0xCD, +0xBD, 0xB4, 0x94, 0x4E, 0x73, 0x4A, 0x6B, 0x2A, +0x83, 0xCC, 0x8C, 0x0D, 0x83, 0xEC, 0x8C, 0x0D, +0xA4, 0xF1, 0x94, 0x6F, 0x8C, 0x0D, 0xAC, 0xF0, +0x94, 0x4D, 0x9C, 0x6E, 0x94, 0x2D, 0x8B, 0xCB, +0x83, 0x89, 0x94, 0x0B, 0x94, 0x0C, 0x7B, 0x8B, +0x7B, 0xAC, 0x9C, 0x8F, 0x8C, 0x2E, 0x8C, 0x2F, +0xC6, 0x17, 0xAD, 0x55, 0xA5, 0x14, 0x7B, 0xAF, +0x4A, 0x49, 0x29, 0x45, 0x18, 0xC3, 0x29, 0x65, +0x39, 0xE7, 0x42, 0x08, 0x42, 0x08, 0x39, 0xE7, +0x42, 0x28, 0x52, 0x8A, 0x5A, 0xCB, 0x5A, 0xEC, +0x63, 0x0C, 0x7B, 0xAE, 0xBD, 0xB7, 0xB5, 0x35, +0x94, 0x51, 0x6A, 0xEC, 0x6B, 0x0B, 0x7B, 0x6C, +0xBD, 0x53, 0xB5, 0x52, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x33, +0xB5, 0x32, 0xB5, 0x32, 0xAD, 0x12, 0xAC, 0xF1, +0xAC, 0xF1, 0xAD, 0x32, 0xB5, 0x32, 0xB5, 0x32, +0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xD0, 0x94, 0x2F, +0x62, 0xEB, 0x39, 0xC7, 0x29, 0x45, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xC3, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x41, 0x05, 0x50, 0xE4, +0x40, 0xC4, 0x28, 0xE4, 0x20, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x20, 0xE4, +0x21, 0x04, 0x20, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x21, 0x05, 0x21, 0x25, +0x21, 0x05, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x20, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x25, 0x29, 0x46, +0x29, 0x46, 0x21, 0x26, 0x29, 0x26, 0x29, 0x47, +0x29, 0x67, 0x31, 0x67, 0x39, 0xA8, 0x39, 0xE9, +0x42, 0x09, 0x42, 0x09, 0x42, 0x09, 0x3A, 0x09, +0x42, 0x4A, 0x52, 0x8B, 0x6B, 0x2C, 0x9C, 0x90, +0x9C, 0xB0, 0x9C, 0x4F, 0x9C, 0x4F, 0x6B, 0x0A, +0x62, 0xC9, 0x9C, 0x6F, 0xA4, 0x90, 0x8B, 0xED, +0x94, 0x2F, 0x9C, 0x70, 0x9C, 0x70, 0x7B, 0x6C, +0x8C, 0x0E, 0xA4, 0xD1, 0x9C, 0x90, 0x9C, 0x90, +0x94, 0x4F, 0x94, 0x4F, 0xA4, 0xB0, 0xAC, 0xF1, +0xB5, 0x32, 0xAC, 0xF0, 0x9C, 0x6E, 0xA4, 0x8F, +0xAC, 0xAF, 0xB4, 0xF0, 0xA4, 0x6F, 0xA4, 0xB0, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x32, 0xAD, 0x11, +0xAD, 0x11, 0xA4, 0xD0, 0x94, 0x2E, 0x94, 0x2E, +0x94, 0x4F, 0x94, 0x6F, 0x63, 0x0B, 0x52, 0x6A, +0x39, 0xC7, 0x31, 0xA7, 0x63, 0x2C, 0x5A, 0xCB, +0x73, 0xAE, 0x52, 0x8A, 0x52, 0x6A, 0x83, 0xCF, +0x83, 0xAF, 0x73, 0x4D, 0xAC, 0xD2, 0xB5, 0x34, +0xC5, 0xB6, 0xBD, 0x95, 0xAC, 0xF2, 0xEE, 0xD7, +0xAD, 0xB4, 0x9D, 0x70, 0x85, 0x0B, 0x8D, 0x4C, +0x8D, 0x0B, 0x74, 0x67, 0x7C, 0xA8, 0x8D, 0x28, +0x9D, 0xC9, 0x8D, 0x08, 0x9D, 0x4A, 0x6B, 0xC7, +0x6B, 0x88, 0x63, 0xA8, 0x6B, 0xE8, 0x95, 0x0D, +0xA5, 0x70, 0x6B, 0x68, 0x9C, 0x6C, 0xB5, 0x0F, +0xAD, 0x2F, 0x7B, 0x6A, 0x7B, 0x8C, 0xB5, 0x94, +0xAD, 0x33, 0x7B, 0xAD, 0x4A, 0x07, 0x42, 0x07, +0x52, 0x68, 0x52, 0x89, 0x42, 0x07, 0x41, 0xE7, +0x42, 0x07, 0x42, 0x07, 0x42, 0x07, 0x7B, 0xAC, +0x73, 0x6B, 0x73, 0x4B, 0x83, 0xED, 0x8C, 0x0D, +0xA4, 0xD0, 0x8B, 0xEC, 0xAC, 0xEF, 0xB5, 0x51, +0xB5, 0x52, 0x94, 0x6F, 0x94, 0x90, 0x8C, 0x4F, +0x94, 0x70, 0xA5, 0x12, 0xA4, 0xD1, 0xAD, 0x32, +0xAD, 0x33, 0xA5, 0x11, 0xAD, 0x11, 0xBD, 0xB4, +0xA4, 0xD0, 0xB5, 0x52, 0xB5, 0x52, 0x9C, 0xB0, +0x9C, 0xB0, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, +0x9C, 0x6E, 0xBD, 0x51, 0xAC, 0xEF, 0xC5, 0xB3, +0xCE, 0x15, 0xB5, 0x73, 0xAD, 0x52, 0xB5, 0x93, +0xC5, 0xF5, 0xC5, 0xF5, 0xCE, 0x15, 0xC5, 0xF5, +0xCE, 0x36, 0xC5, 0xF5, 0xAD, 0x32, 0xB5, 0x73, +0xAD, 0x53, 0xAD, 0x53, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0xD4, 0xAD, 0x53, 0xB5, 0x94, 0xBD, 0xD4, +0xB5, 0x73, 0xBD, 0x72, 0xB5, 0x31, 0x7B, 0x6B, +0x39, 0xC6, 0x31, 0x86, 0x31, 0x65, 0x4A, 0x49, +0x52, 0x8A, 0x5A, 0xCB, 0x73, 0x6E, 0x6B, 0x4D, +0x7B, 0xCF, 0x8C, 0x72, 0x9C, 0xD3, 0xA4, 0xF4, +0xB5, 0x97, 0xCE, 0x7A, 0xAD, 0x56, 0x8C, 0x51, +0xAD, 0x13, 0x8C, 0x4F, 0x52, 0x68, 0x39, 0xC6, +0xAD, 0x33, 0xAD, 0x32, 0x8C, 0x0D, 0x94, 0x4E, +0x8C, 0x2E, 0x9C, 0x8F, 0x94, 0x6F, 0x94, 0x8F, +0xA4, 0xD1, 0x9C, 0x8F, 0x8C, 0x2E, 0x94, 0x6F, +0x94, 0x8F, 0xAD, 0x10, 0xAD, 0x10, 0x8C, 0x2D, +0x94, 0x2D, 0x9C, 0x8E, 0x9C, 0x6E, 0x94, 0x8F, +0x83, 0xED, 0x84, 0x0E, 0x9C, 0xD1, 0xAD, 0x54, +0xC6, 0x38, 0xA5, 0x35, 0xA5, 0x14, 0x6B, 0x6D, +0x31, 0x86, 0x31, 0x86, 0x21, 0x24, 0x18, 0xE3, +0x31, 0x86, 0x4A, 0x48, 0x4A, 0x49, 0x31, 0x86, +0x39, 0xE7, 0x4A, 0x48, 0x4A, 0x69, 0x52, 0x8A, +0x5A, 0xEB, 0x62, 0xEC, 0x73, 0x4D, 0x94, 0x51, +0xCE, 0x18, 0x8C, 0x10, 0x6B, 0x0C, 0x8C, 0x0F, +0x9C, 0x50, 0xAC, 0xF2, 0xAD, 0x12, 0xAC, 0xF1, +0xA4, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, +0x9C, 0x90, 0xA4, 0xD0, 0xB5, 0x32, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, +0xAD, 0x12, 0xB5, 0x53, 0xBD, 0xB4, 0xAD, 0x12, +0x94, 0x4F, 0x52, 0x89, 0x4A, 0x69, 0x39, 0xE7, +0x21, 0x25, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x20, 0xE4, 0x41, 0x05, 0x49, 0x05, +0x38, 0xC4, 0x28, 0xE4, 0x21, 0x05, 0x21, 0x05, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC3, 0x18, 0xA3, 0x18, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, 0x20, 0xE4, +0x21, 0x25, 0x21, 0x05, 0x18, 0xC4, 0x20, 0xE4, +0x29, 0x25, 0x29, 0x46, 0x21, 0x05, 0x21, 0x05, +0x29, 0x46, 0x21, 0x26, 0x21, 0x05, 0x29, 0x46, +0x29, 0x67, 0x31, 0x67, 0x31, 0x87, 0x31, 0xA8, +0x39, 0xE9, 0x42, 0x09, 0x42, 0x09, 0x42, 0x09, +0x39, 0xE8, 0x42, 0x09, 0x52, 0xAB, 0x5A, 0xEB, +0x94, 0x70, 0x9C, 0x90, 0x9C, 0x8F, 0x73, 0x6C, +0x7B, 0xAD, 0x94, 0x2F, 0xA4, 0xD1, 0xA4, 0xF1, +0xAD, 0x12, 0xA4, 0xD1, 0xAD, 0x12, 0x9C, 0x90, +0xA4, 0xD1, 0xA4, 0xF1, 0xAC, 0xF1, 0x9C, 0x90, +0x9C, 0xB0, 0x94, 0x6F, 0xA4, 0xB0, 0xAC, 0xF1, +0xB5, 0x31, 0xAC, 0xF0, 0xB5, 0x32, 0xBD, 0x52, +0xBD, 0x72, 0xBD, 0x72, 0xB5, 0x11, 0x94, 0x4E, +0x9C, 0x8F, 0xB5, 0x32, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x32, 0x83, 0xCC, 0x8C, 0x0D, +0x94, 0x2E, 0x94, 0x4F, 0x83, 0xCE, 0x42, 0x28, +0x63, 0x0C, 0x39, 0xC7, 0x73, 0x6E, 0x52, 0x8A, +0x5A, 0xCB, 0x4A, 0x6A, 0x73, 0x8E, 0x73, 0x8E, +0x73, 0x4D, 0x7B, 0x6D, 0x8B, 0xCF, 0xA4, 0x91, +0xCE, 0x17, 0xCE, 0x17, 0xA4, 0xD1, 0xC5, 0xB3, +0x5B, 0x8A, 0x8D, 0x0E, 0x6C, 0x68, 0x85, 0x08, +0x74, 0xA7, 0x64, 0x05, 0x85, 0x08, 0x8D, 0x48, +0x84, 0xE7, 0x7C, 0xC7, 0x84, 0xC9, 0x9D, 0x0C, +0x8C, 0x8A, 0x74, 0x48, 0x95, 0x2C, 0xA5, 0x6E, +0x9D, 0x4E, 0xC6, 0x71, 0xA5, 0x2C, 0xB5, 0x4F, +0xAD, 0x4F, 0xBD, 0x92, 0xCE, 0x35, 0xBD, 0xB3, +0x9C, 0xAF, 0xAC, 0xD0, 0xB5, 0x31, 0xB5, 0x11, +0xAC, 0xF1, 0xA4, 0xAF, 0x9C, 0x4E, 0x94, 0x4E, +0x9C, 0x8F, 0x94, 0x6E, 0x94, 0x2E, 0x94, 0x2E, +0x83, 0xCC, 0x6B, 0x2B, 0x7B, 0x6B, 0x7B, 0x8B, +0x8B, 0xED, 0x9C, 0x6E, 0xAC, 0xCF, 0x8C, 0x0C, +0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xF1, 0x9C, 0xB0, +0x73, 0x4B, 0xA5, 0x12, 0x9C, 0xB0, 0x8C, 0x2E, +0xA4, 0xD0, 0xA4, 0xD1, 0xA4, 0xF1, 0xAD, 0x12, +0x9C, 0xB0, 0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x11, +0x94, 0x4E, 0xA4, 0xF0, 0xAD, 0x11, 0x8B, 0xEC, +0x83, 0xCB, 0xBD, 0x51, 0xBD, 0x30, 0xD6, 0x56, +0xD6, 0x76, 0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x36, +0xC6, 0x15, 0xC5, 0xF4, 0xCE, 0x35, 0xCD, 0xF4, +0xC5, 0xF4, 0xCE, 0x35, 0xC5, 0xF5, 0xC5, 0xF5, +0xC5, 0xD4, 0xC5, 0xF5, 0xCE, 0x35, 0xCE, 0x15, +0xC5, 0xF4, 0xC5, 0xF4, 0xC6, 0x15, 0xC5, 0xF4, +0xAD, 0x11, 0xBD, 0x72, 0xB5, 0x10, 0x8B, 0xCD, +0x63, 0x0B, 0x52, 0x8A, 0x5A, 0xAA, 0x62, 0xEB, +0x6B, 0x0C, 0x73, 0x8E, 0x73, 0x8E, 0x6B, 0x4D, +0x73, 0x8E, 0x73, 0x8E, 0x84, 0x10, 0xAD, 0x55, +0xBD, 0xF8, 0xC6, 0x18, 0xBD, 0xF8, 0x9C, 0xB2, +0x8C, 0x2F, 0x52, 0x8A, 0x41, 0xE8, 0x39, 0xC7, +0x7B, 0xCE, 0xCE, 0x36, 0x8C, 0x0E, 0xA5, 0x11, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x53, 0xB5, 0x73, +0xBD, 0xD5, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x93, +0xBD, 0xB4, 0xC5, 0xF4, 0xBD, 0xB3, 0xAC, 0xF0, +0xAD, 0x10, 0xAC, 0xEF, 0xAC, 0xCF, 0x8C, 0x0E, +0x84, 0x0E, 0x94, 0x4F, 0x9C, 0xB0, 0xB5, 0x74, +0xC6, 0x18, 0xA5, 0x35, 0xA5, 0x15, 0x8C, 0x50, +0x63, 0x0B, 0x29, 0x45, 0x29, 0x65, 0x21, 0x04, +0x18, 0xE3, 0x31, 0xA6, 0x4A, 0x49, 0x42, 0x08, +0x31, 0xA6, 0x39, 0xE7, 0x4A, 0x49, 0x4A, 0x69, +0x52, 0x8A, 0x4A, 0x48, 0x52, 0x69, 0x6B, 0x0C, +0x73, 0x8D, 0x52, 0x49, 0x83, 0xCF, 0xA4, 0xB2, +0x94, 0x30, 0x94, 0x2F, 0xC5, 0xD5, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xCD, 0xF4, 0xCE, 0x15, +0xBD, 0x93, 0xC5, 0xD3, 0xD6, 0x35, 0xCE, 0x15, +0xD6, 0x15, 0xC5, 0xD4, 0xB5, 0x52, 0xAD, 0x32, +0xA4, 0xF1, 0x9C, 0xB0, 0xBD, 0xB4, 0xB5, 0x32, +0xA4, 0xD1, 0x8C, 0x2F, 0x83, 0xEE, 0x6B, 0x2C, +0x31, 0xA6, 0x21, 0x04, 0x19, 0x04, 0x18, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x29, 0x45, +0x18, 0xC3, 0x20, 0xE4, 0x39, 0x04, 0x49, 0x25, +0x30, 0xE4, 0x20, 0xE4, 0x20, 0xE4, 0x18, 0xE4, +0x18, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x20, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE5, +0x21, 0x25, 0x29, 0x66, 0x29, 0x46, 0x21, 0x05, +0x21, 0x25, 0x21, 0x26, 0x21, 0x05, 0x21, 0x26, +0x29, 0x46, 0x21, 0x26, 0x21, 0x05, 0x29, 0x67, +0x31, 0x87, 0x39, 0xC8, 0x39, 0xE9, 0x41, 0xE9, +0x39, 0xC8, 0x31, 0xA8, 0x39, 0xE9, 0x4A, 0x6A, +0x5A, 0xCB, 0x83, 0xEF, 0x9C, 0x6F, 0x83, 0xCD, +0x9C, 0x4F, 0x94, 0x2F, 0x94, 0x2E, 0x8B, 0xED, +0xAC, 0xF1, 0xB5, 0x32, 0xAC, 0xF1, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xB0, 0x83, 0xAC, 0x62, 0xC9, +0x9C, 0xB1, 0x9C, 0x90, 0xA4, 0xD1, 0xAD, 0x11, +0xB5, 0x11, 0xA4, 0xD0, 0xBD, 0x72, 0xC5, 0xD4, +0xB5, 0x52, 0xBD, 0x73, 0xAD, 0x11, 0x9C, 0xB0, +0xAD, 0x12, 0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x32, +0xBD, 0x93, 0xAC, 0xF1, 0x7B, 0xAC, 0x94, 0x4E, +0xA4, 0xB0, 0x9C, 0x4F, 0x8C, 0x2F, 0x63, 0x0B, +0x73, 0x8E, 0x31, 0x66, 0x42, 0x08, 0x31, 0x66, +0x31, 0x66, 0x31, 0x66, 0x31, 0x86, 0x39, 0xA7, +0x5A, 0xCB, 0x94, 0x51, 0x7B, 0x4C, 0x9C, 0x71, +0xC5, 0xD6, 0xDE, 0x99, 0x94, 0x51, 0x62, 0xCA, +0x8D, 0x10, 0xA5, 0xB2, 0x64, 0x06, 0x8D, 0x68, +0x74, 0x86, 0x53, 0x64, 0x7C, 0xA7, 0x85, 0x08, +0x95, 0x8B, 0x7C, 0x88, 0x5B, 0x45, 0x6B, 0xC8, +0x63, 0xC6, 0x6C, 0x26, 0x84, 0xE9, 0x8C, 0xEB, +0x7C, 0x89, 0xA5, 0xCB, 0xA5, 0x6A, 0x94, 0xAB, +0xA5, 0x2F, 0xA5, 0x30, 0xAD, 0x30, 0xB5, 0x30, +0xB5, 0x10, 0xAC, 0xD0, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xD0, 0xB5, 0x10, 0xB5, 0x10, 0xAD, 0x10, +0xAD, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, +0xBD, 0x71, 0xC5, 0x92, 0xC5, 0x72, 0xC5, 0x92, +0xC5, 0x72, 0xC5, 0x51, 0xC5, 0x71, 0xC5, 0x71, +0xB5, 0x31, 0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xCF, 0xA4, 0x8E, 0x9C, 0x4D, +0x94, 0x2D, 0x94, 0x2D, 0x94, 0x2D, 0x8B, 0xEC, +0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, +0x94, 0x0C, 0x94, 0x0D, 0x8B, 0xEC, 0x83, 0xAB, +0x94, 0x2D, 0xC5, 0x71, 0xA4, 0x8E, 0xAC, 0xF0, +0xC5, 0xB3, 0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x31, +0xBD, 0x72, 0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0x93, +0xAC, 0xF0, 0xBD, 0xB3, 0xBD, 0x93, 0xC5, 0xD4, +0xC5, 0xF4, 0xC5, 0xF4, 0xD6, 0x56, 0xCE, 0x15, +0xCD, 0xF5, 0xC5, 0xF4, 0xC5, 0xB4, 0xC5, 0xB4, +0x9C, 0x6E, 0xC5, 0x72, 0xBD, 0x31, 0xAD, 0x12, +0x62, 0xEB, 0x63, 0x0B, 0x5A, 0xAA, 0x52, 0x69, +0x6B, 0x4D, 0x6B, 0x4D, 0x6B, 0x2D, 0x7B, 0xAF, +0x73, 0x8E, 0x73, 0xAF, 0x9C, 0xB3, 0xA5, 0x14, +0xAD, 0x56, 0xBD, 0xD8, 0xAD, 0x15, 0x8C, 0x30, +0x8C, 0x10, 0x52, 0x8A, 0x42, 0x08, 0x31, 0xA6, +0x42, 0x28, 0xBD, 0xB5, 0xC6, 0x15, 0xBD, 0xD4, +0xC5, 0xF5, 0xCE, 0x16, 0xCE, 0x56, 0xCE, 0x56, +0xCE, 0x36, 0xBD, 0xD4, 0xC6, 0x15, 0xCE, 0x36, +0xD6, 0x76, 0xC6, 0x15, 0xC5, 0xD4, 0xAD, 0x10, +0xAD, 0x10, 0xAD, 0x0F, 0xAC, 0xF0, 0x7B, 0xAC, +0x83, 0xEE, 0x9C, 0xB0, 0x9C, 0xD1, 0xB5, 0xB5, +0xC6, 0x18, 0xA5, 0x35, 0x9C, 0xF4, 0x9C, 0xD2, +0x8C, 0x71, 0x73, 0xAE, 0x29, 0x24, 0x31, 0x86, +0x21, 0x24, 0x18, 0xE3, 0x39, 0xC7, 0x4A, 0x48, +0x31, 0xA6, 0x31, 0x86, 0x41, 0xE7, 0x52, 0x8A, +0x52, 0xAA, 0x63, 0x0C, 0x73, 0x6D, 0x4A, 0x49, +0x29, 0x45, 0x41, 0xE8, 0x5A, 0xAA, 0x8C, 0x10, +0xA4, 0xB2, 0x94, 0x0F, 0xB5, 0x53, 0xEE, 0xF8, +0xDE, 0x96, 0xD6, 0x76, 0xDE, 0x96, 0xDE, 0x96, +0xB5, 0x32, 0xBD, 0x73, 0xD6, 0x56, 0xD6, 0x35, +0xD6, 0x55, 0xCE, 0x35, 0xC5, 0xF5, 0xBD, 0xD4, +0xA4, 0xF1, 0xA4, 0xD1, 0xBD, 0x73, 0x94, 0x4F, +0x94, 0x2E, 0x94, 0x2E, 0x9C, 0x4F, 0x94, 0x2E, +0x6B, 0x0B, 0x52, 0x69, 0x4A, 0x28, 0x41, 0xE7, +0x41, 0xE7, 0x52, 0x89, 0x7B, 0xAD, 0x83, 0xCE, +0x39, 0xA6, 0x31, 0x66, 0x39, 0x25, 0x41, 0x25, +0x28, 0xE4, 0x20, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x21, 0x05, 0x21, 0x25, +0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, +0x21, 0x05, 0x21, 0x25, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x29, 0x46, 0x29, 0x46, 0x21, 0x05, +0x21, 0x05, 0x21, 0x25, 0x21, 0x25, 0x21, 0x26, +0x29, 0x46, 0x29, 0x46, 0x21, 0x05, 0x21, 0x26, +0x29, 0x67, 0x31, 0xA8, 0x31, 0xA8, 0x31, 0xA8, +0x39, 0xC8, 0x31, 0xA8, 0x39, 0xC9, 0x3A, 0x09, +0x42, 0x4A, 0x52, 0x6A, 0x6A, 0xEB, 0x73, 0x4C, +0x7B, 0x6C, 0x6B, 0x0A, 0x6A, 0xEA, 0x6B, 0x0A, +0x73, 0x4B, 0x83, 0xAD, 0x8B, 0xED, 0x7B, 0x8C, +0x8C, 0x0E, 0x9C, 0x6F, 0x6B, 0x0A, 0x6B, 0x0A, +0x9C, 0xB1, 0x8C, 0x0E, 0xA4, 0xD1, 0xB5, 0x32, +0xB5, 0x31, 0xB5, 0x31, 0xBD, 0x93, 0xBD, 0x72, +0xBD, 0x72, 0xC5, 0xB3, 0xAD, 0x11, 0xAC, 0xF1, +0x9C, 0x8F, 0xA4, 0xD0, 0xAD, 0x32, 0xAC, 0xF1, +0xBD, 0xB4, 0xAD, 0x32, 0x8C, 0x2E, 0x9C, 0x90, +0xAC, 0xD1, 0xA4, 0xD1, 0x9C, 0xB0, 0x7B, 0xAD, +0x4A, 0x49, 0x29, 0x45, 0x41, 0xE8, 0x62, 0xEC, +0x39, 0xC7, 0x29, 0x45, 0x21, 0x04, 0x31, 0x66, +0x39, 0xC7, 0x6B, 0x0C, 0x73, 0x0C, 0x83, 0xAE, +0x8B, 0xEF, 0x94, 0x30, 0x83, 0x8E, 0x52, 0x49, +0xAD, 0xF4, 0x95, 0x31, 0x4B, 0x45, 0x74, 0xC7, +0x74, 0xA7, 0x74, 0x48, 0x6C, 0x25, 0x6C, 0x66, +0x8D, 0x4A, 0x84, 0xCA, 0x4A, 0xC5, 0x5B, 0x66, +0x5B, 0x86, 0x7C, 0xA8, 0x7C, 0xC7, 0x85, 0x0A, +0x7C, 0xA9, 0x7C, 0xE6, 0xAE, 0x0A, 0x94, 0xCA, +0x8C, 0x4B, 0x8C, 0x4C, 0xA4, 0xAE, 0xB5, 0x10, +0x94, 0x0C, 0x83, 0xCC, 0x83, 0xCC, 0x7B, 0x8B, +0x83, 0xED, 0x84, 0x0D, 0x8C, 0x2E, 0x94, 0x4E, +0xA4, 0xD0, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAF, +0xAC, 0xCF, 0xA4, 0x8F, 0xA4, 0x6E, 0x94, 0x0D, +0x94, 0x2D, 0x9C, 0x4D, 0xA4, 0x8E, 0x9C, 0x6E, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0xBD, 0x31, +0xAC, 0xCF, 0xAC, 0xCF, 0xA4, 0x6D, 0x9C, 0x4D, +0x9C, 0x6D, 0xA4, 0x8E, 0xA4, 0x8E, 0xB4, 0xEF, +0xB5, 0x10, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, +0xCD, 0x92, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xB2, +0xC5, 0x92, 0xC5, 0x51, 0xC5, 0x91, 0xBD, 0x51, +0xB4, 0xEF, 0xAC, 0xAF, 0x94, 0x2D, 0x8B, 0xCC, +0x83, 0xAB, 0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, +0x93, 0xEC, 0x94, 0x0C, 0x93, 0xEC, 0x93, 0xEC, +0x83, 0x8B, 0x83, 0xAB, 0x8B, 0xED, 0x8B, 0xEC, +0xA4, 0xAF, 0xB5, 0x52, 0xC5, 0xB3, 0xB5, 0x51, +0xC5, 0xB2, 0xCD, 0xB2, 0xBD, 0x51, 0xC5, 0xB4, +0x41, 0xE7, 0x7B, 0xCF, 0x7B, 0x8D, 0x4A, 0x28, +0x52, 0x69, 0x6B, 0x2C, 0x5A, 0xAA, 0x62, 0xEB, +0x52, 0x6A, 0x6B, 0x2D, 0x7B, 0xCF, 0x84, 0x10, +0xA5, 0x35, 0x94, 0xB2, 0x94, 0x72, 0xA4, 0xF4, +0x94, 0x51, 0x62, 0xEB, 0x41, 0xE7, 0x31, 0x86, +0x42, 0x28, 0x7B, 0xEE, 0xD6, 0x77, 0xBD, 0xD4, +0xC5, 0xF5, 0xC6, 0x15, 0xC6, 0x15, 0xC6, 0x15, +0xBD, 0xF4, 0xA5, 0x11, 0xC6, 0x15, 0xCE, 0x36, +0xCE, 0x35, 0xD6, 0x56, 0xC5, 0xF4, 0x9C, 0x6E, +0xBD, 0x50, 0xB5, 0x10, 0xB5, 0x11, 0x73, 0x6B, +0x84, 0x0E, 0x9C, 0xD1, 0xA4, 0xF1, 0xBD, 0xD6, +0xBD, 0xF8, 0xA5, 0x35, 0x84, 0x31, 0x8C, 0x50, +0x9C, 0xD1, 0x9C, 0xF2, 0x84, 0x0F, 0x63, 0x2C, +0x21, 0x24, 0x18, 0xE3, 0x29, 0x86, 0x31, 0xA6, +0x42, 0x07, 0x42, 0x08, 0x39, 0xC6, 0x42, 0x07, +0x5A, 0xEB, 0x52, 0x8A, 0x8C, 0x10, 0x83, 0xCF, +0x5A, 0x8A, 0x52, 0x49, 0x6B, 0x0C, 0x8B, 0xEF, +0x83, 0xAE, 0x8C, 0x0F, 0xA4, 0xB1, 0xBD, 0x73, +0xD6, 0x76, 0xDE, 0x96, 0xE6, 0xB7, 0xDE, 0x97, +0xB5, 0x52, 0xCE, 0x36, 0xD6, 0x56, 0xD6, 0x35, +0xCE, 0x35, 0xCE, 0x15, 0xBD, 0xD4, 0xBD, 0xB4, +0xAD, 0x32, 0xAD, 0x12, 0xB5, 0x53, 0x94, 0x4F, +0x7B, 0x8C, 0x9C, 0x6F, 0xBD, 0x52, 0xBD, 0x52, +0xAC, 0xF1, 0x9C, 0x90, 0x94, 0x2E, 0x94, 0x4F, +0xA4, 0xD1, 0xB5, 0x53, 0xC5, 0x93, 0xBD, 0x53, +0x94, 0x2F, 0x7B, 0x8D, 0x73, 0x2C, 0x49, 0xE7, +0x29, 0x05, 0x21, 0x04, 0x21, 0x04, 0x18, 0xC4, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xC3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x21, 0x05, +0x21, 0x05, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xA3, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x21, 0x25, 0x21, 0x25, +0x18, 0xE5, 0x21, 0x26, 0x29, 0x46, 0x21, 0x05, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x25, 0x29, 0x46, +0x21, 0x25, 0x21, 0x25, 0x21, 0x05, 0x21, 0x05, +0x21, 0x26, 0x29, 0x67, 0x31, 0x87, 0x31, 0xA8, +0x39, 0xC8, 0x39, 0xC8, 0x31, 0xA8, 0x31, 0xA8, +0x39, 0xE9, 0x42, 0x2A, 0x4A, 0x4A, 0x63, 0x0C, +0x83, 0xCE, 0x83, 0xCE, 0x83, 0xAD, 0x83, 0xAD, +0x7B, 0x8D, 0x7B, 0x8C, 0x7B, 0x8C, 0x73, 0x2B, +0x6B, 0x2B, 0x6B, 0x0A, 0x6B, 0x2B, 0x73, 0x2B, +0x62, 0xEA, 0x73, 0x2B, 0x8C, 0x0E, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x4E, 0x94, 0x2E, 0x9C, 0x6F, +0xAC, 0xF1, 0xA4, 0xD0, 0xA4, 0x8F, 0xA4, 0xD0, +0xB5, 0x31, 0x9C, 0x6F, 0xBD, 0x73, 0xAC, 0xF1, +0xBD, 0x73, 0x94, 0x4E, 0x94, 0x4F, 0x94, 0x4F, +0x94, 0x4F, 0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0xAD, +0x4A, 0x49, 0x21, 0x25, 0x5A, 0xCB, 0x6B, 0x4D, +0x39, 0xC7, 0x39, 0xA7, 0x4A, 0x49, 0x62, 0xCB, +0x52, 0x8A, 0x52, 0x69, 0x6A, 0xEB, 0x41, 0xA6, +0x62, 0xAA, 0x8B, 0xAE, 0x8B, 0xCE, 0x5A, 0xAA, +0x8D, 0x10, 0x84, 0xCE, 0x7C, 0xAB, 0x7C, 0xC9, +0x8D, 0x4C, 0x8D, 0x0B, 0x63, 0xC4, 0x5B, 0xE3, +0x74, 0x66, 0x95, 0x2B, 0x63, 0x87, 0x53, 0x25, +0x53, 0x44, 0x74, 0x87, 0x6C, 0x65, 0x6C, 0x87, +0x6C, 0x87, 0x74, 0xC5, 0x9D, 0xA7, 0x9D, 0x2B, +0x84, 0x4D, 0xA5, 0x52, 0xBE, 0x15, 0xC6, 0x15, +0xA4, 0xD0, 0x94, 0x90, 0xA5, 0x12, 0x84, 0x2F, +0x84, 0x2E, 0x7B, 0xCD, 0x84, 0x2F, 0x9C, 0xB0, +0xA4, 0xD0, 0x7B, 0xAC, 0x7B, 0xAC, 0xAD, 0x32, +0xA4, 0xD0, 0x9C, 0xAF, 0x9C, 0x8F, 0x84, 0x0E, +0x7B, 0xAC, 0x8C, 0x2E, 0xA4, 0xF1, 0x9C, 0x90, +0x9C, 0xB0, 0x8C, 0x2E, 0x94, 0x0D, 0xB5, 0x10, +0x94, 0x0C, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x6E, +0x94, 0x0C, 0x8B, 0xEC, 0x94, 0x0C, 0x94, 0x2D, +0x8B, 0xCB, 0xAC, 0x8E, 0x83, 0x6A, 0x7B, 0x49, +0x7B, 0x49, 0x7B, 0x6A, 0x83, 0x8B, 0x83, 0x8B, +0x8B, 0xAB, 0x93, 0xEB, 0x9C, 0x2C, 0xA4, 0x6E, +0xAC, 0xAF, 0xAC, 0xCF, 0xAC, 0xEF, 0xB5, 0x10, +0xBD, 0x71, 0xC5, 0x92, 0xBD, 0x51, 0xB5, 0x30, +0xB4, 0xF0, 0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xAE, 0xA4, 0x8E, 0x9C, 0x6D, 0xA4, 0x8E, +0xB5, 0x0F, 0xBD, 0x10, 0xBD, 0x30, 0xBD, 0x72, +0xA4, 0xD2, 0x9C, 0x92, 0x6B, 0x2C, 0x39, 0xA7, +0x42, 0x28, 0x52, 0x69, 0x42, 0x08, 0x42, 0x07, +0x4A, 0x28, 0x62, 0xEC, 0x4A, 0x49, 0x8C, 0x51, +0x8C, 0x71, 0xA5, 0x14, 0xBD, 0xB7, 0xBD, 0xD7, +0x9C, 0xD3, 0x73, 0x8E, 0x4A, 0x28, 0x52, 0x69, +0x4A, 0x48, 0x42, 0x28, 0xB5, 0x73, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0xD3, 0xBD, 0xB3, 0xC5, 0xD4, +0xC5, 0xF4, 0xB5, 0x72, 0xBD, 0xD4, 0xC5, 0xD3, +0xBD, 0xB3, 0xBD, 0xD3, 0xAD, 0x31, 0x8C, 0x0C, +0xB5, 0x30, 0xBD, 0x50, 0xBD, 0x31, 0x7B, 0xAC, +0x83, 0xEE, 0x84, 0x0E, 0x9C, 0xB0, 0xC6, 0x17, +0xBD, 0xB7, 0xA5, 0x15, 0x84, 0x30, 0xA5, 0x13, +0xA5, 0x33, 0xAD, 0x53, 0xA5, 0x33, 0xA4, 0xF2, +0x7B, 0xCE, 0x52, 0x89, 0x4A, 0x69, 0x4A, 0x69, +0x39, 0xC7, 0x42, 0x08, 0x31, 0xA6, 0x39, 0xC6, +0x4A, 0x48, 0x8C, 0x30, 0x94, 0x71, 0x94, 0x51, +0xAC, 0xF3, 0xC5, 0xB5, 0x73, 0x2C, 0x73, 0x4D, +0x8B, 0xEF, 0x6A, 0xEB, 0xA4, 0xB1, 0x7B, 0x8D, +0x9C, 0x50, 0xCD, 0xF5, 0xE6, 0xB7, 0xDE, 0xB7, +0xD6, 0x76, 0xDE, 0x77, 0xCE, 0x35, 0xBD, 0xB3, +0xC5, 0xD4, 0xC5, 0xF5, 0xBD, 0xD4, 0xC5, 0xF5, +0xAD, 0x53, 0xA4, 0xF1, 0xB5, 0x32, 0xAC, 0xF1, +0x83, 0xAC, 0xA4, 0xD0, 0xBD, 0x52, 0xBD, 0x52, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x93, 0xC5, 0x93, +0xC5, 0x93, 0xCD, 0xB4, 0xCD, 0xB3, 0xC5, 0x93, +0xCD, 0xB4, 0xBD, 0x73, 0xB5, 0x12, 0x73, 0x6D, +0x29, 0x04, 0x21, 0x05, 0x21, 0x04, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x20, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x10, 0xA3, 0x18, 0xE4, 0x21, 0x05, 0x21, 0x26, +0x21, 0x05, 0x21, 0x05, 0x21, 0x26, 0x29, 0x46, +0x18, 0xE5, 0x18, 0xC4, 0x18, 0xE5, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE5, 0x21, 0x05, +0x18, 0xE5, 0x21, 0x05, 0x29, 0x46, 0x31, 0x87, +0x31, 0x87, 0x31, 0x87, 0x31, 0xA8, 0x31, 0xA7, +0x31, 0xA8, 0x42, 0x09, 0x42, 0x2A, 0x4A, 0x49, +0x6B, 0x2C, 0xA4, 0xD2, 0xA4, 0xD1, 0xAD, 0x12, +0xAC, 0xF1, 0xAC, 0xF2, 0xA4, 0xD1, 0xA4, 0xB0, +0xA4, 0xB0, 0x9C, 0x70, 0x94, 0x4F, 0x94, 0x4F, +0x9C, 0x70, 0x9C, 0x90, 0xA4, 0xB0, 0xA4, 0xD0, +0xA4, 0xD1, 0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xD0, 0xA4, 0xB0, +0x9C, 0x90, 0x94, 0x6F, 0x9C, 0x90, 0x9C, 0x6F, +0x9C, 0x8F, 0x8C, 0x0E, 0x8B, 0xED, 0x83, 0xCD, +0x8C, 0x0E, 0x8B, 0xEE, 0x83, 0xAC, 0xA4, 0xD1, +0x73, 0xAD, 0x31, 0xA6, 0x5A, 0xCB, 0x5A, 0xCB, +0x42, 0x08, 0x5A, 0xCB, 0x6B, 0x0C, 0x52, 0x49, +0x39, 0xA6, 0x41, 0xC7, 0x4A, 0x07, 0x62, 0xAA, +0x4A, 0x08, 0x7B, 0x6C, 0x94, 0x30, 0x5A, 0xAA, +0xA5, 0xF3, 0x7C, 0x8C, 0x6C, 0x28, 0x6C, 0x48, +0x8D, 0x4D, 0x9D, 0x6D, 0x5B, 0xA4, 0x85, 0x09, +0x9D, 0xAD, 0x84, 0xAA, 0x7C, 0x68, 0x7C, 0xA8, +0x74, 0x87, 0x64, 0x04, 0x5C, 0x03, 0x74, 0xA7, +0x6C, 0x86, 0x7D, 0x05, 0x9D, 0xC9, 0xBE, 0x73, +0xDF, 0x3A, 0xD7, 0x3A, 0xC6, 0x97, 0xBE, 0x14, +0x94, 0xAF, 0xAD, 0x53, 0xB5, 0xD5, 0x8C, 0x70, +0x8C, 0x4F, 0x73, 0xAD, 0x7B, 0xEE, 0x8C, 0x4F, +0x83, 0xED, 0x73, 0x8C, 0x8C, 0x70, 0xC6, 0x16, +0xBD, 0xB5, 0xA4, 0xF1, 0x94, 0x6F, 0x8C, 0x4F, +0x7B, 0xCD, 0x84, 0x0E, 0x8C, 0x70, 0x94, 0xB1, +0x9C, 0xD2, 0x9C, 0xB1, 0xA4, 0xB0, 0xBD, 0x51, +0x9C, 0x4D, 0xB5, 0x11, 0xB5, 0x32, 0xBD, 0x93, +0xB5, 0x31, 0xB5, 0x31, 0xBD, 0x72, 0xB5, 0x31, +0xAC, 0xF0, 0xA4, 0xD0, 0x94, 0x0D, 0x94, 0x0D, +0x94, 0x2E, 0x8C, 0x0D, 0x83, 0xAC, 0x83, 0xAC, +0x83, 0xAC, 0x83, 0x8B, 0x8B, 0xEC, 0x8C, 0x0D, +0x8B, 0xEC, 0x8B, 0xEC, 0xB4, 0xEF, 0xB5, 0x10, +0xBD, 0x72, 0xB5, 0x11, 0xA4, 0xCF, 0x9C, 0x8F, +0x94, 0x2D, 0x7B, 0x8B, 0x8C, 0x0C, 0x8B, 0xCB, +0x8B, 0xEC, 0x94, 0x2D, 0x94, 0x2C, 0x94, 0x0C, +0x9C, 0x4D, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xF0, +0xA4, 0xAE, 0xA4, 0x6D, 0xA4, 0xAE, 0xBD, 0x73, +0xBD, 0x95, 0x7B, 0x8E, 0x4A, 0x08, 0x29, 0x24, +0x4A, 0x49, 0x42, 0x07, 0x21, 0x03, 0x31, 0x85, +0x52, 0x69, 0x5A, 0xAA, 0x73, 0x8E, 0x8C, 0x51, +0x94, 0xB3, 0xAD, 0x76, 0xB5, 0xB7, 0xBD, 0xF8, +0xB5, 0x76, 0x94, 0x72, 0x63, 0x0C, 0x52, 0x8A, +0x7B, 0x8D, 0x83, 0xCD, 0x7B, 0x8B, 0x83, 0xAB, +0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0xAE, 0xAC, 0xCF, +0xA4, 0xCF, 0xA4, 0xCF, 0xB5, 0x10, 0xAC, 0xCF, +0xA4, 0xAF, 0xA4, 0xCE, 0xA4, 0xAE, 0xAC, 0xCF, +0xAC, 0xEF, 0xBD, 0x10, 0xB5, 0x10, 0x94, 0x2D, +0x83, 0xED, 0x83, 0xED, 0x94, 0x90, 0xCE, 0x38, +0xAD, 0x55, 0x9C, 0xD3, 0x84, 0x0F, 0x8C, 0x4F, +0xA4, 0xF2, 0xAD, 0x73, 0xA5, 0x12, 0xA4, 0xF2, +0xA4, 0xF2, 0x8C, 0x2F, 0x8C, 0x2F, 0x83, 0xCE, +0x63, 0x0B, 0x52, 0xAA, 0x39, 0xE7, 0x42, 0x07, +0x52, 0x69, 0x62, 0xCA, 0x73, 0x2C, 0x6B, 0x0B, +0x9C, 0x70, 0xBD, 0x54, 0x9C, 0x91, 0x41, 0xC7, +0x5A, 0x8A, 0x7B, 0x6D, 0x83, 0xAE, 0xAC, 0xF2, +0x94, 0x4F, 0x94, 0x4F, 0xDE, 0x77, 0xDE, 0xB7, +0xDE, 0xB7, 0xE6, 0xF8, 0xDE, 0xB8, 0xD6, 0x56, +0xCE, 0x36, 0xCE, 0x15, 0xBD, 0x94, 0xBD, 0xD5, +0xAD, 0x52, 0xAD, 0x32, 0xB5, 0x53, 0xB5, 0x53, +0x83, 0xCC, 0xA4, 0x8F, 0xB5, 0x11, 0xBD, 0x72, +0xBD, 0x93, 0xC5, 0xB3, 0xCD, 0xD4, 0xD5, 0xF5, +0xD5, 0xF5, 0xD5, 0xF4, 0xD5, 0xF4, 0xC5, 0x93, +0xC5, 0x73, 0xC5, 0x73, 0xAC, 0xF1, 0x73, 0x4C, +0x29, 0x45, 0x21, 0x25, 0x18, 0xE4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xA4, 0x18, 0xE5, 0x29, 0x46, 0x21, 0x26, +0x21, 0x25, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x18, 0xE5, 0x18, 0xE4, 0x18, 0xE5, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x18, 0xE5, 0x18, 0xE4, +0x18, 0xE5, 0x18, 0xE5, 0x21, 0x26, 0x29, 0x67, +0x31, 0x87, 0x31, 0xA8, 0x29, 0x87, 0x29, 0x87, +0x29, 0x67, 0x31, 0xA8, 0x42, 0x2A, 0x4A, 0x6B, +0x4A, 0x8B, 0x6B, 0x4C, 0x8C, 0x2F, 0x83, 0xED, +0x83, 0xED, 0x6B, 0x2B, 0x7B, 0x8C, 0x94, 0x4F, +0xA4, 0xB0, 0xC5, 0xB3, 0xCD, 0xD4, 0xB5, 0x11, +0xA4, 0xD0, 0xA4, 0xB0, 0xAC, 0xF1, 0xB5, 0x32, +0xBD, 0x73, 0xC5, 0x93, 0xC5, 0xB4, 0xC5, 0xB4, +0xBD, 0x52, 0xBD, 0x93, 0xB5, 0x32, 0xC5, 0xB4, +0xC5, 0xB4, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x73, +0xBD, 0x52, 0xBD, 0x73, 0xB5, 0x12, 0xAD, 0x12, +0xAD, 0x32, 0xA4, 0xB0, 0xA4, 0xD1, 0xAD, 0x53, +0x7B, 0x8D, 0x39, 0xC7, 0x39, 0xA6, 0x4A, 0x28, +0x42, 0x08, 0x39, 0xC7, 0x31, 0x65, 0x39, 0x86, +0x39, 0xC7, 0x41, 0xC7, 0x52, 0x28, 0x5A, 0x89, +0x49, 0xE7, 0x7B, 0x6D, 0x9C, 0x50, 0x62, 0xCB, +0x84, 0xEE, 0xB6, 0x73, 0x6C, 0x4A, 0x53, 0x85, +0x6C, 0x48, 0x85, 0x0B, 0x6C, 0x47, 0x95, 0x6C, +0x95, 0x4D, 0x8C, 0xEB, 0x74, 0x67, 0x6C, 0x65, +0x74, 0xC6, 0x64, 0x24, 0x7C, 0xE8, 0x6C, 0x67, +0x7C, 0xE8, 0x74, 0xC5, 0xB6, 0x4F, 0xBE, 0x54, +0xA5, 0x92, 0xA5, 0x92, 0x94, 0xCF, 0xA5, 0x10, +0x94, 0x6E, 0xBD, 0xD5, 0xBD, 0xF6, 0x8C, 0x70, +0x84, 0x2F, 0x7B, 0xCE, 0x84, 0x0F, 0x8C, 0x2F, +0x84, 0x0E, 0x7B, 0xEE, 0xA5, 0x33, 0xC6, 0x37, +0xCE, 0x37, 0xC6, 0x37, 0xA5, 0x33, 0x94, 0xB1, +0x8C, 0x70, 0x9C, 0xD2, 0x94, 0x90, 0x94, 0x91, +0xA5, 0x13, 0xB5, 0x95, 0xA4, 0xF1, 0xBD, 0x51, +0xA4, 0x8E, 0xC5, 0xB3, 0xBD, 0x93, 0xC5, 0xD4, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, 0xB5, 0x72, +0xBD, 0x93, 0xBD, 0xB3, 0xAD, 0x11, 0xB5, 0x32, +0xAD, 0x52, 0xAD, 0x31, 0xAD, 0x32, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xD0, 0x9C, 0xCF, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x72, 0xB5, 0x10, 0xAC, 0xCF, +0xCE, 0x14, 0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x32, +0xAD, 0x32, 0x9C, 0xD1, 0xAD, 0x11, 0xA4, 0xB0, +0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xD0, 0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x11, +0xA4, 0xD0, 0x8B, 0xEC, 0x8B, 0xED, 0xC5, 0xD6, +0xB5, 0x34, 0x73, 0x4C, 0x4A, 0x28, 0x21, 0x04, +0x21, 0x04, 0x21, 0x24, 0x29, 0x44, 0x39, 0xC6, +0x4A, 0x69, 0x5A, 0xAB, 0x6B, 0x6D, 0x7B, 0xF0, +0x84, 0x31, 0x9C, 0xD3, 0xAD, 0x55, 0xAD, 0x76, +0xBD, 0xD8, 0xB5, 0x96, 0x83, 0xF0, 0x83, 0xEE, +0x9C, 0x90, 0xA4, 0x8F, 0x94, 0x2E, 0x9C, 0x6E, +0xA4, 0xAF, 0xAC, 0xCF, 0xB5, 0x0F, 0xB5, 0x10, +0xB5, 0x30, 0xBD, 0x50, 0xBD, 0x71, 0xB5, 0x30, +0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x50, 0xBD, 0x50, +0xBD, 0x50, 0xBD, 0x50, 0xC5, 0x50, 0xC5, 0x71, +0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x93, 0xCE, 0x58, +0xA5, 0x35, 0x94, 0xB2, 0x9C, 0xB1, 0x9C, 0x6F, +0xAC, 0xD0, 0xAC, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, +0xAC, 0xAF, 0xA4, 0x8E, 0xAC, 0xAF, 0xAC, 0xAF, +0xA4, 0xAF, 0x94, 0x4E, 0x39, 0xA6, 0x42, 0x28, +0x5A, 0xCA, 0x52, 0x69, 0x7B, 0x4D, 0x62, 0xCB, +0x83, 0xCE, 0x94, 0x30, 0x94, 0x50, 0x8C, 0x10, +0x39, 0x86, 0x7B, 0x6D, 0x5A, 0x69, 0x52, 0x28, +0x7B, 0x4C, 0x8B, 0xEF, 0xAC, 0xF2, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xD4, +0xA5, 0x12, 0xBD, 0x94, 0xB5, 0x53, 0xBD, 0x73, +0x7B, 0x8B, 0x94, 0x4E, 0xA4, 0xB0, 0xCD, 0xD4, +0xCD, 0xF4, 0xCD, 0xD4, 0xCD, 0xF4, 0xD5, 0xF4, +0xD6, 0x15, 0xD6, 0x15, 0xDE, 0x35, 0xDE, 0x35, +0xCD, 0xB4, 0xD5, 0xF5, 0xBD, 0x93, 0x83, 0xAD, +0x39, 0xA6, 0x29, 0x25, 0x18, 0xE4, 0x10, 0xC3, +0x10, 0xC3, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x21, 0x05, 0x18, 0xE4, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC3, 0x18, 0xE4, 0x29, 0x46, 0x21, 0x25, +0x21, 0x25, 0x21, 0x25, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, +0x21, 0x05, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x21, 0x46, +0x29, 0x67, 0x31, 0x87, 0x31, 0xA8, 0x31, 0xC8, +0x31, 0x87, 0x29, 0x67, 0x31, 0xC8, 0x42, 0x4A, +0x4A, 0x8B, 0x52, 0x8B, 0x6B, 0x6D, 0x94, 0x70, +0x94, 0x4F, 0x62, 0xEA, 0x8C, 0x4F, 0xBD, 0x53, +0xC5, 0x92, 0xD5, 0xF3, 0xE6, 0x96, 0xE6, 0x96, +0xE6, 0x96, 0xE6, 0x96, 0xE6, 0x96, 0xDE, 0x76, +0xDE, 0x55, 0xDE, 0x55, 0xDE, 0x55, 0xCD, 0xF4, +0xA4, 0xB0, 0x94, 0x4E, 0xB5, 0x52, 0xBD, 0x72, +0xCD, 0xD4, 0xDE, 0x56, 0xE6, 0x96, 0xDE, 0x56, +0xD6, 0x15, 0xDE, 0x76, 0xD6, 0x36, 0xAC, 0xF1, +0x94, 0x6F, 0xB5, 0x32, 0xA4, 0xB0, 0x9C, 0xB0, +0x83, 0xCE, 0x52, 0x69, 0x18, 0xE3, 0x31, 0x86, +0x39, 0xA7, 0x31, 0x86, 0x5A, 0xEB, 0x84, 0x10, +0x42, 0x08, 0x4A, 0x08, 0x62, 0xAA, 0x62, 0x8A, +0x49, 0xE7, 0x83, 0x8D, 0x83, 0xAD, 0x83, 0xAE, +0x8D, 0x4F, 0xBE, 0x95, 0xBE, 0x54, 0x6C, 0x09, +0x64, 0x07, 0x64, 0x07, 0x6C, 0x07, 0x64, 0x07, +0x84, 0xCB, 0x8D, 0x0B, 0x85, 0x08, 0x74, 0x85, +0x7C, 0xE6, 0x85, 0x47, 0x95, 0x89, 0x64, 0x25, +0x74, 0xA7, 0x74, 0x87, 0x95, 0x4C, 0x8C, 0xCD, +0x8C, 0xEE, 0x94, 0xEF, 0x8C, 0x6D, 0xAD, 0x30, +0x9C, 0xAF, 0xBD, 0xD5, 0xB5, 0x94, 0x8C, 0x71, +0x8C, 0x50, 0x84, 0x0F, 0x84, 0x30, 0x63, 0x2B, +0x73, 0xCD, 0x94, 0xB1, 0xA5, 0x54, 0xD6, 0x98, +0xCE, 0x37, 0xCE, 0x77, 0xAD, 0x53, 0xAD, 0x74, +0xB5, 0xB5, 0xBD, 0xD6, 0x9C, 0xF2, 0x94, 0xD2, +0xA5, 0x33, 0xAD, 0x53, 0xA4, 0xD0, 0xB5, 0x31, +0xA4, 0xAF, 0xC5, 0xD3, 0xBD, 0xB3, 0xBD, 0xB3, +0xC5, 0xB4, 0xBD, 0x93, 0xC5, 0xF4, 0xBD, 0x93, +0xBD, 0x72, 0xBD, 0xB3, 0xB5, 0x72, 0xC6, 0x15, +0xBD, 0xB3, 0xB5, 0x52, 0xB5, 0x32, 0xA4, 0xF1, +0xA4, 0xF1, 0xAD, 0x11, 0xAD, 0x52, 0xB5, 0x52, +0xAD, 0x31, 0xBD, 0x92, 0xB5, 0x10, 0xAC, 0xAF, +0xCD, 0xF4, 0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0xD4, +0xB5, 0x73, 0xAD, 0x53, 0xBD, 0x94, 0xC5, 0xD4, +0xC5, 0xF5, 0xBD, 0x93, 0xBD, 0xB4, 0xC5, 0xF5, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x52, 0xBD, 0x93, +0xBD, 0xB4, 0xB5, 0x72, 0xB5, 0x53, 0xCE, 0x17, +0xAD, 0x13, 0xAC, 0xF2, 0x9C, 0x4F, 0x41, 0xE7, +0x31, 0x85, 0x31, 0xA5, 0x42, 0x28, 0x39, 0xE7, +0x42, 0x08, 0x52, 0x8A, 0x6B, 0x2D, 0x73, 0xAF, +0x7C, 0x10, 0x9C, 0xF4, 0x9C, 0xF4, 0x84, 0x31, +0xC6, 0x19, 0xB5, 0x76, 0x83, 0xEF, 0x83, 0xEF, +0x7B, 0x8C, 0xBD, 0x94, 0x9C, 0x90, 0x94, 0x2F, +0x73, 0x6B, 0x62, 0xE9, 0x5A, 0xA8, 0x62, 0xC8, +0x62, 0xA8, 0x6B, 0x09, 0x83, 0xAB, 0x83, 0xCB, +0xB5, 0x30, 0x9C, 0x6E, 0x9C, 0x6D, 0xAC, 0xCE, +0xA4, 0x8D, 0xAC, 0xCE, 0xBD, 0x50, 0xBD, 0x50, +0xBD, 0x50, 0xBD, 0x50, 0xC5, 0xB4, 0xC6, 0x17, +0xAD, 0x55, 0x94, 0x92, 0xA4, 0xD1, 0xD6, 0x35, +0xEE, 0xD7, 0xDE, 0x35, 0xD6, 0x14, 0xD5, 0xF3, +0xCD, 0xB2, 0xBD, 0x51, 0xC5, 0x51, 0xBD, 0x30, +0xB5, 0x10, 0xAC, 0xAF, 0x83, 0xCC, 0x4A, 0x27, +0x52, 0x69, 0x4A, 0x08, 0x62, 0xAA, 0x6B, 0x0B, +0x4A, 0x08, 0x5A, 0xAA, 0x9C, 0x51, 0xCE, 0x17, +0x73, 0x6E, 0x39, 0x86, 0x52, 0x49, 0x52, 0x28, +0x94, 0x10, 0x94, 0x0F, 0xA4, 0xD2, 0x8B, 0xEE, +0xB5, 0x53, 0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x11, 0xAD, 0x11, 0x9C, 0xB0, 0x83, 0xED, +0x83, 0xCD, 0xAD, 0x12, 0xA4, 0xB0, 0x8C, 0x0D, +0x7B, 0x8C, 0x83, 0xAC, 0x83, 0xED, 0x9C, 0x6F, +0xAD, 0x11, 0xB5, 0x32, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x73, 0xB5, 0x32, 0xBD, 0x72, 0xC5, 0x93, +0xC5, 0xB4, 0xCD, 0xF5, 0xBD, 0x93, 0x8C, 0x0E, +0x4A, 0x07, 0x29, 0x45, 0x21, 0x04, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC3, +0x10, 0xA3, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x21, 0x25, +0x21, 0x05, 0x21, 0x05, 0x18, 0xC4, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xE4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x21, 0x25, 0x21, 0x25, +0x21, 0x05, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x21, 0x05, 0x21, 0x25, 0x21, 0x26, 0x21, 0x46, +0x29, 0x67, 0x21, 0x26, 0x29, 0x67, 0x31, 0xC8, +0x31, 0xC8, 0x31, 0x87, 0x29, 0x67, 0x31, 0xA8, +0x42, 0x0A, 0x4A, 0x4A, 0x4A, 0x6A, 0x73, 0xAE, +0x94, 0x90, 0x6B, 0x4C, 0xA4, 0xF1, 0xC5, 0x93, +0xDE, 0x55, 0xDE, 0x14, 0xE6, 0x96, 0xEE, 0xB6, +0xEE, 0x96, 0xEE, 0xB6, 0xEE, 0xB7, 0xEE, 0x96, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x96, +0xEE, 0xD7, 0xEE, 0xD8, 0xC5, 0xD4, 0xCD, 0xD4, +0x9C, 0xB0, 0xDE, 0x76, 0xD6, 0x14, 0xD6, 0x14, +0xCD, 0xF4, 0xCD, 0xD3, 0xDE, 0x76, 0xA4, 0xB0, +0xB5, 0x53, 0xD6, 0x77, 0xC5, 0xD5, 0xBD, 0x94, +0xA4, 0xF1, 0x7B, 0xAD, 0x39, 0xC7, 0x18, 0xC3, +0x18, 0xC3, 0x21, 0x04, 0x8C, 0x51, 0xCE, 0x39, +0x84, 0x11, 0x52, 0x49, 0x6A, 0xEB, 0x7B, 0x4C, +0x52, 0x08, 0x52, 0x28, 0x62, 0xAA, 0x94, 0x50, +0x53, 0x86, 0x84, 0xED, 0xA5, 0xD2, 0xAE, 0x12, +0x6C, 0x28, 0x64, 0x06, 0x63, 0xE6, 0x53, 0x65, +0x6C, 0x47, 0x7C, 0xA8, 0x85, 0x08, 0x7C, 0xE6, +0x95, 0x66, 0xA5, 0xE8, 0x74, 0x84, 0x6C, 0x85, +0x6C, 0x85, 0x85, 0x08, 0x84, 0xC9, 0x84, 0xAA, +0x84, 0xCB, 0x8C, 0x8D, 0x9C, 0xAE, 0xAC, 0xEF, +0x8C, 0x2D, 0xB5, 0xB4, 0xB5, 0xD5, 0xA5, 0x54, +0x9D, 0x13, 0xA5, 0x13, 0x94, 0xB1, 0x84, 0x2F, +0x94, 0x90, 0xA5, 0x13, 0xA5, 0x53, 0xBD, 0xD5, +0xB5, 0x94, 0xBD, 0xD5, 0xA5, 0x12, 0xAD, 0x54, +0xBD, 0xD5, 0xBD, 0xF6, 0xA5, 0x33, 0xAD, 0x54, +0xAD, 0x74, 0xB5, 0x74, 0xA4, 0xD0, 0xB5, 0x10, +0xA4, 0xAF, 0xC5, 0xB3, 0xC5, 0xB4, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xF4, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x72, 0xC5, 0xF4, +0xC5, 0xD4, 0xC5, 0xB4, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x72, 0xB5, 0x93, 0xBD, 0x93, 0xBD, 0x73, +0xAD, 0x11, 0xBD, 0x71, 0xBD, 0x30, 0xB5, 0x10, +0xCE, 0x14, 0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x94, +0xAD, 0x32, 0xBD, 0xD5, 0xC6, 0x15, 0xCE, 0x15, +0xD6, 0x56, 0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x35, +0xC5, 0xF5, 0xCE, 0x15, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x36, 0xBD, 0x95, +0xAD, 0x13, 0xAC, 0xF1, 0xAD, 0x11, 0x6A, 0xEA, +0x4A, 0x48, 0x42, 0x07, 0x39, 0xE7, 0x39, 0xA6, +0x4A, 0x48, 0x5A, 0xAA, 0x62, 0xEC, 0x63, 0x0C, +0x7B, 0xD0, 0x8C, 0x31, 0x84, 0x31, 0xAD, 0x55, +0xC6, 0x18, 0xA4, 0xF3, 0x8C, 0x51, 0xA4, 0xF3, +0x4A, 0x28, 0x8C, 0x50, 0xC5, 0xF7, 0xA4, 0xF2, +0xB5, 0x53, 0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xB0, +0x84, 0x0E, 0x7B, 0xAD, 0x5A, 0xC9, 0x6B, 0x2A, +0x8C, 0x2E, 0x6B, 0x2A, 0x52, 0x48, 0x52, 0x68, +0x52, 0x68, 0x62, 0xC8, 0x8B, 0xEC, 0xB5, 0x31, +0xB5, 0x52, 0xA4, 0xB0, 0xBD, 0xB5, 0xBD, 0xD7, +0xAD, 0x35, 0x94, 0x71, 0xBD, 0x73, 0xD6, 0x35, +0xDE, 0x96, 0xD6, 0x55, 0xD6, 0x14, 0xCD, 0xF4, +0xC5, 0x92, 0xD6, 0x14, 0xC5, 0x92, 0xBD, 0x51, +0xBD, 0x72, 0xBD, 0x72, 0xC5, 0xB3, 0xAD, 0x12, +0x4A, 0x07, 0x41, 0xE7, 0x6A, 0xEB, 0x73, 0x0B, +0x5A, 0x69, 0x62, 0xCB, 0x9C, 0x71, 0xC5, 0xD6, +0xC5, 0xB6, 0x5A, 0x8A, 0x73, 0x2C, 0x7B, 0x8D, +0x73, 0x2C, 0x9C, 0x70, 0x94, 0x0F, 0x9C, 0x50, +0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x53, 0xBD, 0x94, +0xBD, 0x94, 0xAD, 0x32, 0xBD, 0xB4, 0xC5, 0xB5, +0xBD, 0x94, 0xC5, 0xF5, 0xCD, 0xF5, 0xCD, 0xF5, +0xC5, 0xD5, 0xC5, 0xB5, 0xBD, 0x94, 0xB5, 0x73, +0xB5, 0x32, 0xAD, 0x11, 0xA4, 0xD1, 0xA4, 0xD1, +0xAC, 0xF2, 0xA4, 0xF2, 0xA4, 0xD1, 0x9C, 0x90, +0x94, 0x6F, 0x8C, 0x0E, 0x83, 0xCD, 0x83, 0xAD, +0x52, 0x48, 0x29, 0x45, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE4, 0x18, 0xC3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x21, 0x05, 0x21, 0x25, +0x18, 0xE5, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE5, +0x21, 0x05, 0x21, 0x26, 0x21, 0x46, 0x29, 0x46, +0x29, 0x46, 0x21, 0x26, 0x21, 0x26, 0x29, 0x67, +0x31, 0xA8, 0x31, 0xA8, 0x29, 0x87, 0x29, 0x67, +0x39, 0xC8, 0x42, 0x29, 0x42, 0x2A, 0x4A, 0x8B, +0x84, 0x0F, 0x7B, 0xCE, 0xA4, 0xF1, 0xC5, 0xD4, +0xD6, 0x14, 0xDE, 0x14, 0xE6, 0x75, 0xEE, 0xB6, +0xEE, 0xB6, 0xEE, 0x96, 0xEE, 0xB6, 0xE6, 0x96, +0xDE, 0x54, 0xD6, 0x13, 0xD5, 0xF3, 0xCD, 0xD3, +0xDE, 0x35, 0xDE, 0x76, 0xBD, 0x93, 0xE6, 0xB8, +0xDE, 0x97, 0xDE, 0x76, 0xD6, 0x35, 0xD6, 0x14, +0xD6, 0x34, 0xD5, 0xF4, 0xDE, 0x76, 0xA4, 0xD0, +0xBD, 0x94, 0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xB4, +0xB5, 0x73, 0x9C, 0xD1, 0x7B, 0xCE, 0x29, 0x66, +0x10, 0xA3, 0x18, 0xE4, 0x39, 0xC7, 0xB5, 0x97, +0xBD, 0xB7, 0x73, 0x4D, 0x6A, 0xCB, 0x83, 0xAE, +0x52, 0x08, 0x7B, 0x6D, 0x6A, 0xEA, 0x8C, 0x0F, +0x4B, 0x44, 0x53, 0xA6, 0x7C, 0xCC, 0x95, 0x6F, +0x6C, 0x48, 0x64, 0x06, 0x64, 0x07, 0x53, 0x45, +0x64, 0x27, 0x74, 0xA7, 0x6C, 0x65, 0x74, 0x84, +0x8D, 0x44, 0x9D, 0xC7, 0x5B, 0xE2, 0x4B, 0x61, +0x53, 0xC2, 0x7C, 0xE7, 0x74, 0x86, 0x74, 0x66, +0x7C, 0x88, 0x7C, 0x69, 0x9C, 0xCD, 0xB5, 0x50, +0x9C, 0x8E, 0x9C, 0xB0, 0xA4, 0xF1, 0xA5, 0x12, +0xAD, 0x73, 0xBD, 0xB5, 0xBD, 0x94, 0xA4, 0xD1, +0x9C, 0xB0, 0xA5, 0x12, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x33, 0xB5, 0xB4, 0x8C, 0x4F, 0xBD, 0xB5, +0xC6, 0x37, 0xBD, 0xF6, 0xB5, 0x94, 0xBD, 0xD5, +0xB5, 0x94, 0xAD, 0x53, 0xAC, 0xF0, 0xB5, 0x10, +0xA4, 0xAF, 0xC5, 0xD3, 0xC5, 0xD4, 0xC5, 0xF5, +0xC5, 0xD4, 0xC5, 0xF4, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xB5, 0x52, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xF5, 0xC5, 0xD4, 0xBD, 0xB4, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, 0xC5, 0xD4, +0xBD, 0xB3, 0xB5, 0x51, 0xBD, 0x31, 0xAD, 0x10, +0xCD, 0xF4, 0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xF5, +0xB5, 0x73, 0xCE, 0x36, 0xC5, 0xF5, 0xB5, 0x53, +0xC5, 0xF5, 0xCE, 0x15, 0xCE, 0x36, 0xCE, 0x35, +0xAD, 0x12, 0xB5, 0x73, 0xCE, 0x16, 0xC6, 0x15, +0xBD, 0xD4, 0xC5, 0xF5, 0xC5, 0xF5, 0xAD, 0x12, +0xAD, 0x12, 0xAC, 0xF0, 0xAD, 0x10, 0xA4, 0xB1, +0x52, 0x89, 0x52, 0x69, 0x41, 0xE7, 0x42, 0x07, +0x42, 0x28, 0x4A, 0x69, 0x52, 0x8A, 0x5A, 0xEB, +0x5A, 0xEB, 0x6B, 0x6D, 0x9C, 0xB3, 0xAD, 0x76, +0x9C, 0xF4, 0x73, 0x8E, 0xA4, 0xF3, 0xBD, 0x96, +0x5A, 0xAB, 0x39, 0xA7, 0x83, 0xEF, 0xB5, 0x54, +0xCD, 0xF5, 0xD6, 0x76, 0xCE, 0x36, 0xC5, 0xF5, +0xCE, 0x15, 0xD6, 0x56, 0x9C, 0xB0, 0xA4, 0xF1, +0xAD, 0x32, 0xA5, 0x11, 0x9C, 0xB1, 0x94, 0x6F, +0x84, 0x0E, 0x7B, 0xAD, 0x8C, 0x0E, 0x8C, 0x4F, +0x94, 0x4F, 0x8C, 0x2F, 0xC6, 0x38, 0xB5, 0x96, +0xA5, 0x35, 0x9C, 0xB2, 0xBD, 0x53, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x72, 0xCD, 0xF4, +0xB5, 0x72, 0xBD, 0x72, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x51, 0xC5, 0xB3, 0xC5, 0xD4, 0xBD, 0x73, +0x5A, 0x89, 0x39, 0x86, 0x6B, 0x2C, 0x52, 0x48, +0x39, 0xC6, 0x4A, 0x28, 0x6A, 0xEA, 0x9C, 0x50, +0xCD, 0xF7, 0x94, 0x30, 0x62, 0x8A, 0x9C, 0x50, +0x73, 0x2C, 0x73, 0x2C, 0x94, 0x2F, 0xAD, 0x12, +0xBD, 0x74, 0x94, 0x50, 0x73, 0x4B, 0xB5, 0x53, +0xA4, 0xF1, 0xB5, 0x53, 0x9C, 0x90, 0x83, 0xCD, +0x83, 0xCD, 0x94, 0x4F, 0x94, 0x4F, 0x8C, 0x0E, +0x94, 0x4F, 0x9C, 0x6F, 0x9C, 0x4F, 0xA4, 0xD1, +0xAD, 0x12, 0xAD, 0x11, 0xBD, 0x73, 0xA4, 0xD1, +0xAD, 0x12, 0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x53, +0xBD, 0x94, 0xBD, 0x74, 0xBD, 0x94, 0xA4, 0x90, +0x4A, 0x08, 0x29, 0x45, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC4, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xA4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA4, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xE5, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA4, 0x10, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x25, 0x21, 0x26, 0x21, 0x26, +0x21, 0x46, 0x29, 0x46, 0x21, 0x26, 0x21, 0x26, +0x29, 0x46, 0x29, 0x87, 0x31, 0x88, 0x29, 0x67, +0x31, 0x87, 0x39, 0xE9, 0x42, 0x2A, 0x4A, 0x4A, +0x5A, 0xEC, 0x7B, 0xAE, 0xA4, 0xF2, 0xC5, 0xD4, +0xDE, 0x35, 0xD5, 0xD3, 0xE6, 0x75, 0xE6, 0x96, +0xEE, 0x96, 0xEE, 0x96, 0xEE, 0xB6, 0xE6, 0x75, +0xE6, 0x75, 0xD6, 0x14, 0xD5, 0xF4, 0xD5, 0xF4, +0xDE, 0x35, 0xCD, 0xF4, 0xC5, 0xD4, 0xDE, 0x97, +0xDE, 0x56, 0xCD, 0xD4, 0xD6, 0x35, 0xCE, 0x14, +0xCD, 0xF4, 0xDE, 0x76, 0xD6, 0x35, 0xA4, 0xF1, +0xA4, 0xD0, 0x9C, 0x8F, 0xC5, 0xF4, 0xC5, 0xF4, +0xB5, 0x73, 0xAD, 0x12, 0xC5, 0xF5, 0x73, 0x8D, +0x18, 0xE4, 0x18, 0xA3, 0x41, 0xE8, 0xAD, 0x35, +0xCE, 0x59, 0xAD, 0x35, 0x41, 0xC7, 0x52, 0x48, +0x39, 0x85, 0x6A, 0xCB, 0x8B, 0xAE, 0x94, 0x0F, +0x7C, 0xEA, 0x53, 0xE6, 0x64, 0x48, 0x74, 0xAA, +0x64, 0x26, 0x5B, 0xC5, 0x74, 0x69, 0x5B, 0x87, +0x42, 0xE4, 0x6C, 0x27, 0x6C, 0x26, 0x6C, 0x45, +0x6C, 0x63, 0x6C, 0x24, 0x7C, 0x6A, 0x74, 0x28, +0x6C, 0x26, 0x7C, 0xA8, 0x6C, 0x06, 0x5B, 0xA4, +0x63, 0xE6, 0x8C, 0xAA, 0x9C, 0xED, 0xAC, 0xCE, +0xB5, 0x10, 0xAD, 0x10, 0xB5, 0x51, 0xBD, 0x51, +0xAC, 0xF0, 0xBD, 0x51, 0xBD, 0x52, 0xC5, 0x92, +0xBD, 0x51, 0xB5, 0x31, 0xAD, 0x10, 0xAC, 0xF0, +0xAD, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, 0xA4, 0xD0, +0xAD, 0x11, 0xAD, 0x31, 0xAD, 0x32, 0xAD, 0x11, +0xA4, 0xD0, 0x9C, 0x6E, 0xB5, 0x31, 0xC5, 0x71, +0xB4, 0xF0, 0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x31, +0xBD, 0x72, 0xBD, 0x72, 0xB5, 0x52, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x52, +0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x72, +0xC5, 0xB4, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x15, +0xC5, 0xD4, 0xB5, 0x31, 0xC5, 0x71, 0xA4, 0xAF, +0xD6, 0x76, 0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x36, +0xC6, 0x15, 0xCE, 0x56, 0xCE, 0x36, 0xC6, 0x15, +0xC6, 0x15, 0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x15, +0xC5, 0xD5, 0xCE, 0x56, 0xCE, 0x16, 0xCE, 0x35, +0xC6, 0x15, 0xCE, 0x15, 0xC5, 0xF5, 0xAD, 0x33, +0xB5, 0x74, 0xA4, 0xB0, 0xBD, 0x52, 0xD6, 0x57, +0x63, 0x0B, 0x62, 0xEB, 0x39, 0xC6, 0x39, 0xE7, +0x42, 0x07, 0x42, 0x28, 0x4A, 0x48, 0x52, 0x8A, +0x6B, 0x4D, 0x8C, 0x51, 0x8C, 0x72, 0x94, 0x92, +0x84, 0x10, 0x84, 0x31, 0x8C, 0x51, 0x94, 0x71, +0x73, 0x6E, 0x5A, 0xAB, 0x4A, 0x48, 0xA4, 0xF3, +0xCD, 0xF6, 0xD6, 0x56, 0xCE, 0x14, 0xCE, 0x15, +0xCE, 0x15, 0xD6, 0x56, 0xBD, 0x92, 0xCE, 0x35, +0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x36, +0xC5, 0xD4, 0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0xB4, +0xB5, 0x94, 0xAD, 0x53, 0xCE, 0x59, 0xAD, 0x55, +0x9C, 0xF4, 0xA4, 0xF2, 0xB5, 0x52, 0xD6, 0x36, +0xC5, 0xB4, 0xB5, 0x52, 0xB5, 0x72, 0xBD, 0xB3, +0xBD, 0xB3, 0xB5, 0x72, 0xBD, 0x72, 0xB5, 0x72, +0xB5, 0x31, 0xAD, 0x11, 0xBD, 0x92, 0x83, 0xCD, +0x73, 0x4C, 0x6B, 0x0B, 0x42, 0x07, 0x41, 0xE7, +0x42, 0x07, 0x41, 0xE7, 0x5A, 0xAA, 0x7B, 0x6C, +0x83, 0xCE, 0x73, 0x4C, 0x52, 0x49, 0x49, 0xE7, +0x6B, 0x0C, 0x6A, 0xEB, 0x83, 0xAE, 0x94, 0x50, +0xB5, 0x33, 0x94, 0x2F, 0x83, 0xCE, 0x5A, 0x89, +0x6B, 0x2B, 0x83, 0xAD, 0x62, 0xEA, 0x4A, 0x48, +0x52, 0x49, 0x52, 0x68, 0x5A, 0xA9, 0x6B, 0x2B, +0x7B, 0x8C, 0x9C, 0x90, 0x9C, 0x4F, 0xAD, 0x12, +0xAD, 0x12, 0xAC, 0xF1, 0xB5, 0x53, 0xAD, 0x11, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x93, 0xB5, 0x52, +0xBD, 0x52, 0xBD, 0x73, 0xCD, 0xD4, 0xA4, 0x90, +0x41, 0xC7, 0x29, 0x45, 0x21, 0x25, 0x21, 0x25, +0x21, 0x04, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xC3, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA4, 0x10, 0xC4, 0x10, 0xC4, +0x19, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x87, 0x31, 0x88, +0x29, 0x67, 0x31, 0xA8, 0x39, 0xE9, 0x42, 0x4A, +0x42, 0x4A, 0x63, 0x0C, 0xA4, 0xD1, 0xC5, 0xB3, +0xE6, 0x96, 0xDE, 0x14, 0xDE, 0x55, 0xE6, 0x96, +0xEE, 0x96, 0xEE, 0x96, 0xEE, 0x96, 0xE6, 0x75, +0xE6, 0x75, 0xCD, 0xF3, 0xCD, 0xB3, 0xCD, 0xD3, +0xDE, 0x55, 0xCD, 0xF4, 0xD6, 0x36, 0xE6, 0xB7, +0xDE, 0x77, 0xDE, 0x56, 0xD6, 0x35, 0xCD, 0xF4, +0xCD, 0xD4, 0xE6, 0x96, 0xC5, 0x93, 0xB5, 0x12, +0xBD, 0x73, 0xCD, 0xF5, 0xC5, 0xD4, 0xC5, 0xF4, +0xBD, 0x93, 0xAD, 0x53, 0xCE, 0x36, 0xBD, 0xD5, +0x31, 0x86, 0x18, 0xA3, 0x5A, 0xAB, 0xA4, 0xF3, +0xAD, 0x55, 0xBD, 0xD7, 0x4A, 0x69, 0x4A, 0x28, +0x31, 0x65, 0x52, 0x28, 0x8B, 0xAD, 0xB5, 0x12, +0x5B, 0xE6, 0x64, 0x47, 0x7C, 0xEA, 0x74, 0xA9, +0x5B, 0xE5, 0x6C, 0x28, 0x84, 0xCB, 0x6B, 0xEA, +0x3A, 0x64, 0x4A, 0xE5, 0x63, 0xC7, 0x7C, 0x89, +0x6C, 0x06, 0x8C, 0xED, 0xBE, 0x55, 0x95, 0x0E, +0x84, 0xAA, 0x95, 0x4C, 0x8C, 0xEB, 0x6C, 0x49, +0x64, 0x08, 0x6C, 0x08, 0x9C, 0xED, 0x9C, 0x6D, +0x7B, 0x49, 0x9C, 0x6E, 0x8C, 0x0C, 0x7B, 0x8B, +0x83, 0xCC, 0x7B, 0x8B, 0x83, 0xCB, 0x8B, 0xEC, +0x83, 0xCC, 0x8B, 0xEC, 0xAC, 0xCF, 0xAC, 0xF0, +0xA4, 0x8F, 0xA4, 0xAF, 0xAC, 0xCF, 0xB5, 0x10, +0xB5, 0x30, 0xC5, 0x92, 0xC5, 0x92, 0xCD, 0x92, +0xD5, 0xF3, 0xCD, 0xB2, 0xBD, 0x71, 0xBD, 0x50, +0xAC, 0xCF, 0xB4, 0xEF, 0xC5, 0x71, 0xC5, 0x92, +0xCD, 0x92, 0xC5, 0x72, 0xC5, 0x71, 0xC5, 0x92, +0xC5, 0x92, 0xC5, 0x92, 0xC5, 0x92, 0xC5, 0x71, +0xBD, 0x51, 0xBD, 0x31, 0xB4, 0xF0, 0xB5, 0x10, +0xB4, 0xF0, 0xA4, 0xCF, 0xAC, 0xCF, 0xB5, 0x31, +0xBD, 0x51, 0xBD, 0x50, 0xC5, 0x71, 0xB4, 0xEF, +0xB5, 0x10, 0xCE, 0x35, 0xC5, 0xB3, 0xB5, 0x52, +0xB5, 0x72, 0xC5, 0xF4, 0xCE, 0x35, 0xD6, 0x56, +0xCE, 0x36, 0xCE, 0x36, 0xD6, 0x56, 0xD6, 0x56, +0xC5, 0xD4, 0xBD, 0x93, 0xCE, 0x15, 0xCE, 0x15, +0xCE, 0x56, 0xD6, 0x97, 0xDE, 0x97, 0xC5, 0xD5, +0xB5, 0x54, 0x9C, 0x4F, 0xC5, 0x93, 0xDE, 0x98, +0x83, 0xEF, 0x73, 0x8D, 0x4A, 0x28, 0x39, 0xC6, +0x52, 0x89, 0x4A, 0x48, 0x4A, 0x48, 0x52, 0x69, +0x52, 0xAA, 0x5A, 0xEB, 0x7B, 0xCF, 0x8C, 0x72, +0xA4, 0xF4, 0xAD, 0x55, 0xBD, 0xB7, 0xB5, 0x97, +0xA4, 0xF3, 0x8C, 0x30, 0x9C, 0xD2, 0xBD, 0xB5, +0xCE, 0x15, 0xD6, 0x76, 0xD6, 0x35, 0xD6, 0x35, +0xDE, 0x56, 0xCD, 0xF4, 0xD6, 0x56, 0xD6, 0x36, +0xD6, 0x35, 0xDE, 0x76, 0xD6, 0x76, 0xD6, 0x76, +0xC5, 0xD4, 0xD6, 0x56, 0xCE, 0x16, 0xC5, 0xF5, +0xCE, 0x15, 0xC6, 0x16, 0xCE, 0x59, 0xB5, 0xB7, +0x9C, 0xB3, 0xAD, 0x12, 0xB5, 0x31, 0xB5, 0x72, +0xB5, 0x32, 0xBD, 0x73, 0xBD, 0x93, 0xCE, 0x15, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xD3, 0xC5, 0xD4, 0xC5, 0xD3, 0xCD, 0xF4, +0xD6, 0x15, 0xD6, 0x15, 0x94, 0x2E, 0x39, 0x85, +0x39, 0xC7, 0x42, 0x07, 0x73, 0x4C, 0x8C, 0x0F, +0x94, 0x30, 0x9C, 0x71, 0x9C, 0x92, 0x62, 0xAA, +0x39, 0xA6, 0x7B, 0x8D, 0x73, 0x2C, 0x8B, 0xEE, +0x8B, 0xEF, 0xB5, 0x34, 0x94, 0x71, 0x62, 0xCA, +0x5A, 0xCA, 0x52, 0x89, 0x52, 0xAA, 0x73, 0x6C, +0x94, 0x70, 0xA4, 0xD1, 0xAD, 0x32, 0xA4, 0xF1, +0xA4, 0xF1, 0xB5, 0x72, 0xC5, 0xB4, 0xD6, 0x15, +0xBD, 0x93, 0xAD, 0x12, 0xB5, 0x53, 0xAD, 0x12, +0xC5, 0xB4, 0xC5, 0xD4, 0xCD, 0xF4, 0xC5, 0xD3, +0xCD, 0xD4, 0xC5, 0xB3, 0xCD, 0xD4, 0x9C, 0x4F, +0x41, 0xC7, 0x29, 0x25, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xA3, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xC3, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA4, 0x18, 0xC4, +0x21, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x05, 0x21, 0x26, 0x29, 0x46, 0x21, 0x26, +0x29, 0x46, 0x29, 0x67, 0x29, 0x67, 0x31, 0xA8, +0x31, 0x87, 0x29, 0x87, 0x31, 0xC8, 0x39, 0xE9, +0x42, 0x2A, 0x4A, 0x4A, 0x8C, 0x0F, 0xAC, 0xF1, +0xBD, 0x52, 0xDE, 0x56, 0xEE, 0xD7, 0xF6, 0xF7, +0xF6, 0xF7, 0xF6, 0xF7, 0xEE, 0xD7, 0xEE, 0xD6, +0xEE, 0xD6, 0xE6, 0x96, 0xDE, 0x35, 0xDE, 0x75, +0xE6, 0x96, 0xCD, 0xD4, 0xDE, 0x76, 0xE6, 0xB7, +0xE6, 0x97, 0xDE, 0x56, 0xD6, 0x15, 0xCD, 0xD4, +0xC5, 0xB3, 0xDE, 0x76, 0xC5, 0x93, 0x9C, 0x8F, +0xCE, 0x36, 0xD6, 0x56, 0xCE, 0x15, 0xCE, 0x15, +0xBD, 0xB4, 0xAD, 0x32, 0xCE, 0x36, 0xD6, 0x77, +0x5A, 0xAA, 0x18, 0xE4, 0x29, 0x24, 0x6B, 0x2B, +0x94, 0x91, 0x62, 0xEA, 0x42, 0x07, 0x5A, 0xA9, +0x4A, 0x07, 0x52, 0x28, 0x6A, 0xCA, 0x8B, 0xCD, +0x63, 0xEA, 0x43, 0x44, 0x6C, 0x86, 0x64, 0x45, +0x6C, 0x47, 0x74, 0x69, 0x8D, 0x0D, 0x74, 0x2A, +0x6B, 0xEA, 0x42, 0x86, 0x42, 0x84, 0x53, 0x46, +0x64, 0x08, 0x6B, 0xEA, 0x84, 0x6D, 0x8C, 0xCD, +0x84, 0xAB, 0x9D, 0x2D, 0x94, 0xCD, 0xB5, 0xD1, +0xAD, 0xD1, 0xA5, 0x70, 0xBE, 0x13, 0xA4, 0xEF, +0x9C, 0xAF, 0x9C, 0xB0, 0x7B, 0xCC, 0xA4, 0xD1, +0xAD, 0x32, 0x8C, 0x2E, 0x9C, 0x8F, 0x9C, 0x90, +0x9C, 0x90, 0x83, 0xED, 0x94, 0x8F, 0x8C, 0x4E, +0x83, 0xED, 0x8C, 0x2E, 0x8C, 0x0E, 0xBD, 0x93, +0xBD, 0x51, 0x9C, 0x4D, 0xA4, 0x6D, 0xAC, 0xCE, +0xBD, 0x51, 0xB5, 0x31, 0xAC, 0xF0, 0x9C, 0x4D, +0x83, 0xAB, 0x73, 0x29, 0x94, 0x2D, 0x9C, 0x8E, +0xA4, 0x8F, 0xAC, 0xD0, 0xB5, 0x31, 0xA4, 0xAE, +0xB5, 0x31, 0xBD, 0x51, 0xBD, 0x51, 0xA4, 0x8E, +0x9C, 0x4D, 0xA4, 0xAF, 0xAC, 0xAF, 0xC5, 0x92, +0xC5, 0x92, 0xB4, 0xEF, 0xBD, 0x50, 0xB5, 0x10, +0xAC, 0xCF, 0xAC, 0xAF, 0xAC, 0xAE, 0xB4, 0xEF, +0xA4, 0x8E, 0xAC, 0xAF, 0xA4, 0x8E, 0x9C, 0x4E, +0xA4, 0xAF, 0xAC, 0xCF, 0xAC, 0xCF, 0xA4, 0x8E, +0xA4, 0x8E, 0xA4, 0xAF, 0xA4, 0xCF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xAC, 0xD0, 0xAC, 0xF0, +0xAC, 0xF1, 0xAD, 0x11, 0xA4, 0xD0, 0x9C, 0x6F, +0x73, 0x4B, 0x9C, 0x6F, 0xC5, 0xD4, 0xCE, 0x15, +0x9C, 0x90, 0x83, 0xEE, 0x52, 0x89, 0x39, 0xE7, +0x42, 0x28, 0x52, 0x69, 0x42, 0x28, 0x42, 0x28, +0x52, 0x8A, 0x63, 0x0C, 0x7B, 0xCF, 0x94, 0x92, +0x9C, 0xF4, 0xA5, 0x35, 0xAD, 0x76, 0xAD, 0x55, +0xAD, 0x34, 0x7B, 0xAE, 0x9C, 0xB1, 0xDE, 0xB8, +0xD6, 0x77, 0xD6, 0x77, 0xCE, 0x15, 0xD6, 0x56, +0xD6, 0x55, 0xCE, 0x14, 0xCE, 0x15, 0xCE, 0x15, +0xBD, 0x93, 0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x35, +0xB5, 0x72, 0xD6, 0x56, 0xCE, 0x36, 0xC5, 0xD4, +0xCE, 0x36, 0xCE, 0x37, 0xD6, 0xBB, 0xCE, 0x59, +0x9C, 0xD3, 0xB5, 0x52, 0xCD, 0xF4, 0xC5, 0xB3, +0xC5, 0xB3, 0xCD, 0xF4, 0xB5, 0x31, 0xCE, 0x15, +0xD6, 0x35, 0xCE, 0x14, 0xCD, 0xF4, 0xCD, 0xF4, +0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x34, 0xDE, 0x55, +0xD5, 0xF3, 0xCD, 0xF3, 0xDE, 0x55, 0xB5, 0x12, +0x4A, 0x27, 0x42, 0x07, 0x4A, 0x28, 0x83, 0xCE, +0x83, 0xEF, 0x8B, 0xEF, 0xC5, 0x95, 0x94, 0x2F, +0x49, 0xE8, 0x41, 0xA7, 0x73, 0x4D, 0x73, 0x2C, +0x83, 0xCE, 0x9C, 0x91, 0xAC, 0xF3, 0x83, 0xCE, +0x7B, 0xAD, 0x6B, 0x2C, 0x73, 0x6D, 0x94, 0x70, +0xA4, 0xD1, 0xBD, 0x93, 0xBD, 0x93, 0xAD, 0x32, +0xB5, 0x32, 0xAD, 0x31, 0xB5, 0x52, 0xC5, 0xB3, +0xC5, 0xB3, 0xAC, 0xF1, 0xBD, 0x73, 0xAD, 0x12, +0xBD, 0x93, 0xC5, 0xB3, 0xCE, 0x14, 0xC5, 0x93, +0xC5, 0x93, 0xCD, 0xD4, 0xC5, 0xD4, 0x9C, 0x6F, +0x41, 0xC7, 0x21, 0x04, 0x18, 0xE4, 0x29, 0x25, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, +0x10, 0x83, 0x08, 0x83, 0x19, 0x04, 0x21, 0x05, +0x18, 0xC4, 0x21, 0x05, 0x21, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x25, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x10, 0xA4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA4, 0x18, 0xE4, +0x21, 0x25, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x47, +0x21, 0x46, 0x29, 0x67, 0x29, 0x67, 0x29, 0x87, +0x29, 0x87, 0x29, 0x87, 0x29, 0x87, 0x39, 0xC8, +0x42, 0x2A, 0x4A, 0x4A, 0x52, 0xAA, 0xAD, 0x32, +0xBD, 0x93, 0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xD0, +0xAC, 0xF0, 0xB4, 0xF0, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB4, 0xF0, 0xB5, 0x31, 0xB5, 0x31, +0xAD, 0x31, 0xBD, 0x73, 0xDE, 0x56, 0xDE, 0x76, +0xDE, 0x76, 0xDE, 0x76, 0xD6, 0x35, 0xD6, 0x15, +0xCD, 0xF4, 0xDE, 0x76, 0xC5, 0x93, 0x9C, 0x6F, +0xBD, 0x93, 0xBD, 0xB4, 0xBD, 0x93, 0xC5, 0xD4, +0xB5, 0x73, 0xA4, 0xD1, 0xCE, 0x16, 0xCE, 0x16, +0x63, 0x2B, 0x29, 0x65, 0x10, 0xA3, 0x31, 0x65, +0x39, 0xE6, 0x29, 0x24, 0x39, 0x86, 0x52, 0x48, +0x49, 0xE7, 0x41, 0xE7, 0x52, 0x07, 0x83, 0x6D, +0xAD, 0xF4, 0x63, 0xEB, 0x43, 0x42, 0x4B, 0xA2, +0x3A, 0xC2, 0x4B, 0x06, 0x84, 0xAC, 0x7C, 0x6C, +0xAD, 0x91, 0x6B, 0x89, 0x3A, 0x44, 0x5B, 0x87, +0x4B, 0x05, 0x8C, 0xAE, 0xAD, 0xB2, 0x94, 0xEE, +0x9D, 0x0F, 0x9C, 0xCE, 0x9C, 0xCE, 0xCE, 0x54, +0xBD, 0xF3, 0xAD, 0x50, 0x94, 0x6D, 0x84, 0x0D, +0xB5, 0x73, 0xBD, 0xD5, 0xB5, 0xB4, 0xB5, 0x94, +0xCE, 0x56, 0xB5, 0x72, 0x94, 0x8F, 0xAD, 0x53, +0xCE, 0x57, 0xBD, 0xD5, 0xCE, 0x57, 0xCE, 0x57, +0xBD, 0xF5, 0xCE, 0x36, 0xD6, 0x98, 0xD6, 0x56, +0xDE, 0x96, 0xBD, 0x72, 0xAC, 0xEF, 0xC5, 0xB3, +0xCD, 0xF5, 0xCE, 0x15, 0xC5, 0xF4, 0xBD, 0x92, +0xAD, 0x11, 0x9C, 0xAF, 0x9C, 0xAF, 0x8C, 0x2E, +0xA4, 0xF0, 0xA4, 0xF1, 0xAD, 0x11, 0xA4, 0xF0, +0xA5, 0x11, 0xA4, 0xF0, 0x9C, 0x8F, 0xA4, 0xF0, +0xAD, 0x31, 0xC5, 0xD4, 0xC5, 0xF4, 0xB5, 0x51, +0xCD, 0xF3, 0xA4, 0x8E, 0xB5, 0x10, 0x8B, 0xEC, +0x9C, 0x4E, 0x94, 0x4D, 0x9C, 0x6E, 0xB5, 0x10, +0xA4, 0x8E, 0x9C, 0x4E, 0xA4, 0x8E, 0xA4, 0x8E, +0x8B, 0xCC, 0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, +0x8B, 0xEC, 0x94, 0x0C, 0x9C, 0x6E, 0xA4, 0x8E, +0xAC, 0xCF, 0xAC, 0xAF, 0xAC, 0xCF, 0xB5, 0x10, +0xB5, 0x30, 0xAC, 0xD0, 0xB5, 0x10, 0xBD, 0x51, +0xB5, 0x10, 0xA4, 0x8E, 0xA4, 0xAE, 0xA4, 0x8F, +0x94, 0x6E, 0x94, 0x4F, 0x5A, 0x89, 0x52, 0x89, +0x42, 0x07, 0x42, 0x07, 0x39, 0xA6, 0x4A, 0x28, +0x52, 0x8A, 0x5A, 0xEC, 0x73, 0x8E, 0x84, 0x10, +0x73, 0x8E, 0x8C, 0x51, 0x84, 0x30, 0x8C, 0x51, +0x94, 0x72, 0x5A, 0xAB, 0x73, 0x4C, 0xC5, 0xB5, +0xCD, 0xF6, 0x8C, 0x2F, 0x8C, 0x2E, 0xBD, 0xB4, +0xAD, 0x31, 0xB5, 0x72, 0xAD, 0x31, 0xC5, 0xF4, +0xB5, 0x52, 0xD6, 0x56, 0xCE, 0x35, 0xBD, 0x72, +0x9C, 0x8F, 0xAD, 0x31, 0xCE, 0x35, 0xCE, 0x15, +0xDE, 0x77, 0x9C, 0x91, 0x94, 0x72, 0x94, 0xB3, +0x9C, 0xD2, 0xB5, 0x52, 0xBD, 0x52, 0xAC, 0xF0, +0xC5, 0xB3, 0xCE, 0x14, 0xC5, 0xB3, 0xCD, 0xF4, +0xD6, 0x14, 0xD6, 0x14, 0xCD, 0xF4, 0xCD, 0xD3, +0xDE, 0x35, 0xDE, 0x55, 0xDE, 0x75, 0xDE, 0x75, +0xCD, 0xB2, 0xD6, 0x13, 0xDE, 0x34, 0xDE, 0x35, +0xC5, 0xD4, 0x94, 0x6F, 0x62, 0xEA, 0x4A, 0x28, +0x7B, 0x6D, 0x7B, 0x8E, 0xB5, 0x54, 0xA4, 0xB1, +0x6A, 0xCB, 0x39, 0x65, 0x62, 0xCB, 0x5A, 0x69, +0x83, 0xAE, 0x83, 0xAE, 0xCD, 0xF7, 0x9C, 0x91, +0x94, 0x50, 0x8C, 0x0F, 0x94, 0x70, 0xAC, 0xF1, +0xBD, 0x94, 0xBD, 0x73, 0xAC, 0xD0, 0xBD, 0x52, +0xBD, 0x52, 0xB5, 0x31, 0xA4, 0xAF, 0xBD, 0x72, +0xC5, 0xD4, 0xAD, 0x11, 0xC5, 0x94, 0xB5, 0x32, +0xBD, 0x73, 0xC5, 0x93, 0xCD, 0xD3, 0xC5, 0x92, +0xCD, 0xD4, 0xC5, 0x72, 0xCD, 0xD3, 0xA4, 0x6F, +0x49, 0xC7, 0x20, 0xE4, 0x21, 0x04, 0x21, 0x25, +0x21, 0x04, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xC3, 0x21, 0x05, 0x21, 0x05, +0x18, 0xC3, 0x21, 0x05, 0x21, 0x25, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x21, 0x05, 0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, 0x19, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x46, +0x29, 0x67, 0x29, 0x46, 0x29, 0x67, 0x29, 0x67, +0x29, 0x67, 0x29, 0x46, 0x29, 0x67, 0x29, 0x87, +0x3A, 0x09, 0x42, 0x29, 0x42, 0x09, 0x63, 0x2C, +0xB5, 0x53, 0xAC, 0xF1, 0xBD, 0x94, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xD1, 0xAC, 0xF1, +0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x12, 0xB5, 0x53, +0xB5, 0x32, 0xAD, 0x12, 0xAC, 0xF1, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x32, +0xAD, 0x31, 0xB5, 0x52, 0xAD, 0x11, 0xAC, 0xF1, +0xA4, 0xB0, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x90, +0xA4, 0xD0, 0x9C, 0x90, 0x94, 0x90, 0x9C, 0x70, +0x94, 0x6F, 0x52, 0x89, 0x20, 0xC3, 0x21, 0x04, +0x31, 0x85, 0x31, 0x45, 0x39, 0x85, 0x42, 0x07, +0x41, 0xC6, 0x39, 0xA6, 0x52, 0x48, 0x7B, 0x4C, +0x9D, 0x52, 0xAD, 0xF4, 0x6C, 0x2C, 0x43, 0x03, +0x3A, 0xA2, 0x3A, 0xA4, 0x74, 0x4A, 0x53, 0x27, +0x8C, 0xAD, 0x84, 0x4C, 0x52, 0xE6, 0x53, 0x06, +0x7C, 0x2B, 0x9D, 0x30, 0x84, 0x2C, 0x84, 0x6C, +0xAD, 0x51, 0x9C, 0xAE, 0xA4, 0xEF, 0xD6, 0x76, +0xC6, 0x14, 0xA4, 0xF0, 0x9C, 0xCF, 0xA5, 0x11, +0xCE, 0x16, 0xC5, 0xF5, 0xBD, 0xB5, 0xBD, 0xD4, +0xCE, 0x36, 0xBD, 0xD4, 0x9C, 0xD0, 0xA4, 0xF1, +0xB5, 0x94, 0xC5, 0xF6, 0x9C, 0xD1, 0xD6, 0x98, +0xC6, 0x36, 0xD6, 0x77, 0xD6, 0x56, 0xBD, 0x93, +0xBD, 0xB3, 0xC5, 0xB3, 0xB5, 0x10, 0xD6, 0x76, +0xDE, 0x97, 0xDE, 0x97, 0xDE, 0xB7, 0xDE, 0x96, +0xD6, 0x76, 0xCE, 0x15, 0xAD, 0x32, 0x94, 0x6F, +0x9C, 0x90, 0x84, 0x0E, 0xA4, 0xF1, 0xB5, 0x73, +0x9C, 0xD0, 0xAD, 0x11, 0xBD, 0xB4, 0x9C, 0xB0, +0xA4, 0xF1, 0xCE, 0x15, 0xCE, 0x56, 0xBD, 0xB3, +0xC5, 0xD3, 0xA4, 0x8E, 0xB5, 0x10, 0x83, 0xAB, +0x8C, 0x4E, 0x9C, 0xB0, 0x94, 0x4E, 0xA4, 0xD0, +0xB5, 0x31, 0xB5, 0x52, 0xAD, 0x31, 0xA4, 0xD0, +0x7B, 0x8C, 0x7B, 0x8C, 0x6B, 0x4B, 0x73, 0x6C, +0x73, 0x4B, 0x9C, 0xB0, 0xBD, 0x94, 0xBD, 0x73, +0x9C, 0x6E, 0x94, 0x2E, 0xAD, 0x11, 0x9C, 0x8E, +0x8B, 0xEC, 0xB4, 0xEF, 0xB4, 0xEF, 0xAD, 0x10, +0xC5, 0x92, 0xB5, 0x10, 0xB5, 0x30, 0xCD, 0xF4, +0xC5, 0xD3, 0xB5, 0x52, 0x62, 0xA9, 0x52, 0x69, +0x42, 0x07, 0x42, 0x07, 0x42, 0x07, 0x4A, 0x48, +0x4A, 0x49, 0x52, 0xAA, 0x63, 0x0C, 0x6B, 0x4D, +0x7B, 0xF0, 0x94, 0x92, 0xA5, 0x14, 0xA5, 0x35, +0x8C, 0x51, 0x6B, 0x4D, 0x83, 0xEF, 0xA4, 0xD2, +0xB5, 0x34, 0x7B, 0x8E, 0x41, 0xC7, 0x94, 0x6F, +0xAC, 0xCF, 0xA4, 0xAE, 0xA4, 0x6E, 0xA4, 0x8E, +0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x6E, 0xA4, 0x8F, 0xA4, 0xAF, 0xB5, 0x10, +0xBD, 0x52, 0xB5, 0x54, 0x9C, 0xB3, 0x83, 0xF0, +0xAD, 0x12, 0xBD, 0x72, 0xB4, 0xF0, 0xA4, 0xAF, +0xAC, 0xF0, 0xA4, 0x8E, 0xB5, 0x10, 0xB4, 0xD0, +0xAC, 0xCF, 0xA4, 0x8E, 0x94, 0x2D, 0xA4, 0x6E, +0xBD, 0x51, 0xCD, 0xB2, 0xCD, 0xF3, 0xCD, 0xD2, +0xB5, 0x0F, 0xBD, 0x50, 0xDE, 0x34, 0xCD, 0xB2, +0xBD, 0x71, 0xB5, 0x10, 0x8C, 0x0E, 0x5A, 0xAA, +0x83, 0xAE, 0x94, 0x30, 0x6A, 0xEB, 0x5A, 0x8A, +0x4A, 0x08, 0x52, 0x49, 0x39, 0x86, 0x6B, 0x0B, +0x5A, 0x69, 0x73, 0x6D, 0xCE, 0x17, 0x83, 0x8D, +0x8B, 0xEF, 0xBD, 0x95, 0xA4, 0xF1, 0xBD, 0x73, +0xD5, 0xF4, 0xC5, 0x92, 0xBD, 0x51, 0xCD, 0xD3, +0xC5, 0x72, 0xAD, 0x11, 0x7B, 0x8B, 0x7B, 0x8C, +0xC5, 0xB4, 0xAD, 0x11, 0xC5, 0xB4, 0xAD, 0x12, +0xB5, 0x52, 0xBD, 0x72, 0xC5, 0xB3, 0xBD, 0x92, +0xBD, 0x72, 0xBD, 0x31, 0xC5, 0x72, 0x9C, 0x6F, +0x62, 0xA9, 0x39, 0xA7, 0x29, 0x46, 0x21, 0x05, +0x21, 0x05, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, +0x10, 0xA3, 0x10, 0xC3, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x21, 0x25, 0x19, 0x05, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, +0x19, 0x05, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC3, 0x18, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x21, 0x46, 0x29, 0x46, +0x29, 0x67, 0x29, 0x46, 0x29, 0x67, 0x29, 0x67, +0x29, 0x67, 0x21, 0x26, 0x29, 0x46, 0x29, 0x87, +0x39, 0xC8, 0x42, 0x09, 0x3A, 0x09, 0x39, 0xE8, +0x8C, 0x30, 0xBD, 0xB4, 0xC5, 0xF5, 0x94, 0x70, +0x8C, 0x0E, 0x9C, 0xB0, 0x8C, 0x2E, 0xAD, 0x12, +0xA4, 0xD1, 0xC5, 0xF5, 0xBD, 0xD5, 0xBD, 0xB5, +0xB5, 0x54, 0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x12, +0xB5, 0x73, 0xAD, 0x12, 0x9C, 0xB0, 0x94, 0x70, +0x94, 0x70, 0x94, 0x4F, 0x8C, 0x0E, 0x83, 0xEE, +0x94, 0x2F, 0x94, 0x6F, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0x90, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0x6F, +0xA4, 0xF1, 0x73, 0x8C, 0x20, 0xE4, 0x18, 0xA3, +0x31, 0x65, 0x31, 0x65, 0x39, 0x85, 0x39, 0xA6, +0x4A, 0x07, 0x39, 0xA6, 0x4A, 0x07, 0x8B, 0xCE, +0x7C, 0x8D, 0x63, 0xCA, 0x84, 0xAE, 0x5B, 0x88, +0x43, 0x04, 0x53, 0x66, 0x8D, 0x0D, 0x6B, 0xE9, +0x52, 0xC6, 0x4A, 0x65, 0x4A, 0x85, 0x94, 0xEE, +0xAD, 0xB1, 0x8C, 0xAE, 0x73, 0xEB, 0xAD, 0x71, +0xB5, 0x92, 0x9C, 0xCE, 0xA4, 0xEF, 0xCE, 0x55, +0xCE, 0x14, 0xAD, 0x31, 0xA4, 0xF0, 0xBD, 0xB4, +0xC5, 0xF5, 0xB5, 0x94, 0xB5, 0x73, 0xC6, 0x15, +0xD6, 0xB7, 0xD6, 0x77, 0xC6, 0x15, 0xBD, 0xD4, +0xB5, 0x94, 0xAD, 0x53, 0x6B, 0x4C, 0x9C, 0xD1, +0xBD, 0xB4, 0xC5, 0xF5, 0xCE, 0x15, 0xD6, 0x76, +0xD6, 0x76, 0xBD, 0x72, 0xB5, 0x51, 0xD6, 0x56, +0xCE, 0x14, 0xCE, 0x14, 0xD6, 0x55, 0xCE, 0x14, +0xCE, 0x35, 0xD6, 0x76, 0xCE, 0x35, 0xBD, 0xB4, +0xBD, 0xB4, 0xAD, 0x53, 0xB5, 0x94, 0xCE, 0x36, +0xAD, 0x52, 0xAD, 0x11, 0x94, 0x6F, 0xA4, 0xD0, +0xB5, 0x72, 0xCE, 0x35, 0xCE, 0x35, 0xCE, 0x14, +0xCD, 0xF4, 0xAC, 0xEF, 0xB4, 0xEF, 0x8C, 0x0D, +0x9C, 0xB0, 0xAD, 0x12, 0x8C, 0x0D, 0x9C, 0x6F, +0xB5, 0x52, 0xC5, 0xD4, 0xC5, 0xD4, 0xB5, 0x93, +0x9C, 0xB1, 0x84, 0x0F, 0x6B, 0x6C, 0x5A, 0xEA, +0x6B, 0x6C, 0xB5, 0x94, 0x8C, 0x0E, 0xAC, 0xF1, +0x9C, 0x8F, 0xBD, 0xB3, 0xCE, 0x15, 0x9C, 0x8F, +0x83, 0xAB, 0xB5, 0x10, 0xB5, 0x0F, 0xC5, 0xB2, +0xCE, 0x15, 0xD6, 0x35, 0xB5, 0x51, 0xCE, 0x14, +0xC5, 0xD4, 0xBD, 0xB3, 0xBD, 0x73, 0x83, 0xCD, +0x4A, 0x68, 0x4A, 0x48, 0x42, 0x07, 0x4A, 0x48, +0x4A, 0x48, 0x4A, 0x69, 0x5A, 0xCA, 0x63, 0x2D, +0x7B, 0xCF, 0x84, 0x10, 0x94, 0x92, 0x8C, 0x71, +0x8C, 0x51, 0xAD, 0x55, 0x9C, 0xB2, 0x83, 0xCE, +0x9C, 0x91, 0x9C, 0x91, 0x42, 0x08, 0x7B, 0x8D, +0xB5, 0x52, 0x94, 0x2D, 0x8B, 0xEC, 0x83, 0xAB, +0x8B, 0xCC, 0x94, 0x2C, 0x93, 0xEC, 0x94, 0x0C, +0x9C, 0x4E, 0xA4, 0x8E, 0xAC, 0xAE, 0xBD, 0x30, +0xC5, 0x73, 0xC5, 0xF7, 0xA5, 0x14, 0x8C, 0x51, +0xAC, 0xF2, 0xB5, 0x10, 0xBD, 0x31, 0xBD, 0x31, +0xB5, 0x31, 0xBD, 0x31, 0xBD, 0x50, 0xBD, 0x51, +0xBD, 0x31, 0xBD, 0x50, 0xC5, 0x51, 0xBD, 0x30, +0xB5, 0x10, 0xB4, 0xEF, 0xB4, 0xCE, 0xAC, 0x8E, +0x9C, 0x2C, 0x9C, 0x4D, 0xB5, 0x0F, 0xBD, 0x10, +0xAC, 0xAE, 0xB5, 0x10, 0x9C, 0x6F, 0x5A, 0xA9, +0x7B, 0xAE, 0x8B, 0xEF, 0x41, 0xE7, 0x29, 0x45, +0x4A, 0x08, 0x5A, 0x69, 0x4A, 0x08, 0x83, 0xCF, +0x7B, 0x8D, 0x4A, 0x08, 0x9C, 0x91, 0x7B, 0x8D, +0x73, 0x2C, 0x9C, 0x90, 0xA4, 0xD0, 0xCD, 0xD4, +0xDE, 0x15, 0xD6, 0x14, 0xCD, 0x92, 0xC5, 0x92, +0xBD, 0x72, 0xBD, 0x72, 0x9C, 0x6F, 0xA4, 0xB1, +0xC5, 0xD4, 0x9C, 0x8F, 0xC5, 0xB4, 0xAC, 0xF1, +0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x11, +0xB5, 0x31, 0xB5, 0x10, 0xB5, 0x31, 0xAC, 0xAF, +0x9C, 0x4E, 0x6B, 0x0B, 0x31, 0x66, 0x21, 0x25, +0x21, 0x25, 0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE5, 0x21, 0x05, 0x21, 0x46, +0x21, 0x46, 0x29, 0x46, 0x21, 0x46, 0x21, 0x46, +0x29, 0x46, 0x29, 0x67, 0x29, 0x67, 0x29, 0x67, +0x29, 0x67, 0x29, 0x46, 0x29, 0x46, 0x29, 0x67, +0x31, 0xC8, 0x3A, 0x09, 0x39, 0xE9, 0x31, 0xC8, +0x39, 0xC8, 0x94, 0x71, 0xCE, 0x16, 0x94, 0x90, +0x94, 0x4F, 0xA4, 0xD1, 0xA4, 0xD0, 0xB5, 0x53, +0xAD, 0x53, 0xCE, 0x77, 0xC6, 0x37, 0xC5, 0xF6, +0xC6, 0x17, 0xBD, 0xF6, 0xAD, 0x53, 0x9C, 0xB1, +0xAD, 0x33, 0xA5, 0x12, 0x8C, 0x50, 0x8C, 0x50, +0x9C, 0x91, 0xA4, 0xD1, 0x9C, 0xB1, 0x94, 0x70, +0x9C, 0xD2, 0xA4, 0xD2, 0xA5, 0x12, 0xB5, 0x74, +0xAD, 0x53, 0xA4, 0xF1, 0xA4, 0xD1, 0x8C, 0x2E, +0xA4, 0xF1, 0xAD, 0x12, 0x29, 0x44, 0x21, 0x04, +0x18, 0xC3, 0x29, 0x44, 0x39, 0x85, 0x41, 0xE7, +0x52, 0x48, 0x5A, 0x69, 0x4A, 0x07, 0x8B, 0xCE, +0x63, 0xCA, 0x6C, 0x0A, 0x5B, 0x89, 0x4B, 0x26, +0x5B, 0xC7, 0x5B, 0xC8, 0x6B, 0xE8, 0x5B, 0x67, +0x73, 0xEA, 0x4A, 0xA6, 0x6B, 0x68, 0x84, 0x4B, +0x7C, 0x0A, 0x7C, 0x0B, 0x84, 0x6D, 0x8C, 0xAE, +0x8C, 0x6D, 0xAD, 0x72, 0xB5, 0xB3, 0xC6, 0x34, +0xCE, 0x55, 0xCE, 0x35, 0xB5, 0x72, 0xBD, 0xB3, +0xBD, 0xD4, 0xA5, 0x12, 0xB5, 0x73, 0xC6, 0x35, +0xDE, 0xB7, 0xD6, 0x97, 0xCE, 0x56, 0xCE, 0x36, +0xC5, 0xF5, 0xB5, 0x74, 0x9C, 0xB1, 0xAD, 0x74, +0xB5, 0x94, 0xC5, 0xF5, 0xC5, 0xF4, 0xCE, 0x55, +0xD6, 0x55, 0xB5, 0x10, 0xB5, 0x51, 0xC5, 0xD3, +0xCD, 0xF4, 0xA4, 0xAF, 0xB5, 0x72, 0xCE, 0x35, +0xD6, 0x76, 0xB5, 0x52, 0x83, 0xEE, 0x9C, 0xD1, +0xBD, 0xD5, 0xD6, 0x57, 0xAD, 0x53, 0xB5, 0x53, +0xCE, 0x36, 0xBD, 0xD4, 0xAD, 0x53, 0xB5, 0x93, +0xCE, 0x36, 0xD6, 0x76, 0xCE, 0x56, 0xCD, 0xF4, +0xC5, 0xB3, 0xB4, 0xEF, 0xB4, 0xEF, 0x8C, 0x0D, +0x94, 0x6F, 0xA4, 0xF1, 0x8C, 0x0D, 0x9C, 0x8F, +0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0xB4, 0xBD, 0xB4, +0xA4, 0xF2, 0x8C, 0x2F, 0x83, 0xEF, 0x73, 0xCD, +0x84, 0x2F, 0xBD, 0xB5, 0x9C, 0x90, 0x73, 0x4B, +0x7B, 0x8C, 0xB5, 0x73, 0xBD, 0x94, 0x9C, 0x90, +0x94, 0x2D, 0xBD, 0x31, 0xB5, 0x10, 0xCD, 0xF4, +0xB5, 0x72, 0xCE, 0x14, 0xBD, 0x92, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x73, 0xB5, 0x73, 0x94, 0x6F, +0x4A, 0x68, 0x4A, 0x69, 0x39, 0xC6, 0x31, 0xA5, +0x39, 0xE7, 0x4A, 0x48, 0x5A, 0xCB, 0x63, 0x2C, +0x6B, 0x4D, 0x73, 0x8E, 0x83, 0xF0, 0x8C, 0x51, +0xAD, 0x75, 0xAD, 0x75, 0x94, 0x71, 0xA4, 0xB2, +0x9C, 0x91, 0x9C, 0x91, 0x5A, 0x8A, 0x62, 0xEB, +0xB5, 0x73, 0xAD, 0x11, 0x9C, 0xAF, 0x94, 0x6F, +0x7B, 0xAC, 0x83, 0xCC, 0x9C, 0x8F, 0x94, 0x0D, +0x94, 0x2D, 0xA4, 0xCF, 0x9C, 0x6D, 0xB4, 0xF0, +0xBD, 0x93, 0xBD, 0xD6, 0xAD, 0x35, 0x94, 0x71, +0x8B, 0xEE, 0x8B, 0xEC, 0x83, 0xAB, 0x7B, 0x6B, +0x83, 0xAC, 0x94, 0x2D, 0xA4, 0x6E, 0xAC, 0xCF, +0xAC, 0xCF, 0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xEF, 0xB5, 0x10, 0xB4, 0xEF, +0xB5, 0x0F, 0xC5, 0x71, 0xBD, 0x51, 0xB4, 0xEF, +0xBD, 0x31, 0xBD, 0x52, 0x6B, 0x0A, 0x62, 0xEA, +0x4A, 0x28, 0x41, 0xE7, 0x29, 0x44, 0x31, 0x86, +0x41, 0xC7, 0x4A, 0x08, 0x52, 0x49, 0x5A, 0x89, +0x94, 0x30, 0x62, 0xCB, 0x5A, 0x69, 0x7B, 0x8E, +0x7B, 0x8E, 0x83, 0x8E, 0xB5, 0x13, 0xCE, 0x16, +0xAD, 0x12, 0x9C, 0x90, 0x9C, 0x6F, 0x94, 0x2E, +0xA4, 0xAF, 0xAD, 0x11, 0xBD, 0x53, 0xB5, 0x32, +0xAC, 0xF0, 0x94, 0x2E, 0xBD, 0x74, 0xA4, 0xB0, +0x9C, 0x6F, 0x9C, 0x4E, 0x9C, 0x4E, 0x9C, 0x6E, +0xA4, 0xAF, 0xAC, 0xD0, 0xAC, 0xD0, 0xA4, 0xB0, +0xAC, 0xF1, 0x94, 0x0E, 0x5A, 0x69, 0x31, 0x66, +0x21, 0x25, 0x21, 0x25, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x82, 0x08, 0x83, 0x08, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x19, 0x04, 0x18, 0xC4, +0x18, 0xE4, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x05, 0x19, 0x05, +0x18, 0xE5, 0x18, 0xE5, 0x21, 0x26, 0x21, 0x46, +0x21, 0x46, 0x29, 0x46, 0x21, 0x46, 0x21, 0x46, +0x29, 0x46, 0x29, 0x46, 0x21, 0x46, 0x29, 0x46, +0x21, 0x46, 0x21, 0x46, 0x29, 0x46, 0x29, 0x46, +0x29, 0x87, 0x39, 0xE9, 0x39, 0xE9, 0x39, 0xE9, +0x31, 0x87, 0x39, 0xE8, 0x8C, 0x50, 0x9C, 0xF1, +0x94, 0x6F, 0x9C, 0x90, 0x9C, 0xB0, 0xB5, 0x53, +0xB5, 0x53, 0xCE, 0x57, 0xC6, 0x37, 0xBD, 0xB5, +0xB5, 0xB5, 0xBD, 0xB5, 0xA5, 0x12, 0x84, 0x2F, +0x8C, 0x91, 0x8C, 0x50, 0x7B, 0xEE, 0x8C, 0x50, +0x94, 0x91, 0x9C, 0xF2, 0xA5, 0x13, 0xA5, 0x33, +0xBD, 0xB5, 0xA5, 0x12, 0x9C, 0x91, 0xA4, 0xF2, +0x9C, 0xB0, 0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xF1, +0xC5, 0xB4, 0xD6, 0x56, 0x52, 0x89, 0x18, 0xE4, +0x10, 0x82, 0x29, 0x44, 0x39, 0x85, 0x39, 0xA6, +0x52, 0x48, 0x6A, 0xEA, 0x5A, 0x89, 0x7B, 0x8D, +0x95, 0x70, 0x9D, 0x91, 0x74, 0x6D, 0x5B, 0xC9, +0x6C, 0x49, 0x53, 0x66, 0x53, 0x46, 0x6C, 0x08, +0x6B, 0xE9, 0x5B, 0x27, 0x8C, 0x6C, 0x8C, 0x4C, +0x84, 0x0B, 0x73, 0xCB, 0x74, 0x0B, 0x6B, 0xEB, +0x7C, 0x4D, 0xBE, 0x34, 0xA5, 0x10, 0xA5, 0x10, +0xB5, 0x71, 0xBD, 0xB3, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0xD4, 0x9C, 0xD0, 0xAD, 0x32, 0xBD, 0xD4, +0xCE, 0x35, 0xBD, 0xB3, 0xAD, 0x31, 0xCE, 0x36, +0xC5, 0xD5, 0xAD, 0x33, 0x8C, 0x2F, 0xB5, 0xB5, +0xB5, 0x94, 0xCE, 0x36, 0xCE, 0x56, 0xCE, 0x55, +0xD6, 0x55, 0xAD, 0x10, 0xBD, 0x92, 0xBD, 0x92, +0xD6, 0x35, 0x94, 0x6F, 0x39, 0xA5, 0x73, 0x4B, +0xB5, 0x73, 0xD6, 0x57, 0xBD, 0xB5, 0x5A, 0xCA, +0x4A, 0x68, 0x73, 0xAD, 0x83, 0xEE, 0x9C, 0xB1, +0xB5, 0x95, 0xCE, 0x57, 0xD6, 0x78, 0xCE, 0x57, +0xCE, 0x36, 0xD6, 0x97, 0xDE, 0x97, 0xD6, 0x76, +0xCE, 0x14, 0xB4, 0xEF, 0xB5, 0x10, 0xA4, 0xB0, +0xAD, 0x32, 0xAD, 0x52, 0xA4, 0xF0, 0xA4, 0xF1, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x94, 0xB5, 0x93, +0xAD, 0x32, 0x94, 0xD1, 0xA4, 0xF2, 0xA5, 0x13, +0x7B, 0xEE, 0xB5, 0x95, 0xB5, 0x53, 0x6B, 0x2A, +0x83, 0xCD, 0xBD, 0xB4, 0xCD, 0xF5, 0x9C, 0x8F, +0x94, 0x4E, 0xBD, 0x31, 0xBD, 0x30, 0xCE, 0x35, +0xBD, 0xB3, 0xC5, 0xF4, 0xC5, 0xF4, 0xBD, 0xB3, +0xC5, 0xD3, 0xBD, 0xB4, 0xB5, 0x52, 0xA4, 0xF1, +0x41, 0xE7, 0x62, 0xEB, 0x4A, 0x48, 0x29, 0x44, +0x39, 0xA6, 0x42, 0x28, 0x4A, 0x49, 0x52, 0x8A, +0x6B, 0x4D, 0x73, 0x6E, 0x84, 0x10, 0x94, 0x92, +0xA5, 0x14, 0xA5, 0x14, 0xAD, 0x55, 0xC5, 0xD7, +0x9C, 0x92, 0x6B, 0x2C, 0x62, 0xEB, 0x73, 0x8D, +0x94, 0x6F, 0x9C, 0xD0, 0xAD, 0x52, 0xB5, 0x73, +0xA5, 0x11, 0xA4, 0xF1, 0x8C, 0x0D, 0x73, 0x4A, +0x84, 0x0D, 0xB5, 0x31, 0xAC, 0xF0, 0xAC, 0xCF, +0xC5, 0xB4, 0xBD, 0xD6, 0xA5, 0x35, 0x84, 0x10, +0x6A, 0xEA, 0x8C, 0x0D, 0x83, 0x8B, 0x7B, 0x6C, +0x5A, 0x89, 0x5A, 0x89, 0x4A, 0x07, 0x41, 0xE6, +0x52, 0x47, 0x62, 0xC9, 0x5A, 0xA8, 0x62, 0xC9, +0x62, 0xC9, 0x62, 0xA8, 0x6A, 0xE9, 0x94, 0x2D, +0xB5, 0x10, 0x8B, 0xEC, 0x73, 0x29, 0x8B, 0xEC, +0xB5, 0x32, 0x9C, 0x4F, 0x62, 0xCA, 0x62, 0xCA, +0x31, 0x85, 0x21, 0x04, 0x29, 0x45, 0x31, 0x85, +0x31, 0x65, 0x39, 0xA6, 0x6B, 0x2C, 0x4A, 0x08, +0x41, 0xA7, 0x73, 0x4D, 0x83, 0xCE, 0x62, 0xEB, +0xC6, 0x18, 0xDE, 0x9A, 0xBD, 0x95, 0xC5, 0xD6, +0xD6, 0x37, 0xB5, 0x33, 0xBD, 0x94, 0xBD, 0x94, +0xC5, 0xD4, 0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x53, +0xB5, 0x32, 0xB5, 0x53, 0xC5, 0xD5, 0xC5, 0xD5, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD5, 0xC5, 0xB4, +0xC5, 0xB4, 0xCD, 0xD4, 0xCD, 0xB4, 0xC5, 0x94, +0xCD, 0xD4, 0xAC, 0xF1, 0x8B, 0xCE, 0x52, 0x28, +0x29, 0x25, 0x21, 0x25, 0x18, 0xE4, 0x19, 0x04, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xA3, +0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x05, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x46, 0x21, 0x26, +0x21, 0x46, 0x21, 0x46, 0x21, 0x46, 0x21, 0x46, +0x29, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x46, +0x21, 0x46, 0x21, 0x46, 0x21, 0x46, 0x29, 0x46, +0x29, 0x67, 0x31, 0xA8, 0x39, 0xE9, 0x39, 0xE9, +0x39, 0xC8, 0x29, 0x87, 0x42, 0x28, 0x83, 0xEF, +0x94, 0x4F, 0x9C, 0xB0, 0x8C, 0x2F, 0xB5, 0x53, +0xB5, 0x53, 0xD6, 0x98, 0xCE, 0x57, 0xBD, 0xB5, +0xAD, 0x74, 0xB5, 0x74, 0x9C, 0xF2, 0x84, 0x30, +0x8C, 0x91, 0x84, 0x2F, 0x7B, 0xEE, 0x7B, 0xEF, +0x94, 0x71, 0xA5, 0x13, 0xA4, 0xF2, 0x94, 0x90, +0xB5, 0x94, 0xA5, 0x13, 0x8C, 0x50, 0xA5, 0x33, +0x94, 0xB0, 0x94, 0x90, 0xA4, 0xD1, 0xAD, 0x12, +0xC5, 0xB4, 0xD6, 0x55, 0x9C, 0x90, 0x18, 0xE4, +0x10, 0xA3, 0x18, 0xE3, 0x39, 0xC6, 0x39, 0xA5, +0x4A, 0x27, 0x62, 0xEA, 0x6B, 0x0B, 0x7B, 0x6C, +0x63, 0xEB, 0x8D, 0x10, 0x74, 0x4D, 0x74, 0x4C, +0x64, 0x29, 0x5B, 0xC8, 0x43, 0x04, 0x64, 0x07, +0x53, 0x26, 0x52, 0xE6, 0x6B, 0x89, 0x94, 0xAE, +0x84, 0x2C, 0x74, 0x0B, 0x74, 0x4A, 0x6C, 0x09, +0x84, 0x6D, 0x94, 0x6D, 0xA4, 0xAF, 0xA4, 0xAE, +0x9C, 0x6D, 0xA4, 0xAF, 0xAC, 0xF0, 0xB5, 0x31, +0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x11, 0xAC, 0xF0, +0xAC, 0xCF, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x31, +0xB5, 0x11, 0xAC, 0xF1, 0xA4, 0xB0, 0x94, 0x6F, +0x9C, 0x8F, 0xA4, 0xD0, 0xB5, 0x31, 0xC5, 0xB3, +0xBD, 0x92, 0xBD, 0x51, 0xBD, 0x31, 0x9C, 0x6D, +0xAC, 0xF0, 0xA4, 0x8F, 0x73, 0x2A, 0x39, 0xC6, +0x52, 0xA9, 0x5A, 0xC9, 0x6B, 0x6C, 0x73, 0x6D, +0x31, 0x65, 0x42, 0x49, 0x52, 0x8A, 0x42, 0x29, +0x42, 0x4A, 0x5A, 0xEC, 0x7B, 0xF0, 0xA5, 0x34, +0xC6, 0x37, 0xD6, 0x97, 0xDE, 0x97, 0xD6, 0x76, +0xC5, 0xB3, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x52, +0xB5, 0x93, 0xBD, 0xB4, 0xBD, 0x94, 0xAD, 0x11, +0xC5, 0xD5, 0xC5, 0xF5, 0xC5, 0xD4, 0xC5, 0xD4, +0xB5, 0x73, 0xA5, 0x33, 0xA5, 0x33, 0xAD, 0x54, +0x7B, 0xAE, 0x84, 0x0E, 0x8C, 0x2E, 0x5A, 0xC9, +0x8C, 0x0E, 0xA4, 0xD0, 0xAD, 0x32, 0x8C, 0x2E, +0x9C, 0x6E, 0xBD, 0x51, 0xB5, 0x10, 0xC5, 0xF4, +0xC5, 0xD3, 0xC5, 0xF4, 0xC5, 0xF4, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x93, +0x73, 0x6C, 0x42, 0x07, 0x5A, 0xEA, 0x31, 0xA6, +0x39, 0xA6, 0x42, 0x07, 0x42, 0x28, 0x52, 0x8A, +0x63, 0x0C, 0x6B, 0x4D, 0x73, 0x8E, 0x84, 0x10, +0x9C, 0xD3, 0xA5, 0x15, 0xB5, 0x96, 0xCE, 0x38, +0xBD, 0x96, 0x94, 0x51, 0x73, 0x6D, 0xA5, 0x13, +0xAD, 0x53, 0x9C, 0xD1, 0xB5, 0x73, 0xC5, 0xF5, +0xCE, 0x36, 0xB5, 0x93, 0x8C, 0x2E, 0x9C, 0xD1, +0xAD, 0x32, 0xAD, 0x11, 0xB5, 0x31, 0xAC, 0xD0, +0xD6, 0x57, 0x9C, 0xD3, 0x7B, 0xCF, 0x94, 0x71, +0x83, 0xED, 0x8B, 0xED, 0x8B, 0xED, 0xB5, 0x52, +0x83, 0xCD, 0x94, 0x4F, 0x6B, 0x4C, 0x52, 0x8A, +0x52, 0x89, 0x52, 0x89, 0x84, 0x0F, 0xA4, 0xD1, +0xA4, 0xD1, 0x94, 0x4F, 0x5A, 0x89, 0x94, 0x4F, +0xA4, 0x8F, 0x94, 0x4E, 0x83, 0xCD, 0x94, 0x4F, +0xBD, 0x73, 0x94, 0x2F, 0x41, 0xE7, 0x62, 0xCA, +0x4A, 0x07, 0x20, 0xE3, 0x21, 0x24, 0x29, 0x44, +0x29, 0x44, 0x29, 0x45, 0x5A, 0x89, 0x52, 0x69, +0x41, 0xC7, 0x5A, 0xAA, 0x39, 0xA6, 0x39, 0xA7, +0x6B, 0x2D, 0xAD, 0x14, 0xCD, 0xF7, 0xAD, 0x13, +0xC5, 0xD6, 0x83, 0xCD, 0x94, 0x4F, 0x94, 0x6F, +0xBD, 0x73, 0xB5, 0x52, 0xB5, 0x53, 0xBD, 0xB4, +0xBD, 0x94, 0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xB0, +0x8C, 0x0D, 0xAD, 0x32, 0xA4, 0xD1, 0xA4, 0xD0, +0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xD1, 0xA4, 0xB0, +0xC5, 0xD4, 0xC5, 0xB4, 0x9C, 0x6F, 0x73, 0x2B, +0x41, 0xE7, 0x29, 0x45, 0x21, 0x04, 0x21, 0x25, +0x18, 0xC4, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x08, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE5, 0x21, 0x05, 0x21, 0x05, +0x19, 0x05, 0x21, 0x26, 0x29, 0x46, 0x21, 0x26, +0x21, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x46, +0x21, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x46, +0x29, 0x46, 0x29, 0x87, 0x39, 0xE9, 0x39, 0xC8, +0x39, 0xC8, 0x29, 0x87, 0x29, 0x67, 0x52, 0x6A, +0xA4, 0xF2, 0xBD, 0xB4, 0x8C, 0x0E, 0xB5, 0x53, +0xAD, 0x53, 0xCE, 0x57, 0xC6, 0x37, 0xC6, 0x37, +0xC6, 0x16, 0xC5, 0xF6, 0xAD, 0x54, 0x94, 0xB2, +0x94, 0xD2, 0x94, 0x91, 0x84, 0x30, 0x8C, 0x50, +0xA5, 0x13, 0xB5, 0x94, 0x8C, 0x4F, 0x7B, 0xCE, +0xAD, 0x54, 0x94, 0x91, 0x8C, 0x70, 0xB5, 0x94, +0x9C, 0xD1, 0x94, 0xB1, 0x9C, 0xB1, 0xA4, 0xF2, +0xCE, 0x15, 0xD6, 0x54, 0xD6, 0x56, 0x39, 0xA6, +0x18, 0xE3, 0x10, 0x82, 0x31, 0x65, 0x41, 0xE7, +0x4A, 0x28, 0x5A, 0xA9, 0x6A, 0xEB, 0x5A, 0x89, +0x7C, 0x6D, 0x74, 0x4D, 0x74, 0x4D, 0x63, 0xEA, +0x64, 0x0A, 0x5B, 0xA7, 0x4B, 0x44, 0x64, 0x07, +0x4B, 0x24, 0x84, 0xCC, 0x74, 0x4B, 0x53, 0x08, +0x84, 0xAD, 0x6C, 0x28, 0x74, 0x67, 0x95, 0x4D, +0x8C, 0x8D, 0x7B, 0xCC, 0x7B, 0x8B, 0x73, 0x2A, +0x83, 0xCC, 0x8C, 0x0D, 0xAD, 0x31, 0xCD, 0xD4, +0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x4E, 0xB5, 0x31, +0xAC, 0xF0, 0xAC, 0xCF, 0x9C, 0x6E, 0x9C, 0x8E, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xAC, 0xF0, +0xB5, 0x10, 0xAD, 0x10, 0xA4, 0xAF, 0xAC, 0xCF, +0xB5, 0x31, 0xBD, 0x31, 0xD5, 0xF4, 0xCD, 0xD2, +0xD5, 0xF3, 0xC5, 0x92, 0xCD, 0xB3, 0x7B, 0x8B, +0x5A, 0xCA, 0x63, 0x0B, 0x29, 0x65, 0x18, 0xC3, +0x19, 0x04, 0x18, 0xC3, 0x29, 0x45, 0x31, 0x86, +0x29, 0x66, 0x29, 0x87, 0x31, 0xA8, 0x31, 0xC9, +0x4A, 0x8B, 0x7B, 0xCF, 0x9C, 0xB1, 0x9C, 0xB0, +0xA4, 0x8E, 0xBD, 0x51, 0xB5, 0x30, 0xBD, 0x72, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x73, 0xC5, 0xD4, +0xCE, 0x15, 0xBD, 0x93, 0xCE, 0x35, 0xCE, 0x15, +0xB5, 0x93, 0xAD, 0x74, 0x9C, 0xD2, 0x9C, 0xD2, +0x7B, 0xAE, 0x7B, 0xCD, 0x9C, 0xB0, 0x83, 0xED, +0xAD, 0x12, 0xB5, 0x73, 0xA4, 0xD0, 0x83, 0xED, +0x8B, 0xED, 0xBD, 0x71, 0xAC, 0xEF, 0xB5, 0x31, +0xB5, 0x72, 0xB5, 0x72, 0xC5, 0xF4, 0xC5, 0xF4, +0xD6, 0x55, 0xC5, 0xF5, 0xC5, 0xD4, 0xCE, 0x15, +0xAD, 0x12, 0x31, 0x65, 0x63, 0x0B, 0x42, 0x07, +0x29, 0x65, 0x4A, 0x48, 0x4A, 0x69, 0x4A, 0x69, +0x5A, 0xAA, 0x63, 0x0B, 0x73, 0x6E, 0x8C, 0x31, +0x94, 0xB3, 0x9C, 0xD4, 0xB5, 0x96, 0xBD, 0xD7, +0xAD, 0x34, 0xAD, 0x14, 0xAD, 0x34, 0xAD, 0x33, +0xB5, 0x94, 0xB5, 0x53, 0xAD, 0x52, 0xCE, 0x15, +0xCE, 0x56, 0xCE, 0x36, 0xB5, 0x73, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xF1, 0xC5, 0xD4, 0xB5, 0x53, +0xD6, 0x58, 0x83, 0xEF, 0x63, 0x2D, 0x8C, 0x51, +0xAD, 0x11, 0xAC, 0xF1, 0x94, 0x0D, 0xC5, 0xD4, +0x9C, 0x6F, 0x9C, 0x90, 0x7B, 0x8D, 0x73, 0x6D, +0x6B, 0x4C, 0x5A, 0xAA, 0x84, 0x0E, 0xA4, 0xF1, +0xAD, 0x12, 0xB5, 0x52, 0x7B, 0x8C, 0xA4, 0xB0, +0xC5, 0x93, 0xD6, 0x15, 0xA4, 0xD0, 0xAC, 0xF1, +0xBD, 0x73, 0x9C, 0xB0, 0x83, 0xEE, 0x5A, 0x69, +0x62, 0xAA, 0x4A, 0x69, 0x6B, 0x4C, 0x5A, 0xCB, +0x31, 0x85, 0x31, 0x85, 0x31, 0x85, 0x39, 0xC6, +0x4A, 0x49, 0x39, 0xA6, 0x29, 0x44, 0x29, 0x44, +0x42, 0x08, 0x52, 0x49, 0x6B, 0x0C, 0x6B, 0x0C, +0x94, 0x50, 0xB5, 0x53, 0x9C, 0x70, 0x94, 0x6F, +0xBD, 0x94, 0xB5, 0x32, 0xBD, 0x73, 0xC5, 0xF5, +0xCE, 0x36, 0xA4, 0xF1, 0x9C, 0xB0, 0x8C, 0x0D, +0x8C, 0x2E, 0xA4, 0xD0, 0xAD, 0x11, 0xC5, 0xD5, +0xCD, 0xF5, 0xAC, 0xF1, 0x9C, 0x90, 0x8C, 0x0D, +0xAD, 0x11, 0xC5, 0xB3, 0xC5, 0x93, 0xAC, 0xF1, +0x9C, 0x91, 0x73, 0x4C, 0x52, 0x49, 0x6B, 0x2C, +0x31, 0xA6, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x19, 0x04, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xA3, 0x18, 0xE4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x46, 0x21, 0x26, +0x21, 0x26, 0x29, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x29, 0x46, 0x29, 0x67, +0x21, 0x46, 0x29, 0x67, 0x31, 0xC8, 0x31, 0xC8, +0x31, 0xA8, 0x31, 0xA8, 0x31, 0x87, 0x31, 0x87, +0x6B, 0x4C, 0xBD, 0xB4, 0x94, 0x4E, 0xB5, 0x53, +0xB5, 0x94, 0xD6, 0x98, 0xD6, 0x98, 0xCE, 0x78, +0xCE, 0x57, 0xC6, 0x36, 0xBD, 0xB5, 0xA5, 0x33, +0xAD, 0x74, 0xA5, 0x34, 0xA5, 0x34, 0xB5, 0x95, +0xC6, 0x16, 0xAD, 0x74, 0x73, 0xAD, 0x9C, 0xF2, +0xAD, 0x74, 0xA5, 0x13, 0x9C, 0xD2, 0xBD, 0xB5, +0xAD, 0x53, 0x9C, 0xB1, 0x9C, 0xB1, 0xA4, 0xF2, +0xD6, 0x56, 0xDE, 0x75, 0xDE, 0x96, 0x52, 0x89, +0x18, 0xE4, 0x10, 0xA3, 0x18, 0xA3, 0x41, 0xE7, +0x4A, 0x07, 0x4A, 0x27, 0x62, 0xEA, 0x52, 0x48, +0xBE, 0x75, 0x6C, 0x0B, 0x5B, 0xAA, 0x7C, 0xCE, +0x6C, 0x0A, 0x53, 0x86, 0x4B, 0x64, 0x53, 0x85, +0x63, 0xE7, 0x85, 0x0C, 0x6C, 0x49, 0x5B, 0xA7, +0x5B, 0xA6, 0x64, 0x05, 0x7C, 0xC8, 0x9D, 0x8E, +0x8C, 0xAF, 0x63, 0x09, 0x9C, 0xD1, 0x9C, 0xD1, +0x8C, 0x4F, 0x8C, 0x2E, 0x9C, 0xD1, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0xAF, 0xB5, 0x10, +0xAC, 0xF0, 0xB5, 0x52, 0xA4, 0xB0, 0xA4, 0xD1, +0xAD, 0x33, 0xA4, 0xF2, 0xA4, 0xD1, 0xA4, 0xF0, +0x94, 0x6E, 0x8C, 0x4E, 0x8C, 0x2E, 0x8C, 0x0D, +0x83, 0x8B, 0x7B, 0x8B, 0xA4, 0xAF, 0x9C, 0x4D, +0xAC, 0xF0, 0xAC, 0xF0, 0xA4, 0x8F, 0x94, 0x2D, +0x6B, 0x0A, 0x5A, 0xCA, 0x5A, 0xCA, 0x31, 0x86, +0x21, 0x04, 0x21, 0x25, 0x19, 0x04, 0x10, 0xA3, +0x10, 0xC3, 0x21, 0x25, 0x21, 0x25, 0x21, 0x47, +0x29, 0xA8, 0x31, 0xC9, 0x42, 0x2A, 0x6B, 0x6E, +0x94, 0x70, 0xAC, 0xF1, 0xBD, 0x72, 0xC5, 0x92, +0xBD, 0x51, 0xBD, 0x31, 0xB5, 0x30, 0xB5, 0x10, +0xB5, 0x10, 0xAC, 0xCF, 0x9C, 0x6E, 0x94, 0x2D, +0x83, 0xCB, 0x8C, 0x2E, 0x94, 0x4E, 0x94, 0x2E, +0x8B, 0xEC, 0x9C, 0x6F, 0xA4, 0xD0, 0x8B, 0xED, +0xA4, 0xB0, 0xB5, 0x31, 0xB5, 0x32, 0xB5, 0x31, +0xAC, 0xF0, 0xAC, 0xCE, 0x83, 0xAA, 0x7B, 0x6A, +0x94, 0x4D, 0xA4, 0xCF, 0xB5, 0x72, 0xCE, 0x14, +0xD6, 0x35, 0xCE, 0x35, 0xCD, 0xF4, 0xBD, 0x72, +0xC5, 0xD4, 0x52, 0x68, 0x42, 0x28, 0x5A, 0xEB, +0x39, 0xC6, 0x31, 0xA6, 0x42, 0x28, 0x39, 0xC6, +0x4A, 0x69, 0x62, 0xEB, 0x6B, 0x6D, 0x7B, 0xAF, +0x8C, 0x72, 0x94, 0x93, 0xA5, 0x35, 0xB5, 0x96, +0xB5, 0x75, 0xAD, 0x14, 0xCE, 0x38, 0xAD, 0x13, +0xBD, 0xB5, 0xBD, 0xB4, 0xC5, 0xF5, 0xD6, 0x97, +0xD6, 0x56, 0xCE, 0x56, 0xBD, 0xB4, 0xB5, 0x73, +0xB5, 0x72, 0xAD, 0x52, 0xBD, 0xB3, 0xB5, 0x32, +0xBD, 0x95, 0x94, 0x92, 0x7B, 0xEF, 0x9C, 0xB1, +0xBD, 0x73, 0xAC, 0xD0, 0x8B, 0xCC, 0xC5, 0xB4, +0xA4, 0xD0, 0xB5, 0x53, 0x8C, 0x2F, 0x8C, 0x2F, +0x73, 0x8D, 0x6B, 0x4C, 0x94, 0x90, 0xBD, 0xB4, +0xCD, 0xF5, 0xC5, 0xD4, 0x83, 0xCD, 0xA5, 0x11, +0xB5, 0x31, 0xCD, 0xF4, 0x9C, 0x8F, 0xA4, 0xD0, +0xC5, 0xB4, 0xA4, 0xB0, 0xA4, 0xD1, 0x6B, 0x2B, +0x39, 0xA6, 0x39, 0xC6, 0x41, 0xE7, 0xA5, 0x13, +0x7B, 0xCD, 0x39, 0xA6, 0x29, 0x65, 0x39, 0xC7, +0x39, 0xC6, 0x31, 0xA6, 0x31, 0x85, 0x29, 0x44, +0x29, 0x64, 0x42, 0x07, 0x83, 0xEF, 0x9C, 0x92, +0x7B, 0x6D, 0xA4, 0xD2, 0xCE, 0x16, 0xA4, 0xD1, +0xBD, 0x73, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x36, +0xC5, 0xD4, 0xB5, 0x53, 0x94, 0x6F, 0x8C, 0x2E, +0x9C, 0x90, 0xC5, 0xB4, 0xB5, 0x73, 0xC5, 0xF5, +0xBD, 0x93, 0xA4, 0xB0, 0xAD, 0x32, 0x8C, 0x2E, +0xA4, 0xD1, 0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0x73, +0xC5, 0xD4, 0xB5, 0x32, 0xAC, 0xD1, 0xBD, 0x73, +0x7B, 0x8C, 0x52, 0x69, 0x29, 0x25, 0x18, 0xE4, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0x83, 0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, +0x21, 0x05, 0x21, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x29, 0x46, +0x29, 0x46, 0x21, 0x46, 0x31, 0x87, 0x39, 0xE9, +0x31, 0xA8, 0x31, 0xA7, 0x39, 0xC8, 0x31, 0x87, +0x39, 0xA7, 0x7B, 0xAE, 0x9C, 0x90, 0xB5, 0x53, +0xB5, 0x73, 0xC6, 0x16, 0xAD, 0x53, 0xBD, 0xB5, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x94, 0xB5, 0x94, +0xB5, 0x74, 0xA5, 0x13, 0xAD, 0x33, 0xA5, 0x13, +0xAD, 0x33, 0x9C, 0xD1, 0x84, 0x0E, 0xA4, 0xF2, +0xB5, 0x74, 0xAD, 0x53, 0xA5, 0x13, 0xBD, 0xB5, +0xCE, 0x37, 0xB5, 0x74, 0xA4, 0xF1, 0xAD, 0x12, +0xCE, 0x15, 0xE6, 0xB6, 0xD6, 0x35, 0x7B, 0xAD, +0x39, 0xC7, 0x18, 0xC3, 0x10, 0x82, 0x31, 0x66, +0x42, 0x07, 0x4A, 0x07, 0x6B, 0x2B, 0x4A, 0x27, +0x64, 0x29, 0x5B, 0xE8, 0x2A, 0x43, 0x42, 0xE8, +0x74, 0x6C, 0x63, 0xE8, 0x4B, 0x44, 0x4B, 0x64, +0x6C, 0x28, 0x6C, 0x29, 0x4B, 0x65, 0x64, 0x27, +0x6C, 0x68, 0x7C, 0xCB, 0x9D, 0xAF, 0xA5, 0x70, +0xA5, 0x11, 0x9C, 0xF1, 0xA5, 0x33, 0xB5, 0x94, +0x9C, 0xD1, 0x94, 0x90, 0x8C, 0x4F, 0x8C, 0x6F, +0x94, 0x90, 0x9C, 0xD1, 0x9C, 0xAF, 0xB5, 0x10, +0xB5, 0x10, 0xC5, 0xD4, 0xAD, 0x53, 0xB5, 0x94, +0xAD, 0x53, 0xA5, 0x12, 0xA5, 0x12, 0xA4, 0xF1, +0x9C, 0xD0, 0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xD1, 0xAD, 0x11, +0xC5, 0xD4, 0xCD, 0xF4, 0x94, 0x6F, 0x94, 0x6F, +0xA4, 0xF2, 0x62, 0xEB, 0x52, 0xAA, 0x52, 0xAA, +0x31, 0x86, 0x19, 0x04, 0x18, 0xE4, 0x10, 0xC3, +0x08, 0x82, 0x08, 0x82, 0x10, 0xE3, 0x19, 0x25, +0x21, 0x46, 0x21, 0x67, 0x31, 0xA9, 0x31, 0xC9, +0x39, 0xEA, 0x4A, 0x69, 0x5A, 0xA9, 0x73, 0x4B, +0x8B, 0xEC, 0x9C, 0x4E, 0xA4, 0xAF, 0x9C, 0x6D, +0xA4, 0x8E, 0xB4, 0xEF, 0xC5, 0x71, 0xBD, 0x51, +0xB5, 0x10, 0xB5, 0x31, 0xBD, 0x51, 0xB5, 0x10, +0xBD, 0x30, 0xBD, 0x51, 0xC5, 0x72, 0xBD, 0x30, +0xBD, 0x51, 0xC5, 0x72, 0xC5, 0x92, 0xC5, 0xB2, +0xCD, 0xB2, 0xC5, 0x92, 0xBD, 0x30, 0xB5, 0x31, +0xBD, 0x71, 0xBD, 0x51, 0xAC, 0xCF, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x4D, 0x9C, 0x4D, 0x94, 0x2D, +0x94, 0x2E, 0x52, 0x68, 0x18, 0xE3, 0x52, 0x89, +0x5A, 0xCA, 0x39, 0xC6, 0x42, 0x07, 0x31, 0x86, +0x42, 0x08, 0x52, 0x8A, 0x63, 0x0C, 0x63, 0x0C, +0x73, 0x8E, 0x73, 0xAF, 0x94, 0xB3, 0xAD, 0x55, +0x8C, 0x71, 0xAD, 0x55, 0xD6, 0x58, 0xD6, 0x58, +0xBD, 0x94, 0xC5, 0xF5, 0xD6, 0x77, 0xD6, 0x56, +0xCE, 0x56, 0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x73, +0xAD, 0x32, 0xBD, 0xB4, 0xAD, 0x11, 0xC5, 0xB5, +0xB5, 0x95, 0x9C, 0xF3, 0x84, 0x30, 0xBD, 0x94, +0xC5, 0x94, 0x8B, 0xCD, 0xAC, 0xF1, 0xC5, 0xB3, +0xB5, 0x52, 0xC5, 0xB4, 0x9C, 0x6F, 0xB5, 0x73, +0x94, 0x4F, 0x94, 0x2F, 0xBD, 0x94, 0xCE, 0x36, +0xCE, 0x15, 0xC5, 0xD4, 0x7B, 0x8C, 0xAD, 0x11, +0x83, 0xCC, 0xB5, 0x32, 0x9C, 0x8F, 0x9C, 0x8F, +0xC5, 0xB4, 0x94, 0x6F, 0xAD, 0x32, 0x9C, 0xB1, +0x31, 0x64, 0x21, 0x24, 0x52, 0x89, 0xB5, 0x53, +0xB5, 0x73, 0x7B, 0xCD, 0x31, 0x85, 0x31, 0x85, +0x31, 0x85, 0x39, 0xC6, 0x39, 0xC6, 0x31, 0x85, +0x39, 0xC6, 0x42, 0x07, 0x4A, 0x08, 0x7B, 0x8E, +0x62, 0xCA, 0x73, 0x6C, 0xBD, 0xB5, 0xBD, 0xB5, +0xC5, 0xB5, 0xCE, 0x16, 0xD6, 0x77, 0xCE, 0x35, +0xBD, 0xB4, 0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0x8F, +0x94, 0x4E, 0xA4, 0xD0, 0xBD, 0x93, 0xC5, 0xD4, +0xB5, 0x52, 0xAD, 0x52, 0xB5, 0x73, 0xAD, 0x12, +0xB5, 0x53, 0xC5, 0xF4, 0xC5, 0xF4, 0xD6, 0x15, +0xD6, 0x15, 0xCD, 0xD4, 0xCD, 0xD4, 0xC5, 0xF4, +0xB5, 0x32, 0x9C, 0x6F, 0x62, 0xEB, 0x39, 0xA6, +0x29, 0x25, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x83, 0x08, 0x82, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC3, +0x08, 0x83, 0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, 0x21, 0x26, +0x21, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x26, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x46, +0x21, 0x46, 0x21, 0x46, 0x29, 0x46, 0x39, 0xC8, +0x31, 0xA8, 0x29, 0x67, 0x39, 0xC8, 0x39, 0xE9, +0x31, 0x87, 0x4A, 0x4A, 0x73, 0x6D, 0x94, 0x70, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, 0x94, 0x6F, +0x8C, 0x2E, 0x8C, 0x0E, 0x84, 0x0E, 0x84, 0x0E, +0x8C, 0x2F, 0x8C, 0x0E, 0x83, 0xEE, 0x83, 0xCD, +0x73, 0x6C, 0x73, 0x6C, 0x7B, 0x8C, 0x7B, 0xAD, +0x94, 0x4F, 0x83, 0xEE, 0x84, 0x0E, 0x84, 0x0E, +0x94, 0x70, 0x84, 0x0E, 0x8C, 0x2F, 0x9C, 0xB0, +0xA4, 0x90, 0xCD, 0xD4, 0xD6, 0x55, 0x9C, 0xB0, +0x4A, 0x48, 0x21, 0x04, 0x18, 0xA3, 0x18, 0xC3, +0x41, 0xC7, 0x4A, 0x28, 0x73, 0x4C, 0x62, 0xCA, +0x64, 0x07, 0x64, 0x48, 0x53, 0x87, 0x3A, 0xA5, +0x5B, 0xA9, 0x53, 0x87, 0x6C, 0x28, 0x53, 0x85, +0x6C, 0x28, 0x42, 0xE4, 0x43, 0x44, 0x74, 0xAA, +0xA5, 0xF1, 0xC6, 0xF7, 0xA5, 0x71, 0x8C, 0xCF, +0x8C, 0xAF, 0x9C, 0xF0, 0xA5, 0x53, 0xB5, 0xD4, +0xB5, 0xB4, 0xA5, 0x53, 0x94, 0x90, 0x9C, 0xF2, +0xA5, 0x12, 0xB5, 0x94, 0xA4, 0xAF, 0xAC, 0xF0, +0xBD, 0x72, 0xD6, 0x56, 0xCE, 0x15, 0xE6, 0xF9, +0xD6, 0x97, 0xCE, 0x36, 0xB5, 0x74, 0xAD, 0x73, +0xAD, 0x53, 0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x53, +0xAD, 0x53, 0xB5, 0x94, 0xB5, 0x94, 0xC5, 0xF5, +0xDE, 0xB7, 0xE6, 0xD8, 0xD6, 0x77, 0xCE, 0x58, +0xF7, 0x9D, 0xCE, 0x38, 0x4A, 0x48, 0x42, 0x07, +0x18, 0xC3, 0x08, 0x82, 0x08, 0x62, 0x08, 0x82, +0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x10, 0xA3, +0x21, 0x25, 0x21, 0x66, 0x21, 0x47, 0x21, 0x67, +0x29, 0x88, 0x29, 0x88, 0x29, 0x87, 0x63, 0x2D, +0x52, 0x8A, 0x63, 0x0A, 0x8C, 0x4E, 0xA4, 0xB0, +0x94, 0x2D, 0x8C, 0x0C, 0xB5, 0x10, 0xC5, 0x71, +0xAC, 0xAE, 0x7B, 0x6A, 0x94, 0x4D, 0x94, 0x0C, +0x9C, 0x6E, 0x9C, 0x4E, 0x8B, 0xEC, 0x94, 0x2D, +0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xCF, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0x8E, 0xB4, 0xEF, 0xAC, 0xAF, +0xB4, 0xEF, 0xAC, 0xEF, 0xAC, 0xCF, 0xA4, 0x8F, +0xB4, 0xF0, 0xB5, 0x10, 0xB4, 0xEF, 0xB5, 0x10, +0xB4, 0xF0, 0x83, 0xAC, 0x29, 0x45, 0x39, 0xE7, +0x5A, 0xEB, 0x4A, 0x48, 0x42, 0x28, 0x39, 0xC6, +0x39, 0xE7, 0x4A, 0x69, 0x52, 0xAA, 0x52, 0x8A, +0x6B, 0x6D, 0x7B, 0xF0, 0x8C, 0x71, 0x84, 0x30, +0x9C, 0xB3, 0xBD, 0x96, 0xCE, 0x17, 0xB5, 0x74, +0xBD, 0xB5, 0xB5, 0x31, 0xAD, 0x10, 0xB5, 0x10, +0xB5, 0x31, 0xAC, 0xF0, 0x9C, 0xAF, 0x9C, 0x8F, +0x9C, 0x8F, 0xAD, 0x11, 0xAC, 0xF0, 0xD6, 0x37, +0xAD, 0x34, 0x9C, 0xD3, 0xA4, 0xD2, 0xDE, 0x97, +0xDE, 0x55, 0xBD, 0x52, 0xC5, 0x73, 0xC5, 0x93, +0xC5, 0x93, 0xBD, 0x72, 0xB5, 0x11, 0xE6, 0xB7, +0xDE, 0x35, 0xDE, 0x56, 0xDE, 0x56, 0xB5, 0x72, +0xB5, 0x72, 0xAD, 0x11, 0x8C, 0x0E, 0xC5, 0xB4, +0x94, 0x2E, 0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0x6F, +0xC5, 0xD5, 0x94, 0x4F, 0xAD, 0x52, 0xA4, 0xD1, +0x6B, 0x4B, 0x63, 0x0B, 0xAD, 0x53, 0xB5, 0x93, +0xB5, 0x73, 0xB5, 0x74, 0x73, 0x8D, 0x39, 0xC6, +0x41, 0xE7, 0x39, 0xE7, 0x39, 0xC6, 0x39, 0xE7, +0x42, 0x07, 0x29, 0x44, 0x21, 0x24, 0x4A, 0x28, +0x6B, 0x2C, 0x4A, 0x28, 0x39, 0xA6, 0x4A, 0x48, +0x73, 0x6C, 0xA4, 0xD1, 0xCE, 0x15, 0xCE, 0x16, +0xAD, 0x32, 0x9C, 0xB0, 0x94, 0x2E, 0x9C, 0x8F, +0x83, 0xEC, 0x73, 0x6A, 0xA4, 0xD0, 0xCE, 0x15, +0xC5, 0xF5, 0xBD, 0x93, 0xB5, 0x93, 0x9C, 0xB0, +0xB5, 0x52, 0xC5, 0xF4, 0xD6, 0x36, 0xCD, 0xF4, +0xD6, 0x15, 0xCD, 0xF4, 0xCD, 0xD3, 0xC5, 0x93, +0xB5, 0x52, 0xB5, 0x32, 0xAC, 0xF1, 0x8C, 0x0E, +0x73, 0x2C, 0x62, 0xEB, 0x52, 0x69, 0x31, 0x66, +0x20, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x19, 0x04, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE5, 0x21, 0x05, 0x21, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x05, 0x21, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x29, 0x87, +0x31, 0xA8, 0x21, 0x46, 0x31, 0xC8, 0x39, 0xE9, +0x31, 0x87, 0x39, 0xC8, 0x52, 0x8B, 0x63, 0x0C, +0x9C, 0xD1, 0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x53, +0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x12, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x12, +0xB5, 0x74, 0xAD, 0x32, 0xAD, 0x32, 0xBD, 0xB4, +0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x12, 0xAD, 0x32, +0xA4, 0xF2, 0xA4, 0xD1, 0xA4, 0xF2, 0xAD, 0x12, +0xAC, 0xF2, 0x9C, 0x90, 0x8C, 0x2F, 0x94, 0x70, +0x52, 0x89, 0x21, 0x04, 0x18, 0xC3, 0x10, 0x82, +0x31, 0x65, 0x42, 0x07, 0x73, 0x4C, 0x73, 0x6C, +0x74, 0xAA, 0x5C, 0x07, 0x53, 0xC7, 0x42, 0xE5, +0x4B, 0x47, 0x43, 0x05, 0x8D, 0x2D, 0x6C, 0x49, +0x4B, 0x25, 0x4B, 0x65, 0x5C, 0x07, 0x5B, 0xE7, +0x7C, 0xAC, 0xB6, 0x54, 0x8C, 0xEF, 0x7C, 0x4C, +0x84, 0x8D, 0x9D, 0x11, 0x9D, 0x11, 0x9C, 0xD1, +0xB5, 0x73, 0xAD, 0x53, 0x9C, 0xD1, 0xAD, 0x94, +0xAD, 0x74, 0xB5, 0x94, 0xA4, 0xD0, 0xAC, 0xEF, +0xC5, 0xF4, 0xCE, 0x55, 0xD6, 0x56, 0xE7, 0x19, +0xEF, 0x3A, 0xE7, 0x1A, 0xD6, 0x57, 0xC5, 0xF5, +0xC5, 0xF5, 0xC6, 0x16, 0xBD, 0xD5, 0xBD, 0xB5, +0xB5, 0x95, 0xAD, 0x54, 0xA5, 0x34, 0xAD, 0x54, +0xAD, 0x33, 0x9C, 0xD1, 0x7B, 0xCE, 0x6B, 0x2D, +0x7B, 0xCF, 0x73, 0x8E, 0x29, 0x45, 0x10, 0xA3, +0x10, 0x82, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x08, 0xA3, 0x08, 0x83, 0x08, 0x82, +0x08, 0xA3, 0x21, 0x46, 0x31, 0x87, 0x29, 0x87, +0x21, 0x67, 0x21, 0x46, 0x21, 0x46, 0x42, 0x29, +0x94, 0xB3, 0x8C, 0x91, 0x6B, 0x4C, 0xA4, 0xF2, +0x9C, 0x90, 0xAD, 0x11, 0xBD, 0x51, 0xC5, 0x92, +0xB4, 0xF0, 0x94, 0x6F, 0xA4, 0xD0, 0xA4, 0xD1, +0x94, 0x6F, 0xA4, 0xD1, 0xAD, 0x32, 0xB5, 0x93, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0x8F, 0xA4, 0xF0, +0xAD, 0x31, 0xB5, 0x52, 0xAC, 0xF0, 0xA4, 0xD0, +0xA4, 0xAF, 0x94, 0x4E, 0xA4, 0xF0, 0x8C, 0x2D, +0x9C, 0x6E, 0x9C, 0x8F, 0xB5, 0x10, 0xBD, 0x31, +0xA4, 0x6E, 0x94, 0x4E, 0x6B, 0x0B, 0x31, 0x85, +0x39, 0xE7, 0x5A, 0xAA, 0x4A, 0x28, 0x39, 0xC6, +0x4A, 0x48, 0x52, 0x89, 0x42, 0x08, 0x4A, 0x69, +0x73, 0x8E, 0x73, 0xAE, 0x73, 0x8E, 0x83, 0xEF, +0x9C, 0xB3, 0xB5, 0x96, 0xC5, 0xF7, 0xCE, 0x17, +0xDE, 0x98, 0xAD, 0x12, 0xA4, 0xAF, 0xAD, 0x10, +0xAC, 0xF0, 0xB5, 0x11, 0xBD, 0x51, 0xBD, 0x31, +0xB5, 0x30, 0xB5, 0x31, 0xB5, 0x52, 0xB5, 0x74, +0x9C, 0xD3, 0x8C, 0x51, 0x9C, 0x90, 0xAC, 0xAF, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, 0xAC, 0xCF, +0xAC, 0xCF, 0xC5, 0x71, 0xBD, 0x31, 0xC5, 0x71, +0xCD, 0x92, 0xC5, 0x71, 0xBD, 0x51, 0xB5, 0x31, +0xAC, 0xD0, 0xA4, 0xAF, 0xB5, 0x11, 0xD6, 0x15, +0xBD, 0x72, 0xAC, 0xB0, 0x83, 0x8B, 0x8B, 0xED, +0xC5, 0xB4, 0x8C, 0x2E, 0x9C, 0xB0, 0x8C, 0x2E, +0x8C, 0x2F, 0x8C, 0x4F, 0xAD, 0x52, 0xA5, 0x12, +0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x53, 0x6B, 0x4C, +0x41, 0xE7, 0x42, 0x07, 0x42, 0x07, 0x42, 0x07, +0x42, 0x28, 0x29, 0x65, 0x31, 0x85, 0x31, 0x85, +0x39, 0xC6, 0x41, 0xE7, 0x42, 0x28, 0x29, 0x45, +0x31, 0x65, 0x62, 0xCA, 0x8B, 0xEE, 0xB5, 0x74, +0xC5, 0xD5, 0xBD, 0xB4, 0x9C, 0xB0, 0x94, 0x4E, +0x9C, 0x8F, 0x9C, 0xB0, 0xB5, 0x53, 0xD6, 0x57, +0xCE, 0x56, 0xC5, 0xD4, 0xC5, 0xF5, 0xAD, 0x32, +0xAD, 0x52, 0xC5, 0xB4, 0xD6, 0x36, 0xD6, 0x35, +0xD6, 0x15, 0xD6, 0x15, 0xCD, 0xD4, 0xB5, 0x11, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0xB4, 0xBD, 0x93, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0x7B, 0xAD, +0x52, 0x69, 0x21, 0x04, 0x18, 0xC4, 0x10, 0xC3, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC3, 0x10, 0xC4, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE5, 0x19, 0x05, 0x18, 0xE5, 0x18, 0xE5, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x46, +0x21, 0x46, 0x21, 0x46, 0x21, 0x46, 0x29, 0x67, +0x29, 0x67, 0x21, 0x26, 0x29, 0x67, 0x31, 0x87, +0x29, 0x66, 0x21, 0x46, 0x39, 0xC9, 0x52, 0x8B, +0x63, 0x0C, 0xAD, 0x53, 0xD6, 0x77, 0xB5, 0x94, +0xB5, 0x73, 0xCE, 0x36, 0xCE, 0x36, 0xCE, 0x36, +0xC5, 0xF5, 0xBD, 0xD4, 0xBD, 0x94, 0xBD, 0xB4, +0xD6, 0x56, 0xB5, 0x53, 0xB5, 0x73, 0xBD, 0x94, +0xBD, 0xB4, 0xA4, 0xD1, 0xB5, 0x73, 0xB5, 0x32, +0xB5, 0x73, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x11, +0xAD, 0x12, 0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x73, +0x6B, 0x2C, 0x29, 0x46, 0x18, 0xC3, 0x10, 0xA2, +0x21, 0x04, 0x4A, 0x08, 0x5A, 0xA9, 0x62, 0xEA, +0x74, 0x8A, 0x53, 0xA6, 0x5B, 0xE7, 0x53, 0xA8, +0x3A, 0xC5, 0x43, 0x05, 0x43, 0x04, 0x53, 0x65, +0x43, 0x24, 0x7C, 0xEB, 0x53, 0xC6, 0x4B, 0x44, +0x6C, 0x29, 0x8D, 0x0E, 0x6B, 0xEA, 0x5B, 0x67, +0xAD, 0xF2, 0xBE, 0x76, 0xA5, 0x53, 0x84, 0x0F, +0x94, 0xB1, 0x94, 0xB1, 0x8C, 0x71, 0x9C, 0xD2, +0x9C, 0xF2, 0xA5, 0x13, 0x94, 0x90, 0x9C, 0xB0, +0xA4, 0xF1, 0xA4, 0xF2, 0x94, 0xB1, 0x94, 0x91, +0x8C, 0x50, 0x84, 0x0F, 0x7B, 0xEF, 0x7B, 0xCF, +0x73, 0x8E, 0x6B, 0x4D, 0x63, 0x2E, 0x63, 0x2E, +0x63, 0x2E, 0x63, 0x2E, 0x6B, 0x4E, 0x63, 0x0E, +0x52, 0xAC, 0x4A, 0x6B, 0x42, 0x2A, 0x41, 0xE9, +0x39, 0xC8, 0x29, 0x67, 0x29, 0x46, 0x21, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, +0x08, 0x83, 0x21, 0x25, 0x29, 0x46, 0x31, 0xC8, +0x31, 0xA8, 0x29, 0x67, 0x21, 0x46, 0x21, 0x46, +0x4A, 0x6B, 0xBE, 0x18, 0xDE, 0xFC, 0x94, 0xB2, +0x94, 0x50, 0xBD, 0xB4, 0xBD, 0x71, 0xC5, 0x92, +0xB5, 0x31, 0xC5, 0xD4, 0xC6, 0x16, 0xC5, 0xF5, +0xB5, 0x73, 0xBD, 0xB4, 0xC6, 0x16, 0xCE, 0x36, +0xC5, 0xF5, 0xB5, 0x94, 0xBD, 0x94, 0xC6, 0x16, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xD4, +0xB5, 0x73, 0xAD, 0x52, 0xB5, 0x94, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x93, 0xBD, 0x92, 0xB5, 0x10, +0xA4, 0xAF, 0xBD, 0x93, 0xBD, 0xD4, 0x9C, 0xD1, +0x6B, 0x2B, 0x52, 0x89, 0x4A, 0x48, 0x31, 0x85, +0x39, 0xC6, 0x39, 0xE7, 0x4A, 0x48, 0x5A, 0xCB, +0x5A, 0xAA, 0x6B, 0x2D, 0x8C, 0x30, 0x94, 0x92, +0xA4, 0xF3, 0x94, 0x71, 0xB5, 0x75, 0xCE, 0x17, +0xCE, 0x17, 0xE6, 0xDA, 0x94, 0x50, 0xCE, 0x15, +0xCD, 0xF4, 0xA4, 0xB0, 0x94, 0x2D, 0x9C, 0x8E, +0x94, 0x2C, 0x8B, 0xEC, 0xA4, 0xB0, 0xB5, 0x75, +0x9C, 0xD3, 0x83, 0xF0, 0x9C, 0xB1, 0xBD, 0x51, +0xCD, 0x92, 0xCD, 0xB2, 0xC5, 0x51, 0x9C, 0x4D, +0x9C, 0x6D, 0xA4, 0x8E, 0xAC, 0xEF, 0xAC, 0xAE, +0xB4, 0xEF, 0xBD, 0x31, 0xC5, 0x72, 0xCD, 0x92, +0xC5, 0x92, 0xC5, 0xB2, 0xC5, 0x51, 0xBD, 0x30, +0xC5, 0x51, 0xC5, 0x71, 0xC5, 0x72, 0xC5, 0x93, +0xC5, 0x94, 0xC5, 0xD5, 0xBD, 0x94, 0xB5, 0x73, +0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x53, +0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x12, 0x7B, 0xAD, +0x41, 0xE7, 0x4A, 0x28, 0x42, 0x28, 0x42, 0x28, +0x42, 0x07, 0x4A, 0x48, 0x42, 0x28, 0x39, 0xA6, +0x39, 0xE7, 0x42, 0x07, 0x29, 0x65, 0x29, 0x44, +0x42, 0x07, 0x83, 0xEF, 0x73, 0x6D, 0x8C, 0x0F, +0xAD, 0x32, 0xAD, 0x32, 0x9C, 0xB0, 0xA4, 0xF0, +0xB5, 0x73, 0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x56, +0xCE, 0x35, 0xCE, 0x15, 0xBD, 0xB4, 0xAD, 0x32, +0xC5, 0xD4, 0xCE, 0x15, 0xD6, 0x56, 0xD6, 0x76, +0xD6, 0x35, 0xD6, 0x15, 0xC5, 0xB3, 0x94, 0x0D, +0xBD, 0x73, 0xBD, 0x72, 0xA4, 0xD0, 0xC5, 0xD4, +0xC5, 0xB4, 0xC5, 0xB4, 0xC5, 0xB3, 0xCD, 0xD4, +0x94, 0x2F, 0x6B, 0x0B, 0x52, 0x89, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x19, 0x05, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE5, 0x18, 0xE5, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x25, 0x21, 0x26, 0x21, 0x46, 0x29, 0x66, +0x21, 0x46, 0x29, 0x67, 0x29, 0x46, 0x29, 0x46, +0x21, 0x46, 0x19, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x46, 0x19, 0x05, 0x29, 0x66, 0x39, 0xE8, +0x4A, 0x6A, 0x6B, 0x4D, 0x94, 0x90, 0x94, 0x70, +0xD6, 0x77, 0xDE, 0xB8, 0xCE, 0x56, 0xD6, 0x97, +0xD6, 0x77, 0xD6, 0x57, 0xCE, 0x36, 0xD6, 0x56, +0xD6, 0x77, 0xD6, 0x56, 0xD6, 0x76, 0xD6, 0x97, +0xD6, 0x77, 0x9C, 0x90, 0x8C, 0x0E, 0xAD, 0x32, +0xC5, 0xF5, 0xBD, 0x93, 0xB5, 0x73, 0xBD, 0xB4, +0xB5, 0x73, 0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x93, +0x9C, 0xB1, 0x31, 0xA6, 0x18, 0xC4, 0x10, 0xA3, +0x18, 0xC3, 0x4A, 0x49, 0x4A, 0x28, 0x4A, 0x28, +0x64, 0x28, 0x5B, 0xE8, 0x4B, 0x45, 0x4B, 0x46, +0x3A, 0xE5, 0x43, 0x25, 0x3A, 0xE3, 0x3A, 0xE3, +0x3A, 0xE4, 0x5B, 0xC7, 0x3A, 0xC3, 0x43, 0x24, +0x53, 0x85, 0x5B, 0x86, 0x5B, 0x87, 0x84, 0x8C, +0xA5, 0x71, 0xA5, 0x52, 0x94, 0xB0, 0x31, 0x86, +0x39, 0xC8, 0x39, 0xE8, 0x3A, 0x09, 0x42, 0x09, +0x42, 0x29, 0x42, 0x4A, 0x4A, 0x4A, 0x4A, 0x6B, +0x52, 0x8B, 0x4A, 0x8B, 0x4A, 0x8B, 0x52, 0xAB, +0x52, 0xAC, 0x5B, 0x0D, 0x63, 0x2E, 0x63, 0x2D, +0x63, 0x4E, 0x73, 0xB0, 0x73, 0x90, 0x73, 0x90, +0x73, 0x8F, 0x6B, 0x4E, 0x6B, 0x4E, 0x6B, 0x4E, +0x73, 0x8E, 0x6B, 0x4D, 0x4A, 0x6B, 0x52, 0xAB, +0x42, 0x09, 0x21, 0x26, 0x18, 0xE4, 0x19, 0x04, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0xA3, 0x08, 0xA3, +0x21, 0x46, 0x73, 0xAF, 0x94, 0xD4, 0x8C, 0x94, +0x73, 0xB0, 0x4A, 0x4B, 0x29, 0x67, 0x31, 0xA8, +0x29, 0x87, 0x42, 0x4A, 0xAD, 0xB7, 0xEF, 0x9E, +0xC6, 0x38, 0xA4, 0xD1, 0xBD, 0x51, 0xC5, 0x71, +0xB5, 0x31, 0xC5, 0xF4, 0xC6, 0x16, 0xC5, 0xF5, +0xC5, 0xF5, 0xCE, 0x56, 0xC5, 0xF5, 0xBD, 0xD4, +0xC5, 0xF5, 0xBD, 0xD5, 0xC5, 0xF5, 0x84, 0x0E, +0x9C, 0xD1, 0xC5, 0xF5, 0xC6, 0x15, 0xC6, 0x36, +0xC5, 0xF5, 0xBD, 0xD5, 0xBD, 0xB4, 0xBD, 0xD4, +0xBD, 0xF5, 0xD6, 0x97, 0xC5, 0xB3, 0xB4, 0xF0, +0xAC, 0xF0, 0xC6, 0x15, 0xBD, 0xD5, 0x84, 0x0E, +0x5A, 0xCA, 0x39, 0xC6, 0x52, 0x69, 0x52, 0x69, +0x42, 0x07, 0x42, 0x08, 0x52, 0x69, 0x5A, 0xAA, +0x63, 0x0C, 0x73, 0x8E, 0x8C, 0x30, 0x94, 0x72, +0xAD, 0x14, 0xA4, 0xF3, 0xB5, 0x96, 0xBD, 0xD7, +0xB5, 0x55, 0xBD, 0xB6, 0x9C, 0x91, 0xB5, 0x53, +0xAD, 0x11, 0x7B, 0x8C, 0x7B, 0x8B, 0xA4, 0xF0, +0xAD, 0x10, 0x94, 0x4E, 0x9C, 0xD1, 0xB5, 0x75, +0x9C, 0xB3, 0x7B, 0xCF, 0x7B, 0xAD, 0xA4, 0xAF, +0xC5, 0x51, 0xBD, 0x30, 0x93, 0xEC, 0x8C, 0x0D, +0xAC, 0xF0, 0x9C, 0x8E, 0x94, 0x2D, 0x8B, 0xED, +0x7B, 0x8B, 0x7B, 0x6B, 0x8B, 0xCC, 0x83, 0xAC, +0x8B, 0xCC, 0x8B, 0xCC, 0x8B, 0xED, 0x7B, 0x6A, +0x73, 0x2A, 0x7B, 0x6A, 0x8C, 0x0C, 0x9C, 0x6E, +0xA4, 0xF0, 0x9C, 0x6F, 0x94, 0x4F, 0xAD, 0x12, +0xB5, 0x53, 0xA4, 0xD1, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xD1, 0xA4, 0xD1, 0x9C, 0xF1, 0x7B, 0xAD, +0x29, 0x45, 0x4A, 0x48, 0x4A, 0x48, 0x42, 0x07, +0x39, 0xC6, 0x4A, 0x69, 0x39, 0xC6, 0x4A, 0x28, +0x52, 0xAA, 0x5A, 0xCB, 0x5A, 0xCA, 0x39, 0xE7, +0x7B, 0xAE, 0x5A, 0xAA, 0x83, 0xAE, 0x94, 0x30, +0x8B, 0xEE, 0xAD, 0x12, 0xBD, 0x73, 0xB5, 0x53, +0xAD, 0x32, 0xAD, 0x12, 0xAC, 0xF1, 0xA4, 0xD1, +0xA4, 0xB0, 0xAD, 0x11, 0xA4, 0xD0, 0x94, 0x70, +0x9C, 0xB0, 0xB5, 0x32, 0xBD, 0x93, 0xBD, 0xB4, +0xC5, 0xB4, 0xBD, 0x52, 0xB5, 0x11, 0xA4, 0xD0, +0xC5, 0xB4, 0xCD, 0xF4, 0xC5, 0x93, 0xD6, 0x56, +0xDE, 0x76, 0xDE, 0x76, 0xE6, 0x97, 0xDE, 0x97, +0xC5, 0xB4, 0xCD, 0xD5, 0x62, 0xCA, 0x18, 0xC3, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC3, 0x10, 0xC3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xA3, 0x18, 0xE4, 0x10, 0xA3, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x19, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x26, 0x29, 0x67, +0x21, 0x46, 0x29, 0x67, 0x29, 0x67, 0x21, 0x46, +0x21, 0x05, 0x19, 0x05, 0x18, 0xE5, 0x18, 0xE5, +0x21, 0x26, 0x19, 0x05, 0x21, 0x26, 0x31, 0x87, +0x39, 0xC8, 0x52, 0x8A, 0x7B, 0xAE, 0x94, 0x91, +0xD6, 0x78, 0xDE, 0xD8, 0xD6, 0x97, 0xD6, 0x77, +0xD6, 0x97, 0xD6, 0x97, 0xDE, 0xB8, 0xDE, 0xB7, +0xD6, 0x56, 0xCE, 0x56, 0xD6, 0x76, 0xDE, 0xB7, +0xCE, 0x35, 0x9C, 0xB0, 0xAD, 0x32, 0xBD, 0xD4, +0xCE, 0x15, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x73, 0xB5, 0x52, 0xBD, 0x93, +0xBD, 0xD4, 0x5A, 0xA9, 0x21, 0x04, 0x18, 0xA3, +0x10, 0x82, 0x41, 0xE7, 0x4A, 0x28, 0x41, 0xE7, +0x53, 0x86, 0x53, 0x86, 0x43, 0x05, 0x42, 0xE5, +0x4B, 0x67, 0x43, 0x05, 0x5B, 0xC7, 0x53, 0x86, +0x4B, 0x86, 0x4B, 0x86, 0x53, 0x85, 0x5B, 0xC7, +0x63, 0xC7, 0x7C, 0x4A, 0x94, 0xCD, 0xA5, 0x0F, +0xA5, 0x0F, 0xA4, 0xF0, 0x62, 0xEA, 0x18, 0xC3, +0x21, 0x25, 0x29, 0x46, 0x29, 0x66, 0x29, 0x66, +0x31, 0xA7, 0x4A, 0x49, 0x63, 0x0B, 0x6B, 0x2C, +0x73, 0x6D, 0x73, 0x8D, 0x73, 0x6D, 0x73, 0x6D, +0x7B, 0xAE, 0x83, 0xAE, 0x73, 0x6D, 0x6B, 0x4C, +0x6B, 0x2C, 0x6B, 0x6D, 0x6B, 0x4D, 0x7B, 0x8E, +0x8C, 0x0F, 0xAD, 0x33, 0xD6, 0x57, 0xDE, 0x77, +0xE6, 0x97, 0xD6, 0x36, 0x62, 0xA9, 0x41, 0xE8, +0x4A, 0x49, 0x21, 0x25, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x82, 0x08, 0x82, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x5B, 0x2D, 0xD6, 0xDC, 0xE7, 0x7E, 0xEF, 0x7E, +0xEF, 0x5E, 0xD6, 0x7B, 0x7B, 0xD1, 0x29, 0x67, +0x29, 0xA8, 0x29, 0xA8, 0x3A, 0x4B, 0x94, 0xF4, +0xEF, 0x7E, 0xE6, 0xFB, 0xBD, 0x32, 0xB5, 0x10, +0xBD, 0x72, 0xCE, 0x36, 0xCE, 0x77, 0xCE, 0x56, +0xC5, 0xF5, 0xC6, 0x15, 0xA4, 0xF1, 0x94, 0x90, +0xC6, 0x15, 0xC6, 0x16, 0xC5, 0xF6, 0xA5, 0x33, +0xB5, 0xB5, 0xCE, 0x36, 0xC6, 0x15, 0xC6, 0x15, +0xC5, 0xF5, 0xBD, 0xD5, 0xC6, 0x15, 0xC6, 0x36, +0xC6, 0x15, 0xD6, 0x97, 0xC5, 0xB3, 0xAC, 0xEF, +0xB5, 0x31, 0xC6, 0x15, 0xB5, 0x73, 0xB5, 0x74, +0x94, 0x70, 0x29, 0x45, 0x39, 0xC6, 0x52, 0x89, +0x31, 0x86, 0x39, 0xC6, 0x4A, 0x48, 0x52, 0x8A, +0x63, 0x0B, 0x7B, 0xAE, 0x7B, 0xAE, 0x7B, 0xCF, +0x8C, 0x31, 0xA4, 0xF4, 0xAD, 0x55, 0xA5, 0x14, +0x8C, 0x51, 0x73, 0x8E, 0x8C, 0x50, 0x94, 0x70, +0x94, 0x70, 0x83, 0xEE, 0x8C, 0x2E, 0xAD, 0x11, +0xA4, 0xF0, 0x94, 0x8F, 0xBD, 0x95, 0xAD, 0x35, +0x8C, 0x72, 0x7B, 0xCF, 0x6B, 0x4C, 0xA4, 0xAF, +0xBD, 0x51, 0xAC, 0xAF, 0x83, 0x8B, 0xA4, 0xF0, +0xB5, 0x73, 0xA4, 0xD0, 0x94, 0x8F, 0x83, 0xCD, +0x73, 0x4B, 0x62, 0xEA, 0x5A, 0xA9, 0x62, 0xEA, +0x6B, 0x2B, 0x62, 0xEA, 0x83, 0xED, 0x62, 0xCA, +0x5A, 0xCA, 0x62, 0xCA, 0x73, 0x4B, 0x94, 0x4E, +0x94, 0x8F, 0x83, 0xCD, 0x83, 0xCC, 0xA4, 0xF1, +0xAD, 0x32, 0xB5, 0x33, 0xBD, 0x93, 0xC5, 0xB4, +0xC5, 0xB5, 0xAD, 0x33, 0xAD, 0x12, 0xAD, 0x33, +0x83, 0xEE, 0x39, 0xC6, 0x39, 0xE7, 0x42, 0x07, +0x41, 0xE7, 0x39, 0xE7, 0x42, 0x07, 0x5A, 0xCA, +0x5A, 0xCA, 0x5A, 0xAA, 0x4A, 0x69, 0x5A, 0xCB, +0xB5, 0x96, 0xAD, 0x34, 0x6A, 0xEB, 0x94, 0x0F, +0x8B, 0xCE, 0xAC, 0xF2, 0xB5, 0x53, 0xB5, 0x53, +0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x73, 0xB5, 0x73, +0xBD, 0x94, 0xBD, 0xB4, 0xC5, 0xD5, 0xCD, 0xF5, +0xCD, 0xF5, 0xC5, 0xB4, 0xBD, 0xB4, 0xBD, 0xB3, +0xC5, 0xB4, 0xC5, 0xB4, 0xCD, 0xD4, 0xCD, 0xD5, +0xCD, 0xF5, 0xCD, 0xD4, 0xC5, 0xB4, 0xC5, 0xB3, +0xB5, 0x32, 0xB5, 0x32, 0xBD, 0x32, 0xB5, 0x11, +0xAC, 0xF0, 0xAC, 0xF1, 0x41, 0xC6, 0x10, 0xC3, +0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x82, +0x08, 0x82, 0x08, 0x82, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x21, 0x05, 0x21, 0x05, 0x21, 0x05, 0x21, 0x26, +0x19, 0x05, 0x21, 0x05, 0x21, 0x46, 0x29, 0x67, +0x21, 0x26, 0x29, 0x46, 0x29, 0x67, 0x21, 0x26, +0x18, 0xE5, 0x18, 0xE4, 0x10, 0xC3, 0x18, 0xC4, +0x21, 0x25, 0x21, 0x26, 0x21, 0x26, 0x29, 0x67, +0x31, 0xA8, 0x52, 0x8B, 0x94, 0xB2, 0xBD, 0xB5, +0x8C, 0x2F, 0xC5, 0xF6, 0xD6, 0x97, 0xD6, 0x77, +0xD6, 0x97, 0xDE, 0xB8, 0xCE, 0x35, 0xD6, 0x97, +0xD6, 0x97, 0xD6, 0x77, 0xD6, 0x97, 0xDE, 0xB7, +0xDE, 0xD7, 0xBD, 0xB3, 0xAD, 0x32, 0xB5, 0x73, +0xC6, 0x15, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0xD4, 0xAD, 0x11, 0xCE, 0x35, 0xC5, 0xF4, +0xCE, 0x56, 0x8C, 0x2F, 0x29, 0x45, 0x18, 0xC3, +0x10, 0xA2, 0x29, 0x65, 0x42, 0x07, 0x41, 0xC6, +0x5B, 0xC8, 0x5B, 0xC7, 0x5B, 0xC7, 0x42, 0xE5, +0x43, 0x45, 0x32, 0x82, 0x4B, 0x45, 0x5B, 0xE7, +0x43, 0x25, 0x53, 0x86, 0x74, 0x8A, 0x7C, 0x6B, +0x74, 0x0A, 0x63, 0x89, 0x73, 0xA9, 0x84, 0x0B, +0x8C, 0x4D, 0xA4, 0xCF, 0xA4, 0xD0, 0x8C, 0x4E, +0x8C, 0x4F, 0x94, 0x4F, 0x9C, 0xB1, 0x94, 0x70, +0x8C, 0x2F, 0x9C, 0x90, 0xA4, 0xF0, 0xB5, 0x11, +0xB5, 0x10, 0xB5, 0x11, 0xB5, 0x11, 0xB4, 0xF0, +0xAC, 0xF0, 0xB5, 0x31, 0xBD, 0x51, 0xB5, 0x11, +0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xCF, +0xAC, 0xAF, 0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x6D, +0x9C, 0x6D, 0xB5, 0x10, 0xAC, 0xF0, 0x9C, 0x6F, +0x73, 0x2B, 0x41, 0xE6, 0x4A, 0x6A, 0x8C, 0x72, +0x29, 0x66, 0x08, 0x82, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x21, 0x25, +0x94, 0xF4, 0xD7, 0x1C, 0xDF, 0x5D, 0xE7, 0x5D, +0xE7, 0x5E, 0xEF, 0x7F, 0xE7, 0x3E, 0x94, 0xB4, +0x19, 0x05, 0x21, 0x46, 0x21, 0x88, 0x31, 0xC9, +0x73, 0xB0, 0xDE, 0xFC, 0xF7, 0x5C, 0xB5, 0x31, +0xCD, 0xD4, 0xD6, 0x76, 0xCE, 0x36, 0xC6, 0x15, +0xCE, 0x36, 0xCE, 0x77, 0xC6, 0x15, 0xBD, 0xD5, +0xB5, 0x94, 0xC5, 0xF5, 0xAD, 0x53, 0xBD, 0xD5, +0xC6, 0x16, 0xCE, 0x56, 0xC5, 0xF5, 0xC6, 0x15, +0xBD, 0xF5, 0xBD, 0xF5, 0xC6, 0x16, 0xAD, 0x53, +0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0x92, 0xB5, 0x10, +0xB5, 0x31, 0xB5, 0x73, 0xBD, 0x94, 0xBD, 0xD5, +0xCE, 0x36, 0x6B, 0x4C, 0x29, 0x45, 0x42, 0x08, +0x42, 0x07, 0x39, 0xA6, 0x39, 0xA6, 0x4A, 0x49, +0x52, 0x8A, 0x5A, 0xAA, 0x5A, 0xCB, 0x6B, 0x2D, +0x73, 0x6E, 0x94, 0x92, 0x9C, 0xB2, 0x7B, 0xAE, +0x73, 0x6D, 0x84, 0x10, 0xB5, 0x95, 0xB5, 0x95, +0x84, 0x0F, 0x94, 0x90, 0x94, 0x6F, 0x94, 0x8F, +0xA4, 0xD0, 0xA4, 0xD1, 0xBD, 0xB5, 0x94, 0xB3, +0x84, 0x31, 0x83, 0xEF, 0x7B, 0xAD, 0xA4, 0xCF, +0xC5, 0x51, 0x9C, 0x4E, 0x73, 0x6B, 0x83, 0xED, +0x9C, 0xD0, 0x94, 0x6F, 0xB5, 0x73, 0xAD, 0x52, +0x73, 0x4B, 0x62, 0xEA, 0x63, 0x0B, 0x62, 0xEB, +0x62, 0xEB, 0x5A, 0xCA, 0x8C, 0x4F, 0x7B, 0xAD, +0x7B, 0xCD, 0x6B, 0x4B, 0x7B, 0xAD, 0x8C, 0x2E, +0x8C, 0x2E, 0x73, 0x4B, 0x73, 0x8C, 0xAD, 0x32, +0xAD, 0x32, 0xBD, 0x94, 0xCE, 0x15, 0xCD, 0xF5, +0xC5, 0xF5, 0xB5, 0x74, 0xAD, 0x12, 0xAD, 0x32, +0xC5, 0xD5, 0x94, 0x4F, 0x31, 0x65, 0x4A, 0x68, +0x39, 0xC6, 0x39, 0xC6, 0x52, 0x89, 0x5A, 0xEB, +0x42, 0x28, 0x52, 0x89, 0x39, 0xE7, 0x52, 0xAA, +0x84, 0x30, 0xCE, 0x79, 0x9C, 0xB3, 0x73, 0x0C, +0x8B, 0xCE, 0x94, 0x2F, 0x9C, 0x50, 0x9C, 0x90, +0x8C, 0x2E, 0x9C, 0x8F, 0x9C, 0x90, 0x9C, 0x90, +0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xD0, 0x8B, 0xED, +0xAD, 0x32, 0xB5, 0x33, 0xB5, 0x32, 0x9C, 0xAF, +0x94, 0x4E, 0x8C, 0x2E, 0x94, 0x6F, 0x94, 0x6F, +0x9C, 0x4F, 0x9C, 0x6F, 0xAC, 0xF0, 0xB5, 0x31, +0xAC, 0xF1, 0xBD, 0x73, 0xBD, 0x73, 0xD6, 0x15, +0xCD, 0xD4, 0x9C, 0x90, 0x39, 0x85, 0x18, 0xC3, +0x10, 0xC3, 0x10, 0xC3, 0x18, 0xC4, 0x19, 0x05, +0x18, 0xE4, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0x83, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x26, 0x21, 0x25, 0x21, 0x26, +0x19, 0x05, 0x21, 0x25, 0x21, 0x26, 0x21, 0x46, +0x21, 0x26, 0x21, 0x46, 0x21, 0x26, 0x21, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA4, 0x18, 0xE4, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x46, +0x31, 0x87, 0x4A, 0x4A, 0xA5, 0x34, 0xB5, 0x95, +0x8C, 0x2F, 0xDE, 0xB9, 0xDE, 0xB8, 0xDE, 0x97, +0xE6, 0xF9, 0xBD, 0xB4, 0xC6, 0x15, 0xD6, 0x97, +0xD6, 0x77, 0xD6, 0x77, 0xD6, 0x76, 0xD6, 0x76, +0xD6, 0x96, 0xBD, 0xB4, 0xAD, 0x32, 0xB5, 0x52, +0xCE, 0x36, 0xC5, 0xF4, 0xC5, 0xF4, 0xCE, 0x15, +0xCE, 0x15, 0xBD, 0x93, 0xCE, 0x35, 0xCE, 0x14, +0xC5, 0xF4, 0xA4, 0xF1, 0x5A, 0xCB, 0x20, 0xE4, +0x18, 0xC3, 0x21, 0x04, 0x4A, 0x28, 0x41, 0xC6, +0x74, 0x8B, 0x74, 0x69, 0x74, 0x6A, 0x64, 0x08, +0x53, 0xA6, 0x64, 0x28, 0x4B, 0x45, 0x4B, 0x45, +0x32, 0x62, 0x63, 0xC9, 0x74, 0x2B, 0x53, 0x28, +0x52, 0xE8, 0x6B, 0xAB, 0x53, 0x07, 0x4A, 0xE6, +0x6B, 0xAA, 0x73, 0x89, 0x9C, 0xAE, 0xB5, 0x70, +0xBD, 0xB2, 0xA5, 0x11, 0xA5, 0x11, 0x9C, 0xD0, +0x9C, 0x90, 0x94, 0x4E, 0xA4, 0xF0, 0xCD, 0xF3, +0xA4, 0xAE, 0xC5, 0xB3, 0xC5, 0xD3, 0xBD, 0x52, +0xBD, 0x92, 0xCD, 0xD3, 0xC5, 0x93, 0x9C, 0x6E, +0xAD, 0x10, 0xD6, 0x14, 0xCD, 0xF4, 0xB5, 0x31, +0x9C, 0x4D, 0xB4, 0xEF, 0xC5, 0xB2, 0xC5, 0xB2, +0xBD, 0x51, 0xA4, 0x6E, 0xBD, 0x31, 0xB5, 0x30, +0xAC, 0xF0, 0xB5, 0x53, 0xE7, 0x3B, 0xF7, 0x7D, +0x5A, 0xEB, 0x08, 0x82, 0x08, 0x82, 0x10, 0x83, +0x08, 0x82, 0x08, 0x83, 0x10, 0xC3, 0x3A, 0x09, +0xB5, 0xD8, 0xD6, 0xDB, 0xD7, 0x1C, 0xDF, 0x3D, +0xE7, 0x3E, 0xE7, 0x5E, 0xEF, 0x7E, 0xEF, 0x7F, +0xAD, 0x76, 0x31, 0xA8, 0x19, 0x05, 0x19, 0x26, +0x21, 0x66, 0x63, 0x4D, 0xE7, 0x3B, 0xE6, 0xB9, +0xB5, 0x31, 0xC5, 0xD3, 0xBD, 0xB3, 0xB5, 0x51, +0xB5, 0x52, 0xBD, 0xB4, 0xBD, 0xD4, 0xBD, 0xD5, +0xBD, 0x93, 0xC5, 0xD5, 0xC5, 0xF5, 0xC6, 0x16, +0xCE, 0x36, 0xCE, 0x56, 0xC6, 0x15, 0xC6, 0x16, +0xC5, 0xF5, 0xC6, 0x16, 0xD6, 0x77, 0xC6, 0x36, +0xBD, 0xD4, 0xC5, 0xF5, 0x9C, 0x8F, 0xBD, 0x30, +0xB5, 0x31, 0xC6, 0x15, 0xCE, 0x36, 0xC6, 0x36, +0xD6, 0x77, 0xBD, 0xB4, 0x41, 0xE7, 0x52, 0xAA, +0x63, 0x0B, 0x42, 0x07, 0x39, 0xC6, 0x39, 0xA6, +0x4A, 0x49, 0x52, 0x89, 0x5A, 0xAA, 0x6B, 0x2C, +0x73, 0x6E, 0x94, 0x92, 0x94, 0x71, 0x8C, 0x30, +0x83, 0xEF, 0x9C, 0xD2, 0x94, 0x71, 0xC5, 0xD7, +0xA5, 0x13, 0x9C, 0xB1, 0x94, 0x90, 0x94, 0x6F, +0xA5, 0x11, 0xAD, 0x33, 0xB5, 0x95, 0xA5, 0x14, +0x94, 0x72, 0x7B, 0xAE, 0x83, 0xCE, 0xAC, 0xD0, +0xBD, 0x50, 0x83, 0xAC, 0x7B, 0xCD, 0xA5, 0x12, +0xB5, 0x53, 0x9C, 0x90, 0x94, 0x6F, 0x94, 0x6F, +0x6B, 0x2B, 0x5A, 0xEA, 0x62, 0xEB, 0x5A, 0xCB, +0x62, 0xEB, 0x5A, 0xEA, 0xA5, 0x12, 0xA4, 0xF1, +0xA4, 0xD1, 0x84, 0x0E, 0x94, 0x6F, 0x9C, 0x90, +0xA4, 0xD0, 0x73, 0x4B, 0x7B, 0x8C, 0xBD, 0x94, +0xA4, 0xF1, 0xBD, 0x94, 0xC5, 0xF5, 0xC5, 0xD5, +0xC5, 0xF5, 0xB5, 0x94, 0xB5, 0x53, 0xA4, 0xF1, +0xAD, 0x32, 0xA4, 0xF2, 0x73, 0x8C, 0x8C, 0x50, +0x63, 0x0B, 0x39, 0xE7, 0x4A, 0x28, 0x5A, 0xCA, +0x42, 0x07, 0x4A, 0x49, 0x52, 0xAA, 0x52, 0xAA, +0x62, 0xEC, 0x9C, 0xF3, 0xAD, 0x34, 0x6B, 0x0B, +0x94, 0x0F, 0x8B, 0xCE, 0x94, 0x50, 0x83, 0xCE, +0x7B, 0xAD, 0x7B, 0xAD, 0xA4, 0xF1, 0xA4, 0xF1, +0xB5, 0x52, 0xAD, 0x32, 0xBD, 0xB4, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x53, 0x9C, 0xB0, 0x94, 0x6F, +0x9C, 0x8F, 0x9C, 0x8F, 0xAD, 0x32, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xD0, 0xA4, 0xD0, 0xA5, 0x10, +0x9C, 0xAF, 0xC5, 0xB4, 0xB5, 0x32, 0xC5, 0x93, +0xBD, 0x93, 0x9C, 0x6F, 0x39, 0x86, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC3, 0x21, 0x25, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x10, 0x83, 0x08, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x25, 0x19, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x21, 0x26, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, +0x21, 0x25, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x29, 0x87, 0x31, 0xA8, 0x94, 0xB2, 0xA5, 0x12, +0x8C, 0x2F, 0xE6, 0xFA, 0xD6, 0x97, 0xDE, 0xD8, +0xDE, 0xB8, 0x83, 0xCE, 0xDE, 0xB8, 0xDE, 0xB7, +0xD6, 0x97, 0xDE, 0x97, 0xDE, 0xB7, 0xD6, 0x96, +0xDE, 0xB7, 0xB5, 0x52, 0xAD, 0x12, 0xCE, 0x35, +0xD6, 0x35, 0xCE, 0x35, 0xCE, 0x14, 0xCE, 0x14, +0xCE, 0x35, 0xBD, 0xB3, 0xCE, 0x14, 0xC6, 0x14, +0xC5, 0xF4, 0xCE, 0x35, 0xC5, 0xF6, 0x39, 0xA7, +0x18, 0xE4, 0x18, 0xA3, 0x4A, 0x08, 0x39, 0xC6, +0x4B, 0x27, 0x3A, 0xC4, 0x5B, 0xC8, 0x42, 0xE4, +0x53, 0x86, 0x53, 0x86, 0x32, 0x42, 0x43, 0x05, +0x53, 0x48, 0x74, 0x0B, 0x74, 0x2C, 0x63, 0x8A, +0x95, 0x10, 0x9D, 0x31, 0x5B, 0xA9, 0x63, 0xE8, +0xA5, 0xAF, 0x9D, 0x4D, 0x7C, 0x69, 0xA5, 0x8E, +0xAD, 0x70, 0xAD, 0x11, 0xA4, 0xF1, 0x94, 0x4F, +0x94, 0x6F, 0x83, 0xED, 0xAD, 0x11, 0xCE, 0x34, +0xCE, 0x14, 0xD6, 0x55, 0xC5, 0xD3, 0xC5, 0xD3, +0xC5, 0xD4, 0xCE, 0x15, 0xC5, 0xD3, 0xCD, 0xD3, +0xB5, 0x31, 0xCD, 0xF4, 0xD6, 0x55, 0xBD, 0x51, +0x8B, 0xAB, 0xB5, 0x10, 0xAC, 0xCF, 0xAC, 0xAE, +0xDE, 0x34, 0x9C, 0x4D, 0xCD, 0xF4, 0xD6, 0x35, +0xBD, 0x92, 0xCE, 0x56, 0xEF, 0x7C, 0xEF, 0x7D, +0x8C, 0x31, 0x08, 0x63, 0x08, 0x82, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x63, 0x6E, +0xC6, 0x79, 0xD6, 0xFC, 0xD6, 0xFC, 0xDE, 0xFC, +0xDF, 0x1C, 0xDF, 0x1C, 0xE7, 0x1D, 0xEF, 0x5E, +0xF7, 0xBE, 0xCE, 0x39, 0x41, 0xE8, 0x21, 0x46, +0x29, 0x87, 0x21, 0x45, 0x6B, 0x8E, 0xE7, 0x1A, +0xB5, 0x11, 0xB5, 0x10, 0xBD, 0x50, 0xBD, 0x51, +0xC5, 0x72, 0xBD, 0x31, 0xB5, 0x10, 0xAC, 0xEF, +0xA4, 0xAF, 0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x4D, +0x94, 0x4D, 0x94, 0x4D, 0x94, 0x4E, 0x94, 0x2D, +0x9C, 0x8F, 0xAD, 0x11, 0xAD, 0x31, 0xAC, 0xF1, +0xA4, 0xAF, 0xAC, 0xF0, 0x9C, 0x8E, 0xB5, 0x10, +0xBD, 0x51, 0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x15, +0xCE, 0x36, 0xD6, 0x77, 0xC5, 0xF5, 0xC5, 0xF5, +0xB5, 0x73, 0x5A, 0x88, 0x42, 0x07, 0x39, 0xC6, +0x41, 0xE7, 0x4A, 0x28, 0x52, 0x8A, 0x63, 0x0C, +0x73, 0x8E, 0x7B, 0xCF, 0x73, 0x6D, 0x7B, 0xCF, +0x8C, 0x51, 0x9C, 0xB2, 0xAD, 0x55, 0xBD, 0xD6, +0xBD, 0xD6, 0xA5, 0x13, 0xAD, 0x53, 0xA4, 0xF1, +0xA5, 0x11, 0xB5, 0x74, 0xAD, 0x54, 0x9C, 0xD3, +0xAD, 0x15, 0x73, 0x6D, 0x83, 0xEE, 0xA4, 0xCF, +0xB4, 0xEF, 0x7B, 0x8B, 0x94, 0x4F, 0xAD, 0x32, +0xB5, 0x52, 0xAD, 0x32, 0x9C, 0x90, 0x8C, 0x2F, +0x8C, 0x2F, 0x6B, 0x4C, 0x84, 0x0F, 0x73, 0x8D, +0x73, 0x6D, 0x63, 0x2B, 0xB5, 0x74, 0xAD, 0x11, +0xA4, 0xD1, 0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, +0x94, 0x8F, 0x73, 0x6B, 0x7B, 0xCD, 0xBD, 0xD5, +0xA4, 0xF2, 0xA5, 0x12, 0xB5, 0x94, 0xAD, 0x53, +0x9C, 0xB1, 0x9C, 0xB0, 0xA4, 0xD1, 0x94, 0x4F, +0x94, 0x4F, 0x8C, 0x4F, 0x73, 0x6C, 0x8C, 0x30, +0x83, 0xEE, 0x52, 0x89, 0x39, 0xC6, 0x5A, 0xAA, +0x52, 0x89, 0x5A, 0xCA, 0x5A, 0xCA, 0x5A, 0xCB, +0x6B, 0x2D, 0x62, 0xEC, 0x52, 0x8A, 0x41, 0xE7, +0x73, 0x4C, 0x7B, 0x4C, 0x7B, 0x8D, 0x6B, 0x0C, +0x62, 0xCB, 0x4A, 0x28, 0xA4, 0xD1, 0xBD, 0xD4, +0xB5, 0x53, 0xAD, 0x52, 0xB5, 0x73, 0xAD, 0x12, +0x9C, 0xD0, 0xB5, 0x73, 0x9C, 0xB0, 0xA4, 0xD1, +0x94, 0x6F, 0x8C, 0x2E, 0x9C, 0xD0, 0x94, 0x6F, +0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x4E, 0x94, 0x6F, +0x9C, 0x8F, 0xBD, 0x94, 0xBD, 0x73, 0xC5, 0xD4, +0xBD, 0x93, 0xA4, 0xB0, 0x39, 0x86, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC3, 0x21, 0x25, +0x19, 0x04, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0x82, +0x10, 0x83, 0x21, 0x05, 0x42, 0x08, 0x5A, 0xCA, +0x4A, 0x69, 0x29, 0x65, 0x18, 0xE4, 0x21, 0x05, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC3, 0x18, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x10, 0xA3, +0x18, 0xE4, 0x19, 0x04, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, 0x21, 0x05, +0x19, 0x05, 0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x19, 0x05, 0x21, 0x05, 0x18, 0xE5, +0x18, 0xC4, 0x19, 0x05, 0x21, 0x05, 0x18, 0xE5, +0x19, 0x05, 0x21, 0x26, 0x21, 0x25, 0x18, 0xE4, +0x18, 0xE5, 0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x46, +0x31, 0x87, 0x31, 0x87, 0x5A, 0xCB, 0x9C, 0xD2, +0xBD, 0x94, 0xD6, 0x77, 0xD6, 0x77, 0xD6, 0x98, +0xD6, 0x78, 0x8C, 0x30, 0xE7, 0x1A, 0xDE, 0xD8, +0xD6, 0x77, 0xCE, 0x15, 0xC5, 0xF4, 0xDE, 0x96, +0xE6, 0xF8, 0xAD, 0x11, 0xA4, 0xB0, 0xDE, 0x96, +0xE6, 0xB6, 0xDE, 0x96, 0xD6, 0x55, 0xDE, 0x76, +0xD6, 0x75, 0xC5, 0xD3, 0xD6, 0x35, 0xD6, 0x55, +0xCE, 0x14, 0xD6, 0x35, 0xDE, 0xB7, 0x83, 0xEE, +0x20, 0xE4, 0x10, 0xA3, 0x29, 0x24, 0x41, 0xE7, +0x53, 0x69, 0x5B, 0x89, 0x74, 0x2B, 0x63, 0xA9, +0x42, 0xC4, 0x42, 0xA3, 0x3A, 0x64, 0x3A, 0x85, +0x5B, 0x69, 0x5B, 0x29, 0x3A, 0x66, 0x42, 0xA7, +0x9D, 0x52, 0x74, 0x0C, 0x3A, 0xA3, 0x4B, 0x64, +0x53, 0xA4, 0x6C, 0x26, 0x9D, 0x8C, 0xBE, 0x30, +0xBD, 0xD2, 0xC6, 0x15, 0xB5, 0x73, 0x94, 0x8F, +0x94, 0x70, 0xA4, 0xD1, 0xC6, 0x15, 0xDE, 0x96, +0xD6, 0x75, 0xD6, 0x76, 0xC5, 0xF4, 0xAD, 0x11, +0xB5, 0x73, 0xB5, 0x73, 0xA4, 0xF0, 0xC5, 0xB3, +0xBD, 0x92, 0xB5, 0x31, 0xCE, 0x34, 0xC5, 0xB2, +0x8B, 0xCC, 0xA4, 0x8E, 0xB5, 0x30, 0xDE, 0x55, +0xD5, 0xF4, 0xCD, 0xD3, 0xD6, 0x55, 0xCE, 0x14, +0xC5, 0xD4, 0xC6, 0x15, 0xDE, 0xFA, 0xE7, 0x1B, +0xAD, 0x55, 0x18, 0xA3, 0x08, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, 0x7C, 0x31, +0xC6, 0x59, 0xD6, 0xFB, 0xD6, 0xDB, 0xD6, 0xDB, +0xD6, 0xDB, 0xDE, 0xDB, 0xDE, 0xDB, 0xDE, 0xFC, +0xE7, 0x1C, 0xEF, 0x5D, 0xB5, 0x75, 0x29, 0x66, +0x31, 0xA7, 0x29, 0x86, 0x21, 0x45, 0x7B, 0xEF, +0xAD, 0x32, 0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0xAF, +0x8B, 0xEC, 0xA4, 0xAE, 0x9C, 0x4D, 0x94, 0x0C, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0x8E, 0x9C, 0x6D, +0xAC, 0xEF, 0xB5, 0x0F, 0xAC, 0xEF, 0xA4, 0xAE, +0x9C, 0x6E, 0x9C, 0x4D, 0xA4, 0x8E, 0xA4, 0x8E, +0xAC, 0xCF, 0xB5, 0x0F, 0xB5, 0x10, 0xB5, 0x10, +0xA4, 0x8E, 0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, +0x9C, 0x6E, 0xA4, 0x8E, 0x9C, 0x6E, 0x9C, 0x6D, +0x94, 0x2D, 0x7B, 0x6B, 0x52, 0x48, 0x39, 0xA6, +0x39, 0xC6, 0x39, 0xA6, 0x52, 0x69, 0x63, 0x0C, +0x73, 0x6D, 0x52, 0x8A, 0x63, 0x0C, 0x7B, 0xAF, +0xA4, 0xF3, 0xA4, 0xF3, 0xBD, 0xB6, 0xAD, 0x54, +0xB5, 0x75, 0xCE, 0x17, 0xA5, 0x12, 0x9C, 0xB0, +0x94, 0x8F, 0xAD, 0x54, 0xA5, 0x14, 0x9C, 0xD3, +0xB5, 0xB7, 0x7B, 0xCE, 0x73, 0x6B, 0xA4, 0xD0, +0xB5, 0x10, 0x7B, 0x8B, 0x73, 0x4B, 0x94, 0x6F, +0xA4, 0xF1, 0xAD, 0x12, 0x9C, 0x90, 0x94, 0x70, +0x6B, 0x2B, 0x63, 0x0B, 0x94, 0x91, 0x8C, 0x2F, +0x73, 0x8D, 0x6B, 0x8D, 0xB5, 0x94, 0xC5, 0xF5, +0xC5, 0xF5, 0xAD, 0x32, 0xAD, 0x52, 0x9C, 0xD0, +0x8C, 0x4E, 0x73, 0x4B, 0x84, 0x0E, 0xC5, 0xF6, +0xA4, 0xF2, 0x83, 0xEE, 0x7B, 0xAD, 0x73, 0x8C, +0x6B, 0x4C, 0x62, 0xEA, 0x6B, 0x4C, 0x6B, 0x2B, +0x6B, 0x2B, 0x6B, 0x4B, 0x62, 0xEB, 0x63, 0x0B, +0x63, 0x0B, 0x63, 0x0B, 0x4A, 0x28, 0x4A, 0x48, +0x42, 0x07, 0x4A, 0x48, 0x52, 0x89, 0x4A, 0x69, +0x63, 0x0C, 0x6B, 0x2C, 0x6B, 0x4D, 0x41, 0xC7, +0x5A, 0x69, 0x62, 0xAA, 0x62, 0x8A, 0x73, 0x0C, +0x83, 0xCF, 0x7B, 0x6D, 0x83, 0xCD, 0xAD, 0x32, +0xCE, 0x57, 0xB5, 0x93, 0xAD, 0x31, 0xA4, 0xF0, +0x9C, 0xB0, 0xBD, 0x74, 0xBD, 0x93, 0xA5, 0x11, +0x9C, 0xB0, 0x8C, 0x2E, 0x94, 0x90, 0x8C, 0x4E, +0x94, 0x6F, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x9C, 0xB0, 0xBD, 0x73, 0xB5, 0x52, 0xCD, 0xF5, +0xC5, 0xD4, 0xB5, 0x33, 0x4A, 0x08, 0x18, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x18, 0xC4, 0x21, 0x45, +0x19, 0x04, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, 0x08, 0x83, +0x21, 0x05, 0x73, 0xAE, 0x94, 0x91, 0x9C, 0xB1, +0x9C, 0xD1, 0x8C, 0x2F, 0x63, 0x0B, 0x6B, 0x4C, +0x4A, 0x48, 0x19, 0x04, 0x10, 0xC3, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, +0x19, 0x05, 0x18, 0xE5, 0x18, 0xE5, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE5, 0x18, 0xE5, 0x21, 0x05, 0x18, 0xE5, +0x18, 0xC4, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xC4, +0x10, 0xC4, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, 0x21, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x05, 0x29, 0x46, +0x31, 0xA8, 0x29, 0x87, 0x39, 0xE8, 0x73, 0x6D, +0x94, 0x70, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0xB1, +0x9C, 0x90, 0x8C, 0x2F, 0x9C, 0x90, 0x9C, 0x6F, +0x94, 0x2F, 0x8C, 0x0E, 0x94, 0x2E, 0xA4, 0xB0, +0xB5, 0x31, 0xAC, 0xF0, 0x9C, 0x8F, 0xA4, 0x8F, +0xB5, 0x11, 0xC5, 0xB3, 0xC5, 0xD3, 0xC5, 0xD3, +0xB5, 0x52, 0xBD, 0x92, 0xD6, 0x35, 0xD6, 0x35, +0xCE, 0x15, 0xD6, 0x76, 0xD6, 0x76, 0xCE, 0x36, +0x73, 0x8D, 0x6B, 0x4C, 0x31, 0x86, 0x41, 0xE7, +0x74, 0x4D, 0x53, 0x28, 0x42, 0xA6, 0x5B, 0x48, +0x6B, 0xE9, 0x74, 0x4A, 0x6C, 0x0A, 0x4B, 0x06, +0x42, 0xE6, 0x4A, 0xE7, 0x5B, 0x8A, 0x95, 0x31, +0xBE, 0x15, 0x6B, 0xCB, 0x43, 0x24, 0x5B, 0xC5, +0x5B, 0xE4, 0x8D, 0x0A, 0xA5, 0x6D, 0xAD, 0x90, +0xAD, 0x51, 0x9C, 0xF0, 0x8C, 0x4E, 0x8C, 0x2E, +0x8C, 0x2E, 0x9C, 0xD1, 0xCE, 0x14, 0xDE, 0xB6, +0xD6, 0x54, 0xCE, 0x35, 0xC5, 0xF4, 0xAD, 0x31, +0xBD, 0xB4, 0xAD, 0x32, 0xA4, 0xF1, 0xBD, 0x92, +0xCD, 0xF4, 0xAD, 0x31, 0xCE, 0x14, 0xB5, 0x31, +0xB5, 0x31, 0xA4, 0x8E, 0xB5, 0x10, 0xD5, 0xF3, +0xCD, 0xD3, 0xCD, 0xD3, 0xCE, 0x14, 0xCD, 0xF4, +0xCE, 0x15, 0xC6, 0x35, 0xD6, 0xB9, 0xCE, 0x78, +0xC5, 0xF7, 0x62, 0xEB, 0x08, 0x82, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x19, 0x25, 0x84, 0x72, +0xBE, 0x38, 0xCE, 0xBA, 0xCE, 0x9A, 0xCE, 0x9A, +0xD6, 0xBA, 0xD6, 0x99, 0xCE, 0x99, 0xCE, 0x9A, +0xD6, 0x9A, 0xD6, 0x99, 0xC6, 0x37, 0x7B, 0xAE, +0x29, 0x45, 0x21, 0x25, 0x21, 0x45, 0x39, 0xC7, +0x94, 0x90, 0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x2E, +0x94, 0x6F, 0x94, 0x6F, 0x7B, 0xCC, 0x83, 0xED, +0x94, 0x4E, 0x94, 0x6E, 0x83, 0xCB, 0x83, 0xCB, +0xA4, 0x8E, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, +0xB5, 0x51, 0xAC, 0xEF, 0x94, 0x2C, 0x8B, 0xEB, +0x9C, 0x4D, 0xB5, 0x30, 0xAC, 0xCF, 0x9C, 0x4D, +0xA4, 0x6D, 0xA4, 0xAE, 0xAC, 0xEF, 0xB5, 0x10, +0xBD, 0x31, 0xC5, 0x71, 0xB5, 0x30, 0xAC, 0xCF, +0x9C, 0x6E, 0x94, 0x4E, 0x8B, 0xED, 0x52, 0x68, +0x42, 0x08, 0x4A, 0x28, 0x52, 0x89, 0x5A, 0xCB, +0x73, 0x6D, 0x62, 0xEB, 0x73, 0x8E, 0x94, 0x71, +0x9C, 0xD3, 0x9C, 0xD3, 0xBD, 0xD7, 0xBD, 0xB6, +0xA5, 0x13, 0xCE, 0x38, 0xD6, 0x58, 0xAC, 0xF2, +0xA4, 0xD1, 0xAD, 0x33, 0x94, 0x91, 0x84, 0x10, +0x6B, 0x4D, 0x83, 0xCD, 0x94, 0x2D, 0xBD, 0x52, +0xC5, 0x72, 0xAC, 0xF0, 0x8B, 0xED, 0x8B, 0xCD, +0x9C, 0x6E, 0x94, 0x4E, 0x8C, 0x0D, 0x83, 0xAC, +0x83, 0xAC, 0x73, 0x6C, 0x84, 0x0E, 0x83, 0xED, +0x7B, 0xCD, 0x83, 0xEE, 0xBD, 0xB4, 0xC5, 0xF5, +0xB5, 0x73, 0x94, 0x6F, 0xAD, 0x11, 0xA4, 0xD0, +0x8C, 0x2E, 0x62, 0xEA, 0x7B, 0xAD, 0xC5, 0xF5, +0xA4, 0xF1, 0x8C, 0x2F, 0x8C, 0x2F, 0x8C, 0x2F, +0x84, 0x2F, 0x73, 0x8D, 0x84, 0x0F, 0x7B, 0xCE, +0x73, 0x8D, 0x6B, 0x6D, 0x6B, 0x4C, 0x5A, 0xCA, +0x6B, 0x4C, 0x62, 0xEB, 0x5A, 0xEB, 0x5A, 0xCA, +0x39, 0xA6, 0x42, 0x08, 0x4A, 0x48, 0x4A, 0x49, +0x52, 0x8A, 0x6B, 0x4C, 0x63, 0x0C, 0x41, 0xE7, +0x5A, 0x69, 0x62, 0xAA, 0x73, 0x2C, 0x7B, 0x6D, +0x73, 0x4C, 0x7B, 0x6D, 0x83, 0xAD, 0x83, 0xCE, +0xAD, 0x13, 0xB5, 0x93, 0xB5, 0x73, 0xAD, 0x31, +0x9C, 0xB0, 0xB5, 0x73, 0xAD, 0x12, 0xAD, 0x12, +0xA4, 0xF1, 0x94, 0x90, 0xAD, 0x32, 0x9C, 0xD0, +0xA4, 0xF1, 0x9C, 0xD1, 0xAD, 0x12, 0xAD, 0x52, +0x9C, 0xB0, 0xBD, 0x94, 0xB5, 0x52, 0xD6, 0x56, +0xCE, 0x15, 0xC5, 0xB4, 0x62, 0xCA, 0x18, 0xC3, +0x10, 0x83, 0x10, 0x83, 0x18, 0xC3, 0x21, 0x46, +0x21, 0x05, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0x82, 0x10, 0xA3, +0x63, 0x0C, 0x9C, 0xF1, 0xB5, 0x94, 0xB5, 0x73, +0xC5, 0xD5, 0xAD, 0x12, 0xA4, 0xD1, 0xA5, 0x12, +0xA4, 0xD1, 0x52, 0x89, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x25, 0x21, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE4, +0x10, 0xA4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x21, 0x25, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x29, 0x46, +0x31, 0xA8, 0x29, 0x66, 0x31, 0x87, 0x5A, 0xCC, +0x94, 0x50, 0xCE, 0x16, 0xCD, 0xF5, 0xD6, 0x15, +0xCD, 0xF5, 0xC5, 0xB4, 0xBD, 0x73, 0xB5, 0x53, +0xC5, 0xB4, 0x94, 0x4F, 0xA4, 0xB0, 0xA4, 0xB0, +0x94, 0x4E, 0x9C, 0x8F, 0xB5, 0x32, 0x9C, 0x8F, +0xAC, 0xF1, 0xC5, 0x92, 0xC5, 0x93, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x8F, +0x94, 0x2E, 0x9C, 0x8F, 0xA4, 0xD0, 0xA5, 0x11, +0x9C, 0xB0, 0x63, 0x2B, 0x18, 0xA2, 0x39, 0xA6, +0x8D, 0x10, 0x8C, 0xEF, 0x63, 0xCA, 0x53, 0x48, +0x53, 0x27, 0x5B, 0x67, 0x53, 0x06, 0x42, 0xC6, +0x63, 0xC9, 0x7C, 0x8D, 0xAD, 0xD3, 0x8C, 0xD0, +0xB5, 0xB4, 0x84, 0x6C, 0x43, 0x03, 0x4B, 0x63, +0x6C, 0x27, 0x84, 0x89, 0x94, 0xAC, 0xA5, 0x0F, +0x94, 0x8E, 0xA5, 0x10, 0x94, 0x8F, 0x94, 0x6F, +0x8C, 0x2E, 0x7B, 0xAC, 0xAD, 0x31, 0xD6, 0x55, +0xC5, 0xF3, 0xCE, 0x34, 0xBD, 0x93, 0xA5, 0x11, +0xBD, 0xB4, 0x9C, 0x90, 0x8C, 0x2F, 0xB5, 0x52, +0xC5, 0xF4, 0xC5, 0xD3, 0xCE, 0x34, 0xB5, 0x30, +0xD6, 0x35, 0xAC, 0xCF, 0xAC, 0xEF, 0xC5, 0x91, +0xCD, 0xD3, 0xD6, 0x35, 0xD6, 0x55, 0xCE, 0x15, +0xCE, 0x35, 0xCE, 0x56, 0xD6, 0x97, 0xC6, 0x37, +0xBD, 0xB6, 0x94, 0x71, 0x31, 0x86, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x19, 0x04, 0x7C, 0x30, +0xB5, 0xF7, 0xBE, 0x38, 0xC6, 0x38, 0xC6, 0x38, +0xC6, 0x58, 0xCE, 0x58, 0xC6, 0x58, 0xC6, 0x38, +0xC6, 0x58, 0xC6, 0x37, 0xC5, 0xF6, 0xB5, 0x94, +0x7B, 0xAE, 0x31, 0xA6, 0x19, 0x04, 0x21, 0x24, +0x73, 0xAD, 0x84, 0x2F, 0x7B, 0xCD, 0x6B, 0x6B, +0x63, 0x4B, 0x73, 0x8C, 0x7B, 0xAC, 0x73, 0x8C, +0x73, 0x8C, 0x7B, 0xAC, 0x7B, 0xAB, 0x8C, 0x0D, +0x8B, 0xEC, 0xB4, 0xF0, 0xAC, 0xEF, 0xC5, 0xB2, +0xB5, 0x51, 0x9C, 0x6D, 0x94, 0x4D, 0xA4, 0xF0, +0xAD, 0x10, 0xA4, 0xCF, 0x9C, 0x8E, 0x9C, 0x8E, +0xAC, 0xF0, 0xA4, 0xCF, 0xB5, 0x30, 0xBD, 0x71, +0xBD, 0x30, 0xC5, 0x91, 0xC5, 0x91, 0xAC, 0xEF, +0xBD, 0xB2, 0xC5, 0xF4, 0xCE, 0x35, 0x9C, 0xB0, +0x52, 0x68, 0x52, 0x8A, 0x52, 0x8A, 0x52, 0x69, +0x6B, 0x4D, 0x7B, 0xAE, 0x83, 0xEF, 0x73, 0x8E, +0x8C, 0x71, 0xA4, 0xF3, 0xB5, 0x76, 0xBD, 0xB6, +0x9C, 0x92, 0xC5, 0xF7, 0xE6, 0xBA, 0xC5, 0xB5, +0x9C, 0xB1, 0x94, 0x50, 0x83, 0xEF, 0x8C, 0x51, +0x94, 0x51, 0xB5, 0x53, 0xAC, 0xF0, 0xA4, 0x8E, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0x8F, 0xB4, 0xF0, +0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x51, 0xB4, 0xF0, +0xAC, 0xF0, 0xA4, 0xD0, 0xA4, 0x8F, 0xA4, 0x8F, +0x9C, 0x4E, 0x94, 0x0D, 0xA4, 0xCF, 0xA4, 0xCF, +0x9C, 0x6E, 0x8C, 0x0D, 0x8C, 0x0D, 0x8C, 0x0D, +0x7B, 0xAD, 0x7B, 0x8D, 0x94, 0x90, 0xBD, 0xB4, +0xA4, 0xF1, 0x8C, 0x2F, 0x83, 0xEE, 0x83, 0xEE, +0x83, 0xEE, 0x7B, 0xCE, 0x83, 0xEE, 0x83, 0xEE, +0x83, 0xEE, 0x83, 0xEE, 0x83, 0xEE, 0x83, 0xEE, +0x8C, 0x2F, 0x73, 0x8D, 0x6B, 0x4C, 0x6B, 0x6C, +0x5A, 0xAA, 0x39, 0xC7, 0x42, 0x28, 0x42, 0x07, +0x52, 0x89, 0x63, 0x0B, 0x52, 0x8A, 0x52, 0x8A, +0x5A, 0xAA, 0x5A, 0x89, 0x62, 0xAA, 0x7B, 0x6D, +0x6B, 0x0C, 0x7B, 0x8E, 0x94, 0x50, 0x8B, 0xEF, +0x7B, 0x8D, 0xA4, 0xF2, 0x94, 0x70, 0x84, 0x0E, +0x9C, 0xB0, 0xBD, 0x93, 0xBD, 0xB4, 0xB5, 0x94, +0xAD, 0x52, 0xAD, 0x73, 0xBD, 0xD5, 0xB5, 0x94, +0xB5, 0x73, 0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xB4, +0xA4, 0xF1, 0xBD, 0x94, 0xB5, 0x53, 0xDE, 0x97, +0xCE, 0x36, 0xC5, 0xF5, 0x62, 0xEA, 0x18, 0xC3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xC3, 0x29, 0x66, +0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x5A, 0xAA, +0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xD5, 0xC5, 0xD4, +0xBD, 0xB4, 0xA4, 0xF1, 0xAD, 0x32, 0xC6, 0x15, +0xC5, 0xF5, 0xA4, 0xF2, 0x29, 0x65, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE5, 0x21, 0x05, 0x19, 0x05, 0x21, 0x26, +0x19, 0x05, 0x19, 0x05, 0x21, 0x26, 0x29, 0x46, +0x31, 0xA8, 0x29, 0x46, 0x21, 0x25, 0x42, 0x29, +0x7B, 0xAE, 0xCD, 0xF5, 0xD6, 0x35, 0xD5, 0xF5, +0xD5, 0xF4, 0xD6, 0x14, 0xC5, 0xB3, 0xC5, 0xB3, +0xD5, 0xF5, 0xA4, 0x90, 0x8B, 0xED, 0x8B, 0xED, +0xA4, 0xAF, 0xBD, 0x51, 0xBD, 0x52, 0x9C, 0x6F, +0xBD, 0x52, 0xD5, 0xF4, 0xDE, 0x55, 0xA4, 0x8F, +0xAD, 0x11, 0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x73, +0xA5, 0x11, 0xA4, 0xD1, 0xA5, 0x11, 0xA4, 0xF1, +0x9C, 0xD0, 0x5A, 0xCA, 0x18, 0xC3, 0x20, 0xE3, +0x3A, 0xC5, 0x42, 0xE6, 0x5B, 0xA9, 0x4B, 0x07, +0x5B, 0x69, 0x4A, 0xA6, 0x42, 0x86, 0x5B, 0x89, +0x6C, 0x0B, 0x8D, 0x0F, 0xA5, 0x93, 0xA5, 0x72, +0x6B, 0x8A, 0x8C, 0xED, 0x4B, 0x24, 0x63, 0xE9, +0xA5, 0xB2, 0x9D, 0x10, 0x94, 0xAD, 0x9C, 0xEE, +0xA5, 0x30, 0xAD, 0x52, 0x9C, 0xF1, 0xA4, 0xF1, +0x9C, 0xD1, 0x8C, 0x4E, 0xB5, 0x73, 0xDE, 0xB7, +0xCE, 0x14, 0xCE, 0x14, 0xB5, 0x72, 0x9C, 0xB0, +0xA5, 0x12, 0x94, 0x90, 0x8C, 0x0F, 0xAD, 0x11, +0xA5, 0x11, 0x94, 0x6E, 0xBD, 0xB2, 0xB5, 0x30, +0xCE, 0x14, 0xAC, 0xCF, 0xA4, 0x6D, 0x8B, 0xEB, +0x94, 0x4D, 0xA4, 0xAE, 0xA4, 0xCF, 0xB5, 0x51, +0xBD, 0x93, 0xBD, 0xD4, 0xCE, 0x36, 0xCE, 0x36, +0xB5, 0x95, 0x9C, 0xB1, 0x6B, 0x0C, 0x18, 0xE3, +0x10, 0xC3, 0x10, 0xA3, 0x18, 0xE4, 0x6B, 0xAE, +0xAD, 0x95, 0xB5, 0xF6, 0xBD, 0xF6, 0xBD, 0xF6, +0xBD, 0xF6, 0xBD, 0xF6, 0xBD, 0xF6, 0xBD, 0xD6, +0xBD, 0xD6, 0xBD, 0xF6, 0xBD, 0xD5, 0xBD, 0xF6, +0xBD, 0xD6, 0xAD, 0x33, 0x5A, 0xCA, 0x10, 0xA2, +0x52, 0xAA, 0x84, 0x2F, 0x7B, 0xEE, 0x73, 0xAC, +0x73, 0xAD, 0x84, 0x0E, 0x83, 0xEE, 0x8C, 0x2F, +0x8C, 0x4F, 0x7B, 0xCD, 0x8C, 0x2E, 0x94, 0x6E, +0xA4, 0xAF, 0xB4, 0xEF, 0xAC, 0xCF, 0xB5, 0x51, +0xBD, 0x92, 0x9C, 0xAF, 0x9C, 0xAF, 0xB5, 0x72, +0xC5, 0xF4, 0xCE, 0x14, 0xBD, 0x92, 0xBD, 0xB3, +0xBD, 0x93, 0xAD, 0x10, 0xAD, 0x31, 0xB5, 0x51, +0xB5, 0x31, 0xD6, 0x35, 0xB5, 0x30, 0xB5, 0x30, +0xCE, 0x14, 0xCE, 0x55, 0xD6, 0x76, 0xBD, 0xB3, +0x83, 0xEE, 0x4A, 0x48, 0x42, 0x07, 0x39, 0xC7, +0x4A, 0x49, 0x52, 0x69, 0x52, 0x69, 0x63, 0x0C, +0x7C, 0x10, 0x9C, 0xF3, 0xB5, 0x96, 0xA4, 0xF4, +0xBD, 0x96, 0xBD, 0xD7, 0xB5, 0x95, 0xCE, 0x17, +0xBD, 0xB6, 0xBD, 0xD7, 0x84, 0x10, 0x84, 0x30, +0x94, 0x91, 0x94, 0x70, 0x83, 0xAC, 0x7B, 0xAC, +0x6B, 0x0A, 0x6B, 0x2A, 0x5A, 0x88, 0x73, 0x6B, +0x7B, 0x8B, 0x8C, 0x2D, 0x94, 0x2D, 0x9C, 0x8E, +0xAC, 0xCF, 0x94, 0x2D, 0x8C, 0x0C, 0x94, 0x2D, +0x9C, 0x6E, 0xAC, 0xF0, 0x9C, 0x8E, 0xA4, 0xCF, +0xAC, 0xCF, 0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x74, 0xBD, 0x94, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0x94, +0xBD, 0x74, 0xC5, 0xD5, 0xC5, 0xF5, 0xC5, 0xD5, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x74, 0xC5, 0xD5, +0xC5, 0xB4, 0xB5, 0x33, 0xB5, 0x74, 0xB5, 0x74, +0xAD, 0x12, 0x83, 0xCE, 0x42, 0x27, 0x42, 0x28, +0x4A, 0x48, 0x52, 0x89, 0x5A, 0x89, 0x83, 0xCE, +0x7B, 0x6D, 0x52, 0x28, 0x7B, 0x8D, 0x9C, 0x71, +0x8B, 0xEF, 0xA4, 0xB2, 0x7B, 0x6D, 0x73, 0x0C, +0x7B, 0x8E, 0x7B, 0x8E, 0xA4, 0xF2, 0xA4, 0xF2, +0xA4, 0xF2, 0xBD, 0x93, 0xC5, 0xD4, 0xD6, 0x97, +0xCE, 0x16, 0xC6, 0x15, 0xD6, 0x77, 0xAD, 0x32, +0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xF4, +0x94, 0x6F, 0xBD, 0xB4, 0xB5, 0x32, 0xDE, 0xB7, +0xDE, 0xB7, 0xCE, 0x15, 0x73, 0x6C, 0x18, 0xC3, +0x10, 0x83, 0x10, 0x82, 0x10, 0xC3, 0x29, 0x86, +0x21, 0x05, 0x19, 0x04, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xC3, 0x10, 0xA3, 0x10, 0xC3, 0x84, 0x0F, +0xCE, 0x56, 0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x35, +0xCE, 0x15, 0xAD, 0x11, 0xB5, 0x52, 0xD6, 0x76, +0xDE, 0x97, 0xD6, 0x77, 0x83, 0xCE, 0x20, 0xE4, +0x10, 0xC3, 0x10, 0xC3, 0x18, 0xC4, 0x10, 0xC4, +0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x05, 0x18, 0xE5, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xA4, 0x10, 0xA3, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x26, 0x18, 0xE5, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x29, 0x46, 0x29, 0x46, +0x31, 0x87, 0x29, 0x67, 0x21, 0x46, 0x31, 0x87, +0x5A, 0xCC, 0xB5, 0x32, 0xE6, 0x76, 0xDE, 0x35, +0xDE, 0x35, 0xDE, 0x35, 0xD6, 0x14, 0xDE, 0x35, +0xDE, 0x35, 0xBD, 0x52, 0xC5, 0xB3, 0xCD, 0xD4, +0xCD, 0xB3, 0xD5, 0xF3, 0xCD, 0xB3, 0xD5, 0xD3, +0xDE, 0x14, 0xDE, 0x34, 0xDE, 0x34, 0xA4, 0x8F, +0xAC, 0xF1, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD5, +0xBD, 0xB4, 0xB5, 0x73, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x32, 0x8C, 0x4F, 0x21, 0x04, 0x10, 0xA2, +0x3A, 0x85, 0x53, 0x88, 0x4B, 0x07, 0x4A, 0xE7, +0x4A, 0xE7, 0x4A, 0x86, 0x5B, 0x08, 0x5B, 0x28, +0x74, 0x0B, 0x7C, 0x6D, 0x8C, 0xAE, 0xA5, 0x30, +0x5B, 0x28, 0x8C, 0xCD, 0x8C, 0xED, 0xC6, 0xD6, +0xD7, 0x39, 0xAD, 0x93, 0x94, 0x8D, 0xAD, 0x2F, +0xAD, 0x0F, 0x9C, 0xAE, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x8F, 0x9C, 0xAF, 0x9C, 0xAF, 0xB5, 0x31, +0x9C, 0x8E, 0xAD, 0x10, 0x9C, 0x8E, 0x94, 0x4E, +0x9C, 0xAF, 0x94, 0x4E, 0x8C, 0x2E, 0x9C, 0x8F, +0xBD, 0x73, 0xAD, 0x10, 0xAC, 0xCF, 0x94, 0x4D, +0xA4, 0xAF, 0x9C, 0x6D, 0xBD, 0x51, 0xB5, 0x30, +0x94, 0x4D, 0xA4, 0xF0, 0xB5, 0x72, 0xB5, 0x72, +0xBD, 0xB3, 0xB5, 0x52, 0xCE, 0x35, 0xD6, 0x77, +0xCE, 0x57, 0xA5, 0x12, 0x73, 0x6C, 0x10, 0xA2, +0x19, 0x04, 0x21, 0x25, 0x18, 0xE4, 0x3A, 0x28, +0x8C, 0x91, 0xA5, 0x54, 0xA5, 0x54, 0xAD, 0x74, +0xAD, 0x74, 0xAD, 0x74, 0xB5, 0x94, 0xB5, 0xB5, +0xAD, 0x74, 0xB5, 0x94, 0xAD, 0x94, 0xB5, 0xB4, +0xBD, 0xD5, 0xA4, 0xF2, 0x31, 0x85, 0x10, 0x82, +0x31, 0xA6, 0x8C, 0x50, 0x8C, 0x4F, 0x73, 0xCD, +0x73, 0xAD, 0x84, 0x2F, 0x94, 0x6F, 0x8C, 0x90, +0xAD, 0x53, 0x94, 0x90, 0x9C, 0xB0, 0x9C, 0xAF, +0xA4, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, 0x9C, 0x8E, +0xAD, 0x10, 0x94, 0x6E, 0xAD, 0x11, 0xC5, 0xD4, +0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x93, 0xB5, 0x52, +0xAD, 0x31, 0x94, 0x6E, 0xAD, 0x51, 0xB5, 0x52, +0xB5, 0x72, 0xCE, 0x35, 0xA4, 0xCE, 0xB5, 0x30, +0xCE, 0x14, 0xCE, 0x34, 0xC5, 0xF4, 0xAD, 0x32, +0xB5, 0x53, 0x5A, 0xA9, 0x4A, 0x08, 0x42, 0x08, +0x4A, 0x49, 0x52, 0x69, 0x52, 0x8A, 0x52, 0xAA, +0x6B, 0x6D, 0x73, 0x8E, 0x7B, 0xCF, 0xAD, 0x55, +0xCE, 0x18, 0x84, 0x10, 0xAD, 0x34, 0xCE, 0x39, +0xCE, 0x38, 0xCE, 0x59, 0xA4, 0xF3, 0x94, 0x71, +0x9C, 0xD2, 0x8C, 0x2F, 0x8C, 0x2F, 0x9C, 0xB1, +0x8C, 0x0E, 0x84, 0x0E, 0x7B, 0xAD, 0x94, 0x90, +0x7B, 0xAC, 0x52, 0x68, 0x73, 0x6B, 0x94, 0x4F, +0x8C, 0x4E, 0x83, 0xED, 0x84, 0x0D, 0x83, 0xED, +0x7B, 0xAC, 0x83, 0xED, 0x83, 0xEC, 0x94, 0x4E, +0x94, 0x4E, 0xA4, 0xD0, 0xAD, 0x11, 0xC5, 0xF5, +0xCE, 0x15, 0xC5, 0xF4, 0xC5, 0xF5, 0xCE, 0x36, +0xCE, 0x15, 0xBD, 0x93, 0xB5, 0x53, 0xAD, 0x32, +0xB5, 0x52, 0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x52, 0xBD, 0x73, 0xB5, 0x53, +0xC5, 0xB4, 0xC5, 0xD5, 0xC5, 0xB4, 0xC5, 0xB4, +0xC5, 0xD5, 0xAD, 0x12, 0x8B, 0xEE, 0x4A, 0x48, +0x42, 0x27, 0x4A, 0x28, 0x7B, 0x8D, 0x8C, 0x2F, +0x94, 0x0F, 0x5A, 0x69, 0x83, 0xCE, 0xAD, 0x13, +0x94, 0x50, 0xA4, 0xD2, 0x8C, 0x0F, 0x6B, 0x0B, +0x8B, 0xEF, 0x8C, 0x10, 0x8C, 0x0F, 0xA4, 0xB2, +0xB5, 0x33, 0xBD, 0x94, 0xA4, 0xD1, 0xA4, 0xD0, +0x9C, 0xB0, 0xA4, 0xB0, 0xA4, 0xD0, 0x94, 0x6F, +0xA4, 0xB0, 0x9C, 0xB0, 0x9C, 0x90, 0x9C, 0xD0, +0xAD, 0x32, 0xB5, 0x73, 0xAD, 0x11, 0xC5, 0xF5, +0xCE, 0x36, 0xCE, 0x15, 0x6B, 0x2B, 0x18, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x18, 0xC3, 0x29, 0x86, +0x19, 0x04, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x10, 0xC3, 0x18, 0xC3, 0x41, 0xE7, 0xAD, 0x53, +0xCE, 0x35, 0xD6, 0x76, 0xD6, 0x56, 0xCE, 0x36, +0xBD, 0xB3, 0xB5, 0x52, 0xAD, 0x11, 0xCE, 0x35, +0xB5, 0x73, 0xD6, 0x56, 0xBD, 0x94, 0x5A, 0xCA, +0x18, 0xE4, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE4, 0x18, 0xE5, 0x18, 0xE4, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE5, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x05, 0x18, 0xE5, 0x19, 0x05, +0x19, 0x05, 0x21, 0x05, 0x29, 0x46, 0x29, 0x46, +0x31, 0x87, 0x29, 0x87, 0x29, 0x87, 0x21, 0x46, +0x4A, 0x4A, 0x7B, 0xAE, 0xE6, 0x97, 0xEE, 0xD7, +0xE6, 0x96, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, +0xDE, 0x55, 0xDE, 0x35, 0xD5, 0xF4, 0xDE, 0x55, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x55, 0xEE, 0x96, +0xE6, 0x75, 0xE6, 0x55, 0xDE, 0x14, 0xAC, 0xD0, +0xAD, 0x11, 0xB5, 0x93, 0xBD, 0xD5, 0xBD, 0xB4, +0xC6, 0x16, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x53, 0xAD, 0x12, 0x6B, 0x2B, 0x18, 0xA2, +0x7C, 0x8E, 0x63, 0xAA, 0x3A, 0x65, 0x32, 0x05, +0x4A, 0xA7, 0x63, 0x4A, 0x6B, 0xAB, 0x63, 0x8A, +0x52, 0xC8, 0x5B, 0x09, 0x63, 0x4A, 0x84, 0x0C, +0x63, 0x68, 0x5B, 0x88, 0x63, 0xC9, 0x84, 0xAF, +0x73, 0xEC, 0x8C, 0x4D, 0x94, 0x6D, 0x9C, 0x6E, +0xA4, 0xAE, 0xA4, 0xAF, 0xB5, 0x10, 0xAC, 0xEF, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x31, 0xB5, 0x10, +0xA4, 0xAE, 0xB5, 0x10, 0xAC, 0xF0, 0xB5, 0x10, +0xB5, 0x30, 0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x30, 0xB5, 0x10, 0xAC, 0xEF, +0xAC, 0xEF, 0xB4, 0xEF, 0xB5, 0x0F, 0xB4, 0xEF, +0xAC, 0xCF, 0xA4, 0xAF, 0x94, 0x4D, 0x8C, 0x0C, +0x9C, 0x6E, 0xA4, 0xCF, 0xAD, 0x10, 0xB5, 0x51, +0xBD, 0x72, 0xB5, 0x31, 0x9C, 0x6F, 0x29, 0x45, +0x10, 0xA3, 0x42, 0x49, 0x42, 0x28, 0x18, 0xE3, +0x52, 0xCB, 0x8C, 0x91, 0x94, 0xD1, 0x9C, 0xD1, +0x9C, 0xD1, 0xA4, 0xF2, 0xA5, 0x12, 0xAD, 0x33, +0xA5, 0x33, 0xA5, 0x32, 0xA5, 0x12, 0x94, 0xB1, +0x63, 0x2B, 0x18, 0xE3, 0x10, 0x82, 0x10, 0xA3, +0x21, 0x04, 0xAD, 0x54, 0xA5, 0x33, 0x8C, 0x4F, +0x8C, 0x4F, 0xA5, 0x33, 0xAD, 0x53, 0x9D, 0x12, +0xB5, 0x94, 0xAD, 0x53, 0xA4, 0xF1, 0xA4, 0xD0, +0xAC, 0xF0, 0xAC, 0xCE, 0xAC, 0xCE, 0x9C, 0x8E, +0x9C, 0xCF, 0x83, 0xED, 0xB5, 0x72, 0xB5, 0x93, +0xBD, 0x92, 0xBD, 0xB3, 0xBD, 0xD3, 0xA5, 0x10, +0xB5, 0x52, 0x7B, 0xAC, 0x94, 0x8F, 0x94, 0x8F, +0x8C, 0x4E, 0xC5, 0xB3, 0xA4, 0x8E, 0xBD, 0x50, +0xCD, 0xF3, 0xCE, 0x14, 0xAD, 0x31, 0xC5, 0xD4, +0xC5, 0xB4, 0x8C, 0x2F, 0x52, 0x69, 0x52, 0x69, +0x4A, 0x49, 0x52, 0x69, 0x52, 0x8A, 0x63, 0x0C, +0x6B, 0x4D, 0x6B, 0x6D, 0x73, 0x8E, 0x8C, 0x72, +0x9C, 0xF3, 0xA4, 0xF3, 0xC5, 0xF8, 0xD6, 0x7A, +0xD6, 0x79, 0xAD, 0x14, 0xA4, 0xD3, 0xC5, 0xF7, +0x8C, 0x30, 0x9C, 0xB1, 0xA4, 0xF2, 0xA4, 0xF2, +0xAD, 0x12, 0xAD, 0x53, 0xA5, 0x12, 0x9C, 0xB1, +0x6B, 0x2B, 0x63, 0x0B, 0x73, 0xAD, 0x73, 0x8C, +0x6B, 0x4B, 0x7B, 0xAC, 0x84, 0x0D, 0x8C, 0x4F, +0x94, 0x6F, 0x8C, 0x2E, 0x8C, 0x4F, 0x84, 0x0E, +0x83, 0xED, 0x94, 0x6F, 0xB5, 0x32, 0xB5, 0x72, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x73, +0xBD, 0xB4, 0xA4, 0xF1, 0x94, 0x4F, 0x8C, 0x2F, +0x83, 0xED, 0x8C, 0x2E, 0x83, 0xEE, 0x7B, 0xAD, +0x7B, 0x8D, 0x7B, 0xAD, 0x7B, 0x8C, 0x83, 0xEE, +0x84, 0x0E, 0x9C, 0x90, 0xB5, 0x73, 0xC5, 0xD5, +0xCE, 0x15, 0xAC, 0xF2, 0xB5, 0x33, 0x7B, 0xAD, +0x42, 0x07, 0x41, 0xE7, 0x6B, 0x2B, 0x83, 0xCD, +0xAC, 0xF2, 0x8B, 0xEE, 0x7B, 0x8D, 0x6B, 0x0B, +0x7B, 0x8D, 0x83, 0xCF, 0x62, 0xAA, 0x6B, 0x2C, +0x8B, 0xEF, 0x94, 0x30, 0x94, 0x30, 0x6A, 0xEB, +0x7B, 0x6D, 0x83, 0xAE, 0xA4, 0xB1, 0xAD, 0x12, +0xB5, 0x53, 0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x73, +0xAD, 0x12, 0xB5, 0x52, 0xAD, 0x32, 0xB5, 0x32, +0xBD, 0x73, 0xBD, 0x94, 0xB5, 0x52, 0xAC, 0xF1, +0xA4, 0xD0, 0xAC, 0xF1, 0x52, 0x48, 0x18, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x18, 0xE4, 0x31, 0x87, +0x19, 0x04, 0x19, 0x04, 0x18, 0xE4, 0x18, 0xC4, +0x18, 0xC3, 0x18, 0xE4, 0x6B, 0x6D, 0xC5, 0xF5, +0xC5, 0xB3, 0xB5, 0x52, 0xAC, 0xF1, 0xCE, 0x15, +0xC5, 0xF4, 0xB5, 0x72, 0xAC, 0xF1, 0xC5, 0xD4, +0xCD, 0xF5, 0xD6, 0x76, 0xD6, 0x56, 0xB5, 0x33, +0x39, 0xA6, 0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE5, 0x18, 0xE5, 0x19, 0x05, +0x18, 0xE5, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xA4, +0x10, 0x83, 0x08, 0x83, 0x10, 0xA4, 0x18, 0xE4, +0x18, 0xE5, 0x19, 0x05, 0x19, 0x05, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x26, 0x29, 0x46, +0x31, 0x87, 0x31, 0x87, 0x31, 0xA8, 0x31, 0xC8, +0x39, 0xE8, 0x4A, 0x4A, 0x8C, 0x30, 0xD6, 0x56, +0xEE, 0xD7, 0xEE, 0xD6, 0xE6, 0x95, 0xEE, 0x96, +0xE6, 0x55, 0xDE, 0x55, 0xCD, 0xF3, 0xDE, 0x54, +0xEE, 0x95, 0xEE, 0x95, 0xEE, 0xB6, 0xEE, 0x96, +0xE6, 0x75, 0xE6, 0x55, 0xDE, 0x14, 0xAC, 0xD0, +0xA4, 0xF1, 0xB5, 0x73, 0xC5, 0xD4, 0xBD, 0xB4, +0xCE, 0x16, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x74, 0xC5, 0xD4, 0xCE, 0x57, 0x5A, 0xAA, +0x95, 0x31, 0x5B, 0x2A, 0x29, 0x83, 0x52, 0xE9, +0x5B, 0x2A, 0x5B, 0x2A, 0x63, 0x4A, 0x6B, 0xCC, +0x6B, 0xAC, 0x6B, 0xAB, 0x42, 0x67, 0x7B, 0xED, +0x63, 0x49, 0x4B, 0x07, 0x53, 0x08, 0x4A, 0xA8, +0x52, 0xE9, 0x7B, 0xED, 0x84, 0x0D, 0x8C, 0x2E, +0x9C, 0x8F, 0x9C, 0xB0, 0x7B, 0xAB, 0x94, 0x6E, +0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xF0, 0xA4, 0xAF, +0x9C, 0x8E, 0xAC, 0xEF, 0x9C, 0x4D, 0x8B, 0xEB, +0x9C, 0x4D, 0x94, 0x0C, 0xA4, 0xCE, 0x94, 0x2D, +0x9C, 0x4D, 0xA4, 0x8E, 0xAC, 0xCF, 0xAC, 0xCF, +0xA4, 0xAE, 0xAC, 0xCE, 0xBD, 0x50, 0xB5, 0x30, +0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x30, 0xBD, 0x30, +0xBD, 0x30, 0xB5, 0x30, 0xBD, 0x50, 0xBD, 0x30, +0xB5, 0x30, 0xBD, 0x50, 0xC5, 0x72, 0x8B, 0xEE, +0x42, 0x07, 0x18, 0xC3, 0x39, 0xE7, 0x21, 0x04, +0x18, 0xE3, 0x4A, 0x89, 0x6B, 0xAD, 0x73, 0xCD, +0x7B, 0xED, 0x84, 0x0E, 0x8C, 0x4F, 0x8C, 0x4F, +0x8C, 0x6F, 0x8C, 0x4F, 0x7B, 0xAD, 0x39, 0xC6, +0x10, 0x82, 0x10, 0xA2, 0x10, 0xA2, 0x10, 0xA3, +0x18, 0xC3, 0xA5, 0x33, 0xD6, 0xB8, 0xB5, 0xB4, +0xAD, 0x73, 0xC6, 0x36, 0xCE, 0x56, 0xBD, 0xF5, +0xBD, 0xF5, 0xB5, 0x94, 0xA4, 0xF1, 0xAD, 0x11, +0xA4, 0xCF, 0xAC, 0xEF, 0xAC, 0xEF, 0x9C, 0x6E, +0x83, 0xEC, 0x6B, 0x6A, 0x9C, 0xD0, 0xC5, 0xD4, +0xC5, 0xF4, 0xBD, 0xB3, 0xBD, 0xB3, 0xA4, 0xF0, +0xAD, 0x52, 0x83, 0xCD, 0x8C, 0x2E, 0x84, 0x0D, +0x7B, 0xAC, 0xAC, 0xF0, 0xA4, 0x6D, 0xBD, 0x30, +0xC5, 0xF3, 0xCD, 0xF4, 0xB5, 0x92, 0xC5, 0xD4, +0xCE, 0x36, 0x9C, 0x70, 0x41, 0xE7, 0x52, 0x69, +0x52, 0x69, 0x52, 0x89, 0x63, 0x0C, 0x73, 0xAE, +0x73, 0x8E, 0x4A, 0x49, 0x6B, 0x4D, 0x8C, 0x72, +0x9C, 0xF3, 0xBD, 0xB7, 0xC6, 0x18, 0xCE, 0x59, +0xAD, 0x14, 0x83, 0xF0, 0xC5, 0xB6, 0xCD, 0xF7, +0x73, 0x4D, 0x9C, 0xB1, 0x6B, 0x0B, 0x62, 0xCA, +0x8C, 0x2F, 0xB5, 0x94, 0xB5, 0x74, 0x6B, 0x6C, +0x5A, 0xEA, 0x7B, 0xEE, 0x8C, 0x50, 0x84, 0x0E, +0x7B, 0xCD, 0x83, 0xEE, 0x94, 0x70, 0xA4, 0xF1, +0xAD, 0x33, 0xA4, 0xF2, 0x9C, 0xD1, 0x94, 0x6F, +0x83, 0xCD, 0x94, 0x4E, 0xB5, 0x52, 0xB5, 0x72, +0xBD, 0x93, 0xB5, 0x72, 0xAD, 0x12, 0x8C, 0x2F, +0x84, 0x0E, 0x84, 0x0E, 0x8C, 0x4F, 0x9C, 0xB0, +0xA4, 0xD1, 0x9C, 0xB1, 0xB5, 0x74, 0xAD, 0x33, +0xAD, 0x33, 0xAD, 0x53, 0xB5, 0x94, 0xA4, 0xF1, +0xA4, 0xD1, 0xB5, 0x53, 0xBD, 0xB4, 0xAD, 0x32, +0xAD, 0x11, 0xAC, 0xF2, 0xB5, 0x33, 0x94, 0x4F, +0x7B, 0xCD, 0x4A, 0x47, 0x41, 0xE6, 0x52, 0x68, +0x83, 0xCD, 0xB5, 0x33, 0xAC, 0xF2, 0x7B, 0x8D, +0x7B, 0x6D, 0x8C, 0x10, 0x73, 0x2C, 0x83, 0xCE, +0x9C, 0x71, 0xA4, 0xB2, 0x8B, 0xEF, 0x83, 0xAE, +0x94, 0x30, 0x94, 0x30, 0x8C, 0x0F, 0x9C, 0x90, +0xC5, 0xF5, 0xBD, 0x94, 0xB5, 0x32, 0xC5, 0xB4, +0xCD, 0xF5, 0xDE, 0x97, 0xCD, 0xF5, 0xCE, 0x15, +0xC5, 0xD4, 0xBD, 0x53, 0xB5, 0x32, 0xAD, 0x32, +0xAD, 0x11, 0xAC, 0xF1, 0x41, 0xA6, 0x18, 0xA3, +0x10, 0x83, 0x10, 0x82, 0x19, 0x04, 0x31, 0xA7, +0x21, 0x04, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC3, +0x18, 0xE4, 0x39, 0xA7, 0xA4, 0xF2, 0xAD, 0x32, +0xB5, 0x11, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xAD, 0x10, 0xAD, 0x11, 0xAC, 0xF1, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF0, 0xB5, 0x11, +0x62, 0xCA, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, 0x19, 0x05, +0x19, 0x04, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x19, 0x05, 0x19, 0x04, 0x19, 0x05, 0x19, 0x05, +0x19, 0x04, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA4, +0x10, 0x83, 0x08, 0x83, 0x10, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x25, 0x21, 0x05, 0x21, 0x26, +0x18, 0xE5, 0x19, 0x05, 0x21, 0x46, 0x29, 0x66, +0x31, 0xA7, 0x31, 0xA8, 0x31, 0xC8, 0x39, 0xE9, +0x31, 0xA8, 0x31, 0xC8, 0x4A, 0x2A, 0x7B, 0x8D, +0xB5, 0x32, 0xDE, 0x35, 0xE6, 0x75, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x95, 0xD6, 0x14, 0xE6, 0x55, +0xEE, 0xB6, 0xEE, 0xB6, 0xEE, 0xD6, 0xEE, 0xB6, +0xE6, 0x95, 0xE6, 0x75, 0xD5, 0xF3, 0xAC, 0xF0, +0xAD, 0x32, 0xAD, 0x52, 0xBD, 0x94, 0xB5, 0x53, +0xC5, 0xF5, 0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x94, +0xBD, 0x94, 0xC5, 0xF5, 0xCE, 0x36, 0x9C, 0xB1, +0x31, 0xE5, 0x42, 0x87, 0x52, 0xE8, 0x6B, 0xCC, +0x6B, 0xAC, 0x63, 0x8C, 0x6B, 0xAC, 0x6B, 0x8C, +0x73, 0xED, 0x6B, 0x8B, 0x3A, 0x46, 0x7C, 0x4E, +0x5B, 0x08, 0x4A, 0xE7, 0x5B, 0x4B, 0x4A, 0xA9, +0x52, 0xC9, 0x84, 0x2E, 0x8C, 0x4F, 0x94, 0x90, +0xA5, 0x12, 0xA5, 0x32, 0x9C, 0xD1, 0xAD, 0x31, +0xA4, 0xCF, 0xAD, 0x31, 0xC5, 0xD4, 0xAD, 0x31, +0xAD, 0x31, 0xBD, 0x93, 0xBD, 0x93, 0xA4, 0xD0, +0xA4, 0xF0, 0xA4, 0xF0, 0xAC, 0xF0, 0xA4, 0xAF, +0xA4, 0xCF, 0xB5, 0x51, 0xBD, 0x72, 0xBD, 0x92, +0xAC, 0xCF, 0xB5, 0x10, 0x7B, 0x6A, 0x8B, 0xEC, +0x94, 0x2D, 0x9C, 0x8E, 0xC5, 0x92, 0xAC, 0xCF, +0xBD, 0x30, 0xCD, 0xD3, 0xB5, 0x10, 0xBD, 0x30, +0x94, 0x2C, 0x94, 0x2C, 0x9C, 0x2D, 0xA4, 0x6E, +0x9C, 0x6F, 0x7B, 0x8C, 0x42, 0x07, 0x18, 0xE3, +0x18, 0xE4, 0x19, 0x04, 0x29, 0x65, 0x42, 0x27, +0x52, 0xA9, 0x62, 0xEA, 0x63, 0x2A, 0x6B, 0x6B, +0x6B, 0x4B, 0x4A, 0x27, 0x18, 0xC2, 0x10, 0x82, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA2, 0x10, 0xA3, +0x10, 0xA3, 0x73, 0x8D, 0xAD, 0x32, 0xAC, 0xF0, +0xA4, 0xCF, 0xAD, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, +0x94, 0x4E, 0x9C, 0x6E, 0x9C, 0x8E, 0xAD, 0x31, +0x9C, 0x8E, 0xB4, 0xEF, 0xC5, 0x91, 0xBD, 0x51, +0x94, 0x2D, 0x83, 0xCC, 0x73, 0x6B, 0xAD, 0x11, +0xBD, 0x93, 0xBD, 0x92, 0xB5, 0x72, 0x8C, 0x2D, +0x94, 0x6E, 0x83, 0xED, 0x8C, 0x2E, 0x9C, 0xD0, +0xAD, 0x52, 0xA4, 0xAF, 0xA4, 0x8E, 0xAC, 0xEF, +0xC5, 0xB2, 0xC5, 0xF3, 0xBD, 0xD3, 0xC5, 0xF4, +0xD6, 0x56, 0xC5, 0xD5, 0x4A, 0x27, 0x52, 0x89, +0x5A, 0xCA, 0x73, 0x8E, 0x8C, 0x10, 0x62, 0xCB, +0x52, 0x8A, 0x6B, 0x4D, 0x7B, 0xCF, 0x8C, 0x31, +0xA4, 0xF4, 0xBD, 0xD7, 0xB5, 0x55, 0x7B, 0xAF, +0x7B, 0x8E, 0xB5, 0x34, 0xBD, 0x95, 0x8C, 0x0F, +0x62, 0xAA, 0x62, 0xAA, 0x29, 0x24, 0x20, 0xE4, +0x5A, 0xEB, 0xB5, 0x95, 0xB5, 0x74, 0x94, 0xB1, +0x94, 0x91, 0x8C, 0x2F, 0x7B, 0xCE, 0x84, 0x0E, +0x84, 0x0F, 0x8C, 0x4F, 0xAD, 0x33, 0xB5, 0x73, +0xAD, 0x53, 0xA5, 0x32, 0xA5, 0x12, 0x94, 0x90, +0x84, 0x0E, 0x94, 0x4F, 0xB5, 0x53, 0xB5, 0x73, +0xA4, 0xD1, 0x94, 0x4F, 0x8C, 0x2E, 0x6B, 0x6C, +0x84, 0x2E, 0xAD, 0x33, 0x9C, 0xD1, 0x9C, 0x90, +0xAD, 0x12, 0x9C, 0xB1, 0xAD, 0x53, 0xAD, 0x32, +0xAD, 0x12, 0xA5, 0x12, 0xBD, 0xB4, 0xA4, 0xF1, +0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0xB0, +0x94, 0x6F, 0xAD, 0x12, 0xAD, 0x32, 0x8C, 0x2E, +0x9C, 0x90, 0x94, 0x6F, 0x5A, 0x88, 0x31, 0x65, +0x41, 0xC6, 0x73, 0x2B, 0xA4, 0xD1, 0x83, 0xCE, +0x62, 0xA9, 0x83, 0xCE, 0x8B, 0xEF, 0x7B, 0x4C, +0x8C, 0x0F, 0x8C, 0x0F, 0x73, 0x2C, 0x8C, 0x0F, +0x9C, 0x71, 0x8B, 0xEF, 0x73, 0x2C, 0x7B, 0x8D, +0x94, 0x2F, 0x9C, 0x91, 0xB5, 0x33, 0xBD, 0x74, +0xB5, 0x53, 0xC5, 0xF5, 0xC5, 0xD4, 0xC5, 0xD4, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x93, 0xC5, 0x93, +0xC5, 0xD4, 0x8B, 0xEE, 0x29, 0x25, 0x10, 0x82, +0x10, 0x82, 0x18, 0xC4, 0x21, 0x25, 0x31, 0x86, +0x19, 0x04, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC3, +0x18, 0xC3, 0x4A, 0x49, 0xB5, 0x74, 0xAC, 0xD0, +0xC5, 0xB3, 0xBD, 0x72, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xAD, 0x11, 0xA4, 0xD0, 0xBD, 0x52, +0xBD, 0x72, 0xCD, 0xF4, 0xD6, 0x15, 0xD6, 0x35, +0x9C, 0x6F, 0x41, 0xE7, 0x18, 0xC4, 0x18, 0xE5, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, +0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, 0x19, 0x05, +0x19, 0x04, 0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x19, 0x04, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x83, 0x08, 0x83, 0x10, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x21, 0x05, 0x18, 0xE5, 0x21, 0x26, +0x18, 0xE5, 0x21, 0x06, 0x29, 0x46, 0x31, 0x87, +0x31, 0xA8, 0x31, 0xA8, 0x31, 0xC8, 0x39, 0xC8, +0x29, 0x67, 0x31, 0xC8, 0x42, 0x0A, 0x4A, 0x6A, +0x63, 0x0C, 0xAC, 0xF1, 0xDE, 0x54, 0xEE, 0x95, +0xE6, 0x95, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x54, 0xEE, 0x95, 0xEE, 0xB6, +0xEE, 0x95, 0xEE, 0x95, 0xCD, 0x93, 0xB5, 0x11, +0xA4, 0xF1, 0xAD, 0x12, 0xBD, 0x94, 0xAD, 0x32, +0xBD, 0xB4, 0xAD, 0x53, 0xB5, 0x53, 0xB5, 0x73, +0xBD, 0xB4, 0xB5, 0x93, 0xC5, 0xF5, 0xBD, 0xB4, +0x32, 0x06, 0x21, 0x62, 0x29, 0xC4, 0x42, 0x67, +0x4A, 0xC9, 0x73, 0xED, 0x7C, 0x0E, 0x7C, 0x0E, +0x7C, 0x2E, 0x73, 0xAC, 0x3A, 0x25, 0x6B, 0xCC, +0x7C, 0x4E, 0x95, 0x11, 0x94, 0xF2, 0x73, 0xCE, +0x5B, 0x0B, 0x84, 0x2F, 0x8C, 0x90, 0xA5, 0x33, +0xC6, 0x16, 0xAD, 0x53, 0xAD, 0x54, 0xB5, 0x53, +0xAC, 0xD0, 0xBD, 0x93, 0xDE, 0x97, 0xC5, 0xF4, +0xB5, 0x52, 0xAD, 0x11, 0xA4, 0xD0, 0xAD, 0x31, +0xC5, 0xD4, 0xC5, 0xB3, 0xCD, 0xD4, 0xCD, 0xD4, +0xC5, 0xB3, 0xCD, 0xF4, 0xC5, 0xD3, 0xC5, 0xB3, +0xC5, 0xB3, 0xC5, 0xB3, 0x9C, 0x8E, 0xA4, 0xF1, +0xA4, 0xAF, 0x9C, 0xAF, 0xC5, 0xD3, 0x9C, 0x4D, +0xBD, 0x30, 0xD6, 0x15, 0xDE, 0x76, 0xDE, 0x55, +0xA4, 0xD0, 0xB5, 0x31, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x11, 0x9C, 0x8F, 0x94, 0x4F, 0x7B, 0x8D, +0x18, 0xE3, 0x10, 0xC3, 0x19, 0x04, 0x29, 0x65, +0x39, 0xC7, 0x39, 0xE6, 0x31, 0xC6, 0x31, 0x85, +0x18, 0xC2, 0x10, 0x82, 0x10, 0x82, 0x10, 0xA2, +0x10, 0x82, 0x08, 0x82, 0x10, 0xA2, 0x10, 0xA3, +0x10, 0xA3, 0x52, 0x69, 0xA4, 0xB0, 0xA4, 0x8E, +0xA4, 0x8E, 0xA4, 0xAE, 0xA4, 0xAE, 0xAC, 0xCF, +0xAC, 0xEF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, +0xBD, 0x30, 0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x51, +0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x31, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xCF, 0xA4, 0xAF, +0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x31, 0xB5, 0x30, +0xBD, 0x71, 0xBD, 0x30, 0xB5, 0x10, 0xA4, 0x8D, +0xAC, 0xCE, 0xBD, 0x72, 0xAD, 0x31, 0xC5, 0xD4, +0xB5, 0x52, 0xA4, 0xD1, 0x94, 0x4F, 0x7B, 0x8D, +0x6B, 0x2C, 0x73, 0x4D, 0x63, 0x0C, 0x52, 0x6A, +0x7B, 0x8E, 0x83, 0xF0, 0x94, 0x72, 0xAD, 0x76, +0xCE, 0x39, 0x9C, 0xD3, 0x5A, 0x8B, 0x62, 0xCB, +0x94, 0x51, 0xAD, 0x14, 0x9C, 0xB2, 0x6A, 0xEB, +0x5A, 0x69, 0x49, 0xE7, 0x29, 0x24, 0x41, 0xE7, +0x9C, 0xD2, 0xAD, 0x33, 0xB5, 0x74, 0x94, 0xB1, +0x94, 0xB1, 0x9C, 0xD2, 0x84, 0x0E, 0x83, 0xEE, +0x94, 0x70, 0x94, 0x90, 0xB5, 0x53, 0xA5, 0x12, +0xAD, 0x32, 0xB5, 0x94, 0xAD, 0x53, 0x9C, 0xD1, +0x8C, 0x2E, 0x94, 0x6F, 0xBD, 0x94, 0xA4, 0xB0, +0x63, 0x0A, 0x6B, 0x4B, 0x73, 0x6C, 0x7B, 0xCD, +0x83, 0xED, 0x9C, 0xF1, 0xC5, 0xF5, 0xA4, 0xF1, +0x94, 0x6F, 0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF2, 0x9C, 0xD1, 0x9C, 0x90, 0x94, 0x90, +0x9C, 0xD1, 0xA4, 0xD1, 0x8C, 0x2F, 0x73, 0x6C, +0x8C, 0x0E, 0xAD, 0x12, 0xB5, 0x53, 0xA4, 0xD0, +0x9C, 0x8F, 0x9C, 0xD0, 0x94, 0x6F, 0x5A, 0xC9, +0x39, 0xA6, 0x39, 0xA5, 0x62, 0xC9, 0x8B, 0xEE, +0x73, 0x2C, 0x52, 0x48, 0x52, 0x48, 0x73, 0x4C, +0x6A, 0xEB, 0x7B, 0x4D, 0x73, 0x0C, 0x94, 0x10, +0x7B, 0x4C, 0x7B, 0x6D, 0x8B, 0xEF, 0x73, 0x0C, +0x6A, 0xEB, 0x6A, 0xEB, 0x8C, 0x0F, 0xB5, 0x54, +0xAD, 0x13, 0xAD, 0x13, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xB0, 0x8C, 0x0D, 0x94, 0x4E, +0x8C, 0x0E, 0x4A, 0x07, 0x31, 0x65, 0x21, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, +0x18, 0xE4, 0x18, 0xC3, 0x18, 0xE4, 0x18, 0xC3, +0x31, 0xA6, 0x8C, 0x2F, 0xB5, 0x32, 0xB5, 0x31, +0xCD, 0xF4, 0xC5, 0xB3, 0xB5, 0x32, 0xB5, 0x52, +0xAC, 0xF1, 0xA4, 0x8F, 0x83, 0xAC, 0x9C, 0x6E, +0xA4, 0xAF, 0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x51, +0xAD, 0x11, 0x7B, 0x8D, 0x29, 0x45, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, +0x21, 0x25, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xE4, +0x19, 0x05, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xC4, 0x10, 0xC4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xC4, 0x18, 0xE4, +0x18, 0xE5, 0x19, 0x05, 0x18, 0xE5, 0x21, 0x26, +0x18, 0xE5, 0x21, 0x46, 0x29, 0x47, 0x31, 0xA8, +0x31, 0x88, 0x31, 0x87, 0x31, 0xA8, 0x31, 0xA8, +0x31, 0xA8, 0x42, 0x2A, 0x42, 0x09, 0x42, 0x09, +0x4A, 0x4A, 0x73, 0x6D, 0xA4, 0x90, 0xA4, 0x8F, +0xB5, 0x10, 0xBD, 0x51, 0xC5, 0x92, 0xCD, 0xD3, +0xD5, 0xD3, 0xD5, 0xD3, 0xD5, 0xD3, 0xD5, 0xD3, +0xDE, 0x34, 0xB4, 0xF0, 0x83, 0x8B, 0xA4, 0xF1, +0x8C, 0x2E, 0x94, 0x4E, 0x9C, 0xB0, 0x9C, 0xD0, +0x9C, 0xD0, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF1, 0x9C, 0xAF, 0xAD, 0x11, +0x4A, 0x88, 0x73, 0xCD, 0x5B, 0x2A, 0x84, 0x4F, +0x84, 0x4F, 0x7C, 0x0E, 0x8C, 0x90, 0x8C, 0x91, +0x8C, 0x90, 0x8C, 0x6E, 0x3A, 0x25, 0x53, 0x09, +0x63, 0x8B, 0x84, 0x6F, 0x84, 0x4F, 0x73, 0xAD, +0x6B, 0x8D, 0x8C, 0x91, 0xA5, 0x33, 0xB5, 0x94, +0xC6, 0x37, 0xAD, 0x74, 0xAD, 0x94, 0xAD, 0x52, +0xA4, 0xD0, 0xAD, 0x31, 0xCE, 0x36, 0xBD, 0xB3, +0xB5, 0x73, 0x8C, 0x2E, 0x6B, 0x2B, 0xCE, 0x15, +0xD6, 0x56, 0xCD, 0xF4, 0xCD, 0xF3, 0xCD, 0xD4, +0xD6, 0x14, 0xD6, 0x14, 0xCD, 0xF4, 0xCD, 0xF4, +0xCD, 0xF4, 0xCD, 0xF4, 0xBD, 0x92, 0xBD, 0x93, +0xBD, 0x93, 0xAD, 0x31, 0xB5, 0x51, 0x9C, 0x6E, +0xBD, 0x51, 0xCD, 0xD3, 0xDE, 0x55, 0xD6, 0x15, +0xC5, 0xB3, 0xC5, 0xF5, 0xCE, 0x15, 0xC5, 0xF4, +0xA4, 0xD1, 0x8B, 0xED, 0x62, 0xCA, 0x5A, 0xCA, +0x21, 0x24, 0x10, 0xA3, 0x08, 0x82, 0x10, 0xA3, +0x31, 0x86, 0x3A, 0x08, 0x39, 0xC7, 0x18, 0xC3, +0x08, 0x62, 0x10, 0x82, 0x10, 0x82, 0x10, 0x82, +0x10, 0x82, 0x08, 0x82, 0x10, 0xA2, 0x10, 0xA2, +0x10, 0xA3, 0x31, 0x86, 0x84, 0x0E, 0x7B, 0xAC, +0x7B, 0x6B, 0x73, 0x6A, 0x73, 0x4A, 0x7B, 0x8A, +0x7B, 0x6A, 0x73, 0x29, 0x73, 0x29, 0x7B, 0x8A, +0x83, 0xCB, 0x9C, 0x4D, 0x8B, 0xEB, 0xA4, 0x8E, +0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, 0xC5, 0x91, +0xB5, 0x0F, 0xAC, 0xCE, 0xB5, 0x0F, 0xB4, 0xEF, +0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x0F, 0xB4, 0xEF, +0xB5, 0x0F, 0xBD, 0x10, 0xAC, 0xCE, 0xB4, 0xEF, +0xA4, 0xAE, 0xBD, 0x93, 0xAD, 0x32, 0x8C, 0x0E, +0x83, 0x8B, 0x83, 0xCC, 0xA4, 0x90, 0x8C, 0x0F, +0x7B, 0x8D, 0x5A, 0xAA, 0x62, 0xCB, 0x62, 0xCB, +0x8C, 0x51, 0xA5, 0x14, 0xB5, 0x96, 0xAD, 0x76, +0x7B, 0xCF, 0x42, 0x29, 0x6B, 0x2D, 0x6B, 0x2D, +0x73, 0x8E, 0xAD, 0x14, 0x8C, 0x30, 0x52, 0x28, +0x52, 0x28, 0x4A, 0x28, 0x52, 0x28, 0x6A, 0xEA, +0x62, 0xEB, 0x8C, 0x4F, 0x9C, 0xB1, 0x94, 0x70, +0x73, 0x8C, 0x9C, 0xD1, 0x9C, 0xB1, 0x9C, 0xD1, +0xAD, 0x12, 0xA4, 0xD2, 0xAD, 0x53, 0xB5, 0x73, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x32, +0x9C, 0xD0, 0x8C, 0x4F, 0xBD, 0xB4, 0xBD, 0x73, +0x94, 0x4F, 0x8C, 0x2F, 0x84, 0x0E, 0x8C, 0x2F, +0x73, 0xAC, 0x84, 0x0E, 0x9C, 0xD1, 0x84, 0x0E, +0x73, 0x6B, 0x94, 0x6F, 0x7B, 0xCD, 0x94, 0x90, +0x9C, 0xD1, 0xA5, 0x12, 0x8C, 0x2F, 0x94, 0x4F, +0x8C, 0x2F, 0x8C, 0x4F, 0x8C, 0x4F, 0x73, 0x8D, +0x8C, 0x2F, 0xB5, 0x52, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x31, 0x94, 0x6F, 0x9C, 0x90, 0x94, 0x6F, +0x63, 0x0A, 0x4A, 0x28, 0x42, 0x07, 0x6B, 0x2B, +0x5A, 0xAA, 0x4A, 0x28, 0x41, 0xE7, 0x62, 0xCA, +0x83, 0xAE, 0x8B, 0xCF, 0x73, 0x0C, 0x6A, 0xEB, +0x83, 0xCF, 0x83, 0xCE, 0x9C, 0x92, 0x7B, 0x6D, +0x94, 0x50, 0x83, 0xCE, 0x94, 0x30, 0x9C, 0x71, +0x94, 0x30, 0x8B, 0xEE, 0x94, 0x30, 0x83, 0xCE, +0x94, 0x2F, 0x39, 0xA6, 0x18, 0xC3, 0x18, 0xA2, +0x18, 0xE3, 0x41, 0xE7, 0x31, 0x66, 0x20, 0xE4, +0x10, 0xC3, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xE4, +0x18, 0xC4, 0x18, 0xC3, 0x18, 0xE4, 0x21, 0x04, +0x94, 0x70, 0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x32, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0xB3, +0xC5, 0xB3, 0xC5, 0xD4, 0xAC, 0xD0, 0xBD, 0x73, +0xC5, 0xD4, 0xC5, 0x93, 0xBD, 0x52, 0xBD, 0x93, +0xB5, 0x72, 0x94, 0x4F, 0x5A, 0x8A, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x19, 0x05, +0x21, 0x05, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x04, 0x19, 0x04, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x46, 0x29, 0x46, 0x29, 0x87, +0x21, 0x46, 0x29, 0x67, 0x29, 0x87, 0x31, 0x87, +0x39, 0xE9, 0x3A, 0x09, 0x39, 0xC8, 0x31, 0xC8, +0x42, 0x09, 0x52, 0xCC, 0x84, 0x0F, 0xB5, 0x32, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x12, 0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x11, +0xAD, 0x11, 0xA4, 0xB0, 0xAD, 0x32, 0xBD, 0x93, +0xB5, 0x32, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0x90, +0x9C, 0x90, 0x94, 0x6F, 0x8C, 0x2E, 0x94, 0x4F, +0x8C, 0x2E, 0x8C, 0x0E, 0x83, 0xED, 0x83, 0xED, +0x8C, 0xB0, 0x94, 0xB1, 0x6B, 0x6C, 0x8C, 0xB0, +0x7C, 0x2F, 0x94, 0xB1, 0xB5, 0xF6, 0xAD, 0x94, +0x9C, 0xD1, 0x52, 0x87, 0x42, 0x26, 0x63, 0x8B, +0x74, 0x2E, 0x84, 0x90, 0x8C, 0xB0, 0x84, 0x50, +0x84, 0x2F, 0x9C, 0xF2, 0xAD, 0x74, 0xAD, 0x74, +0xC6, 0x57, 0xB5, 0xB5, 0xAD, 0x74, 0x9C, 0xD0, +0xAC, 0xF0, 0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0x93, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x52, 0xCE, 0x15, +0xDE, 0x76, 0xD6, 0x15, 0xCE, 0x14, 0xCE, 0x14, +0xDE, 0x76, 0xD6, 0x35, 0xCE, 0x14, 0xCD, 0xF4, +0xCD, 0xF4, 0xD6, 0x55, 0xD6, 0x15, 0xCD, 0xF4, +0xCE, 0x14, 0xBD, 0xB3, 0xAD, 0x11, 0x9C, 0x8E, +0xBD, 0x51, 0xA4, 0xAE, 0xBD, 0x92, 0xC5, 0xB3, +0xC5, 0xD4, 0xD6, 0x56, 0xD6, 0x76, 0xD6, 0x36, +0xA4, 0xB1, 0x8C, 0x2F, 0x73, 0x6C, 0x4A, 0x08, +0x18, 0xE4, 0x10, 0xC3, 0x19, 0x04, 0x29, 0x86, +0x31, 0xC8, 0x31, 0xC8, 0x39, 0xE8, 0x4A, 0x6A, +0x29, 0x46, 0x08, 0x62, 0x08, 0x62, 0x08, 0x82, +0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x08, 0x82, +0x10, 0xA3, 0x21, 0x25, 0xAD, 0x53, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x32, 0x9C, 0xB0, 0x9C, 0xB0, +0xA4, 0xF1, 0xA4, 0xD1, 0x94, 0x6F, 0x8C, 0x2E, +0x94, 0x6E, 0x94, 0x4E, 0x8B, 0xED, 0x9C, 0xAF, +0xAD, 0x11, 0xA4, 0xAF, 0x8C, 0x0D, 0xAC, 0xEF, +0x9C, 0x4D, 0xA4, 0x6D, 0xA4, 0x6D, 0xA4, 0x8E, +0xBD, 0x51, 0xAD, 0x11, 0xAC, 0xD0, 0x7B, 0x8B, +0x73, 0x2A, 0x7B, 0x8B, 0x8C, 0x0C, 0x9C, 0x6E, +0x83, 0xCD, 0xAD, 0x13, 0xA4, 0xF2, 0x73, 0x4C, +0x73, 0x4B, 0xA4, 0x90, 0x9C, 0x4F, 0x6A, 0xCA, +0x6B, 0x2C, 0x7B, 0xAE, 0xA4, 0xF3, 0x94, 0x72, +0x7B, 0xAE, 0x52, 0x8A, 0x39, 0xA7, 0x4A, 0x6A, +0x62, 0xEC, 0x73, 0x6E, 0x63, 0x0C, 0x6B, 0x0C, +0x7B, 0x8E, 0x83, 0xEF, 0x73, 0x2C, 0x6B, 0x2C, +0x5A, 0x89, 0x31, 0x44, 0x29, 0x44, 0x39, 0x85, +0x62, 0xEB, 0x9C, 0x91, 0x94, 0x50, 0x94, 0x50, +0x8C, 0x2E, 0x94, 0x0D, 0x94, 0x0D, 0x94, 0x4E, +0x9C, 0x8E, 0x9C, 0x8F, 0xA4, 0x8F, 0xA4, 0xD0, +0xB5, 0x11, 0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xF1, +0xAD, 0x11, 0x94, 0x4E, 0xA4, 0xD0, 0xAD, 0x12, +0xAD, 0x32, 0x9C, 0x90, 0x7B, 0xAD, 0x7B, 0x8C, +0x7B, 0xCD, 0x83, 0xEE, 0x83, 0xEE, 0x8C, 0x4F, +0x94, 0x6F, 0xA4, 0xF1, 0x9C, 0xB0, 0x8C, 0x2E, +0x83, 0xED, 0x83, 0xEE, 0x73, 0x8C, 0x83, 0xEE, +0x8C, 0x0E, 0x94, 0x70, 0x94, 0x70, 0x9C, 0xB1, +0x9C, 0x90, 0xAC, 0xF1, 0xB5, 0x52, 0xB5, 0x32, +0xC5, 0xD4, 0xB5, 0x52, 0xBD, 0x93, 0xC5, 0xF4, +0xBD, 0x93, 0x8C, 0x2E, 0x41, 0xE6, 0x41, 0xE6, +0x41, 0xE7, 0x41, 0xE7, 0x42, 0x07, 0x41, 0xE7, +0xA5, 0x14, 0xBD, 0x96, 0x94, 0x71, 0x62, 0xCB, +0x62, 0xEB, 0x6A, 0xEB, 0x83, 0xCF, 0x73, 0x2C, +0x94, 0x30, 0x6A, 0xEB, 0x8B, 0xEF, 0xAC, 0xD2, +0x94, 0x30, 0x83, 0x8D, 0x52, 0x49, 0x4A, 0x07, +0x6B, 0x0B, 0x73, 0x4D, 0x83, 0xEF, 0x62, 0xEB, +0x29, 0x24, 0x31, 0x86, 0x21, 0x04, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x18, 0xE4, 0x18, 0xC3, 0x18, 0xE4, 0x29, 0x65, +0xAD, 0x53, 0xC5, 0xD4, 0xAC, 0xF1, 0xBD, 0x73, +0xC5, 0xD4, 0xC5, 0xB3, 0xC5, 0xD4, 0xCD, 0xF4, +0xCD, 0xF4, 0xCD, 0xD4, 0xBD, 0x73, 0xCD, 0xF4, +0xD6, 0x36, 0xCE, 0x15, 0xCD, 0xF5, 0xCD, 0xF5, +0xCE, 0x15, 0xB5, 0x32, 0x83, 0xEE, 0x29, 0x65, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xE4, 0x21, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x04, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE5, +0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA3, 0x10, 0xA3, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x21, 0x26, +0x18, 0xE5, 0x29, 0x46, 0x29, 0x67, 0x29, 0x87, +0x31, 0xC8, 0x39, 0xC9, 0x39, 0xC8, 0x39, 0xE9, +0x42, 0x2A, 0x3A, 0x09, 0x42, 0x49, 0xA4, 0xF2, +0xCE, 0x16, 0xBD, 0x73, 0xBD, 0x93, 0xA4, 0xB0, +0xAC, 0xF1, 0xCD, 0xD4, 0xBD, 0x52, 0x9C, 0x8F, +0x83, 0xCD, 0x7B, 0xAC, 0x94, 0x2E, 0xAD, 0x11, +0xB5, 0x52, 0x9C, 0x6F, 0xA4, 0xF1, 0xAD, 0x12, +0xA4, 0xD1, 0x9C, 0x6F, 0x9C, 0xAF, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, +0x9D, 0x53, 0x8C, 0xB0, 0x5A, 0xC9, 0x73, 0xAD, +0x7C, 0x2E, 0xC6, 0x37, 0xB5, 0xD6, 0x7C, 0x2F, +0x5A, 0xEA, 0x63, 0x0A, 0x52, 0x87, 0x31, 0xE4, +0x3A, 0x46, 0x63, 0x8C, 0x94, 0xF1, 0x9C, 0xF2, +0x9D, 0x13, 0xA5, 0x54, 0xBD, 0xF6, 0xBD, 0xD5, +0xC6, 0x16, 0xBD, 0xD5, 0xA5, 0x33, 0xA4, 0xF1, +0xAD, 0x10, 0xB5, 0x52, 0xAD, 0x11, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0xD4, 0xC5, 0xD4, 0xCE, 0x35, +0xD6, 0x56, 0xC5, 0xF4, 0xD6, 0x35, 0xD6, 0x15, +0xD6, 0x56, 0xCD, 0xD4, 0xC5, 0xD4, 0xD6, 0x35, +0xDE, 0x56, 0xDE, 0x56, 0xBD, 0x52, 0xCE, 0x15, +0xBD, 0xB3, 0xBD, 0xB3, 0xAD, 0x32, 0x9C, 0x4E, +0xBD, 0x30, 0xAC, 0xCF, 0xC5, 0x93, 0xCD, 0xF4, +0xCE, 0x35, 0xD6, 0x77, 0xD6, 0x77, 0x8C, 0x0E, +0x8B, 0xEF, 0x8C, 0x10, 0x62, 0xCB, 0x39, 0xA7, +0x42, 0x08, 0x39, 0xE8, 0x29, 0x86, 0x31, 0xA7, +0x29, 0x66, 0x29, 0x86, 0x21, 0x45, 0x42, 0x29, +0x63, 0x0D, 0x29, 0x45, 0x10, 0xA3, 0x08, 0x62, +0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x10, 0xA2, +0x18, 0xC3, 0x21, 0x24, 0xBD, 0xF6, 0xCE, 0x36, +0xCE, 0x16, 0xAD, 0x53, 0xAD, 0x32, 0xCE, 0x36, +0xCE, 0x57, 0xCE, 0x36, 0xC5, 0xF5, 0xBD, 0x94, +0xAD, 0x52, 0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x93, +0xB5, 0x73, 0xA4, 0xF1, 0x8C, 0x0D, 0xA4, 0xCF, +0xAC, 0xAE, 0xAC, 0xCF, 0xC5, 0xB2, 0xC5, 0xB2, +0xBD, 0xB3, 0xBD, 0xD4, 0xB5, 0x93, 0x9C, 0xF1, +0x94, 0x6F, 0x8C, 0x4F, 0x94, 0x90, 0x83, 0xEE, +0x41, 0xE7, 0x5A, 0x8A, 0x5A, 0xAA, 0x5A, 0xCB, +0x5A, 0xAA, 0x8B, 0xEE, 0x83, 0xAD, 0x5A, 0x89, +0x62, 0xAA, 0x5A, 0x69, 0x62, 0xEB, 0xA4, 0xF4, +0x7B, 0xCF, 0x5A, 0xAB, 0x42, 0x08, 0x39, 0xC7, +0x62, 0xEC, 0x8C, 0x10, 0x5A, 0xAA, 0x83, 0xAF, +0x73, 0x6D, 0x7B, 0xAE, 0x63, 0x0B, 0x52, 0x69, +0x4A, 0x48, 0x39, 0x85, 0x29, 0x24, 0x39, 0x85, +0x62, 0xEB, 0x83, 0xEF, 0x8C, 0x30, 0x7B, 0x8D, +0xAC, 0xF1, 0xBD, 0x31, 0xBD, 0x31, 0xBD, 0x51, +0xBD, 0x51, 0xB5, 0x31, 0xB5, 0x10, 0xBD, 0x10, +0xBD, 0x31, 0xBD, 0x31, 0xBD, 0x31, 0xBD, 0x10, +0xBD, 0x31, 0xB5, 0x10, 0xB5, 0x11, 0xB5, 0x32, +0xAD, 0x12, 0xAD, 0x11, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x33, 0xAC, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, +0x9C, 0x8F, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x70, +0x94, 0x4F, 0x94, 0x4F, 0x8C, 0x2E, 0x8C, 0x2F, +0x8C, 0x2F, 0x8C, 0x2E, 0x8C, 0x2F, 0x94, 0x4F, +0x94, 0x4F, 0xAD, 0x11, 0xB5, 0x32, 0xB5, 0x31, +0xB5, 0x52, 0xCD, 0xF4, 0xC5, 0xF4, 0xBD, 0xB3, +0xC5, 0xD4, 0xBD, 0x93, 0x83, 0xAC, 0x31, 0x85, +0x31, 0x65, 0x39, 0xA6, 0x31, 0x85, 0x42, 0x08, +0x94, 0x92, 0x7B, 0xCF, 0x7B, 0xCF, 0x7B, 0xCF, +0xB5, 0x96, 0x83, 0xF0, 0x62, 0xEB, 0x5A, 0x8A, +0x7B, 0x6D, 0x5A, 0x69, 0x7B, 0x4D, 0x93, 0xEF, +0x7B, 0x2C, 0x8B, 0xCE, 0x62, 0xCB, 0x62, 0xCB, +0x73, 0x2C, 0x6B, 0x0C, 0x83, 0xCF, 0x9C, 0x71, +0x8C, 0x30, 0x4A, 0x08, 0x20, 0xE4, 0x18, 0xC4, +0x10, 0xC4, 0x18, 0xC4, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xC3, 0x42, 0x08, +0xC5, 0xD5, 0xCD, 0xF5, 0xAC, 0xD0, 0xC5, 0x93, +0xDE, 0x35, 0xD6, 0x14, 0xD5, 0xF4, 0xD5, 0xF4, +0xD6, 0x14, 0xD6, 0x35, 0xCD, 0xB3, 0xD5, 0xF5, +0xCD, 0xF4, 0xCD, 0xD4, 0xC5, 0x93, 0xBD, 0x92, +0xAC, 0xF0, 0xC5, 0xB4, 0xAD, 0x12, 0x5A, 0xCA, +0x29, 0x45, 0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x18, 0xE4, 0x18, 0xE4, +0x19, 0x04, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0x83, 0x08, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xC4, 0x10, 0xC4, +0x18, 0xE4, 0x19, 0x05, 0x21, 0x05, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x19, 0x05, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x29, 0x67, +0x31, 0x87, 0x39, 0xC8, 0x39, 0xE9, 0x39, 0xE9, +0x31, 0xA8, 0x31, 0x88, 0x31, 0x87, 0x6B, 0x4C, +0xC5, 0xD5, 0xC5, 0xB4, 0xBD, 0x94, 0xA4, 0xF1, +0xA4, 0xB0, 0xB5, 0x32, 0xBD, 0x72, 0xBD, 0x93, +0xD6, 0x36, 0xD6, 0x56, 0xAD, 0x32, 0x9C, 0x8F, +0xA4, 0xB0, 0xBD, 0x93, 0xCD, 0xF4, 0xBD, 0x93, +0x94, 0x6F, 0x8C, 0x0E, 0x8B, 0xED, 0xBD, 0x93, +0xBD, 0x92, 0xB5, 0x11, 0xB5, 0x31, 0xAD, 0x11, +0xBD, 0xF5, 0xBD, 0xD5, 0x73, 0x8C, 0x6B, 0x4B, +0x52, 0xC8, 0x7C, 0x4E, 0x5B, 0x29, 0x7B, 0xEC, +0x9C, 0xD1, 0xAD, 0x73, 0xA5, 0x52, 0x84, 0x2D, +0x84, 0x2C, 0x7B, 0xEB, 0x84, 0x0D, 0x94, 0xB0, +0x8C, 0x6F, 0x94, 0x90, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x93, 0xB5, 0x94, 0xA4, 0xF2, 0x9C, 0x8F, +0xAC, 0xCF, 0x9C, 0x8F, 0x94, 0x6F, 0xA4, 0xF0, +0xAD, 0x11, 0x94, 0x6F, 0x83, 0xED, 0xBD, 0x93, +0xC5, 0xD4, 0xBD, 0xB4, 0xBD, 0x93, 0x9C, 0xB0, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, 0xCD, 0xF4, +0xCE, 0x15, 0xDE, 0x76, 0xCE, 0x15, 0xCE, 0x15, +0xD6, 0x56, 0xCE, 0x36, 0xCE, 0x36, 0xAC, 0xCF, +0xB4, 0xEF, 0xC5, 0x71, 0xB5, 0x31, 0xB5, 0x52, +0xD6, 0x56, 0xDE, 0x97, 0xC5, 0xF5, 0x8C, 0x0F, +0xAC, 0xF3, 0x83, 0xAF, 0x73, 0x4D, 0x83, 0xEF, +0x6B, 0x2D, 0x5A, 0xEC, 0x3A, 0x08, 0x31, 0xA7, +0x31, 0xC7, 0x42, 0x29, 0x29, 0x86, 0x18, 0xE4, +0x52, 0x8B, 0x5A, 0xCC, 0x4A, 0x6A, 0x21, 0x25, +0x18, 0xE4, 0x08, 0x82, 0x08, 0x82, 0x10, 0xA2, +0x18, 0xC3, 0x21, 0x25, 0xBD, 0xF6, 0xCE, 0x36, +0xCE, 0x15, 0xD6, 0x57, 0xD6, 0x77, 0xD6, 0x56, +0xD6, 0x76, 0xCE, 0x35, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0x94, 0xAD, 0x52, 0xB5, 0x94, 0xBD, 0xB4, +0xC5, 0xF5, 0xAD, 0x52, 0x9C, 0xB0, 0x9C, 0x8E, +0xAC, 0xCF, 0x8C, 0x0C, 0xC5, 0x92, 0xAC, 0xAE, +0x9C, 0x6F, 0x9C, 0xB0, 0x7B, 0xAC, 0x8C, 0x2E, +0x94, 0x70, 0x8C, 0x4F, 0x9C, 0xD2, 0xBD, 0xD6, +0x9C, 0xD3, 0x94, 0x92, 0x9C, 0x92, 0xAD, 0x14, +0x94, 0x30, 0x8C, 0x2F, 0x4A, 0x28, 0x5A, 0x8A, +0x62, 0xEB, 0x5A, 0xAA, 0x5A, 0xAA, 0x6B, 0x2C, +0x7B, 0xCF, 0x8C, 0x10, 0x83, 0xAF, 0x52, 0x69, +0x4A, 0x28, 0x5A, 0x8A, 0x63, 0x0B, 0x73, 0x8D, +0x7B, 0xAE, 0x8C, 0x30, 0x52, 0x69, 0x52, 0x69, +0x41, 0xE7, 0x29, 0x03, 0x31, 0x85, 0x4A, 0x28, +0x39, 0xA6, 0x5A, 0xAA, 0x7B, 0x8E, 0x52, 0x69, +0x52, 0x89, 0x62, 0xC9, 0x73, 0x4B, 0x8C, 0x0D, +0xAD, 0x11, 0xB5, 0x32, 0xBD, 0x52, 0xBD, 0x72, +0xCD, 0xD4, 0xC5, 0xD3, 0xC5, 0x92, 0xDE, 0x55, +0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x35, 0x9C, 0x8F, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x33, 0xB5, 0x33, +0xAD, 0x12, 0xB5, 0x52, 0xBD, 0x73, 0xC5, 0x93, +0xBD, 0x53, 0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x53, 0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x93, 0xBD, 0x53, 0xB5, 0x32, 0xBD, 0x73, +0xBD, 0x94, 0xC5, 0xB4, 0xCD, 0xD5, 0xBD, 0x73, +0xB5, 0x31, 0xAC, 0xF1, 0xAC, 0xF0, 0xB5, 0x31, +0xB5, 0x52, 0xA4, 0x90, 0x7B, 0x6C, 0x31, 0x65, +0x42, 0x07, 0x31, 0x85, 0x29, 0x44, 0x29, 0x45, +0x4A, 0x49, 0x4A, 0x8A, 0x3A, 0x08, 0x52, 0xAA, +0x94, 0x72, 0x9C, 0x92, 0x94, 0x92, 0x8C, 0x51, +0x52, 0x49, 0x52, 0x49, 0x5A, 0x8A, 0x52, 0x28, +0x52, 0x28, 0x8B, 0xEF, 0x62, 0xCB, 0x83, 0xCE, +0x7B, 0x8E, 0x62, 0xAB, 0x7B, 0x6D, 0x94, 0x30, +0x8C, 0x30, 0x83, 0xAE, 0x39, 0x87, 0x18, 0xC4, +0x18, 0xE4, 0x19, 0x04, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x21, 0x24, 0x94, 0x70, +0xD6, 0x56, 0xCD, 0xF4, 0xAC, 0xD0, 0xC5, 0x93, +0xD6, 0x14, 0xD6, 0x14, 0xE6, 0x76, 0xDE, 0x76, +0xDE, 0x75, 0xDE, 0x35, 0xCD, 0xD3, 0xCD, 0xB4, +0xC5, 0x93, 0xBD, 0x72, 0xC5, 0x93, 0xC5, 0xD3, +0xA4, 0xAF, 0xD6, 0x35, 0xCD, 0xF5, 0xAD, 0x12, +0x7B, 0xAD, 0x31, 0x86, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xC4, 0x18, 0xC4, +0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x08, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA4, +0x18, 0xE4, 0x19, 0x05, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x29, 0x67, 0x39, 0xC8, 0x31, 0xC8, 0x39, 0xE9, +0x31, 0xA8, 0x4A, 0x6B, 0x4A, 0x4A, 0x4A, 0x29, +0x7B, 0xAD, 0xB5, 0x32, 0xBD, 0x73, 0xAD, 0x32, +0xA4, 0xF1, 0xAD, 0x11, 0xB5, 0x12, 0xD6, 0x35, +0xDE, 0x76, 0xE6, 0x96, 0xDE, 0x96, 0xBD, 0x72, +0xBD, 0x72, 0xE6, 0xB7, 0xDE, 0x76, 0xD6, 0x56, +0xBD, 0x93, 0xB5, 0x52, 0xBD, 0x52, 0xD6, 0x35, +0xD6, 0x34, 0xDE, 0x54, 0xDE, 0x55, 0xDE, 0x76, +0x7B, 0xAD, 0xAD, 0x32, 0x9C, 0xB1, 0x8C, 0x2E, +0x7B, 0xCC, 0x7C, 0x0D, 0x7B, 0xEC, 0x73, 0xAB, +0x6B, 0x6B, 0x7B, 0xCD, 0x8C, 0x4E, 0x8C, 0x2D, +0x9C, 0xAF, 0xA4, 0xEF, 0xA4, 0xEF, 0x9C, 0xAF, +0xA4, 0xAF, 0xA4, 0xCF, 0xA4, 0xCF, 0xAC, 0xF0, +0xA4, 0xCF, 0xA4, 0xAF, 0xAC, 0xF0, 0xB5, 0x31, +0xBD, 0x31, 0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xCF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xAD, 0x10, 0xB5, 0x31, 0xAC, 0xF0, +0xAC, 0xCF, 0xA4, 0xCF, 0x9C, 0x8E, 0xAC, 0xF0, +0xAD, 0x11, 0xA4, 0xAF, 0x9C, 0xAF, 0x9C, 0xAF, +0xBD, 0x93, 0xBD, 0x72, 0xCE, 0x15, 0xB5, 0x10, +0xB5, 0x10, 0xB4, 0xEF, 0x73, 0x29, 0x7B, 0x6B, +0xC5, 0xD4, 0xCE, 0x16, 0x94, 0x4F, 0x8B, 0xEF, +0x8B, 0xEF, 0x73, 0x6D, 0x8C, 0x10, 0xAD, 0x14, +0x94, 0x72, 0x73, 0x8E, 0x39, 0xE7, 0x31, 0xA6, +0x4A, 0x49, 0x5A, 0xEC, 0x63, 0x0C, 0x52, 0x8A, +0x39, 0xE8, 0x52, 0x8A, 0x5A, 0xCB, 0x5A, 0xCB, +0x29, 0x66, 0x08, 0x62, 0x08, 0x82, 0x10, 0xA3, +0x10, 0xA3, 0x39, 0xE7, 0xC6, 0x37, 0xBD, 0xB4, +0xB5, 0x73, 0xCE, 0x56, 0xD6, 0x56, 0xD6, 0x56, +0xD6, 0x56, 0xCE, 0x36, 0xAD, 0x32, 0xBD, 0xB5, +0xBD, 0x94, 0xAD, 0x52, 0xA5, 0x11, 0xBD, 0xB4, +0xCE, 0x36, 0xB5, 0xB4, 0xAD, 0x52, 0x9C, 0x8E, +0xBD, 0x71, 0x7B, 0x8A, 0xCD, 0xF3, 0x9C, 0x6E, +0x84, 0x0D, 0x8C, 0x4F, 0x83, 0xEE, 0x9C, 0xD1, +0x9C, 0xB0, 0xA5, 0x12, 0xB5, 0x95, 0xAD, 0x34, +0xA5, 0x14, 0xBD, 0x96, 0xB5, 0x76, 0x9C, 0x92, +0xA4, 0xF3, 0x73, 0x6D, 0x31, 0x65, 0x4A, 0x28, +0x5A, 0x8A, 0x62, 0xCB, 0x5A, 0x8A, 0x42, 0x08, +0x5A, 0xCB, 0x73, 0x6E, 0x5A, 0x8A, 0x4A, 0x49, +0x5A, 0xAA, 0x73, 0x6D, 0x94, 0x71, 0x73, 0x6D, +0x73, 0x6D, 0x7B, 0xAE, 0x42, 0x07, 0x5A, 0xAA, +0x41, 0xE7, 0x21, 0x03, 0x29, 0x44, 0x41, 0xE7, +0x21, 0x24, 0x73, 0x6D, 0x73, 0x4D, 0x4A, 0x49, +0x63, 0x0C, 0x5A, 0xCB, 0x63, 0x0B, 0x7B, 0xAD, +0x83, 0xEE, 0x7B, 0xCD, 0x73, 0x6B, 0x63, 0x0A, +0x6B, 0x4B, 0x7B, 0xCD, 0x8C, 0x2E, 0xBD, 0xD4, +0xC5, 0xF5, 0xAD, 0x12, 0xCE, 0x36, 0xB5, 0x73, +0xD6, 0x36, 0xB5, 0x53, 0x9C, 0x6F, 0xAD, 0x12, +0xD6, 0x36, 0xE6, 0xB6, 0xE6, 0xB7, 0xDE, 0x76, +0xDE, 0x56, 0xD6, 0x55, 0xD6, 0x56, 0xDE, 0x76, +0xD6, 0x35, 0xCD, 0xF4, 0xBD, 0x73, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x32, 0xAC, 0xF0, 0x9C, 0x6F, +0x8C, 0x0D, 0xAD, 0x11, 0xB5, 0x11, 0xAD, 0x11, +0xBD, 0x73, 0xBD, 0x73, 0xAD, 0x11, 0xB5, 0x32, +0xB5, 0x32, 0x52, 0x48, 0x39, 0x86, 0x52, 0x68, +0xAD, 0x32, 0x73, 0x6C, 0x31, 0x85, 0x29, 0x44, +0x29, 0x45, 0x31, 0xA6, 0x31, 0x85, 0x31, 0xA6, +0x42, 0x07, 0x4A, 0x29, 0x7B, 0xAF, 0xB5, 0x96, +0x9C, 0xB2, 0x7B, 0xAE, 0x6B, 0x0C, 0x62, 0xAB, +0x49, 0xE7, 0x7B, 0x6E, 0x7B, 0xAE, 0x8C, 0x30, +0x6B, 0x0C, 0x7B, 0xAE, 0x9C, 0x71, 0x9C, 0x70, +0x8B, 0xEF, 0x94, 0x10, 0x73, 0x4D, 0x31, 0x66, +0x18, 0xA3, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x4A, 0x49, 0x8C, 0x0F, +0xBD, 0x93, 0xB5, 0x11, 0xB5, 0x11, 0xCD, 0xF4, +0xE6, 0x96, 0xE6, 0x76, 0xDE, 0x76, 0xE6, 0x96, +0xE6, 0x96, 0xB5, 0x11, 0xA4, 0x6F, 0x8B, 0xED, +0x8B, 0xCD, 0x94, 0x2E, 0x9C, 0x90, 0x94, 0x2E, +0x73, 0x6B, 0xBD, 0xB4, 0xE6, 0xB8, 0xDE, 0x76, +0xBD, 0x93, 0x73, 0x4C, 0x31, 0xA7, 0x18, 0xC4, +0x18, 0xE4, 0x10, 0xE4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x18, 0xE4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xC4, 0x10, 0xA3, 0x18, 0xE4, +0x18, 0xC4, 0x10, 0xC4, 0x10, 0xA4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x18, 0xE4, 0x21, 0x25, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x05, 0x21, 0x46, 0x21, 0x26, 0x19, 0x05, +0x29, 0x46, 0x31, 0xA8, 0x31, 0xA8, 0x31, 0xA8, +0x39, 0xE9, 0x3A, 0x09, 0x39, 0xE9, 0x39, 0xA8, +0x41, 0xE8, 0x73, 0x6C, 0x9C, 0x90, 0xAD, 0x32, +0x9C, 0x90, 0xA4, 0xD1, 0xAC, 0xF1, 0xC5, 0xD4, +0xCD, 0xD4, 0xD6, 0x14, 0xD6, 0x35, 0xCD, 0xD4, +0xCD, 0xD4, 0xD6, 0x35, 0xCE, 0x14, 0xCD, 0xF4, +0xCD, 0xF5, 0xD6, 0x36, 0xC5, 0x93, 0xE6, 0xB7, +0xE6, 0x95, 0xE6, 0x95, 0xE6, 0x95, 0xE6, 0xB6, +0x73, 0x8D, 0x8C, 0x0F, 0x84, 0x0E, 0x94, 0x4E, +0x94, 0x6E, 0x83, 0xED, 0x8C, 0x6E, 0x94, 0x8F, +0x8C, 0x4F, 0x84, 0x0D, 0x8C, 0x2E, 0x9C, 0xD0, +0xA4, 0xF0, 0xA4, 0xCF, 0xA4, 0xEF, 0xA4, 0xCF, +0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xCF, 0x94, 0x4D, +0xA4, 0x8E, 0x94, 0x0C, 0x8B, 0xCB, 0x94, 0x2C, +0xA4, 0x6E, 0xA4, 0x8E, 0xAC, 0xAE, 0xA4, 0x8E, +0xB4, 0xF0, 0xBD, 0x71, 0xB5, 0x30, 0xAC, 0xEF, +0xB4, 0xEF, 0xB4, 0xEF, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x30, 0xBD, 0x51, +0xB5, 0x30, 0xAC, 0xF0, 0xB5, 0x10, 0xB5, 0x10, +0xB4, 0xF0, 0xA4, 0xAF, 0xA4, 0x8E, 0xAC, 0xEF, +0xB5, 0x10, 0xBD, 0x10, 0xB5, 0x10, 0xB4, 0xF0, +0xA4, 0x8E, 0x5A, 0xA8, 0x39, 0xC6, 0x42, 0x07, +0x4A, 0x28, 0x62, 0xCB, 0x94, 0x72, 0xB5, 0x96, +0xBD, 0xF8, 0x6B, 0x4D, 0x4A, 0x69, 0x73, 0x8E, +0x73, 0x8E, 0x7B, 0xCF, 0x8C, 0x51, 0x8C, 0x71, +0x84, 0x31, 0x84, 0x10, 0x6B, 0x2D, 0x31, 0xA7, +0x08, 0x62, 0x08, 0x62, 0x08, 0x62, 0x10, 0xC3, +0x39, 0xE8, 0x6B, 0x6D, 0xD6, 0x57, 0xAD, 0x32, +0x8C, 0x0E, 0xB5, 0x73, 0xD6, 0x76, 0xCE, 0x56, +0xCE, 0x56, 0xCE, 0x36, 0xBD, 0xD4, 0xC5, 0xF5, +0xC5, 0xD5, 0xBD, 0xB4, 0xBD, 0x94, 0xBD, 0xB4, +0xC6, 0x15, 0xC5, 0xD5, 0xB5, 0x52, 0x9C, 0x6E, +0xCD, 0xD3, 0x8C, 0x0C, 0xD6, 0x35, 0xAC, 0xF0, +0x94, 0x8F, 0xA5, 0x12, 0x94, 0xB0, 0xB5, 0xB4, +0xAD, 0x52, 0xBD, 0xB4, 0xBD, 0x95, 0x8C, 0x30, +0x8C, 0x30, 0x9C, 0xB2, 0xA4, 0xF3, 0x73, 0x6D, +0x5A, 0xCB, 0x29, 0x24, 0x41, 0xE7, 0x42, 0x07, +0x4A, 0x48, 0x5A, 0xAA, 0x6B, 0x2C, 0x6B, 0x0C, +0x6B, 0x2C, 0x6B, 0x2C, 0x52, 0x69, 0x4A, 0x08, +0x5A, 0xAA, 0x52, 0x69, 0x63, 0x0B, 0x52, 0x89, +0x5A, 0xAA, 0x5A, 0xCA, 0x52, 0x89, 0x5A, 0xAA, +0x4A, 0x28, 0x39, 0xA6, 0x39, 0xC6, 0x21, 0x24, +0x21, 0x04, 0x6B, 0x4D, 0x63, 0x0B, 0x6B, 0x4C, +0x83, 0xEF, 0x84, 0x0F, 0x94, 0x70, 0x9C, 0xD1, +0xA5, 0x13, 0xAD, 0x53, 0xA5, 0x32, 0x94, 0x90, +0x94, 0x70, 0x94, 0x90, 0x8C, 0x4F, 0x94, 0x70, +0xA4, 0xF2, 0x94, 0x90, 0xA4, 0xF2, 0xB5, 0x53, +0xC5, 0xF5, 0xCE, 0x16, 0xA4, 0xD1, 0xB5, 0x32, +0xDE, 0x76, 0xDE, 0x96, 0xE6, 0x96, 0xE6, 0x96, +0xD6, 0x35, 0xDE, 0x75, 0xE6, 0xB7, 0xC5, 0xB3, +0xBD, 0x72, 0xD6, 0x35, 0xDE, 0x55, 0xD6, 0x35, +0xD6, 0x35, 0xCD, 0xF5, 0xC5, 0xD4, 0xBD, 0x93, +0xAC, 0xF1, 0xB5, 0x52, 0xAC, 0xF0, 0xA4, 0x6F, +0xCD, 0xF4, 0xDE, 0x55, 0xCD, 0xF4, 0xAC, 0xD0, +0xC5, 0xD5, 0xA4, 0xD1, 0x9C, 0xB1, 0x8C, 0x4F, +0xA5, 0x11, 0xA4, 0xD1, 0x8C, 0x2E, 0x52, 0xA9, +0x31, 0xA6, 0x31, 0x85, 0x29, 0x44, 0x29, 0x44, +0x29, 0x65, 0x39, 0xC7, 0x52, 0x8A, 0x63, 0x2C, +0x9D, 0x14, 0xCE, 0x59, 0xB5, 0x96, 0x7B, 0x8E, +0x52, 0x49, 0x83, 0xCE, 0x62, 0xCA, 0x52, 0x29, +0x41, 0xE7, 0x73, 0x6D, 0xA4, 0x91, 0x94, 0x0F, +0x83, 0x8D, 0x8C, 0x0F, 0x83, 0xCE, 0x6B, 0x0C, +0x39, 0x86, 0x21, 0x25, 0x18, 0xE4, 0x18, 0xE4, +0x21, 0x04, 0x5A, 0xAA, 0x9C, 0x91, 0x9C, 0x90, +0xA4, 0xB0, 0xAC, 0xF1, 0xB5, 0x11, 0xAC, 0xF0, +0xAC, 0xD0, 0xA4, 0xAF, 0x9C, 0x4E, 0x9C, 0x4E, +0xA4, 0x8F, 0x94, 0x0D, 0x83, 0xAD, 0x83, 0x8C, +0x7B, 0x4C, 0x6A, 0xEA, 0x5A, 0xA9, 0x5A, 0x89, +0x73, 0x2C, 0xB5, 0x32, 0xA4, 0xD0, 0x94, 0x2E, +0x83, 0xED, 0x83, 0xCD, 0x73, 0x4C, 0x39, 0xC7, +0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC3, 0x10, 0xC4, +0x18, 0xC4, 0x18, 0xE4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x21, 0x05, 0x29, 0x46, 0x29, 0x66, 0x21, 0x26, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x18, 0xE5, +0x21, 0x26, 0x29, 0x46, 0x21, 0x26, 0x21, 0x26, +0x29, 0x67, 0x29, 0x87, 0x29, 0x87, 0x29, 0x67, +0x29, 0x67, 0x29, 0x67, 0x29, 0x67, 0x31, 0xA7, +0x42, 0x09, 0x5A, 0xCB, 0x73, 0x6D, 0xA4, 0xD1, +0x94, 0x6F, 0xA4, 0xB0, 0x9C, 0xB0, 0xB5, 0x73, +0xBD, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, 0xCD, 0xD3, +0xD6, 0x14, 0xD6, 0x55, 0xD6, 0x14, 0xCD, 0xB4, +0xBD, 0x93, 0xC5, 0xD4, 0xD6, 0x15, 0xE6, 0xB7, +0xE6, 0x96, 0xE6, 0x75, 0xDE, 0x75, 0xDE, 0x75, +0x83, 0xEE, 0x83, 0xCE, 0x73, 0x6D, 0xC6, 0x17, +0xC6, 0x16, 0x84, 0x0D, 0x6B, 0x6A, 0x94, 0x8F, +0x9C, 0xD1, 0xA4, 0xF2, 0x8C, 0x4E, 0x94, 0x6F, +0x8C, 0x4E, 0x94, 0x6F, 0xA4, 0xF0, 0x94, 0x4D, +0x9C, 0x4D, 0xA4, 0xAE, 0xAC, 0xEF, 0x9C, 0x8F, +0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x4E, 0x9C, 0x4E, 0x94, 0x4E, 0x94, 0x0D, +0x8B, 0xEC, 0x94, 0x0D, 0x83, 0xAB, 0x8B, 0xEC, +0x83, 0xCB, 0x83, 0xCB, 0x83, 0xAB, 0x7B, 0x4A, +0x73, 0x4A, 0x83, 0x8B, 0xA4, 0x6E, 0xA4, 0xAE, +0xB4, 0xEF, 0xAC, 0xAE, 0xA4, 0x8E, 0xC5, 0xB3, +0xB5, 0x31, 0x9C, 0x6E, 0xB5, 0x10, 0xB5, 0x10, +0xAC, 0xCF, 0xAC, 0xAE, 0xA4, 0x6E, 0x9C, 0x2C, +0xA4, 0xAE, 0x83, 0xCC, 0x39, 0xA5, 0x52, 0x89, +0x39, 0xC6, 0x6B, 0x4D, 0x8C, 0x71, 0x9C, 0xF4, +0xB5, 0x76, 0x5A, 0xCB, 0x73, 0x8E, 0x84, 0x30, +0x84, 0x10, 0x8C, 0x51, 0x94, 0xB2, 0x94, 0xB2, +0x94, 0xB3, 0xB5, 0x76, 0xA5, 0x14, 0x6B, 0x6E, +0x52, 0x8A, 0x42, 0x08, 0x3A, 0x08, 0x4A, 0x8A, +0x41, 0xE8, 0x8C, 0x70, 0xB5, 0x73, 0xB5, 0x52, +0xA4, 0xD1, 0xA4, 0xF1, 0xAD, 0x32, 0xA5, 0x11, +0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, 0xBD, 0xB4, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xD4, 0xBD, 0xB4, +0xBD, 0xD4, 0xBD, 0xD5, 0xB5, 0x52, 0xA4, 0xAF, +0xCD, 0xF3, 0xB5, 0x10, 0xCD, 0xF3, 0xB5, 0x11, +0xB5, 0x32, 0xB5, 0x93, 0xB5, 0x94, 0xBD, 0xB4, +0x9C, 0xB0, 0x9C, 0xD1, 0xA4, 0xF2, 0x6B, 0x4C, +0x73, 0x8E, 0x8C, 0x30, 0x8C, 0x10, 0x6B, 0x0C, +0x52, 0x49, 0x52, 0x69, 0x31, 0x65, 0x41, 0xE7, +0x4A, 0x28, 0x52, 0x69, 0x5A, 0xAA, 0x6B, 0x0C, +0x6B, 0x0C, 0x6B, 0x0C, 0x52, 0x69, 0x41, 0xC7, +0x62, 0xCB, 0x39, 0xA6, 0x39, 0xC6, 0x4A, 0x28, +0x42, 0x28, 0x4A, 0x28, 0x4A, 0x48, 0x52, 0x89, +0x41, 0xE7, 0x29, 0x24, 0x39, 0xA6, 0x4A, 0x28, +0x5A, 0xAA, 0x7B, 0xCE, 0x84, 0x0F, 0x7B, 0xCE, +0x83, 0xEF, 0x7B, 0xEE, 0x84, 0x0F, 0x8C, 0x4F, +0x8C, 0x4F, 0x94, 0x90, 0x9C, 0xD1, 0xB5, 0x73, +0xA5, 0x12, 0x8C, 0x4F, 0x9C, 0xD1, 0x8C, 0x4F, +0xA5, 0x12, 0xBD, 0xD5, 0xBD, 0xB5, 0xB5, 0x53, +0xC5, 0xF5, 0xCE, 0x15, 0xAD, 0x11, 0xB5, 0x32, +0xDE, 0x96, 0xD6, 0x34, 0xD6, 0x34, 0xDE, 0x75, +0xDE, 0x75, 0xE6, 0x96, 0xDE, 0x55, 0xC5, 0x92, +0xD6, 0x14, 0xCD, 0xF4, 0xE6, 0x96, 0xE6, 0x96, +0xE6, 0xB6, 0xE6, 0x96, 0xE6, 0xB6, 0xE6, 0x96, +0xE6, 0x96, 0xCD, 0xD3, 0xBD, 0x51, 0xCD, 0xF4, +0xE6, 0xD7, 0xE6, 0x96, 0xB5, 0x31, 0xAD, 0x11, +0xAD, 0x32, 0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x52, +0x94, 0x8F, 0xBD, 0x94, 0xBD, 0xB4, 0xAD, 0x12, +0x8C, 0x4F, 0x42, 0x07, 0x31, 0x85, 0x29, 0x65, +0x29, 0x44, 0x29, 0x44, 0x31, 0x65, 0x39, 0xC6, +0x52, 0xCA, 0x7B, 0xCE, 0x9C, 0xD3, 0x6B, 0x4C, +0x5A, 0xAA, 0x73, 0x6D, 0x42, 0x28, 0x4A, 0x28, +0x62, 0xCA, 0x62, 0xAA, 0x73, 0x0B, 0x7B, 0x2C, +0x8B, 0xEF, 0x83, 0xAE, 0x6A, 0xAA, 0x7B, 0x6C, +0x73, 0x0C, 0x6B, 0x0C, 0x6B, 0x0B, 0x7B, 0x6D, +0x7B, 0xAE, 0x7B, 0x8D, 0x8C, 0x0E, 0xAD, 0x32, +0xBD, 0x73, 0xBD, 0x52, 0xBD, 0x72, 0xB5, 0x31, +0xAC, 0xD0, 0xA4, 0x8F, 0xA4, 0xB0, 0xAC, 0xF1, +0xB5, 0x11, 0xB5, 0x11, 0xAC, 0xF1, 0xA4, 0x90, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x6F, 0x94, 0x4F, +0x94, 0x4F, 0x9C, 0x70, 0x9C, 0x6F, 0x94, 0x2E, +0x94, 0x4F, 0x94, 0x4F, 0x8C, 0x0E, 0x6B, 0x4C, +0x31, 0x86, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x08, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x21, 0x05, 0x29, 0x66, 0x31, 0xA7, 0x29, 0x67, +0x21, 0x26, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x46, +0x29, 0x46, 0x29, 0x67, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x29, 0x67, 0x31, 0xA8, +0x42, 0x4A, 0x5A, 0xEC, 0x5A, 0xCB, 0x73, 0xAD, +0x9C, 0x90, 0x9C, 0xB0, 0x94, 0x6F, 0xB5, 0x53, +0xB5, 0x72, 0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0x92, 0xD6, 0x55, 0xCD, 0xF4, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x73, 0xCE, 0x15, 0xE6, 0xD7, +0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x34, +0x6B, 0x6C, 0x7B, 0xCE, 0x7B, 0xEF, 0xDE, 0xFB, +0xDE, 0x99, 0xAD, 0x2F, 0x94, 0x6C, 0xAD, 0x31, +0xC5, 0xF5, 0xCE, 0x37, 0xAD, 0x12, 0xAD, 0x32, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0xB5, 0x30, +0xAC, 0xEF, 0xAC, 0xCE, 0xBD, 0x92, 0xE6, 0x97, +0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x32, +0xB5, 0x52, 0xB5, 0x32, 0xAD, 0x11, 0xAD, 0x11, +0x9C, 0xB0, 0x9C, 0x8F, 0xAD, 0x11, 0xB5, 0x52, +0xAD, 0x11, 0xAD, 0x32, 0xC5, 0xB3, 0xBD, 0x93, +0xBD, 0x72, 0xAC, 0xCF, 0xB5, 0x51, 0xC5, 0xF4, +0xBD, 0xB3, 0xAD, 0x32, 0xA4, 0xD0, 0x8C, 0x0D, +0x9C, 0x8E, 0x94, 0x4D, 0x94, 0x4D, 0x8C, 0x2C, +0x9C, 0xAF, 0x8C, 0x2D, 0x52, 0x68, 0x6B, 0x4C, +0x52, 0x69, 0x52, 0x8A, 0x6B, 0x4D, 0x7C, 0x10, +0x9C, 0xD3, 0x5A, 0xEB, 0x94, 0x92, 0x73, 0x8E, +0x94, 0x92, 0x9C, 0xD3, 0x94, 0xB3, 0xA5, 0x14, +0xA5, 0x35, 0x9C, 0xD3, 0x39, 0xC7, 0xA5, 0x14, +0x9C, 0xB3, 0x4A, 0x49, 0x63, 0x2C, 0x5A, 0xCB, +0x8C, 0x2F, 0xB5, 0x72, 0xB5, 0x51, 0xBD, 0x71, +0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x31, 0xB5, 0x30, +0xB5, 0x30, 0xAC, 0xEF, 0xAC, 0xCF, 0x9C, 0x8E, +0x9C, 0x6E, 0x9C, 0x8E, 0xAD, 0x11, 0xAD, 0x31, +0xB5, 0x52, 0xAC, 0xF0, 0x94, 0x4D, 0xB5, 0x10, +0xBD, 0x71, 0xBD, 0x51, 0xC5, 0x71, 0xC5, 0x92, +0xBD, 0x72, 0x94, 0x6F, 0xA5, 0x11, 0xAD, 0x11, +0x8C, 0x2D, 0x8C, 0x2E, 0x9C, 0xB1, 0x6B, 0x0B, +0x4A, 0x28, 0x5A, 0x8A, 0x52, 0x49, 0x52, 0x49, +0x4A, 0x48, 0x4A, 0x28, 0x29, 0x44, 0x41, 0xE7, +0x4A, 0x28, 0x42, 0x07, 0x4A, 0x08, 0x52, 0x8A, +0x5A, 0xAA, 0x52, 0x69, 0x4A, 0x08, 0x39, 0xC6, +0x39, 0xC6, 0x31, 0x86, 0x41, 0xE7, 0x41, 0xE7, +0x5A, 0xAA, 0x62, 0xEB, 0x5A, 0xCA, 0x63, 0x0B, +0x52, 0x8A, 0x4A, 0x48, 0x62, 0xEB, 0x84, 0x0F, +0x83, 0xEF, 0x9C, 0xB2, 0xBD, 0xD6, 0x9C, 0xB2, +0x8C, 0x50, 0x7B, 0xEE, 0x8C, 0x2F, 0x9C, 0xB1, +0x94, 0x4F, 0x9C, 0xB1, 0xA5, 0x12, 0x9C, 0xD1, +0x94, 0x70, 0x7B, 0xAD, 0x8C, 0x4F, 0x6B, 0x6C, +0x8C, 0x50, 0x8C, 0x4F, 0x94, 0x90, 0x9C, 0xB1, +0x94, 0x6F, 0xB5, 0x32, 0xAD, 0x11, 0xAD, 0x11, +0xC5, 0xD4, 0xE6, 0xB6, 0xE6, 0xB6, 0xE6, 0xB6, +0xDE, 0x95, 0xDE, 0x95, 0xD6, 0x14, 0xB5, 0x30, +0xB5, 0x31, 0xC5, 0x92, 0xDE, 0x76, 0xE6, 0x96, +0xE6, 0xB6, 0xE6, 0x95, 0xE6, 0xB6, 0xE6, 0xB6, +0xE6, 0x75, 0xCD, 0xB2, 0xE6, 0x75, 0xE6, 0x96, +0xE6, 0xB6, 0xDE, 0x55, 0xCD, 0xF4, 0xB5, 0x32, +0xAD, 0x11, 0xB5, 0x93, 0xC5, 0xD4, 0xBD, 0x93, +0xBD, 0xD5, 0x9C, 0xB1, 0xBD, 0xD5, 0xBD, 0xD5, +0xC5, 0xF5, 0xAD, 0x32, 0x63, 0x2B, 0x31, 0x85, +0x21, 0x24, 0x29, 0x44, 0x31, 0xA5, 0x29, 0x44, +0x21, 0x24, 0x29, 0x65, 0x31, 0xA6, 0x31, 0x85, +0x29, 0x44, 0x31, 0x85, 0x29, 0x65, 0x4A, 0x48, +0x5A, 0xAA, 0x73, 0x2B, 0x83, 0x8D, 0x73, 0x0C, +0x8B, 0xEF, 0x8B, 0xAE, 0x83, 0x8D, 0x93, 0xEF, +0x72, 0xEB, 0x73, 0x2C, 0x9C, 0x30, 0x83, 0x8E, +0x83, 0xCE, 0xA4, 0xD2, 0x6B, 0x0B, 0x73, 0x6C, +0x9C, 0x90, 0xB5, 0x52, 0xB5, 0x72, 0xAD, 0x11, +0x8B, 0xEC, 0x94, 0x2E, 0x9C, 0x6E, 0x9C, 0x8F, +0xA4, 0xD0, 0xAC, 0xD0, 0xBD, 0x73, 0xD6, 0x15, +0xB5, 0x11, 0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x72, +0xAC, 0xF0, 0xAD, 0x11, 0xB5, 0x11, 0xAC, 0xF1, +0xC5, 0xB4, 0xB5, 0x32, 0xAD, 0x11, 0x7B, 0xAC, +0x29, 0x86, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xC4, 0x18, 0xC4, 0x18, 0xE4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0x83, +0x08, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xC4, +0x21, 0x05, 0x29, 0x66, 0x39, 0xE8, 0x39, 0xC7, +0x29, 0x67, 0x21, 0x05, 0x18, 0xE5, 0x19, 0x05, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x21, 0x26, +0x21, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x29, 0x46, 0x29, 0x87, 0x31, 0xC8, +0x42, 0x2A, 0x42, 0x29, 0x39, 0xA8, 0x4A, 0x29, +0x94, 0x70, 0xA4, 0xD1, 0x9C, 0xB0, 0xAD, 0x32, +0xB5, 0x32, 0xB5, 0x52, 0xAD, 0x12, 0xAD, 0x12, +0xAC, 0xF1, 0xC5, 0x93, 0xBD, 0x93, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF1, 0xBD, 0x93, 0xCE, 0x15, +0xC5, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, 0xC5, 0xD3, +0x63, 0x2B, 0x7B, 0xCE, 0x9C, 0xB2, 0xD6, 0x9A, +0xB5, 0x74, 0xB5, 0x31, 0xBD, 0xB2, 0xBD, 0xD3, +0xCE, 0x36, 0xB5, 0x74, 0xB5, 0x74, 0xC5, 0xF5, +0xAD, 0x52, 0xA5, 0x11, 0xA4, 0xF1, 0xAC, 0xF0, +0xC5, 0x71, 0xAC, 0xAE, 0xB5, 0x31, 0xDE, 0x76, +0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x15, +0xCD, 0xF5, 0xCD, 0xF5, 0xCD, 0xF5, 0xCE, 0x15, +0xCE, 0x15, 0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0xB4, 0xC5, 0xF4, +0xCE, 0x35, 0xC5, 0xF4, 0xC5, 0xD4, 0xDE, 0x97, +0xDE, 0x55, 0xAC, 0xAE, 0xAC, 0xF0, 0xBD, 0xD3, +0xC6, 0x14, 0xB5, 0x52, 0x9C, 0xAF, 0x8C, 0x2E, +0xA4, 0xD0, 0xAD, 0x31, 0xAD, 0x31, 0xAD, 0x31, +0xAD, 0x31, 0xA5, 0x11, 0x73, 0x6C, 0x5A, 0xAA, +0x52, 0x69, 0x4A, 0x69, 0x5A, 0xCB, 0x6B, 0x4D, +0x7B, 0xCF, 0x7B, 0xF0, 0x84, 0x10, 0x6B, 0x6E, +0xA5, 0x35, 0xA5, 0x35, 0x8C, 0x51, 0x9C, 0xD4, +0xA4, 0xF4, 0x5A, 0xAB, 0x73, 0xAF, 0xAD, 0x75, +0x83, 0xEF, 0x29, 0x45, 0x4A, 0x6A, 0x6B, 0x4C, +0x83, 0xCE, 0x94, 0x2E, 0x83, 0xCB, 0xB5, 0x51, +0xAD, 0x10, 0x83, 0xAB, 0x83, 0xAB, 0x8B, 0xEB, +0x8B, 0xEC, 0x94, 0x0C, 0xAC, 0xF0, 0xD6, 0x14, +0xBD, 0x51, 0xB5, 0x30, 0xAC, 0xAE, 0xA4, 0x8E, +0xA4, 0x8E, 0x9C, 0x6E, 0xB4, 0xF0, 0xCD, 0xD2, +0xCD, 0xB2, 0xC5, 0x91, 0xC5, 0x91, 0xC5, 0x71, +0xBD, 0x71, 0xBD, 0x30, 0xBD, 0x51, 0xBD, 0x51, +0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x52, 0x6A, 0xEB, +0x29, 0x04, 0x31, 0x65, 0x31, 0x85, 0x31, 0x85, +0x39, 0xA6, 0x29, 0x44, 0x29, 0x24, 0x41, 0xE7, +0x4A, 0x28, 0x52, 0x69, 0x31, 0x65, 0x4A, 0x48, +0x5A, 0xAA, 0x41, 0xE7, 0x52, 0x69, 0x4A, 0x28, +0x41, 0xE7, 0x39, 0xC7, 0x31, 0x65, 0x31, 0x65, +0x4A, 0x48, 0x62, 0xCA, 0x39, 0xA6, 0x63, 0x0B, +0x6B, 0x4C, 0x73, 0x8D, 0x83, 0xCE, 0x7B, 0xCE, +0x8C, 0x10, 0xA5, 0x34, 0xC6, 0x38, 0xBD, 0xB6, +0xAD, 0x33, 0x84, 0x2F, 0x8C, 0x2F, 0x9C, 0xB1, +0xB5, 0x33, 0xB5, 0x53, 0xB5, 0x73, 0xB5, 0x52, +0xA4, 0xD1, 0x8C, 0x2F, 0x73, 0xAD, 0x6B, 0x4C, +0x84, 0x0F, 0x7B, 0xEE, 0x84, 0x2F, 0x94, 0x90, +0x94, 0x90, 0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x12, +0xD6, 0x15, 0xDE, 0x55, 0xDE, 0x54, 0xDE, 0x75, +0xCD, 0xD3, 0xCD, 0xB2, 0xC5, 0x92, 0xAC, 0xF0, +0xA4, 0xCF, 0xC5, 0xB3, 0xDE, 0x95, 0xE6, 0x96, +0xE6, 0x96, 0xDE, 0x95, 0xDE, 0x34, 0xD6, 0x14, +0xE6, 0x96, 0xC5, 0x71, 0xC5, 0x91, 0xDE, 0x34, +0xDE, 0x54, 0xD6, 0x34, 0xBD, 0x72, 0xB5, 0x53, +0xB5, 0x73, 0xC6, 0x15, 0xBD, 0xD4, 0xBD, 0xD4, +0xC5, 0xF5, 0xB5, 0x53, 0xBD, 0xD5, 0xAD, 0x53, +0xBD, 0xB4, 0xBD, 0xD4, 0xAD, 0x32, 0x94, 0x90, +0x6B, 0x2C, 0x31, 0x85, 0x29, 0x44, 0x21, 0x44, +0x21, 0x03, 0x21, 0x03, 0x21, 0x24, 0x29, 0x44, +0x21, 0x44, 0x29, 0x65, 0x31, 0x65, 0x52, 0x49, +0x62, 0xAA, 0x7B, 0x8D, 0x7B, 0x8D, 0x73, 0x2C, +0x73, 0x2C, 0x7B, 0x6D, 0x83, 0x8D, 0x94, 0x0F, +0x83, 0x8D, 0x83, 0x8D, 0x94, 0x0F, 0x83, 0xAE, +0x94, 0x50, 0xA4, 0xB2, 0x9C, 0x71, 0x94, 0x0F, +0x6B, 0x2B, 0x73, 0x4B, 0x9C, 0x90, 0xBD, 0x93, +0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x52, 0xCD, 0xD4, 0xD6, 0x56, +0xB5, 0x11, 0xAC, 0xF0, 0xA4, 0xD0, 0x8C, 0x0D, +0xAC, 0xF1, 0xC5, 0x93, 0xB5, 0x12, 0x83, 0xED, +0x9C, 0x70, 0x8C, 0x0E, 0x7B, 0xAC, 0x42, 0x07, +0x18, 0xE3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, 0x10, 0xC4, +0x10, 0xC4, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xE4, +0x19, 0x05, 0x29, 0x66, 0x42, 0x29, 0x52, 0x8A, +0x41, 0xE8, 0x29, 0x46, 0x21, 0x25, 0x19, 0x05, +0x21, 0x26, 0x21, 0x26, 0x21, 0x46, 0x21, 0x26, +0x21, 0x46, 0x21, 0x46, 0x21, 0x26, 0x21, 0x26, +0x21, 0x46, 0x29, 0x67, 0x29, 0x87, 0x31, 0xA8, +0x31, 0xA7, 0x29, 0x66, 0x29, 0x46, 0x39, 0xC8, +0x73, 0x4D, 0x94, 0x4F, 0x83, 0xEE, 0x7B, 0xAD, +0x83, 0xCD, 0x83, 0xED, 0x7B, 0xAD, 0x7B, 0xAD, +0x8B, 0xEE, 0x94, 0x4F, 0x94, 0x2F, 0x94, 0x4F, +0x94, 0x6F, 0x9C, 0x90, 0xB5, 0x32, 0xAD, 0x12, +0xAC, 0xF1, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x73, +0x52, 0xAA, 0x6B, 0x4C, 0x8C, 0x50, 0xAD, 0x35, +0x73, 0x8E, 0x9C, 0x91, 0xC5, 0xF6, 0xBD, 0x94, +0xC5, 0xD5, 0xB5, 0x54, 0x62, 0xEB, 0x73, 0x8C, +0xA5, 0x32, 0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xAF, +0xBD, 0x51, 0xAC, 0xAE, 0xA4, 0x8E, 0xD6, 0x36, +0xD6, 0x15, 0xD6, 0x35, 0xCE, 0x15, 0xCE, 0x15, +0xD6, 0x35, 0xD6, 0x35, 0xCE, 0x15, 0xCE, 0x15, +0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x36, 0xD6, 0x77, +0xCE, 0x15, 0xC5, 0xF4, 0xC5, 0xD4, 0xC5, 0xF4, +0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xB3, 0xD6, 0x35, +0xD6, 0x35, 0xAC, 0xAE, 0x94, 0x2D, 0xA4, 0xF0, +0xA4, 0xF0, 0xAD, 0x11, 0x9C, 0xB0, 0xA5, 0x11, +0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, +0xC5, 0xD4, 0xBD, 0xB3, 0xAD, 0x11, 0x52, 0x89, +0x52, 0x69, 0x4A, 0x28, 0x52, 0xCA, 0x5B, 0x0B, +0x4A, 0x49, 0x7B, 0xEF, 0x63, 0x0C, 0x73, 0xAF, +0xAD, 0x75, 0xA5, 0x14, 0x94, 0xB3, 0x8C, 0x72, +0x84, 0x10, 0x8C, 0x72, 0xA5, 0x35, 0x84, 0x10, +0x52, 0x8A, 0x31, 0xA7, 0x6B, 0x4D, 0xAD, 0x33, +0xAD, 0x33, 0x94, 0x6F, 0x7B, 0xAD, 0x62, 0xEA, +0x83, 0xCD, 0x8C, 0x2E, 0x6B, 0x4A, 0x83, 0xED, +0x8C, 0x0E, 0x84, 0x0D, 0x83, 0xCD, 0xB5, 0x31, +0xBD, 0x50, 0xAC, 0xEF, 0xCD, 0xD2, 0xD5, 0xF3, +0xD6, 0x13, 0xCD, 0xB2, 0xC5, 0x92, 0xCD, 0xB2, +0xCD, 0xB2, 0xD5, 0xB2, 0xCD, 0xB2, 0xC5, 0x70, +0xC5, 0x70, 0xC5, 0x71, 0xCD, 0xB2, 0xD5, 0xD2, +0xCD, 0xB2, 0xC5, 0x71, 0xCD, 0xF4, 0x83, 0xCD, +0x31, 0x65, 0x31, 0x44, 0x29, 0x44, 0x29, 0x24, +0x29, 0x24, 0x29, 0x23, 0x21, 0x03, 0x29, 0x44, +0x39, 0xA6, 0x42, 0x07, 0x29, 0x44, 0x31, 0x85, +0x4A, 0x48, 0x4A, 0x48, 0x52, 0x69, 0x41, 0xE7, +0x39, 0xE6, 0x31, 0x65, 0x29, 0x44, 0x39, 0xC6, +0x42, 0x27, 0x62, 0xEA, 0x5A, 0xAA, 0x63, 0x0B, +0x62, 0xEB, 0x6B, 0x2C, 0x6B, 0x4C, 0x73, 0x4C, +0x84, 0x30, 0xC6, 0x18, 0xCE, 0x79, 0xCE, 0x79, +0x9C, 0xB1, 0x8C, 0x0E, 0x94, 0x4F, 0x83, 0xED, +0x8C, 0x2E, 0x83, 0xED, 0x94, 0x2E, 0x9C, 0x8F, +0x8C, 0x2E, 0x94, 0x6F, 0x7B, 0x8D, 0x73, 0xAD, +0x7B, 0xCE, 0x8C, 0x4F, 0x7B, 0xCE, 0x7B, 0xCD, +0x8C, 0x0E, 0x94, 0x6F, 0xB5, 0x52, 0xBD, 0x72, +0xEE, 0xD7, 0xE6, 0x75, 0xDE, 0x55, 0xE6, 0xB6, +0xE6, 0x96, 0xD6, 0x14, 0xC5, 0x92, 0xB5, 0x10, +0xC5, 0xB3, 0xDE, 0x55, 0xE6, 0xB6, 0xEE, 0xB6, +0xEE, 0xD6, 0xE6, 0x95, 0xD6, 0x13, 0xD5, 0xF3, +0xBD, 0x50, 0xCD, 0xD2, 0xCD, 0xB2, 0xD6, 0x13, +0xD6, 0x13, 0xD5, 0xD3, 0xAC, 0xF0, 0xB5, 0x72, +0xBD, 0xB4, 0xC5, 0xD4, 0xCE, 0x36, 0xBD, 0xB4, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x53, 0xAD, 0x32, +0xB5, 0x73, 0xC5, 0xD4, 0xC5, 0xF5, 0xAD, 0x12, +0xB5, 0x32, 0x9C, 0x70, 0x52, 0x68, 0x29, 0x44, +0x21, 0x03, 0x21, 0x24, 0x29, 0x65, 0x31, 0x85, +0x29, 0x64, 0x29, 0x65, 0x62, 0xEB, 0x62, 0xEA, +0x5A, 0x89, 0x73, 0x2C, 0x73, 0x2C, 0x62, 0xCA, +0x62, 0xCA, 0x5A, 0x8A, 0x6A, 0xCA, 0x83, 0x8D, +0x8B, 0xCE, 0x8B, 0xCE, 0x9C, 0x50, 0x8B, 0xEF, +0x7B, 0x6D, 0x83, 0xAE, 0xB4, 0xF3, 0xB5, 0x13, +0xAC, 0xF2, 0x62, 0xAA, 0x62, 0xCA, 0x7B, 0x6D, +0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x31, 0xCE, 0x15, 0xDE, 0x56, 0xD6, 0x56, +0xCD, 0xF5, 0xCE, 0x15, 0xCD, 0xF5, 0xBD, 0x93, +0xC5, 0xD4, 0xC5, 0xB4, 0xC5, 0x94, 0xBD, 0xB4, +0x9C, 0x90, 0x62, 0xA9, 0x31, 0x65, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xC3, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xE4, +0x21, 0x05, 0x31, 0x87, 0x73, 0x4D, 0x8C, 0x30, +0x62, 0xEB, 0x42, 0x08, 0x31, 0xA7, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x29, 0x67, 0x29, 0x46, 0x29, 0x67, 0x29, 0x67, +0x21, 0x26, 0x21, 0x26, 0x29, 0x67, 0x39, 0xC8, +0x52, 0x49, 0x83, 0xEF, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0x74, 0xB5, 0x33, 0xAD, 0x33, 0xB5, 0x53, +0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x32, 0xAD, 0x12, +0xA4, 0xF2, 0xA4, 0xF2, 0xA4, 0xD1, 0xA4, 0xD1, +0x9C, 0xB1, 0x94, 0x70, 0x94, 0x4F, 0x94, 0x6F, +0x3A, 0x07, 0x42, 0x27, 0x52, 0xAA, 0x5A, 0xCA, +0x6B, 0x2D, 0x6B, 0x4D, 0xA5, 0x14, 0xAD, 0x13, +0xC5, 0xB6, 0xC5, 0xB7, 0xA4, 0xB2, 0x6B, 0x2B, +0xBD, 0xB5, 0xB5, 0x93, 0xAD, 0x31, 0x9C, 0x8E, +0xAC, 0xCF, 0xA4, 0x8E, 0x9C, 0x6E, 0xD6, 0x35, +0xD6, 0x35, 0xD6, 0x56, 0xD6, 0x56, 0xD6, 0x76, +0xD6, 0x56, 0xDE, 0x97, 0xDE, 0x76, 0xDE, 0x76, +0xDE, 0x77, 0xD6, 0x56, 0xD6, 0x36, 0xD6, 0x76, +0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x15, 0xD6, 0x36, +0xD6, 0x56, 0xD6, 0x56, 0xCE, 0x15, 0xD6, 0x56, +0xCD, 0xF3, 0xA4, 0xAE, 0x73, 0x29, 0x94, 0x4E, +0x9C, 0xAF, 0xAD, 0x31, 0xBD, 0x93, 0xBD, 0x93, +0xC5, 0xB3, 0xBD, 0xB3, 0xC5, 0xD3, 0xB5, 0x72, +0xC5, 0xD4, 0xC5, 0xF4, 0xC5, 0xB4, 0x9C, 0xB0, +0x39, 0x85, 0x29, 0x44, 0x42, 0x28, 0x52, 0xAA, +0x52, 0xAA, 0x6B, 0x4D, 0x5A, 0xEC, 0x84, 0x10, +0x94, 0x92, 0x8C, 0x51, 0xB5, 0xB7, 0x8C, 0x52, +0x7B, 0xCF, 0x94, 0xB2, 0xA5, 0x14, 0x8C, 0x51, +0x63, 0x0D, 0x5A, 0xEB, 0x5A, 0xCA, 0x6B, 0x2C, +0x6B, 0x2B, 0x7B, 0x8D, 0xAC, 0xF2, 0x94, 0x90, +0x9C, 0xB0, 0xA4, 0xF1, 0xA5, 0x12, 0xBD, 0xB4, +0xB5, 0x94, 0xBD, 0xF5, 0xBD, 0xD5, 0xC5, 0xB4, +0xAC, 0xEF, 0xB4, 0xEF, 0xD5, 0xF3, 0xDD, 0xF3, +0xD5, 0xD2, 0xC5, 0x50, 0xC5, 0x91, 0xDE, 0x54, +0xDE, 0x33, 0xDE, 0x33, 0xCD, 0xB1, 0xBD, 0x50, +0xB5, 0x10, 0xAC, 0xEF, 0xBD, 0x30, 0xCD, 0xB2, +0xC5, 0x71, 0x9C, 0x6D, 0x94, 0x4E, 0x8B, 0xED, +0x6B, 0x2A, 0x6B, 0x0A, 0x62, 0xC9, 0x62, 0xC9, +0x62, 0xC9, 0x4A, 0x27, 0x42, 0x07, 0x41, 0xE7, +0x41, 0xE7, 0x39, 0xA5, 0x29, 0x44, 0x29, 0x24, +0x29, 0x23, 0x31, 0x65, 0x42, 0x28, 0x4A, 0x28, +0x39, 0xC6, 0x31, 0x65, 0x31, 0x85, 0x29, 0x44, +0x42, 0x07, 0x4A, 0x48, 0x39, 0xA6, 0x41, 0xE7, +0x5A, 0xAA, 0x6B, 0x4C, 0x52, 0x8A, 0x84, 0x10, +0x9C, 0xF4, 0x9C, 0xF4, 0xBD, 0xD7, 0xB5, 0x75, +0xC5, 0xD6, 0xBD, 0x32, 0xBD, 0x51, 0xA4, 0xAF, +0x9C, 0x8E, 0xA4, 0x8F, 0x9C, 0x8F, 0xAC, 0xD0, +0x9C, 0x8F, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, +0xAC, 0xF1, 0xAD, 0x12, 0x9C, 0xB1, 0x9C, 0xB0, +0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x32, 0xA4, 0xD0, +0xBD, 0x72, 0xC5, 0xB3, 0xD5, 0xF4, 0xD6, 0x34, +0xD6, 0x14, 0xDE, 0x55, 0xD6, 0x35, 0xD6, 0x14, +0xD6, 0x14, 0xEE, 0xD7, 0xF6, 0xF7, 0xF6, 0xF7, +0xEE, 0xD7, 0xEE, 0xD7, 0xEE, 0x96, 0xE6, 0x75, +0xCD, 0xB2, 0xDE, 0x34, 0xDE, 0x14, 0xE6, 0x54, +0xDE, 0x54, 0xCD, 0xB2, 0xA4, 0x8E, 0xBD, 0x93, +0xC5, 0xD4, 0xAD, 0x32, 0xBD, 0xD4, 0xB5, 0xB4, +0xC6, 0x15, 0xC6, 0x15, 0xBD, 0xD5, 0xBD, 0xB4, +0xB5, 0x93, 0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x11, +0xBD, 0x52, 0xDE, 0x35, 0xE6, 0x76, 0xBD, 0x93, +0x94, 0x2F, 0x41, 0xE7, 0x29, 0x44, 0x29, 0x44, +0x21, 0x24, 0x39, 0xC6, 0x7B, 0xEE, 0x8C, 0x0F, +0x8C, 0x10, 0x4A, 0x28, 0x52, 0x49, 0x41, 0xE7, +0x73, 0x4C, 0x83, 0xCF, 0x73, 0x4C, 0x72, 0xEA, +0x83, 0x8D, 0x93, 0xCE, 0x94, 0x0F, 0x94, 0x0F, +0x6A, 0xCB, 0x62, 0xAA, 0x8B, 0xEF, 0xB5, 0x33, +0xC5, 0x95, 0x7B, 0x6D, 0x6A, 0xCB, 0x5A, 0x89, +0x83, 0xAD, 0xA4, 0xB0, 0xC5, 0xD4, 0xBD, 0xB3, +0xBD, 0x72, 0xDE, 0x76, 0xDE, 0x77, 0x94, 0x2F, +0x41, 0xE7, 0x41, 0xE7, 0x4A, 0x07, 0x52, 0x69, +0x94, 0x70, 0xA4, 0xD1, 0x7B, 0x8C, 0x52, 0x89, +0x31, 0x45, 0x18, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x08, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x19, 0x04, 0x31, 0x66, 0x5A, 0xAA, 0x9C, 0xB1, +0xA4, 0xD1, 0x73, 0x4C, 0x5A, 0xAB, 0x31, 0x87, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x26, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x29, 0x67, +0x29, 0x87, 0x21, 0x46, 0x21, 0x46, 0x21, 0x05, +0x18, 0xE5, 0x21, 0x05, 0x29, 0x67, 0x31, 0x87, +0x39, 0xC7, 0x5A, 0xAA, 0x94, 0x4F, 0xCD, 0xF5, +0xDE, 0x56, 0xCD, 0xD4, 0x9C, 0x90, 0x94, 0x6F, +0x94, 0x4F, 0x8C, 0x2F, 0x94, 0x70, 0x94, 0x6F, +0x8C, 0x2E, 0x94, 0x4F, 0x9C, 0xD1, 0xAD, 0x33, +0xAD, 0x33, 0xA4, 0xF2, 0xA4, 0xF1, 0x9C, 0xD1, +0x3A, 0x07, 0x42, 0x06, 0x42, 0x27, 0x62, 0xEB, +0x84, 0x10, 0x52, 0xAA, 0x73, 0xAF, 0xC5, 0xD7, +0x9C, 0x71, 0x9C, 0x71, 0x9C, 0x71, 0x8C, 0x0D, +0xAD, 0x32, 0xB5, 0x93, 0x83, 0xED, 0x8B, 0xEC, +0xAC, 0xCF, 0xA4, 0x6D, 0x94, 0x2D, 0x9C, 0x8F, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0xF1, +0x94, 0x4E, 0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x12, +0x9C, 0x90, 0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x11, +0x7B, 0x8C, 0x83, 0xAC, 0x8C, 0x0E, 0xAD, 0x11, +0xBD, 0x93, 0xCD, 0xF5, 0xCE, 0x15, 0xBD, 0x72, +0xC5, 0xB2, 0xAC, 0xCF, 0x8B, 0xEC, 0xA5, 0x11, +0xAD, 0x11, 0xB5, 0x93, 0xBD, 0x93, 0xCE, 0x15, +0xCE, 0x35, 0xC5, 0xF4, 0xD6, 0x55, 0xC5, 0xF4, +0xBD, 0xB3, 0xB5, 0x73, 0xBD, 0x73, 0xBD, 0x93, +0x7B, 0x8C, 0x63, 0x0B, 0x6B, 0x2B, 0x4A, 0x28, +0x52, 0x89, 0x73, 0x8E, 0x5A, 0xEC, 0x73, 0xAE, +0x7B, 0xEF, 0x8C, 0x72, 0xAD, 0x55, 0x83, 0xF0, +0x73, 0x8E, 0xB5, 0x96, 0xAD, 0x76, 0x84, 0x10, +0x84, 0x10, 0x62, 0xEC, 0x39, 0xE7, 0x6B, 0x6D, +0xAD, 0x34, 0xB5, 0x75, 0xC5, 0xF6, 0xAD, 0x33, +0xA5, 0x33, 0xC6, 0x16, 0xCE, 0x36, 0xC6, 0x16, +0xC6, 0x15, 0xCE, 0x36, 0xC5, 0xF5, 0xCE, 0x15, +0xC5, 0x72, 0xB5, 0x0F, 0xEE, 0xB6, 0xD5, 0xD2, +0xE6, 0x54, 0xE6, 0x54, 0xEE, 0x75, 0xEE, 0xD6, +0xEE, 0xD6, 0xEE, 0xB5, 0xCD, 0x91, 0xD6, 0x14, +0xCD, 0xD3, 0xBD, 0x72, 0xC5, 0x71, 0xDE, 0x14, +0xC5, 0x91, 0xAC, 0xEF, 0xC5, 0xB3, 0xA4, 0xF0, +0x83, 0xED, 0x94, 0x2E, 0xA4, 0xF0, 0xA4, 0xF0, +0x9C, 0x90, 0x73, 0x6C, 0x73, 0x6C, 0x63, 0x0B, +0x62, 0xEB, 0x42, 0x07, 0x29, 0x44, 0x29, 0x24, +0x21, 0x03, 0x21, 0x03, 0x20, 0xE3, 0x29, 0x44, +0x39, 0xA6, 0x29, 0x64, 0x29, 0x24, 0x29, 0x64, +0x39, 0xA6, 0x42, 0x07, 0x39, 0xA6, 0x29, 0x24, +0x4A, 0x08, 0x63, 0x0C, 0x8C, 0x51, 0xA5, 0x35, +0x94, 0xB3, 0x9C, 0xB3, 0xA4, 0xF4, 0xB5, 0xB6, +0xD6, 0x78, 0xA4, 0xD0, 0xA4, 0x8F, 0x94, 0x2D, +0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0x8E, 0xAC, 0xF0, +0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xF0, 0xAC, 0xCF, +0xBD, 0x51, 0xBD, 0x72, 0xD6, 0x36, 0xD6, 0x36, +0xD6, 0x36, 0xC5, 0xB4, 0xBD, 0x73, 0xB5, 0x52, +0xB5, 0x32, 0xB5, 0x11, 0xAC, 0xF0, 0xAC, 0xD0, +0xB5, 0x11, 0xB5, 0x31, 0xB4, 0xF1, 0xBD, 0x31, +0xB5, 0x10, 0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xD0, +0xB4, 0xF0, 0xB4, 0xF0, 0xBD, 0x31, 0xBD, 0x31, +0xBD, 0x31, 0xBD, 0x10, 0xBD, 0x51, 0xB5, 0x31, +0xA4, 0xAF, 0xA4, 0xAF, 0xB5, 0x31, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x72, 0xC5, 0xF4, 0xC5, 0xF5, +0xC6, 0x15, 0xC5, 0xF5, 0xC6, 0x15, 0xCE, 0x56, +0xCE, 0x36, 0xBD, 0xB4, 0x7B, 0xAC, 0xAC, 0xF1, +0xAC, 0xF0, 0xCD, 0xD4, 0xDE, 0x55, 0xDE, 0x55, +0xE6, 0x97, 0xC5, 0xB4, 0x6B, 0x2A, 0x39, 0xA5, +0x21, 0x03, 0x39, 0xE7, 0x6B, 0x2C, 0x6B, 0x2C, +0x73, 0x8E, 0x39, 0xC7, 0x73, 0x8E, 0x73, 0x6D, +0x5A, 0xAA, 0x62, 0xCA, 0x62, 0xCA, 0x6A, 0xCA, +0x6A, 0xEB, 0x6A, 0xAA, 0x73, 0x0B, 0x8B, 0xEE, +0x5A, 0x69, 0x7B, 0xAE, 0x62, 0x8A, 0x73, 0x2C, +0x8B, 0xCF, 0x83, 0xAE, 0x83, 0xAE, 0x8C, 0x0F, +0x73, 0x2B, 0x6A, 0xEA, 0x83, 0x8D, 0x94, 0x2E, +0xB5, 0x52, 0xEE, 0xD8, 0xBD, 0x94, 0x42, 0x08, +0x18, 0xC4, 0x10, 0xA3, 0x10, 0x82, 0x10, 0x83, +0x18, 0xE4, 0x29, 0x25, 0x20, 0xE4, 0x20, 0xE4, +0x18, 0xC3, 0x18, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, 0x10, 0x83, +0x08, 0x83, 0x08, 0x83, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xC4, 0x10, 0xC4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC4, +0x19, 0x04, 0x29, 0x46, 0x39, 0xC7, 0x84, 0x0E, +0xBD, 0xD4, 0x8B, 0xEE, 0x6B, 0x2C, 0x39, 0xC7, +0x29, 0x46, 0x21, 0x26, 0x21, 0x05, 0x21, 0x05, +0x21, 0x05, 0x21, 0x26, 0x21, 0x26, 0x29, 0x87, +0x21, 0x26, 0x21, 0x26, 0x21, 0x26, 0x21, 0x05, +0x21, 0x05, 0x18, 0xE5, 0x19, 0x05, 0x31, 0x67, +0x39, 0xE8, 0x4A, 0x49, 0x5A, 0xAA, 0xAC, 0xF1, +0xF7, 0x19, 0xCD, 0xF4, 0xAD, 0x12, 0x8C, 0x0E, +0x9C, 0xB0, 0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xD1, +0x94, 0x70, 0x94, 0x70, 0xAD, 0x12, 0xBD, 0xB4, +0xBD, 0x93, 0xA4, 0xF1, 0x83, 0xEE, 0x83, 0xEE, +0x73, 0x8D, 0x52, 0xA9, 0x39, 0xE6, 0x42, 0x07, +0x4A, 0x48, 0x4A, 0x48, 0x6B, 0x4D, 0x94, 0x71, +0x8C, 0x31, 0x39, 0xC7, 0x41, 0xE7, 0x9C, 0xB1, +0xD6, 0x77, 0xCE, 0x16, 0xBD, 0xB5, 0xA4, 0xB0, +0xA4, 0x8E, 0xA4, 0x6E, 0x8B, 0xCB, 0x83, 0xAC, +0x83, 0xAC, 0x94, 0x0D, 0x8C, 0x0D, 0x7B, 0x8B, +0x83, 0x8C, 0x83, 0xAC, 0x73, 0x4B, 0x73, 0x2A, +0x6A, 0xEA, 0x6B, 0x0A, 0x62, 0xC9, 0x62, 0xA9, +0x5A, 0xA9, 0x73, 0x2B, 0x7B, 0x4B, 0x7B, 0x8C, +0x7B, 0x8C, 0x83, 0xAC, 0x9C, 0x8F, 0xBD, 0x72, +0xCD, 0xF3, 0xAC, 0xEF, 0x9C, 0x6E, 0xBD, 0xB3, +0xC5, 0xF4, 0xAD, 0x31, 0x94, 0x4D, 0x94, 0x2D, +0x94, 0x4D, 0x9C, 0xAF, 0xC5, 0xD3, 0xC5, 0xD3, +0xD6, 0x55, 0xD6, 0x76, 0xDE, 0x97, 0xDE, 0x97, +0xBD, 0x94, 0x8C, 0x2F, 0xCE, 0x16, 0xC5, 0xF6, +0xA4, 0xF2, 0x8C, 0x30, 0x39, 0xE8, 0x5A, 0xEC, +0x63, 0x0C, 0x7B, 0xF0, 0x94, 0xB3, 0x5A, 0xEC, +0x84, 0x10, 0xB5, 0x96, 0xB5, 0x76, 0x73, 0x8E, +0x9C, 0xF4, 0x31, 0xA7, 0x73, 0x8D, 0x94, 0xB2, +0xD6, 0x79, 0xDE, 0xDA, 0xE6, 0xFB, 0x8C, 0x30, +0x4A, 0x69, 0xBD, 0xB5, 0xCE, 0x77, 0xCE, 0x56, +0xC6, 0x15, 0xCE, 0x56, 0xBD, 0xD4, 0xC5, 0xB3, +0xBD, 0x30, 0xBD, 0x50, 0xF6, 0xD6, 0xE6, 0x33, +0xDE, 0x13, 0xDE, 0x33, 0xE6, 0x33, 0xDE, 0x33, +0xE6, 0x54, 0xD5, 0xF2, 0xC5, 0x51, 0xD6, 0x14, +0xCD, 0xB2, 0xCD, 0xD3, 0xCD, 0xD3, 0xDE, 0x54, +0xC5, 0x50, 0xBD, 0x30, 0xCE, 0x14, 0xBD, 0x72, +0x7B, 0xAC, 0x73, 0x6B, 0xAD, 0x32, 0xC5, 0xD4, +0xBD, 0x73, 0x9C, 0x8F, 0x94, 0x4F, 0x8C, 0x2F, +0x8C, 0x2F, 0x73, 0x8C, 0x5A, 0xA9, 0x31, 0x65, +0x29, 0x23, 0x29, 0x64, 0x29, 0x44, 0x21, 0x03, +0x29, 0x24, 0x29, 0x44, 0x31, 0x85, 0x31, 0xA5, +0x41, 0xE6, 0x31, 0x85, 0x41, 0xE7, 0x52, 0x49, +0x62, 0xCB, 0x6B, 0x2C, 0xA5, 0x14, 0xAD, 0x55, +0xA5, 0x14, 0xA5, 0x14, 0xA4, 0xF4, 0xB5, 0xB7, +0xCE, 0x59, 0xBD, 0xB5, 0x9C, 0x90, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x92, 0xBD, 0xB3, 0xC5, 0xB3, +0xC5, 0xD4, 0xBD, 0x72, 0xAC, 0xF0, 0x7B, 0x8A, +0xA4, 0xAF, 0xC5, 0xB4, 0xE6, 0x97, 0xCD, 0xD4, +0xD6, 0x15, 0xCD, 0xF5, 0xB5, 0x32, 0xCD, 0xF4, +0xCD, 0xD4, 0xC5, 0x72, 0xC5, 0x93, 0xD6, 0x15, +0xD6, 0x55, 0xDE, 0x97, 0xCD, 0xF4, 0xDE, 0x56, +0xDE, 0x56, 0xDE, 0x56, 0xCD, 0xB4, 0xBD, 0x52, +0xBD, 0x73, 0xBD, 0x52, 0xBD, 0x52, 0xC5, 0x72, +0xC5, 0x72, 0xC5, 0x73, 0xBD, 0x52, 0xA4, 0xB0, +0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x12, 0xB5, 0x32, +0xAD, 0x31, 0xA4, 0xD0, 0xA4, 0xF0, 0xAD, 0x11, +0xAD, 0x11, 0xB5, 0x73, 0xB5, 0x52, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x11, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xD0, 0x9C, 0x6F, 0x94, 0x4F, +0x94, 0x4F, 0x9C, 0x6F, 0x94, 0x2E, 0x7B, 0xAC, +0x41, 0xE7, 0x4A, 0x69, 0x7B, 0xEF, 0x8C, 0x30, +0x84, 0x10, 0x39, 0xC7, 0x8C, 0x71, 0x8C, 0x51, +0x9C, 0xB2, 0x9C, 0xD3, 0x83, 0xCF, 0x8C, 0x10, +0x83, 0xCE, 0x73, 0x6C, 0x6B, 0x0C, 0x5A, 0x8A, +0x62, 0xCB, 0x83, 0xCE, 0x7B, 0xAE, 0x73, 0x2C, +0x62, 0xCA, 0x9C, 0x50, 0x9C, 0x71, 0x8B, 0xEF, +0x94, 0x30, 0x73, 0x2C, 0x6A, 0xCB, 0x7B, 0x4C, +0x6B, 0x0B, 0xB5, 0x32, 0x7B, 0x8D, 0x20, 0xE4, +0x10, 0x83, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0xA3, 0x18, 0xC4, 0x10, 0xA3, +0x10, 0x83, 0x08, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x20, 0xE4, 0x31, 0x66, 0x6B, 0x2B, +0xB5, 0x93, 0x9C, 0x70, 0x73, 0x6D, 0x42, 0x08, +0x29, 0x87, 0x21, 0x26, 0x19, 0x05, 0x21, 0x05, +0x19, 0x05, 0x21, 0x05, 0x21, 0x25, 0x29, 0x87, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x21, 0x05, +0x18, 0xE5, 0x19, 0x05, 0x29, 0x87, 0x31, 0xA8, +0x39, 0xC8, 0x39, 0xC8, 0x41, 0xC8, 0x73, 0x2C, +0xE6, 0x97, 0xC5, 0xD4, 0xAD, 0x32, 0x9C, 0x90, +0xAD, 0x53, 0xAD, 0x53, 0xB5, 0x73, 0xAD, 0x33, +0xA4, 0xD1, 0x9C, 0xB0, 0xBD, 0xB4, 0xBD, 0xB3, +0xC5, 0xD4, 0xB5, 0x73, 0x94, 0x90, 0xA4, 0xF2, +0x9C, 0xF3, 0x84, 0x2F, 0x7B, 0xCD, 0x6B, 0x2B, +0x41, 0xE6, 0x21, 0x23, 0x31, 0x85, 0x4A, 0x48, +0x6B, 0x2C, 0x7B, 0xAE, 0x39, 0xC6, 0x63, 0x0B, +0xBD, 0x95, 0xD6, 0x78, 0xDE, 0xB9, 0xD6, 0x37, +0xAC, 0xF2, 0x8B, 0xED, 0x94, 0x2D, 0x9C, 0x6E, +0xA4, 0x8E, 0xA4, 0xAF, 0xAC, 0xD0, 0xA4, 0x8E, +0xB5, 0x11, 0xB5, 0x31, 0xA4, 0xAF, 0xA4, 0x8F, +0xAC, 0xD0, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0x8F, +0x9C, 0x6E, 0x9C, 0x4E, 0x9C, 0x6E, 0xA4, 0x8E, +0xAC, 0xCE, 0xB4, 0xEF, 0xAC, 0xCF, 0xA4, 0xAE, +0xAC, 0xCF, 0xAC, 0xF0, 0x94, 0x2D, 0x94, 0x4D, +0x94, 0x2D, 0xB5, 0x11, 0xB5, 0x51, 0x94, 0x4D, +0xA4, 0xAE, 0xAD, 0x10, 0xAD, 0x10, 0xB5, 0x32, +0x9C, 0x4F, 0xAD, 0x11, 0xD6, 0x76, 0xE6, 0xD8, +0xBD, 0x94, 0x8C, 0x30, 0x42, 0x28, 0x4A, 0x48, +0x4A, 0x69, 0x5A, 0xCB, 0x7B, 0xEF, 0x52, 0x8A, +0x7B, 0xF0, 0xB5, 0x96, 0x8C, 0x51, 0x9C, 0xF3, +0x8C, 0x31, 0x9C, 0xB2, 0xAD, 0x55, 0x8C, 0x51, +0x9C, 0xB3, 0x94, 0x92, 0x94, 0x92, 0x63, 0x0C, +0x52, 0x6A, 0x84, 0x0F, 0xE7, 0x1A, 0xD6, 0x97, +0xD6, 0x77, 0xCE, 0x56, 0xCE, 0x36, 0xC5, 0xD4, +0xB5, 0x10, 0xC5, 0x91, 0xF6, 0xF6, 0xE6, 0x33, +0xDD, 0xF2, 0xD5, 0xD2, 0xDE, 0x33, 0xE6, 0x33, +0xD5, 0xD2, 0xCD, 0x91, 0xCD, 0xF3, 0xD6, 0x34, +0xD6, 0x34, 0xD5, 0xF4, 0xC5, 0x71, 0xE6, 0x54, +0xC5, 0x50, 0xBD, 0x50, 0xD6, 0x35, 0xC5, 0xD3, +0x9C, 0x6F, 0xAD, 0x32, 0xCE, 0x15, 0xCE, 0x15, +0xBD, 0x93, 0xC5, 0xB4, 0xA4, 0xD1, 0x94, 0x70, +0x94, 0x90, 0x8C, 0x4F, 0x94, 0x4F, 0x6B, 0x2B, +0x31, 0x85, 0x29, 0x64, 0x31, 0x85, 0x31, 0x65, +0x29, 0x44, 0x20, 0xE3, 0x29, 0x24, 0x31, 0x85, +0x31, 0x85, 0x31, 0xA5, 0x52, 0x69, 0x5A, 0xCB, +0x63, 0x0C, 0x6B, 0x2C, 0x73, 0x8E, 0x7B, 0xAF, +0x7B, 0xF0, 0x83, 0xF0, 0x94, 0xB3, 0x94, 0x92, +0xBD, 0xB6, 0xCE, 0x38, 0xAD, 0x54, 0xB5, 0x73, +0xC6, 0x15, 0xC5, 0xF4, 0xC5, 0xD3, 0xC5, 0xF4, +0xC5, 0xF4, 0xA4, 0xCF, 0xB5, 0x51, 0x94, 0x2E, +0xA4, 0xB0, 0xBD, 0xB3, 0xDE, 0x97, 0xCD, 0xF4, +0xD6, 0x35, 0xD6, 0x35, 0xB5, 0x31, 0xBD, 0x72, +0xCD, 0xF4, 0xC5, 0xB3, 0xB5, 0x31, 0xD5, 0xF4, +0xD6, 0x15, 0xDE, 0x76, 0xDE, 0x56, 0xD6, 0x15, +0xC5, 0xB3, 0xDE, 0x76, 0xE6, 0xB7, 0xDE, 0x55, +0xDE, 0x55, 0xDE, 0x35, 0xCD, 0xB3, 0xDE, 0x35, +0xB5, 0x31, 0xAC, 0xF1, 0x9C, 0x70, 0x8C, 0x0E, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, +0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xD0, 0xA4, 0xAF, +0x94, 0x2E, 0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xF0, +0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x12, 0xB5, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x53, 0xBD, 0x73, +0xC5, 0xB4, 0xBD, 0x93, 0xAD, 0x32, 0xAD, 0x12, +0x8C, 0x2F, 0x6B, 0x4C, 0x73, 0x8D, 0x7B, 0xCF, +0x7B, 0xAF, 0x39, 0xC7, 0x5A, 0xCA, 0x42, 0x08, +0x4A, 0x69, 0x6B, 0x4D, 0x7B, 0xCF, 0x9C, 0xD3, +0xAD, 0x34, 0x9C, 0x91, 0x83, 0xEE, 0x73, 0x6D, +0x6B, 0x0B, 0x52, 0x69, 0x6B, 0x0C, 0x7B, 0x8E, +0x8B, 0xEF, 0x83, 0xAD, 0x7B, 0x4C, 0x93, 0xEF, +0x8B, 0xEF, 0xB5, 0x13, 0xA4, 0xB2, 0x7B, 0x6D, +0x6A, 0xEB, 0x83, 0xAF, 0x41, 0xE7, 0x18, 0xC4, +0x18, 0xE4, 0x18, 0xC3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0x82, 0x10, 0x83, 0x10, 0x83, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, +0x18, 0xC4, 0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, +0x31, 0x86, 0x4A, 0x69, 0x29, 0x65, 0x10, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0xA3, 0x18, 0xE4, 0x21, 0x04, 0x41, 0xC7, +0x83, 0xCE, 0xA4, 0xB1, 0x8C, 0x2F, 0x7B, 0xAE, +0x52, 0xAA, 0x31, 0x86, 0x21, 0x25, 0x21, 0x05, +0x19, 0x05, 0x18, 0xE5, 0x21, 0x25, 0x21, 0x46, +0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE5, 0x18, 0xE4, +0x21, 0x25, 0x29, 0x46, 0x29, 0x66, 0x29, 0x66, +0x21, 0x46, 0x21, 0x25, 0x29, 0x66, 0x4A, 0x28, +0xBD, 0x94, 0xC5, 0xD4, 0xB5, 0x53, 0x9C, 0xB1, +0xAD, 0x32, 0xAD, 0x32, 0xBD, 0xB4, 0xA4, 0xD1, +0xA4, 0xF2, 0xA4, 0xF1, 0xBD, 0xB4, 0xAD, 0x32, +0xC5, 0xF5, 0xAD, 0x53, 0x9C, 0xB0, 0xAD, 0x33, +0x94, 0xD3, 0x84, 0x2F, 0x94, 0x6F, 0xAD, 0x32, +0x9C, 0xD0, 0x5A, 0xA8, 0x29, 0x64, 0x31, 0xA6, +0x39, 0xE7, 0x5A, 0xEB, 0x52, 0x69, 0x4A, 0x48, +0x6B, 0x4C, 0x94, 0x91, 0xA4, 0xF3, 0xC5, 0xF7, +0xE6, 0xDB, 0xBD, 0xB6, 0x52, 0x68, 0x6B, 0x09, +0xB5, 0x31, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xF0, +0xBD, 0x92, 0xAC, 0xF0, 0x94, 0x4E, 0x8C, 0x2D, +0xB5, 0x52, 0xB5, 0x31, 0xB5, 0x30, 0xA4, 0x8E, +0x9C, 0x8E, 0x9C, 0x6E, 0xA4, 0xAE, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x8E, 0xA4, 0x8E, 0xAC, 0xCF, +0xAC, 0xCF, 0xB5, 0x10, 0xBD, 0x30, 0xB4, 0xEF, +0xB5, 0x10, 0xBD, 0x30, 0xB5, 0x30, 0xB5, 0x10, +0xB4, 0xEF, 0xAC, 0xCF, 0xAC, 0xCE, 0xAC, 0xCF, +0xAC, 0xEF, 0xB5, 0x10, 0xAC, 0xCF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xCF, 0xA4, 0xCF, +0x8B, 0xCD, 0x6B, 0x0B, 0x5A, 0xCA, 0x42, 0x48, +0x3A, 0x07, 0x42, 0x07, 0x52, 0xAA, 0x4A, 0x69, +0x6B, 0x6D, 0x8C, 0x72, 0x73, 0x8E, 0x94, 0xB3, +0x83, 0xF0, 0x94, 0x72, 0x94, 0x71, 0x7B, 0xAF, +0x5A, 0xCC, 0xB5, 0x76, 0xBD, 0xB6, 0x94, 0x92, +0x83, 0xF0, 0x8C, 0x71, 0x7B, 0xEF, 0xB5, 0x74, +0xCE, 0x57, 0xD6, 0x97, 0xD6, 0x76, 0xD6, 0x75, +0xB5, 0x10, 0xAC, 0xCE, 0xE6, 0x54, 0xEE, 0x95, +0xE6, 0x13, 0xDE, 0x13, 0xE6, 0x54, 0xEE, 0x75, +0xC5, 0x71, 0xCD, 0xB2, 0xD5, 0xF3, 0xDE, 0x55, +0xCD, 0xD3, 0xC5, 0x92, 0xC5, 0x91, 0xE6, 0x75, +0xCD, 0x91, 0xBD, 0x51, 0xDE, 0x96, 0xDE, 0x55, +0xBD, 0x92, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xB3, +0xC5, 0xB3, 0xBD, 0x73, 0xAD, 0x11, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0x90, +0x29, 0x44, 0x29, 0x44, 0x31, 0x85, 0x41, 0xE7, +0x29, 0x24, 0x21, 0x03, 0x31, 0x65, 0x42, 0x07, +0x42, 0x07, 0x52, 0x69, 0x7B, 0xCF, 0xA5, 0x34, +0x7B, 0xAE, 0x5A, 0xAA, 0x63, 0x0C, 0x73, 0x8E, +0x6B, 0x4D, 0x7B, 0xCF, 0x84, 0x10, 0x94, 0x92, +0xA5, 0x35, 0xC6, 0x18, 0xCE, 0x38, 0xB5, 0x95, +0xCE, 0x15, 0xCE, 0x35, 0xB5, 0x72, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xF4, 0xC5, 0xB3, 0xB5, 0x52, +0xAC, 0xD0, 0xC5, 0xB3, 0xE6, 0xB7, 0xC5, 0xB3, +0xB5, 0x51, 0xCD, 0xD4, 0xCD, 0xD3, 0xCD, 0xF4, +0xD6, 0x14, 0xD5, 0xF4, 0xC5, 0x92, 0xD5, 0xF4, +0xDE, 0x55, 0xDE, 0x76, 0xDE, 0x96, 0xDE, 0x75, +0xE6, 0xD7, 0xE6, 0xB7, 0xDE, 0x96, 0xD6, 0x34, +0xDE, 0x54, 0xE6, 0x75, 0xDE, 0x55, 0xDE, 0x34, +0xAC, 0xD0, 0xBD, 0x94, 0x94, 0x4F, 0x84, 0x0E, +0x8C, 0x2F, 0x94, 0x8F, 0xA4, 0xD0, 0xAD, 0x11, +0x94, 0x2E, 0x9C, 0xB0, 0xBD, 0x93, 0xA4, 0xF0, +0x9C, 0xAF, 0x94, 0x4E, 0x9C, 0xB0, 0xB5, 0x52, +0xA4, 0xF1, 0xA4, 0xD0, 0xBD, 0xB4, 0xB5, 0x72, +0xA4, 0xB0, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xB0, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x53, 0xCE, 0x15, +0xBD, 0x94, 0xA4, 0xF2, 0x94, 0x70, 0x84, 0x0F, +0x6B, 0x2C, 0x4A, 0x48, 0x4A, 0x48, 0x4A, 0x28, +0x31, 0x85, 0x29, 0x45, 0x29, 0x44, 0x39, 0xE7, +0x52, 0xAA, 0x6B, 0x4D, 0x73, 0x8E, 0x7B, 0xAE, +0x9C, 0xD2, 0x8C, 0x30, 0x63, 0x0C, 0x62, 0xAA, +0x7B, 0x6D, 0x62, 0xCA, 0x6A, 0xEB, 0x83, 0x8D, +0x94, 0x0F, 0xB5, 0x13, 0xB5, 0x13, 0x6B, 0x0B, +0x5A, 0x8A, 0x5A, 0x69, 0x49, 0xE8, 0x18, 0xC4, +0x21, 0x25, 0x21, 0x45, 0x10, 0xA3, 0x10, 0x82, +0x10, 0xA3, 0x10, 0x83, 0x10, 0x82, 0x10, 0x82, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xC3, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x4A, 0x28, 0x8C, 0x50, +0x94, 0x70, 0x9C, 0x90, 0x73, 0x6C, 0x31, 0xA6, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xC3, 0x18, 0xE4, 0x21, 0x05, +0x4A, 0x28, 0x83, 0xCE, 0xAD, 0x12, 0x9C, 0xB1, +0x63, 0x0B, 0x39, 0xE8, 0x29, 0x66, 0x21, 0x05, +0x18, 0xE4, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x18, 0xC4, 0x21, 0x46, +0x29, 0x66, 0x21, 0x25, 0x21, 0x25, 0x21, 0x05, +0x19, 0x05, 0x19, 0x05, 0x31, 0x87, 0x42, 0x08, +0x83, 0xEE, 0xBD, 0x93, 0xAD, 0x32, 0x9C, 0xB1, +0x9C, 0xD1, 0xAD, 0x32, 0xB5, 0x73, 0xA4, 0xF1, +0xA5, 0x12, 0xA4, 0xF2, 0xB5, 0x73, 0xA4, 0xD1, +0xC6, 0x15, 0xBD, 0x94, 0xA4, 0xF1, 0xA5, 0x12, +0x9C, 0xF3, 0x8C, 0x50, 0x9C, 0xD0, 0xAD, 0x52, +0xB5, 0x92, 0xB5, 0x93, 0x94, 0x6F, 0x4A, 0x47, +0x39, 0xC6, 0x41, 0xE7, 0x62, 0xEB, 0xAD, 0x34, +0x8C, 0x50, 0x6B, 0x0B, 0x7B, 0x8D, 0x7B, 0x8E, +0xC6, 0x18, 0xC5, 0xF7, 0x9C, 0xD2, 0xA4, 0xF2, +0xBD, 0xB3, 0xA4, 0xAF, 0xA4, 0xAF, 0xBD, 0xD4, +0xBD, 0xB3, 0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xD1, +0x7B, 0x8C, 0x6B, 0x0A, 0x6B, 0x2A, 0x8C, 0x0D, +0xA4, 0xF0, 0xA4, 0xD0, 0x94, 0x6E, 0x94, 0x4E, +0x9C, 0xAF, 0x9C, 0x6F, 0x94, 0x4E, 0x8C, 0x0D, +0x8B, 0xEC, 0x8C, 0x0D, 0x94, 0x2D, 0x9C, 0x6E, +0xA4, 0xCF, 0xAC, 0xCF, 0x9C, 0x6D, 0xA4, 0xCF, +0xAC, 0xF0, 0xA4, 0x8E, 0x9C, 0x6D, 0x9C, 0x4D, +0x94, 0x0C, 0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x6E, +0xA4, 0x8E, 0xA4, 0xCF, 0xAC, 0xCF, 0xA4, 0xCF, +0xA4, 0xB0, 0x73, 0x6C, 0x73, 0x8D, 0x4A, 0x48, +0x29, 0x65, 0x31, 0x85, 0x4A, 0x68, 0x42, 0x28, +0x5A, 0xCB, 0x6B, 0x6E, 0x5A, 0xEC, 0x6B, 0x2D, +0x73, 0x8E, 0x21, 0x05, 0x63, 0x0C, 0x94, 0x72, +0x7B, 0xAF, 0x8C, 0x31, 0x39, 0xC8, 0x63, 0x0C, +0xD6, 0x99, 0xE6, 0xFB, 0xAD, 0x35, 0x5A, 0xAA, +0x7B, 0xAD, 0xC5, 0xD5, 0xBD, 0xB4, 0xB5, 0x51, +0xAC, 0xAE, 0xB4, 0xEF, 0xBD, 0x30, 0xDE, 0x54, +0xE6, 0x75, 0xE6, 0x54, 0xE6, 0x75, 0xEE, 0x95, +0xE6, 0x75, 0xDE, 0x13, 0xDE, 0x13, 0xCD, 0xB2, +0xCD, 0x91, 0xDE, 0x34, 0xEE, 0x95, 0xE6, 0x54, +0xC5, 0x30, 0xBD, 0x71, 0xEE, 0xF7, 0xEE, 0xD7, +0xE6, 0xB6, 0xEE, 0xD7, 0xEE, 0xB6, 0xE6, 0xB6, +0xE6, 0x76, 0xD6, 0x15, 0xCD, 0xD4, 0xD6, 0x56, +0xCE, 0x15, 0xC5, 0xB3, 0xC5, 0xD4, 0xCE, 0x16, +0x62, 0xCA, 0x94, 0x70, 0x9C, 0x6F, 0xB5, 0x53, +0x94, 0x2E, 0x41, 0xE6, 0x29, 0x44, 0x42, 0x07, +0x4A, 0x48, 0x41, 0xE7, 0x6B, 0x2C, 0x73, 0x6D, +0x5A, 0xCA, 0x41, 0xE7, 0x5A, 0xAA, 0x52, 0xAA, +0x4A, 0x28, 0x6B, 0x2C, 0x7B, 0xAE, 0x7B, 0xCF, +0x9C, 0xD3, 0xBD, 0xB7, 0xCE, 0x59, 0xCE, 0x37, +0xBD, 0xB4, 0xC5, 0xD3, 0xCE, 0x14, 0xCE, 0x15, +0xCE, 0x35, 0xC5, 0xD4, 0xC5, 0xB3, 0xCD, 0xF5, +0xA4, 0xB0, 0xBD, 0x93, 0xE6, 0xB7, 0xCD, 0xF4, +0xD6, 0x15, 0xCE, 0x14, 0xCD, 0xD3, 0xC5, 0x92, +0xD6, 0x14, 0xCD, 0xB3, 0xCD, 0xB3, 0xD5, 0xF3, +0xDE, 0x55, 0xDE, 0x55, 0xDE, 0x75, 0xDE, 0x75, +0xE6, 0xB6, 0xD6, 0x35, 0xDE, 0x76, 0xDE, 0x55, +0xDE, 0x55, 0xDE, 0x75, 0xD6, 0x14, 0xD6, 0x14, +0xAC, 0xD0, 0xBD, 0x94, 0x83, 0xEE, 0x8C, 0x2E, +0x9C, 0xD1, 0x94, 0x90, 0x94, 0x6F, 0x9C, 0x8F, +0x9C, 0xB0, 0xAD, 0x11, 0xBD, 0x93, 0xAD, 0x11, +0x8C, 0x0E, 0x84, 0x2E, 0x73, 0x8C, 0x83, 0xED, +0xA4, 0xF1, 0xB5, 0x53, 0xC5, 0xF5, 0xCE, 0x35, +0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x73, +0xB5, 0x73, 0xB5, 0x52, 0xBD, 0x94, 0xC5, 0xF5, +0xBD, 0xB5, 0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0x94, +0xBD, 0xB5, 0xAD, 0x53, 0xAD, 0x73, 0xB5, 0x94, +0x9C, 0xD1, 0x4A, 0x48, 0x20, 0xE3, 0x21, 0x24, +0x21, 0x24, 0x29, 0x44, 0x29, 0x45, 0x39, 0xA6, +0x63, 0x0C, 0x7B, 0xEF, 0xA5, 0x13, 0x94, 0x71, +0x73, 0x4D, 0x73, 0x2C, 0x73, 0x2C, 0x7B, 0x4C, +0x83, 0x6D, 0x8B, 0xEF, 0xA4, 0x91, 0x52, 0x28, +0x31, 0x65, 0x52, 0x28, 0x4A, 0x28, 0x39, 0x87, +0x18, 0xC3, 0x19, 0x04, 0x21, 0x05, 0x18, 0xC3, +0x18, 0xC4, 0x10, 0xC3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, 0x21, 0x04, +0x52, 0x69, 0x7B, 0xAD, 0x9C, 0x70, 0xA4, 0xB0, +0x9C, 0x90, 0xAC, 0xF2, 0xAC, 0xF2, 0x83, 0xEE, +0x41, 0xE7, 0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC3, +0x29, 0x46, 0x5A, 0xAA, 0x94, 0x6F, 0xAD, 0x12, +0x73, 0x6C, 0x5A, 0xCB, 0x42, 0x29, 0x29, 0x66, +0x21, 0x25, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x26, 0x29, 0x67, +0x21, 0x25, 0x19, 0x05, 0x21, 0x05, 0x19, 0x05, +0x21, 0x05, 0x29, 0x46, 0x31, 0x87, 0x39, 0xC7, +0x52, 0x8A, 0x9C, 0xB1, 0xAD, 0x12, 0x9C, 0xB0, +0x9C, 0xB0, 0xA5, 0x12, 0xAD, 0x12, 0xA4, 0xF1, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x32, 0xB5, 0x73, +0xCE, 0x15, 0xBD, 0xB4, 0xA4, 0xF2, 0xAD, 0x53, +0x9C, 0xF2, 0x8C, 0x70, 0xA5, 0x11, 0xAD, 0x31, +0xAD, 0x32, 0xBD, 0xB3, 0xBD, 0xB3, 0xAD, 0x52, +0x63, 0x0A, 0x3A, 0x06, 0x39, 0xE6, 0x63, 0x0B, +0xA5, 0x13, 0x63, 0x0B, 0x5A, 0xCA, 0x84, 0x10, +0x84, 0x10, 0x8C, 0x10, 0x9C, 0xB2, 0xDE, 0x99, +0xC5, 0xF5, 0xA4, 0x8E, 0xAC, 0xCF, 0xC5, 0xF4, +0xBD, 0x93, 0xAD, 0x32, 0xAD, 0x73, 0xB5, 0x74, +0xA4, 0xF2, 0x8C, 0x0E, 0x7B, 0xCD, 0x8C, 0x4F, +0xA4, 0xF1, 0xA4, 0xF1, 0xA5, 0x11, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x12, 0xB5, 0x73, +0xBD, 0x72, 0xA4, 0xAE, 0x9C, 0x6E, 0xA5, 0x11, +0xAD, 0x32, 0xB5, 0x52, 0xB5, 0x52, 0xA5, 0x11, +0x9C, 0x8F, 0xA4, 0xD0, 0xA4, 0xF0, 0xA4, 0xF0, +0xA4, 0xD0, 0xA4, 0xF0, 0xA4, 0xCF, 0x9C, 0x8F, +0xA4, 0xD0, 0x94, 0x6F, 0x8C, 0x0E, 0xA4, 0xF1, +0x6B, 0x2B, 0x31, 0x65, 0x31, 0x85, 0x39, 0xC7, +0x39, 0xC7, 0x62, 0xEC, 0x5A, 0xCB, 0x62, 0xEB, +0x7B, 0x8E, 0x52, 0x6A, 0x29, 0x66, 0x31, 0x86, +0x63, 0x0C, 0x62, 0xEC, 0x52, 0x8B, 0x94, 0x92, +0xD6, 0x59, 0xDE, 0x9A, 0x8C, 0x31, 0x7B, 0x8E, +0x41, 0xA7, 0x41, 0xC7, 0x7B, 0xAD, 0xCD, 0xD5, +0xBD, 0x31, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xCE, +0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0x8D, 0xA4, 0x6D, +0xAC, 0x8E, 0xAC, 0x8D, 0xAC, 0xAD, 0xB4, 0xCE, +0xB4, 0xEE, 0xBD, 0x0F, 0xBD, 0x0F, 0xB4, 0xEE, +0xB4, 0xCE, 0xBD, 0x50, 0xCD, 0xB3, 0xCD, 0xD3, +0xD6, 0x14, 0xDE, 0x55, 0xE6, 0x75, 0xE6, 0x75, +0xDE, 0x75, 0xDE, 0x75, 0xE6, 0x76, 0xEE, 0xB6, +0xE6, 0x96, 0xE6, 0x76, 0xE6, 0x96, 0xEE, 0xB7, +0xE6, 0x76, 0xEE, 0xD8, 0xE6, 0xD7, 0xE6, 0x97, +0xD6, 0x35, 0xAC, 0xF1, 0x39, 0x85, 0x31, 0xA5, +0x4A, 0x27, 0x31, 0x85, 0x62, 0xCA, 0x39, 0xA6, +0x31, 0x65, 0x4A, 0x28, 0x4A, 0x49, 0x52, 0x69, +0x52, 0x89, 0x6B, 0x4C, 0x73, 0x8E, 0x7B, 0xCF, +0x94, 0x92, 0xB5, 0x76, 0xC6, 0x18, 0xC6, 0x17, +0xB5, 0x94, 0xA5, 0x11, 0xBD, 0x93, 0xB5, 0x52, +0xBD, 0x93, 0xAD, 0x31, 0xA4, 0xD0, 0xAC, 0xF1, +0xA4, 0xD0, 0xBD, 0xB4, 0xE6, 0xD8, 0xCD, 0xF4, +0xDE, 0x56, 0xE6, 0x97, 0xD6, 0x14, 0xC5, 0x72, +0xBD, 0x51, 0xAC, 0xCF, 0xBD, 0x31, 0xCD, 0xD3, +0xE6, 0x76, 0xE6, 0x96, 0xE6, 0xB6, 0xE6, 0xD7, +0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0x96, 0xE6, 0x96, +0xDE, 0x75, 0xDE, 0x34, 0xCD, 0xD3, 0xCD, 0xD3, +0xAC, 0xF0, 0xBD, 0x94, 0x83, 0xEE, 0x94, 0x90, +0xB5, 0x73, 0xB5, 0xB4, 0xB5, 0x73, 0xAD, 0x53, +0xB5, 0x94, 0xC5, 0xF4, 0xCE, 0x35, 0xBD, 0xB4, +0x9C, 0xB1, 0x9C, 0xF1, 0x7B, 0xAD, 0x8C, 0x4F, +0xAD, 0x52, 0xB5, 0x73, 0xC5, 0xD4, 0xBD, 0xD3, +0xBD, 0x93, 0xAD, 0x11, 0xB5, 0x73, 0xBD, 0x93, +0xB5, 0x73, 0xB5, 0x32, 0xC5, 0xF5, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0xB5, 0xC6, 0x16, 0xBD, 0xD5, +0xBD, 0xD5, 0xC5, 0xF6, 0xC6, 0x16, 0xCE, 0x16, +0xC5, 0xF6, 0xA4, 0xF2, 0x9C, 0xD2, 0x8C, 0x70, +0x5A, 0xCA, 0x31, 0x85, 0x29, 0x44, 0x21, 0x24, +0x21, 0x24, 0x31, 0x85, 0x52, 0xAA, 0x7B, 0xEF, +0x9C, 0xB2, 0xB5, 0x35, 0x7B, 0x6D, 0x73, 0x4C, +0x73, 0x2C, 0x6A, 0xEB, 0x7B, 0x6D, 0x7B, 0x8E, +0x5A, 0x8A, 0x41, 0xC7, 0x39, 0x86, 0x5A, 0x8A, +0x4A, 0x08, 0x20, 0xE4, 0x18, 0xC4, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE4, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x18, 0xC4, 0x29, 0x25, +0x4A, 0x28, 0x52, 0x89, 0x73, 0x4C, 0x9C, 0x90, +0xD6, 0x36, 0xDE, 0x97, 0xD6, 0x35, 0xC5, 0xB3, +0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0xB4, 0xBD, 0x73, +0x8C, 0x0E, 0x39, 0xC6, 0x10, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xC4, 0x29, 0x45, 0x83, 0xEE, 0xAC, 0xF1, +0xA4, 0xB0, 0x94, 0x2F, 0x6B, 0x2C, 0x42, 0x08, +0x29, 0x46, 0x21, 0x25, 0x19, 0x04, 0x18, 0xE4, +0x18, 0xE4, 0x18, 0xE5, 0x21, 0x46, 0x21, 0x25, +0x19, 0x05, 0x19, 0x05, 0x19, 0x05, 0x19, 0x05, +0x21, 0x25, 0x29, 0x46, 0x29, 0x46, 0x29, 0x66, +0x41, 0xE8, 0x83, 0xEF, 0xA4, 0xB1, 0x9C, 0xB1, +0xA4, 0xF2, 0x9C, 0xB1, 0xA4, 0xF1, 0x9C, 0xB1, +0x9C, 0xD1, 0xB5, 0x94, 0x9C, 0xB0, 0xBD, 0x93, +0xB5, 0x93, 0xAD, 0x53, 0x9C, 0xB1, 0x9C, 0xD1, +0x94, 0xD1, 0x8C, 0x6F, 0xA5, 0x11, 0xA5, 0x11, +0xA5, 0x31, 0xAD, 0x52, 0xB5, 0x92, 0xB5, 0x92, +0xB5, 0x93, 0x52, 0xC8, 0x31, 0xA5, 0x31, 0xA6, +0x39, 0xE7, 0x42, 0x07, 0x4A, 0x48, 0x83, 0xEF, +0x73, 0x6D, 0x73, 0x6D, 0x6B, 0x2D, 0xC6, 0x18, +0xE6, 0xFB, 0x94, 0x2F, 0xA4, 0xB0, 0xC5, 0xD4, +0xB5, 0x52, 0xBD, 0xB4, 0xBD, 0xB5, 0xB5, 0x74, +0xAD, 0x53, 0xAD, 0x53, 0x9C, 0xD2, 0xA5, 0x33, +0xB5, 0x74, 0xAD, 0x73, 0xAD, 0x33, 0xAD, 0x33, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x33, 0xB5, 0x73, 0xBD, 0xD4, 0xC5, 0xD4, +0xBD, 0xB2, 0xA4, 0xCE, 0xA4, 0xF0, 0xAD, 0x32, +0xC5, 0xF5, 0xCE, 0x57, 0xD6, 0x77, 0xBD, 0xB4, +0xAD, 0x32, 0xB5, 0x94, 0xAD, 0x52, 0xAD, 0x52, +0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x12, +0xAD, 0x32, 0xBD, 0xB4, 0xBD, 0x93, 0xCE, 0x56, +0xBD, 0xB3, 0x9C, 0xAF, 0x7B, 0xCD, 0x29, 0x44, +0x8C, 0x71, 0xCE, 0x59, 0xC6, 0x18, 0x9C, 0xB2, +0xBD, 0xD6, 0xCE, 0x38, 0xBD, 0xB6, 0x94, 0x92, +0xA5, 0x34, 0xAD, 0x35, 0xBD, 0x97, 0xCD, 0xF8, +0xDE, 0x7A, 0xD6, 0x59, 0xDE, 0xBA, 0xCD, 0xF8, +0x6A, 0xEC, 0x28, 0xE4, 0x39, 0xA7, 0x8B, 0xEF, +0x83, 0xAE, 0x41, 0xC7, 0xAC, 0xF1, 0xB4, 0xEF, +0xAC, 0xCF, 0xC5, 0x71, 0xD6, 0x14, 0xD6, 0x14, +0xD5, 0xF4, 0xD5, 0xF3, 0xCD, 0xB2, 0xAC, 0xCF, +0xAC, 0xEF, 0xAC, 0xCF, 0xA4, 0xAE, 0xAC, 0xCF, +0xA4, 0xAE, 0xA4, 0x8E, 0xA4, 0x6E, 0x9C, 0x4D, +0x9C, 0x4D, 0x9C, 0x2C, 0x94, 0x2C, 0x9C, 0x4D, +0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0xAE, +0xAC, 0xAE, 0xAC, 0xCF, 0xAC, 0xAE, 0xA4, 0x6E, +0xA4, 0x6D, 0x9C, 0x4D, 0x9C, 0x4D, 0xA4, 0x8F, +0xAC, 0xCF, 0xA4, 0xAE, 0x7B, 0x6B, 0x4A, 0x06, +0x39, 0xC6, 0x29, 0x44, 0x31, 0x85, 0x39, 0xC6, +0x41, 0xE7, 0x39, 0xC6, 0x39, 0xA6, 0x52, 0x69, +0x5A, 0xAA, 0x6B, 0x4C, 0x7B, 0xAE, 0x84, 0x0F, +0x8C, 0x51, 0xA5, 0x34, 0xB5, 0xB6, 0xBD, 0xD6, +0xD6, 0x98, 0xCE, 0x36, 0xCE, 0x35, 0xCE, 0x15, +0xC5, 0xF4, 0xBD, 0xD4, 0xB5, 0x72, 0xAD, 0x31, +0xA4, 0xF0, 0xB5, 0x52, 0xE6, 0xD7, 0xCD, 0xD3, +0xD6, 0x35, 0xEE, 0xD7, 0xD6, 0x14, 0xB5, 0x30, +0xB4, 0xF0, 0xBD, 0x31, 0xC5, 0x71, 0xCD, 0xD3, +0xE6, 0x75, 0xDE, 0x55, 0xD6, 0x14, 0xD6, 0x14, +0xDE, 0x55, 0xDE, 0x75, 0xD6, 0x34, 0xCD, 0xF3, +0xD5, 0xF3, 0xD6, 0x34, 0xCD, 0xD2, 0xCD, 0xB3, +0xAC, 0xF1, 0xBD, 0x74, 0x8C, 0x2E, 0x9C, 0xD1, +0xAD, 0x53, 0xB5, 0x94, 0xBD, 0xD5, 0xBD, 0xB4, +0xC5, 0xF5, 0xBD, 0xD4, 0xCE, 0x15, 0xC6, 0x15, +0xAD, 0x53, 0xAD, 0x32, 0x8C, 0x2F, 0x9C, 0xB0, +0xB5, 0x94, 0xC5, 0xF5, 0xCE, 0x35, 0xC5, 0xF4, +0xAD, 0x52, 0xA4, 0xD0, 0xAD, 0x32, 0xBD, 0xD4, +0xB5, 0x73, 0xA4, 0xF1, 0xCE, 0x15, 0xCE, 0x15, +0xBD, 0x94, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xB4, +0xAD, 0x33, 0xBD, 0xB5, 0xC5, 0xF5, 0xC6, 0x16, +0xCE, 0x36, 0xCE, 0x16, 0xCE, 0x36, 0xD6, 0x97, +0xCE, 0x36, 0xB5, 0x73, 0x83, 0xCE, 0x42, 0x07, +0x31, 0x85, 0x29, 0x65, 0x29, 0x45, 0x29, 0x65, +0x52, 0x8A, 0x8C, 0x51, 0x94, 0x71, 0x8C, 0x0F, +0x5A, 0x89, 0x5A, 0x8A, 0x62, 0xAA, 0x94, 0x30, +0xAC, 0xF3, 0x73, 0x2C, 0x4A, 0x08, 0x49, 0xE7, +0x6A, 0xCA, 0x5A, 0x69, 0x31, 0x86, 0x10, 0xA3, +0x18, 0xC3, 0x10, 0xA3, 0x21, 0x04, 0x52, 0xAA, +0x4A, 0x29, 0x42, 0x29, 0x52, 0xAA, 0x94, 0x91, +0x9C, 0xB1, 0x94, 0x70, 0xA4, 0xD1, 0xBD, 0x94, +0xAC, 0xF1, 0x94, 0x6F, 0xAC, 0xF0, 0xB5, 0x52, +0xB5, 0x52, 0x9C, 0xB0, 0x9C, 0x8F, 0x94, 0x4E, +0x9C, 0x90, 0x83, 0xCE, 0x31, 0x86, 0x18, 0xE4, +0x10, 0xC3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x08, 0x82, +0x10, 0xA3, 0x29, 0x24, 0x8C, 0x0F, 0xB5, 0x52, +0xBD, 0x73, 0xB5, 0x32, 0x94, 0x6F, 0x63, 0x0A, +0x39, 0xC7, 0x29, 0x66, 0x21, 0x05, 0x18, 0xE4, +0x19, 0x04, 0x19, 0x05, 0x21, 0x25, 0x19, 0x05, +0x18, 0xE4, 0x18, 0xE4, 0x19, 0x05, 0x21, 0x25, +0x21, 0x25, 0x21, 0x45, 0x21, 0x45, 0x29, 0x66, +0x31, 0x87, 0x73, 0x4C, 0xB5, 0x33, 0xBD, 0x94, +0xB5, 0x53, 0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0xB0, 0xA4, 0xD1, 0x9C, 0xB0, 0xA4, 0xD1, +0xA4, 0xD0, 0x94, 0x70, 0x8C, 0x0F, 0x8C, 0x2F, +0xB5, 0xF6, 0x7C, 0x2D, 0x94, 0xCF, 0xAD, 0x72, +0xAD, 0x72, 0xB5, 0x93, 0xC6, 0x15, 0xB5, 0xB2, +0xAD, 0x4F, 0xA5, 0x4F, 0x8C, 0x4D, 0x31, 0xA5, +0x29, 0x65, 0x39, 0xE6, 0x42, 0x28, 0x6B, 0x4C, +0x52, 0xAA, 0x52, 0xAA, 0x6B, 0x4D, 0xCE, 0x59, +0xCE, 0x59, 0xAD, 0x34, 0xCE, 0x58, 0xB5, 0x53, +0xB5, 0x93, 0xC5, 0xF5, 0xB5, 0xB5, 0xAD, 0x74, +0xAD, 0x53, 0xB5, 0x74, 0xA5, 0x13, 0xAD, 0x74, +0xAD, 0x74, 0xB5, 0x74, 0xA5, 0x32, 0xA4, 0xF2, +0x9C, 0xF2, 0xB5, 0x73, 0xAD, 0x53, 0xB5, 0x53, +0xAD, 0x33, 0xB5, 0x73, 0xB5, 0x93, 0xC6, 0x15, +0xC5, 0xD3, 0xA4, 0xAE, 0xAD, 0x11, 0xAD, 0x32, +0xB5, 0x94, 0xBD, 0xB4, 0xC5, 0xF6, 0xAD, 0x53, +0xB5, 0x73, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0x73, +0xAD, 0x53, 0xBD, 0xB4, 0xB5, 0x53, 0xAD, 0x32, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0xB4, 0xB5, 0x93, +0xA5, 0x11, 0x9C, 0xAF, 0xAD, 0x11, 0x52, 0x68, +0x84, 0x30, 0xB5, 0xB6, 0xCE, 0x18, 0x8C, 0x30, +0xC6, 0x18, 0xE6, 0xDB, 0xBD, 0xD7, 0xCE, 0x59, +0xBD, 0xD7, 0xCE, 0x59, 0xDE, 0xBB, 0xDE, 0xBA, +0xC5, 0xD7, 0xB5, 0x55, 0xD6, 0x38, 0xA4, 0xB2, +0xB5, 0x35, 0x8B, 0xEF, 0x9C, 0x71, 0xAD, 0x13, +0xBD, 0x95, 0xBD, 0x96, 0xD6, 0x17, 0xCD, 0xB4, +0xB4, 0xF0, 0xC5, 0x92, 0xCD, 0xD3, 0xC5, 0x92, +0xD5, 0xF3, 0xCD, 0xD3, 0xCD, 0xB3, 0xA4, 0x8E, +0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x6E, 0xAD, 0x10, +0x94, 0x6E, 0xAD, 0x31, 0xA4, 0xD0, 0x9C, 0x8F, +0xA4, 0xD0, 0x9C, 0xAF, 0x8C, 0x0C, 0xAC, 0xCF, +0x9C, 0x2C, 0x9C, 0x2C, 0x83, 0xAA, 0x8B, 0xCB, +0x8B, 0xEC, 0x7B, 0x6A, 0x83, 0xAB, 0x94, 0x0D, +0x8B, 0xCB, 0x83, 0xAB, 0x8B, 0xEC, 0x94, 0x2D, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0xAF, 0x94, 0x4E, +0x41, 0xE6, 0x31, 0x86, 0x39, 0xC6, 0x42, 0x07, +0x42, 0x07, 0x39, 0xA6, 0x4A, 0x28, 0x52, 0x89, +0x5A, 0xCA, 0x63, 0x0B, 0x6B, 0x2C, 0x6B, 0x6D, +0x84, 0x0F, 0x84, 0x30, 0xAD, 0x55, 0xAD, 0x55, +0xD6, 0x99, 0xB5, 0x74, 0xAD, 0x11, 0xB5, 0x52, +0xB5, 0x51, 0xB5, 0x51, 0xA4, 0xF0, 0xA4, 0xF0, +0xA4, 0xAF, 0x9C, 0x8F, 0xB5, 0x31, 0xB5, 0x31, +0xB5, 0x10, 0xC5, 0xB3, 0xCD, 0xB3, 0xD6, 0x14, +0xD6, 0x35, 0xDE, 0x56, 0xE6, 0x76, 0xDE, 0x34, +0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x55, 0xDE, 0x34, +0xDE, 0x75, 0xDE, 0x55, 0xE6, 0x75, 0xDE, 0x55, +0xDE, 0x54, 0xEE, 0xB6, 0xE6, 0x55, 0xDE, 0x35, +0xB5, 0x32, 0xB5, 0x73, 0x8C, 0x4F, 0xA5, 0x32, +0xB5, 0x94, 0xB5, 0xB4, 0xB5, 0x94, 0xA5, 0x12, +0xBD, 0xD4, 0xC5, 0xF4, 0xC6, 0x15, 0xB5, 0x93, +0xAD, 0x53, 0xAD, 0x73, 0x9C, 0xB1, 0xA5, 0x12, +0xB5, 0xB4, 0xCE, 0x35, 0xD6, 0x76, 0xCE, 0x15, +0xAD, 0x11, 0xA4, 0xD1, 0xB5, 0x52, 0xBD, 0x93, +0xB5, 0x52, 0xA4, 0xF1, 0xC5, 0xD4, 0xC5, 0xF5, +0xAD, 0x32, 0xA5, 0x12, 0xB5, 0x53, 0xBD, 0x94, +0xAD, 0x32, 0xBD, 0xD5, 0xD6, 0x36, 0xC5, 0xD5, +0xCE, 0x36, 0xC5, 0xF5, 0xCE, 0x36, 0xCE, 0x56, +0xCE, 0x35, 0xD6, 0x76, 0xD6, 0x56, 0xBD, 0xD5, +0x8C, 0x2F, 0x4A, 0x27, 0x29, 0x65, 0x29, 0x65, +0x21, 0x45, 0x31, 0xA6, 0x42, 0x08, 0x94, 0x51, +0x9C, 0x92, 0x4A, 0x08, 0x5A, 0x8A, 0x62, 0xAA, +0x83, 0xAE, 0xA4, 0x91, 0x7B, 0x6D, 0x52, 0x28, +0x52, 0x27, 0x6A, 0xA9, 0x5A, 0x69, 0x52, 0x28, +0x31, 0x86, 0x31, 0x66, 0x39, 0xC7, 0x6B, 0x2C, +0x8C, 0x30, 0x9C, 0xD2, 0xAD, 0x34, 0xCE, 0x36, +0xDE, 0x97, 0xCE, 0x36, 0x9C, 0xB0, 0xAD, 0x32, +0xD6, 0x56, 0xCE, 0x15, 0xCE, 0x35, 0xCE, 0x15, +0xCE, 0x14, 0xDE, 0x96, 0xDE, 0x76, 0xCE, 0x15, +0xCD, 0xF5, 0xC5, 0xB4, 0x8B, 0xEE, 0x5A, 0xAA, +0x29, 0x65, 0x10, 0xA3, 0x10, 0x83, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0x83, +0x10, 0xA3, 0x21, 0x04, 0x83, 0xCE, 0xD6, 0x15, +0xD5, 0xF4, 0xC5, 0x72, 0xBD, 0x72, 0x9C, 0x8F, +0x73, 0x4C, 0x41, 0xE7, 0x29, 0x45, 0x21, 0x05, +0x19, 0x04, 0x19, 0x04, 0x19, 0x05, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x21, 0x25, +0x21, 0x25, 0x21, 0x25, 0x21, 0x25, 0x29, 0x46, +0x39, 0xC7, 0x6B, 0x2C, 0x9C, 0x90, 0xA4, 0xD1, +0x9C, 0xB0, 0x94, 0x4F, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0xB0, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xF1, +0xB5, 0x52, 0xAD, 0x12, 0xAD, 0x32, 0xB5, 0x52, +0x95, 0x32, 0x63, 0xCA, 0x8C, 0xEF, 0xAD, 0x72, +0xAD, 0x52, 0xA5, 0x31, 0xA5, 0x6F, 0x8C, 0xCA, +0x7C, 0x68, 0xAD, 0xAD, 0xB5, 0xB1, 0xAD, 0x31, +0x52, 0xA8, 0x31, 0x85, 0x42, 0x28, 0x5A, 0xCA, +0x4A, 0x28, 0x5A, 0xEB, 0x84, 0x10, 0xAD, 0x75, +0xA5, 0x34, 0xBE, 0x18, 0xEF, 0x7D, 0xDE, 0xB9, +0xB5, 0x94, 0xC5, 0xF5, 0xBD, 0xF6, 0xC5, 0xF6, +0xBD, 0xD5, 0x9C, 0xB1, 0x94, 0x70, 0xBD, 0xB5, +0xB5, 0xB5, 0xB5, 0xB4, 0xB5, 0x94, 0xB5, 0x73, +0xB5, 0x74, 0xB5, 0x94, 0xAD, 0x32, 0xBD, 0x94, +0xBD, 0xB4, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB3, +0xC5, 0xB3, 0xAC, 0xCE, 0xAC, 0xF0, 0xB5, 0x53, +0xAD, 0x12, 0xAD, 0x32, 0xB5, 0x94, 0xAD, 0x53, +0xB5, 0x94, 0xBD, 0xD5, 0xB5, 0x94, 0xC5, 0xD5, +0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x73, 0xAD, 0x32, +0x9C, 0xD0, 0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x73, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0x83, 0xED, +0x62, 0xEB, 0x9C, 0xD3, 0xB5, 0x96, 0x83, 0xEF, +0x9C, 0xD3, 0xBD, 0xB7, 0xAD, 0x34, 0x94, 0x92, +0x73, 0x8E, 0x7B, 0xCF, 0xA5, 0x14, 0xC5, 0xF7, +0x94, 0x72, 0x5A, 0xAA, 0x7B, 0xAE, 0xB5, 0x55, +0xD6, 0x38, 0xDE, 0x79, 0xAC, 0xF3, 0x94, 0x50, +0x6B, 0x0B, 0x6B, 0x0C, 0x73, 0x4D, 0xA4, 0x91, +0xD5, 0xF5, 0xD6, 0x15, 0xE6, 0x97, 0xD5, 0xF4, +0xD6, 0x14, 0xDE, 0x34, 0xCD, 0xB2, 0xAC, 0xCF, +0x9C, 0xB0, 0xA5, 0x12, 0x9C, 0xF1, 0xAD, 0x52, +0x9C, 0xD0, 0xAD, 0x53, 0xA5, 0x32, 0xAD, 0x53, +0xB5, 0x73, 0xB5, 0x73, 0xA4, 0xAF, 0xAC, 0xCF, +0xBD, 0x31, 0x9C, 0x8E, 0x9C, 0x8F, 0xB5, 0x72, +0xB5, 0x72, 0xB5, 0x52, 0x9C, 0x8F, 0xA4, 0xF1, +0x8C, 0x2E, 0x94, 0x4F, 0x94, 0x6F, 0x8C, 0x0E, +0x7B, 0xAC, 0x7B, 0x8C, 0x73, 0x4B, 0x83, 0xED, +0x83, 0xEE, 0x4A, 0x27, 0x31, 0x85, 0x31, 0x65, +0x39, 0xA6, 0x41, 0xE7, 0x4A, 0x48, 0x4A, 0x68, +0x5A, 0xAA, 0x63, 0x0C, 0x73, 0x6D, 0x73, 0xAE, +0x7B, 0xEF, 0x7B, 0xCF, 0x84, 0x10, 0xA5, 0x14, +0xCE, 0x59, 0xC5, 0xF7, 0xA4, 0xB0, 0xA4, 0xCF, +0xA4, 0xCF, 0xAC, 0xCF, 0xA4, 0xCF, 0xA4, 0xAF, +0xA4, 0xAF, 0xAC, 0xF1, 0xA4, 0xB0, 0xAC, 0xF0, +0xAD, 0x11, 0xAC, 0xF1, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xD0, 0xAC, 0xF0, 0xB5, 0x11, 0xBD, 0x31, +0xC5, 0x92, 0xC5, 0xB3, 0xC5, 0x92, 0xC5, 0x92, +0xC5, 0x93, 0xCD, 0xD4, 0xCD, 0xF4, 0xD6, 0x14, +0xDE, 0x55, 0xD6, 0x14, 0xC5, 0x92, 0xC5, 0x93, +0xAC, 0xF1, 0xA4, 0xD1, 0x83, 0xED, 0x94, 0x90, +0xB5, 0x73, 0xB5, 0x94, 0xB5, 0x94, 0xB5, 0x94, +0xCE, 0x36, 0xD6, 0x77, 0xD6, 0x77, 0xBD, 0xD4, +0xB5, 0x73, 0xB5, 0x73, 0x9C, 0xF1, 0xA5, 0x12, +0xAD, 0x32, 0xCE, 0x56, 0xD6, 0x76, 0xCE, 0x56, +0xAD, 0x52, 0xAD, 0x11, 0xBD, 0x93, 0xAD, 0x52, +0xAD, 0x32, 0xA4, 0xF1, 0xC5, 0xD4, 0xBD, 0xB4, +0xAD, 0x32, 0xBD, 0x73, 0xBD, 0x73, 0xC5, 0xB4, +0x94, 0x6F, 0x83, 0xED, 0xBD, 0x93, 0xB5, 0x53, +0xBD, 0xB3, 0xBD, 0xB4, 0xC5, 0xF4, 0xCE, 0x15, +0xCE, 0x15, 0xCE, 0x35, 0xCE, 0x35, 0xD6, 0x76, +0xDE, 0x97, 0xCE, 0x15, 0x94, 0x6F, 0x4A, 0x27, +0x31, 0x85, 0x29, 0x65, 0x31, 0x85, 0x4A, 0x49, +0x83, 0xCF, 0x62, 0xEB, 0x52, 0x69, 0x4A, 0x28, +0x4A, 0x28, 0x5A, 0x69, 0x62, 0x8A, 0x4A, 0x07, +0x52, 0x28, 0x52, 0x07, 0x62, 0x89, 0x83, 0x8D, +0x62, 0x8A, 0x4A, 0x08, 0x4A, 0x29, 0x52, 0x69, +0x83, 0xCF, 0xCE, 0x57, 0xDE, 0xD8, 0xDE, 0x97, +0xE6, 0xD8, 0xBD, 0x73, 0xA4, 0xD1, 0xB5, 0x32, +0xE6, 0xF8, 0xE6, 0xD7, 0xDE, 0x97, 0xE6, 0xB7, +0xDE, 0x75, 0xDE, 0x75, 0xDE, 0x75, 0xDE, 0x96, +0xDE, 0x76, 0xDE, 0x55, 0xD6, 0x15, 0xBD, 0x73, +0x83, 0xCD, 0x39, 0xA6, 0x31, 0x65, 0x18, 0xE4, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x83, 0x08, 0x83, +0x08, 0x83, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x83, 0x10, 0x83, 0x10, 0x83, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0xA4, 0xD2, 0xE6, 0x76, +0xDE, 0x34, 0xD5, 0xF4, 0xD6, 0x14, 0xBD, 0x72, +0x8C, 0x2E, 0x62, 0xEA, 0x31, 0x86, 0x29, 0x45, +0x21, 0x25, 0x21, 0x25, 0x21, 0x25, 0x19, 0x05, +0x18, 0xE4, 0x19, 0x04, 0x21, 0x25, 0x19, 0x05, +0x19, 0x05, 0x19, 0x05, 0x21, 0x05, 0x21, 0x46, +0x39, 0xE8, 0x7B, 0x8D, 0x8C, 0x0E, 0x8C, 0x0E, +0x9C, 0x6F, 0x94, 0x4F, 0x94, 0x6F, 0x9C, 0x8F, +0x9C, 0xB0, 0x94, 0x4E, 0x83, 0xED, 0x9C, 0x90, +0xAD, 0x12, 0xAD, 0x11, 0xAC, 0xF1, 0xA4, 0xD1, +0x64, 0x0A, 0x64, 0x09, 0x95, 0x50, 0xBE, 0x55, +0x8C, 0x8E, 0x84, 0x4B, 0x74, 0x46, 0x6C, 0x65, +0x74, 0x65, 0xA5, 0x8B, 0xA5, 0x0D, 0xA4, 0xEE, +0xA5, 0x10, 0x73, 0x6B, 0x41, 0xE6, 0x42, 0x28, +0x4A, 0x28, 0x5A, 0xCA, 0x63, 0x2C, 0x7C, 0x10, +0x8C, 0x51, 0xAD, 0x55, 0xD6, 0xBA, 0xEF, 0x5C, +0xCE, 0x58, 0x9C, 0xD1, 0xA4, 0xD1, 0xA4, 0xF1, +0xAD, 0x33, 0xA5, 0x12, 0xA4, 0xF1, 0xA5, 0x12, +0xA5, 0x12, 0xAD, 0x33, 0xAD, 0x53, 0xAD, 0x53, +0xAD, 0x33, 0xAD, 0x53, 0xAD, 0x73, 0xB5, 0x74, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x73, 0xB5, 0x92, +0xC5, 0xD3, 0xAC, 0xCF, 0x94, 0x2D, 0x9C, 0xD0, +0xAD, 0x52, 0xAD, 0x53, 0xAD, 0x53, 0xA5, 0x12, +0xA5, 0x12, 0xB5, 0x53, 0xAD, 0x53, 0xBD, 0xB5, +0xAD, 0x53, 0xB5, 0x53, 0xAD, 0x52, 0xAD, 0x32, +0xA4, 0xF1, 0xAD, 0x52, 0xBD, 0xB4, 0xB5, 0x73, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0x94, 0x6F, +0x39, 0xA6, 0x5A, 0xCB, 0x83, 0xEF, 0x73, 0x8E, +0x62, 0xEC, 0x7B, 0xEF, 0x6B, 0x6D, 0x52, 0x8A, +0x21, 0x04, 0x42, 0x08, 0xA5, 0x34, 0xCE, 0x59, +0xD6, 0x9A, 0xA5, 0x14, 0x62, 0xCB, 0x9C, 0x71, +0xAD, 0x14, 0xB5, 0x14, 0x7B, 0x4D, 0x94, 0x0F, +0xAC, 0xB2, 0x6B, 0x0C, 0x62, 0xCB, 0xA4, 0xB2, +0xEE, 0xFB, 0xF7, 0x3B, 0xDE, 0x57, 0xBD, 0x74, +0xB5, 0x32, 0xB5, 0x12, 0xB4, 0xF1, 0xA4, 0xAF, +0xAD, 0x53, 0xBE, 0x16, 0xB5, 0x94, 0xB5, 0xB4, +0xAD, 0x94, 0xBD, 0xF6, 0xB5, 0xB5, 0xB5, 0xD5, +0xB5, 0xB4, 0xB5, 0x93, 0xAC, 0xF0, 0xAC, 0xCF, +0xAD, 0x10, 0x9C, 0x8E, 0xB5, 0x52, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, 0xB5, 0x73, +0xA4, 0xD1, 0xA5, 0x12, 0xAD, 0x12, 0xB5, 0x74, +0xB5, 0x74, 0xAD, 0x12, 0xA4, 0xD1, 0xAD, 0x32, +0xC5, 0xD4, 0xA4, 0xD0, 0x52, 0x47, 0x31, 0xA5, +0x29, 0x64, 0x31, 0x85, 0x42, 0x07, 0x4A, 0x28, +0x5A, 0xCA, 0x6B, 0x4C, 0x6B, 0x2C, 0x6B, 0x4C, +0x6B, 0x4C, 0x73, 0xAE, 0x7B, 0xEF, 0xAD, 0x55, +0xBD, 0xD7, 0xD6, 0x79, 0xBD, 0xB6, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x32, 0xA4, 0xF0, 0xA4, 0xB0, +0xA4, 0xB0, 0x9C, 0xAF, 0x7B, 0xAC, 0x9C, 0x8F, +0x9C, 0xB0, 0xA4, 0xD1, 0xAD, 0x11, 0xAC, 0xD1, +0xA4, 0xD0, 0x9C, 0x90, 0xA4, 0xD0, 0xA4, 0xD0, +0xAC, 0xD1, 0xAC, 0xF1, 0xAD, 0x11, 0xB5, 0x11, +0xB5, 0x11, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF1, +0xAC, 0xF0, 0xAC, 0xF1, 0xBD, 0x72, 0xBD, 0x72, +0xBD, 0x73, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xF1, 0x94, 0x6F, +0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0x90, +0x94, 0x4F, 0x8C, 0x2E, 0x94, 0x4F, 0x9C, 0xB0, +0xAD, 0x32, 0xB5, 0x73, 0xC5, 0xF5, 0xCE, 0x35, +0xB5, 0x52, 0xAD, 0x32, 0xBD, 0x93, 0xAD, 0x52, +0xAD, 0x32, 0xA4, 0xD0, 0xCE, 0x15, 0xD6, 0x56, +0xCD, 0xD4, 0xCD, 0xD4, 0xD5, 0xF5, 0xDE, 0x76, +0xBD, 0x93, 0xB5, 0x53, 0xCE, 0x36, 0xCE, 0x36, +0xCE, 0x15, 0xCE, 0x15, 0xD6, 0x56, 0xD6, 0x55, +0xDE, 0x76, 0xD6, 0x56, 0xD6, 0x55, 0xD6, 0x35, +0xDE, 0x55, 0xDE, 0x55, 0xD6, 0x15, 0xBD, 0x73, +0x8C, 0x0E, 0x4A, 0x27, 0x31, 0x85, 0x29, 0x45, +0x31, 0xA6, 0x7B, 0xAE, 0x94, 0x91, 0x62, 0xEB, +0x41, 0xC7, 0x5A, 0x69, 0x5A, 0x8A, 0x4A, 0x08, +0x6A, 0xEB, 0x6A, 0xCB, 0x5A, 0x69, 0x7B, 0x4C, +0x83, 0x6D, 0x83, 0xAE, 0x5A, 0xAA, 0x5A, 0x8A, +0x73, 0x4C, 0xA4, 0xD2, 0xC6, 0x15, 0xE6, 0xB7, +0xEE, 0xF8, 0xAC, 0xD1, 0xAD, 0x12, 0xB5, 0x32, +0xD6, 0x76, 0xD6, 0x55, 0xDE, 0x76, 0xE6, 0xB6, +0xDE, 0x55, 0xE6, 0x95, 0xE6, 0x95, 0xDE, 0x75, +0xE6, 0x75, 0xE6, 0x96, 0xE6, 0xD7, 0xDE, 0x35, +0xC5, 0x94, 0xA4, 0xB1, 0xAD, 0x12, 0x4A, 0x28, +0x10, 0xC3, 0x10, 0x83, 0x08, 0x83, 0x10, 0x82, +0x10, 0x83, 0x08, 0x83, 0x08, 0x83, 0x08, 0x82, +0x08, 0x82, 0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, +0x18, 0xE4, 0x21, 0x04, 0xBD, 0x94, 0xE6, 0xB7, +0xDE, 0x34, 0xD5, 0xF3, 0xC5, 0xB2, 0xBD, 0x52, +0xA4, 0xD0, 0x83, 0xAC, 0x41, 0xE7, 0x39, 0xC6, +0x29, 0x66, 0x21, 0x46, 0x21, 0x25, 0x19, 0x04, +0x18, 0xE4, 0x21, 0x05, 0x21, 0x05, 0x19, 0x05, +0x19, 0x04, 0x19, 0x04, 0x21, 0x05, 0x29, 0x66, +0x4A, 0x49, 0x8C, 0x50, 0x94, 0x6F, 0x8B, 0xED, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x32, 0xA4, 0xD0, +0x94, 0x6F, 0x8C, 0x0E, 0x8C, 0x2E, 0xA4, 0xF1, +0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x52, 0xBD, 0x73, +0x64, 0x29, 0x64, 0x49, 0x8D, 0x4E, 0xBE, 0x75, +0x94, 0xCF, 0x74, 0x09, 0x74, 0x86, 0x6C, 0x64, +0x6C, 0x64, 0x8D, 0x09, 0x8C, 0x8B, 0x9C, 0xAD, +0xAD, 0x50, 0xB5, 0x50, 0x8C, 0x0C, 0x4A, 0x67, +0x39, 0xC6, 0x4A, 0x48, 0x52, 0xCA, 0x63, 0x0C, +0x8C, 0x92, 0xA5, 0x35, 0xBD, 0xF8, 0xBD, 0xD7, +0xDE, 0xFB, 0x9C, 0xD2, 0xA4, 0xF2, 0x94, 0x2E, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x4E, +0x8C, 0x0C, 0x94, 0x2D, 0x9C, 0x6E, 0x94, 0x2D, +0x83, 0xEC, 0x83, 0xCC, 0x7B, 0xAC, 0x84, 0x0D, +0x94, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, 0xAD, 0x10, +0xB5, 0x10, 0xA4, 0x8E, 0xAC, 0xAF, 0x94, 0x2D, +0x83, 0xCC, 0x8C, 0x2E, 0xA4, 0xD1, 0xA5, 0x12, +0xBD, 0xD5, 0xAD, 0x73, 0xAD, 0x32, 0xB5, 0x73, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD1, 0xA4, 0xF1, +0xA5, 0x12, 0xB5, 0x74, 0xBD, 0x94, 0xB5, 0x53, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0xD0, 0xA5, 0x11, +0x5A, 0xC9, 0x6B, 0x2B, 0x73, 0x8D, 0x6B, 0x0B, +0x6B, 0x4B, 0x6B, 0x4C, 0x52, 0x48, 0x31, 0x65, +0x6B, 0x6D, 0x63, 0x0B, 0x8C, 0x30, 0xBD, 0xB6, +0xD6, 0x79, 0xBD, 0x96, 0xB5, 0x54, 0xC5, 0xB6, +0x9C, 0x91, 0x7B, 0x4D, 0x9C, 0x51, 0xCD, 0xD6, +0x9C, 0x51, 0x8B, 0xCF, 0xA4, 0xB2, 0x9C, 0x51, +0x94, 0x51, 0x94, 0x71, 0x8C, 0x31, 0xAD, 0x34, +0xCE, 0x38, 0xDE, 0xBA, 0xDE, 0xB9, 0xC5, 0xF6, +0xBD, 0xB5, 0xA5, 0x33, 0xB5, 0x94, 0xBD, 0xF5, +0xBD, 0xF6, 0xBD, 0xD5, 0xAD, 0x94, 0xBD, 0xF6, +0xBD, 0xF5, 0xB5, 0x73, 0xB5, 0x52, 0xAC, 0xEF, +0xB5, 0x51, 0x9C, 0x8F, 0xBD, 0xB3, 0xCE, 0x35, +0xB5, 0x93, 0xA4, 0xF0, 0xBD, 0xD4, 0xBD, 0x93, +0xAD, 0x32, 0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x94, +0xAD, 0x12, 0xA4, 0xF2, 0xAD, 0x32, 0xB5, 0x52, +0xC5, 0xB3, 0xCD, 0xF4, 0x8C, 0x0E, 0x42, 0x06, +0x29, 0x64, 0x29, 0x43, 0x31, 0x85, 0x42, 0x07, +0x4A, 0x48, 0x52, 0x89, 0x6B, 0x4C, 0x73, 0x8D, +0x6B, 0x4D, 0x73, 0xAE, 0x7B, 0xEF, 0x94, 0xB3, +0xA5, 0x14, 0xAD, 0x75, 0xCE, 0x58, 0xD6, 0x78, +0xCE, 0x57, 0xBD, 0xB4, 0xAD, 0x11, 0xA5, 0x11, +0x94, 0x8F, 0x7B, 0xCC, 0x73, 0x6B, 0x8C, 0x4F, +0x94, 0x6F, 0xA4, 0xD1, 0xB5, 0x53, 0x94, 0x4F, +0xA5, 0x11, 0xB5, 0x32, 0xB5, 0x52, 0xA4, 0xD0, +0xA4, 0xF1, 0xAD, 0x11, 0x9C, 0xAF, 0xA4, 0xB0, +0xB5, 0x52, 0xBD, 0xB3, 0xB5, 0x32, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xF0, 0x94, 0x6E, 0x9C, 0x6F, +0xB5, 0x52, 0xA4, 0xD0, 0x9C, 0x6F, 0x9C, 0x8F, +0xA4, 0xD0, 0xA4, 0xB0, 0xAD, 0x11, 0x94, 0x6F, +0xAC, 0xF1, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x52, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xF1, 0xA4, 0xD0, +0xA4, 0xF1, 0xAD, 0x31, 0xAD, 0x32, 0xAD, 0x11, +0xA4, 0xD0, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x31, +0xBD, 0x73, 0xB5, 0x32, 0xAD, 0x32, 0xB5, 0x32, +0xAC, 0xF0, 0xAC, 0xD0, 0xA4, 0xB0, 0xB5, 0x32, +0xBD, 0x72, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x52, +0xBD, 0x93, 0xC5, 0xB4, 0xCE, 0x15, 0xC5, 0xB3, +0xCD, 0xF4, 0xDE, 0x56, 0xDE, 0x55, 0xD6, 0x35, +0xDE, 0x55, 0xD6, 0x15, 0xD5, 0xF4, 0xC5, 0xB3, +0xC5, 0xB3, 0xB5, 0x52, 0x6B, 0x0A, 0x31, 0x65, +0x29, 0x45, 0x31, 0x85, 0x52, 0x8A, 0x94, 0x71, +0x94, 0x71, 0x73, 0x2D, 0x52, 0x69, 0x52, 0x29, +0x52, 0x28, 0x73, 0x2C, 0x73, 0x0C, 0x5A, 0x48, +0x73, 0x0B, 0x73, 0x0C, 0x94, 0x10, 0x73, 0x4C, +0x6B, 0x0B, 0xA4, 0xB2, 0xBD, 0x95, 0xA4, 0xD1, +0xDE, 0x98, 0xBD, 0x73, 0xB5, 0x32, 0xBD, 0x73, +0xD6, 0x56, 0xDE, 0x75, 0xDE, 0x96, 0xE6, 0x96, +0xDE, 0x54, 0xE6, 0x75, 0xEE, 0xB6, 0xE6, 0x95, +0xE6, 0x75, 0xE6, 0x95, 0xE6, 0x95, 0xD6, 0x14, +0xDE, 0x35, 0xDE, 0x76, 0xE6, 0x97, 0x8B, 0xED, +0x4A, 0x28, 0x20, 0xE4, 0x10, 0x83, 0x08, 0x63, +0x10, 0x83, 0x10, 0x83, 0x08, 0x82, 0x08, 0x82, +0x08, 0x82, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xC3, +0x18, 0xE4, 0x39, 0xA6, 0xD6, 0x56, 0xD6, 0x14, +0xD6, 0x13, 0xD6, 0x14, 0xDE, 0x75, 0xD6, 0x34, +0xC5, 0x93, 0x9C, 0x4E, 0x73, 0x4B, 0x62, 0xEA, +0x42, 0x07, 0x31, 0x86, 0x29, 0x46, 0x29, 0x25, +0x21, 0x05, 0x21, 0x05, 0x21, 0x04, 0x19, 0x04, +0x18, 0xE4, 0x18, 0xE4, 0x21, 0x25, 0x31, 0xA7, +0x73, 0x8D, 0xA4, 0xF1, 0x83, 0xCC, 0x6B, 0x0A, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x32, 0xBD, 0x93, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xD1, +0xAD, 0x12, 0xBD, 0x73, 0xCE, 0x15, 0xDE, 0x76, +0x64, 0x08, 0x64, 0x48, 0x74, 0xCB, 0x7C, 0x8C, +0x84, 0xCE, 0x8C, 0xCC, 0x74, 0x88, 0x6C, 0x65, +0x95, 0xCD, 0x74, 0x49, 0x7C, 0x4B, 0x8C, 0x6D, +0x83, 0xEB, 0x73, 0x6A, 0x8C, 0x0C, 0x9C, 0xAE, +0x52, 0x67, 0x39, 0xC6, 0x4A, 0x48, 0x5A, 0xCA, +0x6B, 0x8D, 0x8C, 0x51, 0xA5, 0x15, 0xC6, 0x19, +0xB5, 0x76, 0x8C, 0x51, 0xEF, 0x5C, 0xB5, 0x53, +0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xEF, +0xB4, 0xEF, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xCF, +0xAC, 0xAF, 0xAC, 0xAF, 0x9C, 0x4D, 0x9C, 0x6D, +0xA4, 0x6E, 0xAC, 0xEF, 0xB4, 0xEF, 0xB4, 0xCF, +0xB4, 0xEF, 0xB4, 0xF0, 0xA4, 0x8E, 0x94, 0x4E, +0x94, 0x4E, 0x8C, 0x2D, 0x8C, 0x0D, 0x8C, 0x0D, +0x83, 0xCD, 0x8C, 0x0D, 0x8C, 0x0D, 0x8C, 0x2E, +0x94, 0x4E, 0xAD, 0x11, 0xA4, 0xF1, 0x9C, 0x8F, +0x8C, 0x2E, 0x94, 0x4E, 0x9C, 0xB0, 0xAD, 0x11, +0x8C, 0x2E, 0x73, 0x8C, 0xCD, 0xF5, 0xBD, 0x92, +0xC5, 0xD4, 0xD6, 0x35, 0xAC, 0xF0, 0x94, 0x2E, +0x5A, 0xAA, 0x8C, 0x51, 0xA5, 0x14, 0xB5, 0x96, +0xCE, 0x59, 0xDE, 0x9A, 0xAD, 0x14, 0xBD, 0x96, +0xB5, 0x54, 0xA4, 0xB2, 0xBD, 0x96, 0xC5, 0xB6, +0xCD, 0xF8, 0xC5, 0x96, 0x8B, 0xCF, 0x83, 0xAE, +0x9C, 0x92, 0x7B, 0xAE, 0xB5, 0x76, 0xBD, 0xB6, +0xC5, 0xF7, 0xAD, 0x75, 0xB5, 0xB6, 0xE6, 0xFC, +0xE7, 0x3C, 0x9C, 0xF3, 0x94, 0x91, 0x9C, 0xD1, +0x9D, 0x12, 0xAD, 0x74, 0xB5, 0xB5, 0xC6, 0x57, +0xCE, 0x77, 0xCE, 0x56, 0xB5, 0x52, 0xAC, 0xF0, +0xB5, 0x52, 0x9C, 0xAF, 0xAD, 0x11, 0xB5, 0x52, +0xBD, 0x93, 0x94, 0x6F, 0xC5, 0xD4, 0xCE, 0x15, +0xBD, 0xB4, 0xBD, 0xD5, 0xAD, 0x53, 0xAD, 0x32, +0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x52, 0xAD, 0x11, +0xB5, 0x52, 0xCE, 0x14, 0xAC, 0xF0, 0x7B, 0xAC, +0x39, 0xC5, 0x31, 0x84, 0x39, 0xA6, 0x4A, 0x27, +0x5A, 0xCA, 0x62, 0xEB, 0x6B, 0x4C, 0x6B, 0x4D, +0x63, 0x0C, 0x63, 0x0C, 0x6B, 0x4D, 0x73, 0x6E, +0x94, 0xB3, 0xAD, 0x76, 0xC6, 0x38, 0xBD, 0xD6, +0xA5, 0x13, 0xA5, 0x33, 0x94, 0x90, 0xB5, 0x73, +0xB5, 0x93, 0x84, 0x2E, 0x84, 0x2F, 0x9C, 0xD1, +0xA4, 0xF1, 0xA4, 0xD1, 0xB5, 0x73, 0x94, 0x6F, +0x9C, 0xB0, 0xAD, 0x11, 0xAD, 0x12, 0xA4, 0xD0, +0xBD, 0xB4, 0xAD, 0x52, 0x9C, 0xD0, 0x9C, 0xB0, +0xB5, 0x93, 0xCE, 0x35, 0xC6, 0x14, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x73, +0xBD, 0x93, 0xAD, 0x31, 0xAD, 0x31, 0xAC, 0xF1, +0xAD, 0x31, 0x9C, 0x8F, 0xA4, 0xF1, 0xBD, 0x94, +0xB5, 0x52, 0xB5, 0x52, 0x9C, 0xB0, 0xB5, 0x52, +0xDE, 0x76, 0xCD, 0xF4, 0xD6, 0x35, 0xD6, 0x55, +0xD6, 0x35, 0xB5, 0x52, 0x9C, 0x90, 0xA4, 0xD0, +0xA4, 0xD0, 0xBD, 0x93, 0xAD, 0x11, 0xB5, 0x73, +0xB5, 0x52, 0xAC, 0xF1, 0x94, 0x2E, 0x94, 0x2E, +0xA4, 0x8F, 0xB5, 0x11, 0xB5, 0x52, 0x9C, 0x6F, +0x9C, 0x6F, 0x94, 0x2E, 0x9C, 0x4F, 0x9C, 0x6F, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0x90, 0x9C, 0x6F, +0xA4, 0x8F, 0x9C, 0x6F, 0x9C, 0x6E, 0x9C, 0x4E, +0x9C, 0x2E, 0x9C, 0x6E, 0xA4, 0x8F, 0x9C, 0x4F, +0x94, 0x2E, 0x9C, 0x6F, 0xA4, 0xB0, 0x8C, 0x0E, +0x4A, 0x27, 0x29, 0x65, 0x29, 0x45, 0x52, 0x69, +0x8C, 0x50, 0x8C, 0x30, 0xA4, 0xF3, 0x94, 0x51, +0x73, 0x6D, 0x62, 0x8A, 0x5A, 0x69, 0x5A, 0x89, +0x5A, 0x69, 0x62, 0xAA, 0x73, 0x0B, 0x7B, 0x6D, +0x5A, 0x8A, 0x62, 0xCB, 0x9C, 0x71, 0xAC, 0xD2, +0x83, 0xAD, 0x94, 0x2F, 0x9C, 0x70, 0xBD, 0x93, +0xEF, 0x18, 0xEE, 0xF7, 0xEE, 0xF7, 0xEE, 0xD6, +0xE6, 0xB6, 0xE6, 0x95, 0xE6, 0x95, 0xEE, 0xB5, +0xE6, 0x95, 0xE6, 0x74, 0xDE, 0x54, 0xDE, 0x34, +0xEE, 0xB6, 0xF6, 0xF7, 0xEE, 0xD7, 0xBD, 0x72, +0x9C, 0x6F, 0x6B, 0x0B, 0x31, 0x65, 0x10, 0x83, +0x10, 0xA3, 0x10, 0x83, 0x08, 0x82, 0x08, 0x82, +0x08, 0x82, 0x10, 0x83, 0x10, 0x83, 0x18, 0xC4, +0x18, 0xE4, 0x73, 0x8C, 0xE6, 0xF8, 0xD6, 0x13, +0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, +0xCE, 0x14, 0xB5, 0x52, 0xA4, 0xD0, 0x83, 0xED, +0x62, 0xEA, 0x39, 0xE7, 0x39, 0xE7, 0x39, 0xC7, +0x29, 0x46, 0x21, 0x25, 0x21, 0x04, 0x21, 0x04, +0x18, 0xE4, 0x21, 0x05, 0x29, 0x66, 0x52, 0x6A, +0xBD, 0xB5, 0xCE, 0x35, 0x94, 0x6F, 0x62, 0xC9, +0xAD, 0x12, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xD4, 0xBD, 0x94, 0xBD, 0x94, +0xC5, 0xD5, 0xCE, 0x15, 0xD6, 0x35, 0xD6, 0x35, +0x53, 0xC6, 0x64, 0x67, 0x5B, 0xC7, 0x53, 0x66, +0x74, 0x8C, 0x7C, 0xAC, 0x74, 0x69, 0x5B, 0xE5, +0xA6, 0x30, 0x95, 0x6F, 0x94, 0xEE, 0xA5, 0x0F, +0xB5, 0x92, 0xAD, 0x51, 0xA4, 0xF0, 0xB5, 0x50, +0xAD, 0x10, 0x62, 0xE9, 0x42, 0x07, 0x3A, 0x07, +0x4A, 0x89, 0x6B, 0x6D, 0x8C, 0x71, 0xAD, 0x76, +0x84, 0x11, 0x94, 0x72, 0xBD, 0xD7, 0x84, 0x30, +0x52, 0x68, 0x83, 0xED, 0x9C, 0x8F, 0x8C, 0x0C, +0x94, 0x4D, 0x9C, 0x6E, 0xA4, 0xAE, 0xB5, 0x31, +0xAC, 0xF0, 0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xCF, +0xB5, 0x10, 0xAC, 0xCF, 0x9C, 0x6E, 0xA4, 0x8E, +0xA4, 0xAE, 0xA4, 0xAF, 0xAC, 0xAE, 0xB4, 0xEF, +0xAC, 0xCF, 0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xAF, +0xA4, 0x8E, 0xAC, 0xD0, 0xAC, 0xD0, 0xA4, 0xAF, +0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xF0, +0xAC, 0xCF, 0xA4, 0xCF, 0xA4, 0xAF, 0xA4, 0xAE, +0xA4, 0xAF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xF0, +0xB5, 0x51, 0x7B, 0xAC, 0xA4, 0xD0, 0xA4, 0x8E, +0xB5, 0x10, 0xBD, 0x31, 0xB4, 0xEF, 0xC5, 0x52, +0x73, 0x2B, 0x4A, 0x07, 0x62, 0xCB, 0x8C, 0x30, +0x94, 0x51, 0xAD, 0x55, 0xE7, 0x1C, 0xA4, 0xF4, +0x52, 0x4A, 0x73, 0x6E, 0x73, 0x6E, 0x73, 0x4E, +0x73, 0x4E, 0x94, 0x72, 0x83, 0xCF, 0x9C, 0x72, +0x8C, 0x10, 0xA4, 0xF4, 0xC5, 0xD7, 0xA5, 0x14, +0x73, 0x6D, 0x52, 0x6A, 0x73, 0xAF, 0xB5, 0xB7, +0xCE, 0x59, 0xCE, 0x59, 0xBD, 0xD7, 0x9C, 0xD2, +0xB5, 0x94, 0xC6, 0x37, 0xC6, 0x37, 0xC6, 0x16, +0xBE, 0x15, 0xC6, 0x15, 0xAD, 0x11, 0xB5, 0x31, +0xB5, 0x51, 0x94, 0x4D, 0xBD, 0x92, 0x9C, 0xAF, +0xAD, 0x31, 0xAD, 0x11, 0xBD, 0xB3, 0xD6, 0x56, +0xC5, 0xF4, 0xC5, 0xF4, 0xB5, 0x52, 0xA4, 0xF1, +0x94, 0x8F, 0xA5, 0x11, 0xAD, 0x32, 0xA4, 0xF1, +0xAD, 0x10, 0xD5, 0xF4, 0xB5, 0x31, 0xA4, 0x8F, +0x62, 0xC9, 0x39, 0xA5, 0x39, 0xC6, 0x4A, 0x48, +0x4A, 0x48, 0x4A, 0x48, 0x62, 0xEB, 0x5A, 0xEB, +0x52, 0x8A, 0x52, 0x8A, 0x5A, 0xEB, 0x7B, 0xCF, +0x94, 0x93, 0xA5, 0x14, 0xB5, 0xB6, 0xCE, 0x59, +0xA5, 0x34, 0xAD, 0x54, 0x94, 0x90, 0xB5, 0x93, +0xB5, 0x73, 0x94, 0xB0, 0xA5, 0x12, 0xB5, 0xB4, +0xAD, 0x33, 0xA4, 0xD1, 0xBD, 0x94, 0x9C, 0x90, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD4, 0xAD, 0x11, +0xBD, 0xB4, 0xB5, 0x93, 0xAD, 0x52, 0xA5, 0x32, +0xA4, 0xF1, 0xC5, 0xF4, 0xC6, 0x15, 0xBD, 0xB3, +0xAD, 0x52, 0xAD, 0x32, 0xAD, 0x52, 0xB5, 0x93, +0xBD, 0xB4, 0xC6, 0x15, 0xBD, 0xD4, 0xBD, 0xD4, +0xC5, 0xF4, 0xA4, 0xD0, 0xB5, 0x52, 0xBD, 0x73, +0xB5, 0x31, 0xC5, 0xB3, 0xBD, 0x93, 0xC5, 0xB3, +0xCD, 0xD3, 0xC5, 0xB2, 0xCD, 0xB3, 0xCD, 0xF3, +0xD6, 0x35, 0xB5, 0x32, 0x9C, 0x6F, 0xA4, 0xF1, +0xAD, 0x52, 0xC5, 0xD5, 0xC5, 0xD5, 0xC5, 0xD4, +0xB5, 0x52, 0xB5, 0x32, 0x8C, 0x2E, 0xA4, 0xD1, +0xB5, 0x73, 0xC5, 0xD4, 0xBD, 0xB4, 0x94, 0x6F, +0xA4, 0xB0, 0xAD, 0x12, 0xAC, 0xF1, 0x9C, 0x8F, +0x9C, 0x4E, 0x9C, 0x8F, 0xA4, 0xB0, 0xA4, 0xB0, +0x9C, 0x6F, 0xA4, 0x8F, 0x9C, 0x8F, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF1, 0xAC, 0xD1, +0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x53, 0xBD, 0x73, +0xAC, 0xF1, 0x73, 0x6C, 0x39, 0xA6, 0x29, 0x24, +0x39, 0x86, 0x5A, 0xAA, 0x8C, 0x30, 0xAD, 0x14, +0xBD, 0x96, 0xAD, 0x14, 0x8C, 0x10, 0x62, 0xEB, +0x4A, 0x08, 0x49, 0xE7, 0x62, 0xAA, 0x94, 0x0F, +0x8B, 0xEF, 0x62, 0xCA, 0x7B, 0x6D, 0x94, 0x0F, +0x8C, 0x0F, 0x5A, 0x8A, 0x5A, 0x8A, 0x83, 0xAD, +0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xB5, 0x30, 0xC5, 0x51, 0xC5, 0x71, +0xC5, 0x71, 0xC5, 0x92, 0xCD, 0xB2, 0xCD, 0xB3, +0xD5, 0xF3, 0xD6, 0x14, 0xD6, 0x14, 0xC5, 0xB3, +0xBD, 0x52, 0xAC, 0xF1, 0x7B, 0x6C, 0x20, 0xE4, +0x10, 0x82, 0x10, 0x83, 0x08, 0x82, 0x08, 0x82, +0x08, 0x82, 0x10, 0x83, 0x10, 0xA3, 0x18, 0xC4, +0x18, 0xE4, 0x9C, 0xD1, 0xDE, 0x96, 0xCD, 0xD3, +0xDE, 0x55, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x75, +0xDE, 0x55, 0xC5, 0xD3, 0xC5, 0xD4, 0xA4, 0xF1, +0x94, 0x6F, 0x73, 0x6C, 0x6B, 0x4B, 0x4A, 0x69, +0x39, 0xC7, 0x29, 0x66, 0x29, 0x46, 0x21, 0x05, +0x21, 0x25, 0x29, 0x66, 0x52, 0x8A, 0xA4, 0xF2, +0xDE, 0xB8, 0xDE, 0xB7, 0xD6, 0x56, 0xB5, 0x73, +0xBD, 0x93, 0xD6, 0x76, 0xCE, 0x15, 0xD6, 0x56, +0xCE, 0x35, 0xC5, 0xD4, 0xC5, 0xF4, 0xD6, 0x56, +0xD6, 0x36, 0xD6, 0x56, 0xCE, 0x14, 0xCD, 0xF4, +0x4B, 0x65, 0x43, 0x23, 0x53, 0xA5, 0x64, 0x28, +0x7C, 0xCC, 0x84, 0xCD, 0x74, 0x6A, 0x5B, 0xC6, +0x85, 0x2C, 0x9D, 0xD0, 0x74, 0x0A, 0x94, 0xED, +0xAD, 0x70, 0xA5, 0x10, 0x8C, 0x4C, 0xA4, 0xCF, +0xB5, 0x92, 0xBD, 0xD3, 0x63, 0x2A, 0x39, 0xE7, +0x3A, 0x07, 0x4A, 0x69, 0x5B, 0x0B, 0x6B, 0x4D, +0x9C, 0xD3, 0xBD, 0xB7, 0xAD, 0x55, 0x63, 0x2C, +0x73, 0x6D, 0x7B, 0xCE, 0xBD, 0xB5, 0xB5, 0x73, +0xAD, 0x32, 0xA4, 0xF1, 0xB5, 0x53, 0xC5, 0xD4, +0xBD, 0x93, 0xDE, 0x76, 0xC5, 0xB3, 0xAC, 0xEF, +0xBD, 0xB3, 0xB5, 0x72, 0xB5, 0x52, 0xAD, 0x31, +0xAD, 0x31, 0xAC, 0xF0, 0xA4, 0xCF, 0xAC, 0xF0, +0xAC, 0xF0, 0xB5, 0x10, 0xAC, 0xCF, 0xA4, 0xCF, +0xAD, 0x10, 0xB5, 0x31, 0xAC, 0xF0, 0xA4, 0xAF, +0xA4, 0xAF, 0xB5, 0x10, 0xAD, 0x10, 0xAC, 0xF0, +0xAD, 0x10, 0xA4, 0xAF, 0xAC, 0xAF, 0xB5, 0x30, +0xB5, 0x30, 0xAC, 0xEF, 0xAC, 0xCF, 0xA4, 0x8E, +0xB5, 0x30, 0x73, 0x8B, 0xA4, 0xF0, 0xBD, 0x71, +0xBD, 0x30, 0xBD, 0x30, 0xC5, 0x71, 0xCD, 0xB2, +0xBD, 0x31, 0x73, 0x2B, 0x5A, 0x89, 0x52, 0x49, +0x7B, 0xAF, 0xCE, 0x59, 0xCE, 0x39, 0xDE, 0xBB, +0xCE, 0x39, 0x5A, 0xAB, 0x10, 0xA4, 0x18, 0xC4, +0x10, 0x83, 0x4A, 0x4A, 0x94, 0x51, 0x7B, 0x8E, +0x94, 0x51, 0xBD, 0xD7, 0x94, 0x72, 0x83, 0xCF, +0x8C, 0x51, 0xA4, 0xF3, 0xBD, 0xF8, 0xBD, 0xD7, +0xC5, 0xF8, 0xD6, 0x9A, 0xE7, 0x3D, 0xEF, 0x3C, +0xB5, 0x96, 0x94, 0x91, 0x94, 0xB0, 0x94, 0x8F, +0xA4, 0xF0, 0xB5, 0x52, 0xB5, 0x10, 0xAC, 0xEF, +0xB5, 0x31, 0xA4, 0xAF, 0xA4, 0xCF, 0x83, 0xAB, +0x9C, 0xAF, 0xA4, 0xCF, 0xB5, 0x51, 0xCE, 0x14, +0xC5, 0xF4, 0xCE, 0x15, 0xBD, 0xB3, 0xB5, 0x73, +0xAD, 0x11, 0xAD, 0x32, 0xB5, 0x52, 0xAD, 0x32, +0xBD, 0x72, 0xCE, 0x14, 0xB4, 0xF0, 0xA4, 0xB0, +0x8C, 0x0E, 0x4A, 0x27, 0x31, 0x64, 0x39, 0xC6, +0x52, 0x89, 0x5A, 0xCA, 0x63, 0x2C, 0x5A, 0xEB, +0x4A, 0x69, 0x5A, 0xEB, 0x6B, 0x4D, 0x7B, 0xF0, +0x8C, 0x31, 0x94, 0x93, 0xB5, 0x96, 0xD6, 0xBA, +0xC6, 0x38, 0xAD, 0x75, 0xAD, 0x53, 0xB5, 0xB4, +0xB5, 0xD4, 0xB5, 0xB4, 0xB5, 0xB4, 0xA5, 0x53, +0xAD, 0x32, 0x9C, 0xB0, 0xBD, 0xB4, 0xA4, 0xD1, +0xBD, 0x94, 0xBD, 0xD5, 0xC5, 0xF5, 0xA5, 0x12, +0xB5, 0x93, 0xBD, 0xD5, 0xBD, 0xB4, 0xBD, 0xD5, +0xA5, 0x12, 0xBD, 0xB4, 0xC5, 0xF5, 0xBD, 0xD4, +0xAD, 0x32, 0xB5, 0x73, 0xA5, 0x11, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, +0xBD, 0xB3, 0x9C, 0x8F, 0xB5, 0x52, 0xC5, 0x93, +0xC5, 0xB3, 0xD6, 0x34, 0xC5, 0xD3, 0xD6, 0x14, +0xD6, 0x34, 0xDE, 0x34, 0xDE, 0x34, 0xE6, 0x95, +0xE6, 0x75, 0xC5, 0xB3, 0xA4, 0xB0, 0xAD, 0x12, +0xBD, 0x94, 0xB5, 0x93, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x53, 0xBD, 0xB4, 0x9C, 0xB0, 0xB5, 0x53, +0xB5, 0x53, 0xBD, 0xB4, 0xCE, 0x15, 0x94, 0x4E, +0xAD, 0x11, 0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xD0, +0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xD0, +0x9C, 0x8F, 0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x32, +0xAC, 0xF1, 0xAC, 0xD1, 0xAD, 0x11, 0x9C, 0x8F, +0x9C, 0x8F, 0xA4, 0x8F, 0x8B, 0xED, 0x83, 0x8B, +0x94, 0x2E, 0x8C, 0x0D, 0x94, 0x4E, 0x52, 0x68, +0x29, 0x44, 0x39, 0x86, 0x41, 0xE7, 0x52, 0x49, +0x6A, 0xEC, 0x8C, 0x30, 0xB5, 0x55, 0xBD, 0xD7, +0x94, 0x92, 0x6B, 0x0C, 0x41, 0xC7, 0x73, 0x2C, +0x9C, 0x50, 0x9C, 0x91, 0x73, 0x2C, 0x73, 0x4D, +0x7B, 0x8D, 0x52, 0x69, 0x6B, 0x0C, 0x83, 0xEF, +0x94, 0x2F, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x12, 0xB5, 0x12, 0xB5, 0x12, +0xAC, 0xF2, 0xAD, 0x12, 0xB5, 0x53, 0xB5, 0x12, +0xAC, 0xF1, 0xA4, 0xD1, 0xAC, 0xF1, 0xAD, 0x11, +0xAD, 0x11, 0xAD, 0x11, 0x94, 0x4F, 0x39, 0xA6, +0x10, 0x82, 0x10, 0x82, 0x10, 0x82, 0x10, 0x82, +0x10, 0x82, 0x10, 0x82, 0x10, 0xC3, 0x18, 0xC3, +0x31, 0xA7, 0x94, 0x70, 0xA4, 0xD0, 0xAD, 0x11, +0xB5, 0x31, 0xBD, 0x92, 0xBD, 0x92, 0xBD, 0x72, +0xBD, 0x72, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xA4, 0xF1, 0x8C, 0x2E, 0x83, 0xED, 0x6B, 0x0B, +0x52, 0x89, 0x42, 0x08, 0x31, 0xA7, 0x31, 0x86, +0x39, 0xA7, 0x4A, 0x69, 0x7B, 0xCE, 0x9C, 0xD1, +0xBD, 0xD4, 0xB5, 0x52, 0xBD, 0xB4, 0x94, 0x4F, +0x83, 0xED, 0xDE, 0x97, 0xD6, 0x77, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x57, 0xD6, 0x77, 0xD6, 0x77, +0xBD, 0xB4, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0x73, +0x32, 0xA3, 0x6C, 0x4A, 0x9D, 0xD2, 0x9D, 0xB2, +0x74, 0x4C, 0x7C, 0x8C, 0x7C, 0xAB, 0x7C, 0x8A, +0x6C, 0x49, 0x74, 0x6A, 0x8D, 0x0C, 0x84, 0xA9, +0x84, 0xCA, 0x8C, 0xAC, 0x8C, 0x6C, 0xA4, 0xCE, +0xC5, 0xD3, 0xC6, 0x15, 0xC5, 0xF5, 0x7B, 0xCE, +0x39, 0xE6, 0x39, 0xE6, 0x42, 0x48, 0x5A, 0xEB, +0x84, 0x31, 0x84, 0x10, 0x94, 0x92, 0x73, 0x6D, +0x7B, 0xAF, 0xBD, 0xD7, 0xD6, 0x79, 0xC6, 0x16, +0xBD, 0xD5, 0xBD, 0xD5, 0xCE, 0x57, 0xCE, 0x56, +0xAD, 0x31, 0xC5, 0xD3, 0xBD, 0x72, 0xB5, 0x30, +0xC5, 0xD4, 0xB5, 0xB4, 0xB5, 0xB4, 0xBD, 0xD4, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xD4, 0xC5, 0xF4, +0xC5, 0xF4, 0xC5, 0xD3, 0xBD, 0xB3, 0xC5, 0xD4, +0xCE, 0x35, 0xD6, 0x55, 0xD6, 0x76, 0xD6, 0x76, +0xCE, 0x35, 0xCE, 0x14, 0xC5, 0xD4, 0xBD, 0x93, +0xC5, 0xD3, 0xBD, 0x92, 0xAC, 0xCF, 0xAC, 0xEF, +0xAC, 0xCF, 0x9C, 0x4D, 0x94, 0x4D, 0x94, 0x0C, +0x94, 0x2D, 0x5A, 0xC9, 0x73, 0xAC, 0x8C, 0x2D, +0x94, 0x4D, 0x8B, 0xEC, 0xA4, 0xAE, 0x9C, 0x6D, +0x9C, 0x4D, 0x94, 0x2F, 0x5A, 0xA9, 0x52, 0x69, +0x8C, 0x31, 0xAD, 0x55, 0x62, 0xEC, 0xB5, 0x97, +0xE6, 0xFC, 0xE7, 0x1C, 0x9C, 0xB3, 0x52, 0x8A, +0x31, 0x87, 0x52, 0xAB, 0x39, 0xC7, 0x4A, 0x29, +0x8C, 0x51, 0x94, 0x92, 0x62, 0xEC, 0x83, 0xEF, +0xA4, 0xF3, 0xAD, 0x75, 0xB5, 0xB7, 0xBD, 0xB7, +0xBD, 0xF8, 0xD6, 0x9B, 0xD6, 0x9A, 0xCE, 0x59, +0xCE, 0x59, 0xC5, 0xF7, 0xAD, 0x54, 0xA4, 0xD1, +0xA4, 0xAF, 0xA4, 0x8E, 0xAC, 0xEF, 0xB5, 0x0F, +0xAD, 0x10, 0xAC, 0xEF, 0xB4, 0xEF, 0xAC, 0xEF, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xEF, +0xAD, 0x10, 0xB5, 0x31, 0xB5, 0x30, 0xB5, 0x51, +0xB5, 0x52, 0xCD, 0xD4, 0xAC, 0xF1, 0xC5, 0x93, +0xA4, 0xD0, 0xAC, 0xF0, 0x9C, 0x4E, 0xB5, 0x11, +0xAC, 0xD1, 0x6B, 0x0A, 0x42, 0x07, 0x42, 0x27, +0x4A, 0x68, 0x4A, 0x48, 0x52, 0x8A, 0x5A, 0xCB, +0x52, 0xAA, 0x5A, 0xEB, 0x73, 0x8E, 0x84, 0x11, +0x84, 0x11, 0x94, 0xB3, 0xB5, 0x96, 0xB5, 0x97, +0xC6, 0x39, 0xCE, 0x79, 0xB5, 0x94, 0xBD, 0xF5, +0xBD, 0xF5, 0xA5, 0x12, 0xA5, 0x32, 0xAD, 0x53, +0xB5, 0xB4, 0x9C, 0xB1, 0xBD, 0xB4, 0xA4, 0xF2, +0xB5, 0x73, 0xBD, 0xB4, 0xC6, 0x16, 0xB5, 0x94, +0xBD, 0xB4, 0xBD, 0xF5, 0xBD, 0xF5, 0xC6, 0x36, +0xB5, 0x73, 0xB5, 0x94, 0xBD, 0xD4, 0xC6, 0x16, +0xBD, 0xD5, 0xB5, 0xB4, 0xB5, 0xB4, 0xAD, 0x32, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xD0, 0xBD, 0xB4, +0xAD, 0x31, 0x9C, 0x8F, 0xB5, 0x52, 0xC5, 0xB3, +0xCD, 0xD2, 0xD6, 0x13, 0xC5, 0x92, 0xCD, 0xF3, +0xDE, 0x34, 0xDE, 0x54, 0xDE, 0x54, 0xE6, 0xB5, +0xDE, 0x55, 0xD6, 0x14, 0xA4, 0xB0, 0xAD, 0x32, +0xBD, 0x94, 0xB5, 0x94, 0xB5, 0x94, 0xBD, 0x94, +0xBD, 0xB4, 0xBD, 0xB5, 0xAD, 0x53, 0xB5, 0x73, +0xBD, 0x94, 0xC5, 0xD4, 0xD6, 0x56, 0x94, 0x4E, +0xAD, 0x32, 0xBD, 0x93, 0xA4, 0xF1, 0xA4, 0x90, +0xA4, 0xD0, 0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xD0, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x52, 0xBD, 0x73, +0xBD, 0x72, 0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0x9C, 0x8F, 0x8B, 0xED, +0x8B, 0xCC, 0x94, 0x2D, 0xAC, 0xF0, 0xA4, 0xD0, +0x83, 0xED, 0x52, 0x67, 0x29, 0x65, 0x29, 0x45, +0x39, 0x85, 0x41, 0xC7, 0x4A, 0x69, 0x7B, 0xCF, +0x9C, 0xF3, 0x94, 0x71, 0x41, 0xE8, 0x5A, 0x8A, +0x73, 0x0B, 0x94, 0x30, 0x8B, 0xEF, 0x5A, 0xAA, +0x4A, 0x49, 0x52, 0x49, 0x4A, 0x28, 0x73, 0x6D, +0x94, 0x50, 0x8C, 0x0E, 0xB5, 0x32, 0xAC, 0xF1, +0xCD, 0xF5, 0xBD, 0x93, 0xB5, 0x12, 0xB5, 0x52, +0xBD, 0x73, 0xBD, 0x52, 0xBD, 0x94, 0xBD, 0x73, +0xB5, 0x52, 0xAD, 0x32, 0xBD, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xB5, 0x53, 0xAD, 0x33, 0x4A, 0x48, +0x18, 0xA3, 0x10, 0x82, 0x10, 0x82, 0x10, 0x82, +0x10, 0x82, 0x10, 0xA3, 0x18, 0xE4, 0x18, 0xE4, +0x63, 0x2C, 0xB5, 0x53, 0xAC, 0xF1, 0xB5, 0x32, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x52, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x52, +0xAD, 0x32, 0xA4, 0xD1, 0x94, 0x4F, 0x8B, 0xEE, +0x73, 0x6C, 0x63, 0x0B, 0x52, 0x89, 0x52, 0x89, +0x63, 0x0B, 0x84, 0x0E, 0x83, 0xEE, 0x83, 0xCE, +0xA4, 0xD1, 0xAD, 0x32, 0xA4, 0xD1, 0x73, 0x8C, +0x62, 0xEB, 0x73, 0x4C, 0x7B, 0x8D, 0x83, 0xCD, +0x83, 0xEE, 0x83, 0xEE, 0x83, 0xEE, 0x73, 0x6C, +0x62, 0xEA, 0x73, 0x4C, 0x7B, 0x6C, 0x94, 0x2E, +0x85, 0x0E, 0xA5, 0xF3, 0xA5, 0xD4, 0xA5, 0xB4, +0xA5, 0xB3, 0x7C, 0x8D, 0x84, 0xCC, 0x8C, 0xCC, +0x85, 0x0C, 0x4B, 0x45, 0x64, 0x06, 0x6C, 0x25, +0x7C, 0x68, 0xA5, 0x2E, 0xA4, 0xEE, 0x9C, 0xCE, +0x8C, 0x4D, 0xAD, 0x72, 0xC5, 0xF5, 0xBD, 0xD5, +0x8C, 0x4F, 0x39, 0xE6, 0x42, 0x48, 0x63, 0x4D, +0x8C, 0x51, 0x84, 0x31, 0x7B, 0xEF, 0x73, 0x6E, +0x7B, 0xAF, 0xC6, 0x18, 0xCE, 0x79, 0xEF, 0x7D, +0xC6, 0x37, 0xB5, 0xB5, 0xCE, 0x57, 0xC5, 0xD5, +0xA4, 0xF1, 0xD6, 0x36, 0xBD, 0x51, 0xAC, 0xCF, +0xBD, 0x93, 0xBD, 0xD4, 0xBD, 0xD5, 0xC5, 0xF5, +0xBD, 0xF4, 0xBD, 0xF4, 0xBD, 0xD4, 0xC5, 0xD4, +0xC5, 0xF4, 0xC5, 0xF4, 0xBD, 0xD4, 0xC5, 0xF4, +0xC5, 0xD4, 0xC5, 0xF4, 0xCE, 0x35, 0xCE, 0x14, +0xCE, 0x15, 0xCE, 0x15, 0xD6, 0x56, 0xC5, 0xD4, +0xC5, 0xF4, 0xC5, 0xD3, 0xAC, 0xCF, 0xAC, 0xEF, +0xBD, 0x93, 0xB5, 0x72, 0xAD, 0x31, 0xA4, 0xD0, +0x8C, 0x0D, 0x7B, 0xAC, 0x8C, 0x6F, 0x94, 0x8F, +0x8C, 0x4D, 0x84, 0x0D, 0xA4, 0xF0, 0x9C, 0xAF, +0x94, 0x4E, 0x84, 0x0E, 0x7B, 0xAD, 0x62, 0xEA, +0x52, 0xAA, 0x73, 0xAF, 0x8C, 0x72, 0xC6, 0x18, +0xCE, 0x7A, 0xD6, 0xBB, 0xC5, 0xF8, 0xB5, 0x76, +0x94, 0x72, 0x8C, 0x31, 0x63, 0x0C, 0x7B, 0xEF, +0x6B, 0x2C, 0x7B, 0xAE, 0x7B, 0xAF, 0x8C, 0x31, +0x9C, 0xD3, 0xB5, 0x76, 0xB5, 0x96, 0x9C, 0xD4, +0xC6, 0x18, 0xBD, 0xB7, 0x9C, 0xD4, 0xA5, 0x15, +0xBD, 0xF8, 0xD6, 0x9A, 0xE7, 0x1B, 0xDE, 0x78, +0xCD, 0xD3, 0xC5, 0x71, 0xCD, 0xF3, 0xCD, 0xD2, +0xBD, 0x50, 0xC5, 0x91, 0xC5, 0x91, 0xBD, 0x30, +0xBD, 0x50, 0xBD, 0x50, 0xB5, 0x10, 0xAC, 0xEF, +0xB4, 0xEF, 0xAC, 0xCE, 0xA4, 0xAE, 0xAC, 0xEF, +0xB4, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xF0, +0xAC, 0xAF, 0x9C, 0x6E, 0xA4, 0xAF, 0xAC, 0xAF, +0x9C, 0x6F, 0x73, 0x4B, 0x52, 0x48, 0x39, 0xA5, +0x3A, 0x06, 0x4A, 0x48, 0x4A, 0x48, 0x4A, 0x69, +0x52, 0x89, 0x52, 0x8A, 0x6B, 0x6D, 0x7B, 0xEF, +0x84, 0x10, 0x8C, 0x31, 0xAD, 0x35, 0xAD, 0x76, +0xB5, 0xD7, 0xC6, 0x58, 0xB5, 0xB5, 0xA5, 0x12, +0xBD, 0xB4, 0xA5, 0x32, 0xAD, 0x53, 0xBD, 0xF6, +0xAD, 0x32, 0x94, 0x90, 0xBD, 0x94, 0xA4, 0xF1, +0xCE, 0x36, 0xBD, 0xF5, 0xC6, 0x36, 0xCE, 0x37, +0xC6, 0x16, 0xBD, 0xF5, 0xBD, 0xD5, 0xBD, 0xD5, +0xBD, 0xD5, 0xB5, 0xB4, 0xBD, 0xF5, 0xBD, 0xF5, +0xC6, 0x36, 0xC5, 0xF5, 0xC6, 0x16, 0xC6, 0x16, +0xBD, 0xD5, 0xAD, 0x52, 0xAD, 0x52, 0xC5, 0xF5, +0x94, 0x6E, 0xA4, 0xF0, 0xB5, 0x32, 0xC5, 0xB3, +0xD6, 0x13, 0xDE, 0x55, 0xDE, 0x34, 0xD6, 0x14, +0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, +0xDE, 0x54, 0xD6, 0x34, 0xA4, 0xF0, 0xAD, 0x32, +0xB5, 0x93, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD5, +0xC5, 0xD5, 0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xB4, +0xC5, 0xD5, 0xCE, 0x15, 0xCE, 0x15, 0x9C, 0x8F, +0xB5, 0x32, 0xC5, 0xD4, 0xBD, 0x73, 0xAD, 0x11, +0xB5, 0x11, 0xAC, 0xD0, 0xA4, 0xD0, 0xAC, 0xF1, +0xAC, 0xF1, 0xAC, 0xF0, 0xAD, 0x11, 0xAD, 0x11, +0xAC, 0xF0, 0xAD, 0x31, 0xB5, 0x31, 0xAD, 0x10, +0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x31, 0xAD, 0x10, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x6E, 0xAD, 0x11, +0xBD, 0xB3, 0xB5, 0x92, 0x73, 0x6B, 0x29, 0x65, +0x21, 0x24, 0x21, 0x03, 0x29, 0x45, 0x31, 0xA6, +0x3A, 0x07, 0x39, 0xC7, 0x39, 0xA6, 0x52, 0x49, +0x4A, 0x28, 0x5A, 0x69, 0x83, 0xCE, 0x83, 0xCE, +0x4A, 0x28, 0x62, 0xCB, 0x52, 0x69, 0x52, 0x8A, +0x73, 0x4D, 0x94, 0x71, 0x94, 0x2F, 0x94, 0x4F, +0xBD, 0x73, 0xEE, 0xD7, 0xD6, 0x15, 0xDE, 0x55, +0xDE, 0x35, 0xCD, 0xD3, 0xC5, 0xB3, 0xCD, 0xD4, +0xCD, 0xB3, 0xD6, 0x55, 0xC5, 0xD4, 0xAD, 0x11, +0xB5, 0x73, 0xB5, 0x73, 0xBD, 0x94, 0x42, 0x07, +0x10, 0xA3, 0x10, 0x82, 0x10, 0x82, 0x10, 0x82, +0x10, 0xA3, 0x10, 0xC3, 0x18, 0xE4, 0x18, 0xE4, +0x73, 0x8D, 0x9C, 0xD1, 0xAD, 0x11, 0xB5, 0x73, +0xAC, 0xF1, 0xB5, 0x73, 0xA4, 0xD0, 0x94, 0x4F, +0xA4, 0xD0, 0xA4, 0xD1, 0x94, 0x4F, 0x9C, 0x6F, +0x9C, 0x8F, 0xA4, 0xD1, 0x94, 0x4F, 0xA4, 0xD0, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0xAD, 0x8C, 0x0F, +0xA5, 0x12, 0xB5, 0x73, 0xBD, 0xB5, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, 0xB5, 0x53, +0xAD, 0x33, 0xAD, 0x33, 0xAD, 0x13, 0xA4, 0xF2, +0xA4, 0xF2, 0xA4, 0xD2, 0x9C, 0xD2, 0x9C, 0x91, +0x94, 0x70, 0x8C, 0x2F, 0x94, 0x4F, 0x8C, 0x0E, +0x8C, 0xEF, 0x7C, 0x8E, 0xAD, 0xF5, 0x9D, 0x93, +0x8D, 0x31, 0x7C, 0xAD, 0x64, 0x09, 0x74, 0x49, +0x85, 0x0C, 0x63, 0xC7, 0x4B, 0x43, 0x63, 0xE5, +0x6B, 0xE7, 0x6B, 0xC8, 0x8C, 0x8B, 0x6B, 0x87, +0x8C, 0x8D, 0xAD, 0x72, 0xB5, 0x73, 0xB5, 0x73, +0xBD, 0xD4, 0x7B, 0xCD, 0x4A, 0x68, 0x63, 0x0B, +0x6B, 0x2C, 0x6B, 0x4C, 0x6B, 0x2C, 0x5A, 0xAB, +0x8C, 0x71, 0x9C, 0xF3, 0xC6, 0x39, 0xE6, 0xFC, +0xDE, 0xFB, 0xD6, 0xBA, 0x9C, 0xD2, 0x73, 0x6D, +0x9C, 0xB2, 0xAD, 0x53, 0x83, 0xCC, 0xA4, 0x8F, +0xB5, 0x73, 0xC5, 0xF5, 0xC6, 0x16, 0xC6, 0x16, +0xC6, 0x15, 0xBD, 0xF5, 0xBD, 0xD4, 0xBD, 0xD4, +0xBD, 0xD4, 0xC5, 0xF5, 0xC6, 0x15, 0xD6, 0x56, +0xC5, 0xD4, 0xB5, 0x93, 0xBD, 0x93, 0xB5, 0x93, +0xBD, 0xB3, 0xB5, 0x73, 0xBD, 0xD4, 0xB5, 0x73, +0xC5, 0xF4, 0xC5, 0xB2, 0xAC, 0xAE, 0xA4, 0xF0, +0xBD, 0xB3, 0xB5, 0x72, 0xA4, 0xF1, 0xA4, 0xF1, +0xA4, 0xD0, 0xA4, 0xF1, 0xB5, 0x73, 0xA4, 0xF1, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, +0xAD, 0x32, 0x94, 0x90, 0x83, 0xEE, 0x84, 0x0E, +0x7B, 0x8D, 0x5A, 0xAA, 0x84, 0x10, 0xAD, 0x55, +0xD6, 0x9A, 0xB5, 0xB7, 0xC5, 0xF8, 0xDE, 0xDB, +0xAD, 0x35, 0xAD, 0x14, 0x52, 0x8A, 0x42, 0x08, +0x52, 0xAA, 0x4A, 0x69, 0x62, 0xEC, 0x7B, 0xAE, +0xAD, 0x55, 0x94, 0x71, 0x94, 0x92, 0xC5, 0xF8, +0xAD, 0x76, 0xA5, 0x35, 0xC5, 0xF8, 0xBD, 0xD7, +0xCE, 0x39, 0xBD, 0xD7, 0x9C, 0xF3, 0xB5, 0x95, +0x94, 0x4F, 0xD6, 0x13, 0xDE, 0x34, 0xD5, 0xF3, +0xB5, 0x2F, 0xC5, 0x91, 0xDE, 0x33, 0xDE, 0x74, +0xE6, 0xB5, 0xDE, 0x74, 0xE6, 0x95, 0xE6, 0x95, +0xD6, 0x33, 0xB5, 0x30, 0xBD, 0x30, 0xB5, 0x10, +0xAC, 0xAE, 0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xEF, +0xBD, 0x50, 0xBD, 0x50, 0xC5, 0x51, 0xBD, 0x51, +0xB5, 0x10, 0x9C, 0x6F, 0x62, 0xEA, 0x42, 0x07, +0x42, 0x07, 0x42, 0x27, 0x39, 0xE6, 0x4A, 0x68, +0x52, 0xA9, 0x5A, 0xAA, 0x5A, 0xCB, 0x63, 0x2C, +0x6B, 0x4D, 0x7B, 0xCF, 0x9C, 0xF3, 0x94, 0x92, +0x73, 0xAE, 0xA5, 0x55, 0xBD, 0xF6, 0xBD, 0x73, +0xBD, 0x52, 0xB5, 0x11, 0x9C, 0xB0, 0x9C, 0xB1, +0x94, 0x4F, 0xAD, 0x12, 0xBD, 0x94, 0x9C, 0xB0, +0xB5, 0x94, 0xBD, 0xD4, 0xAD, 0x53, 0xAD, 0x12, +0xB5, 0x74, 0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x53, +0xAD, 0x32, 0xBD, 0xB4, 0xBD, 0xB4, 0xC6, 0x15, +0xD6, 0x77, 0xCE, 0x56, 0xCE, 0x56, 0xD6, 0x97, +0xCE, 0x77, 0xC6, 0x36, 0xC6, 0x15, 0xA4, 0xF0, +0x9C, 0x6F, 0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x72, +0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x34, 0xE6, 0x75, +0xDE, 0x75, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x75, +0xDE, 0x54, 0xCD, 0xF3, 0xAC, 0xF0, 0xA4, 0xF1, +0xA5, 0x11, 0xA4, 0xF1, 0xB5, 0x74, 0xC6, 0x15, +0xCE, 0x36, 0xD6, 0x56, 0xC5, 0xF5, 0xC5, 0xF5, +0xCE, 0x15, 0xD6, 0x76, 0xBD, 0xB4, 0x9C, 0x8F, +0xB5, 0x11, 0xCD, 0xD4, 0xC5, 0xB3, 0xBD, 0x52, +0xAC, 0xF0, 0xAC, 0xF1, 0x9C, 0x8F, 0xA4, 0xD0, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xCF, 0xAC, 0xF0, 0xAC, 0xF0, 0xA4, 0xAF, +0xAC, 0xF0, 0xBD, 0x31, 0xBD, 0x51, 0xB5, 0x31, +0xAC, 0xF0, 0xA4, 0xAF, 0x94, 0x4E, 0xAD, 0x11, +0xAD, 0x31, 0xB5, 0x72, 0xAD, 0x32, 0x5A, 0xCA, +0x31, 0x85, 0x29, 0x44, 0x29, 0x44, 0x29, 0x65, +0x31, 0xA6, 0x31, 0xA6, 0x39, 0xC7, 0x42, 0x07, +0x31, 0x85, 0x39, 0x86, 0x4A, 0x28, 0x73, 0x4D, +0x83, 0xAE, 0x62, 0xEB, 0x62, 0xCB, 0x83, 0xAE, +0x73, 0x4C, 0x6B, 0x0C, 0x9C, 0x91, 0xAC, 0xF3, +0xB5, 0x32, 0xF6, 0xF8, 0xE6, 0xB6, 0xDE, 0x75, +0xDE, 0x55, 0xDE, 0x75, 0xDE, 0x55, 0xD6, 0x14, +0xDE, 0x55, 0xDE, 0x76, 0xB5, 0x31, 0xDE, 0xB7, +0xDE, 0xB8, 0xDE, 0xB8, 0xBD, 0x95, 0x29, 0x45, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0x82, 0x10, 0x82, +0x10, 0xA3, 0x10, 0xC3, 0x10, 0xC3, 0x21, 0x04, +0x8C, 0x0F, 0xBD, 0x94, 0xD6, 0x97, 0xCE, 0x35, +0xC5, 0xD4, 0xCE, 0x56, 0xCE, 0x15, 0xC5, 0xD4, +0xBD, 0xB4, 0xBD, 0x93, 0xAD, 0x12, 0xAD, 0x32, +0xAD, 0x12, 0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xF1, +0x9C, 0xD0, 0x94, 0x8F, 0x9C, 0xD0, 0xA4, 0xF1, +0xA4, 0xD1, 0xA4, 0xF1, 0xA5, 0x12, 0x9C, 0xD1, +0x9C, 0x90, 0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xF1, +0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x12, 0xA4, 0xD1, +0xA4, 0xD1, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x12, 0xAD, 0x12, +0x74, 0x4D, 0x5B, 0x8A, 0x74, 0x4E, 0x7C, 0xAF, +0x8D, 0x50, 0x84, 0xED, 0x6C, 0x49, 0x64, 0x06, +0x74, 0x68, 0x74, 0x69, 0x43, 0x02, 0x74, 0x48, +0x63, 0xC7, 0x53, 0x66, 0x5B, 0x86, 0x7C, 0x49, +0xB5, 0xD1, 0xB5, 0x72, 0xC6, 0x35, 0xC6, 0x15, +0xC6, 0x15, 0xBD, 0xB4, 0xAD, 0x33, 0x5A, 0xAA, +0x41, 0xE7, 0x4A, 0x28, 0x42, 0x08, 0x4A, 0x29, +0x7B, 0xEF, 0x9C, 0xF4, 0xC6, 0x39, 0xA5, 0x35, +0xAD, 0x55, 0xEF, 0x5D, 0xE7, 0x1C, 0xC6, 0x18, +0xAD, 0x55, 0x73, 0x8D, 0x94, 0x4F, 0xA4, 0xAF, +0xB5, 0x52, 0xBD, 0xD4, 0xC6, 0x15, 0xCE, 0x36, +0xCE, 0x36, 0xBD, 0xD4, 0xBD, 0xF5, 0xCE, 0x36, +0xC6, 0x15, 0xC5, 0xF4, 0xC6, 0x15, 0xCE, 0x56, +0xCE, 0x35, 0xC5, 0xF4, 0xC5, 0xF5, 0xC6, 0x15, +0xCE, 0x56, 0xBD, 0xF4, 0xC5, 0xF5, 0xB5, 0x73, +0xBD, 0xB3, 0xB5, 0x50, 0xAC, 0xEF, 0xA4, 0xAF, +0xB5, 0x93, 0xBD, 0xB3, 0xAD, 0x32, 0xA4, 0xF1, +0xA5, 0x11, 0xB5, 0x93, 0xAD, 0x32, 0xA5, 0x11, +0x9C, 0x8F, 0x94, 0x6F, 0x9C, 0x8F, 0x9C, 0xAF, +0xB5, 0x73, 0xAD, 0x53, 0x8C, 0x0E, 0x83, 0xEE, +0x8C, 0x2E, 0x8C, 0x4F, 0x6B, 0x2B, 0x73, 0xAE, +0x94, 0x72, 0x8C, 0x72, 0x94, 0x92, 0xA5, 0x14, +0x9C, 0xD3, 0xDE, 0xDB, 0xB5, 0x96, 0x52, 0x8A, +0x21, 0x24, 0x29, 0x45, 0x42, 0x28, 0x62, 0xEB, +0x7B, 0xCF, 0x62, 0xEC, 0xAD, 0x55, 0xB5, 0x96, +0x94, 0xB3, 0xB5, 0x96, 0xCE, 0x39, 0xAD, 0x35, +0x83, 0xF0, 0x73, 0xAF, 0x84, 0x31, 0xB5, 0x75, +0xA4, 0xF3, 0xB5, 0x54, 0xCD, 0xD3, 0xDE, 0x54, +0xC5, 0xB1, 0xCD, 0xB1, 0xD6, 0x34, 0xDE, 0x54, +0xD6, 0x13, 0xD6, 0x33, 0xDE, 0x74, 0xDE, 0x33, +0xCD, 0xB1, 0xAC, 0xCE, 0xC5, 0xB2, 0xAC, 0xEF, +0x8B, 0xEB, 0xAD, 0x0F, 0xBD, 0x51, 0xB5, 0x30, +0xD5, 0xF3, 0xCD, 0x92, 0xD5, 0xF3, 0xC5, 0x92, +0xC5, 0x92, 0xA4, 0xD0, 0x9C, 0x8F, 0x52, 0x68, +0x39, 0xC6, 0x31, 0x85, 0x42, 0x07, 0x4A, 0x48, +0x52, 0x89, 0x5A, 0xEB, 0x63, 0x0B, 0x63, 0x2C, +0x6B, 0x6D, 0x8C, 0x51, 0x8C, 0x51, 0x8C, 0x30, +0x6B, 0x6D, 0xA5, 0x34, 0xCE, 0x58, 0xC5, 0xB3, +0xC5, 0x93, 0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0xD1, +0xAD, 0x32, 0xA4, 0xF1, 0xBD, 0x94, 0xBD, 0x94, +0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x53, +0xAD, 0x32, 0xAC, 0xF2, 0xAD, 0x12, 0xAD, 0x12, +0xAD, 0x12, 0xA4, 0xB1, 0x9C, 0xB0, 0xA4, 0xD1, +0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xAD, 0x73, 0xAD, 0x52, 0xBD, 0xB4, 0x9C, 0xB0, +0x9C, 0x8F, 0xAD, 0x11, 0xA4, 0xB0, 0xB5, 0x11, +0xB4, 0xF0, 0xAC, 0xF0, 0xB5, 0x30, 0xC5, 0x71, +0xBD, 0x51, 0xB4, 0xF0, 0xC5, 0x72, 0xCD, 0xD3, +0xC5, 0xB2, 0xC5, 0x92, 0xAC, 0xF0, 0xA4, 0xD0, +0x8C, 0x2E, 0x8C, 0x2E, 0xA4, 0xD1, 0xC5, 0xD4, +0xCE, 0x35, 0xC5, 0xF5, 0xBD, 0x93, 0xCE, 0x36, +0xD6, 0x77, 0xCE, 0x36, 0xB5, 0x32, 0x9C, 0x8F, +0xBD, 0x52, 0xD6, 0x35, 0xD6, 0x35, 0xCD, 0xD3, +0xBD, 0x93, 0xA4, 0xD0, 0x8B, 0xED, 0xA4, 0xD0, +0x94, 0x0D, 0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xCF, 0xAC, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x10, 0xAC, 0xCF, +0x9C, 0x8E, 0x9C, 0x8F, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xF0, 0xAD, 0x11, 0xA4, 0xF0, 0xAD, 0x32, +0x9C, 0xB0, 0x6B, 0x2B, 0x42, 0x07, 0x29, 0x44, +0x29, 0x65, 0x39, 0xE6, 0x42, 0x07, 0x41, 0xE7, +0x4A, 0x48, 0x39, 0xC6, 0x29, 0x45, 0x39, 0x86, +0x5A, 0x8A, 0x83, 0xAE, 0x4A, 0x08, 0x5A, 0x69, +0x83, 0xAE, 0x73, 0x4D, 0x5A, 0x69, 0x83, 0xEF, +0xA4, 0xB2, 0xAC, 0xD1, 0xCD, 0xB4, 0xD6, 0x14, +0xDE, 0x76, 0xE6, 0x76, 0xDE, 0x55, 0xDE, 0x35, +0xE6, 0x76, 0xD6, 0x14, 0xC5, 0x93, 0xE6, 0xB7, +0xE6, 0xD8, 0xDE, 0xB7, 0x9C, 0x90, 0x29, 0x04, +0x10, 0xA3, 0x10, 0x82, 0x10, 0xA3, 0x10, 0x82, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, 0x29, 0x65, +0x9C, 0x91, 0xBD, 0xB4, 0xD6, 0x56, 0xD6, 0x56, +0xC5, 0xD4, 0xCE, 0x15, 0xBD, 0x93, 0xC6, 0x15, +0xCE, 0x35, 0xCE, 0x15, 0xC5, 0xD5, 0xBD, 0xD4, +0xB5, 0x93, 0xBD, 0x94, 0xAD, 0x53, 0xBD, 0x93, +0xB5, 0x73, 0xB5, 0x93, 0xAD, 0x32, 0xB5, 0x53, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0xD5, 0xC5, 0xD5, +0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xD0, 0xAD, 0x11, +0xCD, 0xD4, 0xC5, 0xB3, 0xC5, 0xB3, 0xC5, 0xB3, +0xC5, 0xD4, 0xC5, 0xB3, 0xC5, 0x93, 0xCD, 0xD4, +0xCD, 0xD4, 0xC5, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, +0x53, 0x48, 0x4B, 0x48, 0x5B, 0xCA, 0x64, 0x0B, +0x85, 0x0E, 0xA5, 0xD0, 0x74, 0x8A, 0x5B, 0xE5, +0x5B, 0xE5, 0x53, 0x64, 0x63, 0xE6, 0x74, 0x48, +0x63, 0xC7, 0x53, 0x86, 0x8C, 0xCB, 0xA5, 0x2D, +0x9C, 0xCD, 0x8C, 0x2C, 0x9C, 0x8F, 0x9C, 0x8F, +0xA4, 0xCF, 0xAD, 0x10, 0xAD, 0x11, 0x73, 0x6B, +0x39, 0xC5, 0x39, 0xC6, 0x42, 0x07, 0x4A, 0x28, +0x5A, 0xCB, 0x84, 0x30, 0xA5, 0x35, 0x7B, 0xF0, +0xBD, 0xD7, 0xDE, 0xBB, 0xDE, 0xBB, 0xCE, 0x7A, +0x9C, 0xF4, 0x8C, 0x30, 0xA4, 0xD1, 0xB5, 0x51, +0xCE, 0x35, 0xCE, 0x35, 0xCE, 0x56, 0xCE, 0x35, +0xCE, 0x36, 0xC6, 0x35, 0xCE, 0x36, 0xCE, 0x77, +0xCE, 0x77, 0xCE, 0x36, 0xC6, 0x36, 0xCE, 0x56, +0xCE, 0x36, 0xCE, 0x56, 0xCE, 0x56, 0xCE, 0x56, +0xD6, 0x77, 0xCE, 0x56, 0xD6, 0x77, 0xCE, 0x36, +0xCE, 0x15, 0xB5, 0x51, 0xAC, 0xEF, 0x9C, 0xAF, +0xB5, 0x72, 0xAD, 0x52, 0x9C, 0xD0, 0xA4, 0xF1, +0xAD, 0x32, 0xB5, 0x53, 0x9C, 0xD0, 0xA4, 0xF1, +0x8C, 0x2E, 0x9C, 0xB0, 0x9C, 0xD0, 0x94, 0x8F, +0xAD, 0x53, 0xAD, 0x52, 0x8C, 0x2E, 0x8C, 0x2E, +0xA4, 0xF1, 0xB5, 0x73, 0xA4, 0xF2, 0x7B, 0xAD, +0x52, 0x8A, 0x7B, 0xAF, 0x84, 0x10, 0x9C, 0xD3, +0x5A, 0xCB, 0x9C, 0xD3, 0xDE, 0xBB, 0xBD, 0xB7, +0xA4, 0xF4, 0x63, 0x0C, 0x31, 0x86, 0x4A, 0x49, +0x6B, 0x4D, 0x73, 0x6E, 0xAD, 0x76, 0x9C, 0xD3, +0x9C, 0xD3, 0xBD, 0xD7, 0xA5, 0x14, 0x9C, 0xB3, +0x9C, 0xF4, 0xB5, 0x96, 0xC6, 0x18, 0xCE, 0x59, +0xD6, 0x9A, 0xE7, 0x1C, 0xDE, 0xB9, 0xA4, 0xD1, +0x7B, 0x8B, 0xC5, 0xD3, 0xD5, 0xF3, 0xCD, 0xF2, +0xD5, 0xF2, 0xD6, 0x33, 0xD6, 0x12, 0xD6, 0x13, +0xC5, 0x71, 0xB5, 0x10, 0xAD, 0x10, 0xB5, 0x30, +0xAD, 0x10, 0xAC, 0xEF, 0xB5, 0x30, 0xC5, 0xB2, +0xCD, 0x91, 0xB5, 0x10, 0x7B, 0x6A, 0x94, 0x6E, +0x9C, 0x6F, 0x6B, 0x0A, 0x94, 0x4E, 0x62, 0xE9, +0x39, 0xC6, 0x29, 0x44, 0x31, 0x64, 0x41, 0xE6, +0x52, 0x89, 0x62, 0xEB, 0x5A, 0xEB, 0x5A, 0xEB, +0x73, 0x8E, 0x84, 0x10, 0x73, 0x8E, 0x6B, 0x2C, +0x94, 0x92, 0xBD, 0xD7, 0xB5, 0xB6, 0xC5, 0xD5, +0x9C, 0x6F, 0x94, 0x2E, 0xAD, 0x11, 0xB5, 0x11, +0xAD, 0x11, 0x94, 0x2E, 0xA4, 0xB0, 0xB5, 0x53, +0x9C, 0xB0, 0x94, 0x4F, 0x94, 0x2E, 0xA4, 0xB0, +0xB5, 0x53, 0xBD, 0x53, 0xAD, 0x12, 0xA4, 0xF1, +0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, +0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x73, +0xB5, 0x73, 0xBD, 0x73, 0xB5, 0x53, 0xB5, 0x32, +0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x94, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x73, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xAC, 0xF1, 0xAD, 0x11, +0xB5, 0x31, 0xBD, 0x72, 0xBD, 0x73, 0xC5, 0xD5, +0xC5, 0xD5, 0xC5, 0xB4, 0xAD, 0x12, 0xA4, 0xB0, +0x9C, 0x8F, 0x94, 0x2E, 0x83, 0xED, 0x8C, 0x0E, +0x94, 0x2F, 0x8C, 0x0E, 0x8C, 0x0E, 0x8C, 0x0D, +0x9C, 0x6F, 0xBD, 0x93, 0xD6, 0x35, 0xBD, 0x72, +0xAC, 0xF0, 0x9C, 0x6E, 0x94, 0x2D, 0x9C, 0x6F, +0x83, 0xCC, 0x8B, 0xED, 0x9C, 0x6E, 0xA4, 0x8F, +0xA4, 0xCF, 0xA4, 0xAF, 0xAD, 0x10, 0xAD, 0x10, +0xA4, 0xCF, 0xA4, 0x8F, 0xA4, 0x8F, 0xA4, 0x8F, +0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x8F, 0xA4, 0xCF, +0x9C, 0xAF, 0xB5, 0x51, 0xAD, 0x31, 0xB5, 0x72, +0xA5, 0x11, 0xA5, 0x11, 0x9C, 0xD1, 0x5A, 0xCA, +0x31, 0x65, 0x31, 0x85, 0x31, 0xA6, 0x39, 0xE6, +0x52, 0x69, 0x4A, 0x28, 0x29, 0x45, 0x29, 0x04, +0x31, 0x65, 0x4A, 0x28, 0x52, 0x89, 0x41, 0xE7, +0x62, 0xAA, 0x7B, 0x4D, 0x62, 0xAA, 0x52, 0x49, +0x8B, 0xEF, 0xA4, 0x92, 0x94, 0x30, 0x9C, 0x2F, +0xD6, 0x36, 0xD6, 0x35, 0xCD, 0xD3, 0xCD, 0xD4, +0xCD, 0xD3, 0xD6, 0x14, 0xD6, 0x35, 0xE6, 0xD7, +0xE6, 0xD7, 0xD6, 0x35, 0x7B, 0x8D, 0x21, 0x04, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, 0x73, 0x6D, +0xAD, 0x33, 0xC5, 0xD4, 0xD6, 0x56, 0xCE, 0x35, +0xC5, 0xD4, 0xCE, 0x15, 0xB5, 0x73, 0xAD, 0x32, +0xC5, 0xD4, 0xCE, 0x15, 0xC5, 0xF5, 0xCE, 0x15, +0xC5, 0xD5, 0xBD, 0xD4, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0xD4, 0xC5, 0xF5, 0xB5, 0x93, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xF5, +0xA4, 0xF1, 0xB5, 0x52, 0xD6, 0x35, 0xE6, 0x76, +0xD6, 0x15, 0xD6, 0x34, 0xD6, 0x35, 0xD6, 0x15, +0xDE, 0x35, 0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x15, +0xDE, 0x76, 0xDE, 0x55, 0xD6, 0x14, 0xDE, 0x55, +0x84, 0xAD, 0x6C, 0x4C, 0x7C, 0xAE, 0x63, 0xEB, +0x5B, 0xA8, 0x74, 0xAB, 0x74, 0x8A, 0x63, 0xE6, +0x53, 0x84, 0x4B, 0x24, 0x6C, 0x27, 0x6B, 0xE7, +0x6B, 0xE7, 0x7C, 0x6A, 0x9C, 0xED, 0xA4, 0xCD, +0xA4, 0x8E, 0x9C, 0x8D, 0xA4, 0x8E, 0xAC, 0xEF, +0xB5, 0x10, 0xAC, 0xEF, 0xA4, 0xAE, 0xA4, 0xAF, +0xA4, 0x8F, 0x6B, 0x09, 0x39, 0xC5, 0x39, 0xE7, +0x42, 0x28, 0x5A, 0xCB, 0x6B, 0x4D, 0x8C, 0x51, +0x9C, 0xB3, 0x94, 0x92, 0xC6, 0x18, 0xDE, 0xBB, +0xC6, 0x39, 0x9C, 0xD2, 0xBD, 0x94, 0xAD, 0x10, +0xB5, 0x51, 0xBD, 0x71, 0xBD, 0x72, 0xB5, 0x71, +0xAD, 0x30, 0xAC, 0xF0, 0xAD, 0x31, 0xB5, 0x72, +0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0x93, 0xB5, 0x73, +0xBD, 0xB4, 0xC6, 0x15, 0xC6, 0x35, 0xCE, 0x56, +0xCE, 0x76, 0xD6, 0x77, 0xD6, 0x97, 0xCE, 0x56, +0xCE, 0x15, 0xAC, 0xF0, 0xAC, 0xAE, 0xA4, 0xCF, +0xB5, 0x72, 0xB5, 0x73, 0xA5, 0x11, 0xA5, 0x11, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x32, 0xA5, 0x11, +0x9C, 0xD0, 0xA4, 0xF1, 0xA5, 0x12, 0xA4, 0xF1, +0xAD, 0x32, 0xAD, 0x73, 0x94, 0x8F, 0x94, 0x6F, +0x9C, 0xF1, 0xAD, 0x12, 0x9C, 0x90, 0x9C, 0x90, +0x6B, 0x4C, 0x42, 0x28, 0x6B, 0x4D, 0x9C, 0xB2, +0x83, 0xF0, 0x9C, 0xD3, 0xBD, 0xB7, 0xC5, 0xF8, +0xE7, 0x1C, 0xB5, 0x76, 0x9C, 0xB3, 0x8C, 0x51, +0xA5, 0x34, 0x9C, 0xD3, 0xA5, 0x34, 0x8C, 0x51, +0x7B, 0xAF, 0xC5, 0xF8, 0x7B, 0xAF, 0x8C, 0x51, +0xC6, 0x39, 0xBD, 0xD8, 0xAD, 0x35, 0x94, 0x72, +0x83, 0xF0, 0xC6, 0x39, 0xC5, 0xF7, 0x94, 0x92, +0x5A, 0xAA, 0x8C, 0x2E, 0xD6, 0x34, 0xD6, 0x13, +0xD6, 0x34, 0xD6, 0x13, 0xCE, 0x13, 0xD6, 0x33, +0xBD, 0x71, 0xB5, 0x30, 0xB5, 0x30, 0xC5, 0xB2, +0xBD, 0x71, 0xAD, 0x10, 0xBD, 0x51, 0xC5, 0x71, +0xB4, 0xEF, 0xAC, 0xCF, 0x73, 0x2A, 0x8C, 0x0D, +0x94, 0x4E, 0x94, 0x4E, 0x8C, 0x0D, 0x83, 0xCC, +0x52, 0x88, 0x39, 0xA5, 0x29, 0x64, 0x31, 0xA5, +0x42, 0x27, 0x52, 0x89, 0x5A, 0xCA, 0x63, 0x2C, +0x73, 0x8E, 0x63, 0x2C, 0x4A, 0x49, 0x73, 0x8E, +0x94, 0xB2, 0x9C, 0xF4, 0xA4, 0xF4, 0xCE, 0x38, +0x9C, 0x91, 0x94, 0x6F, 0xBD, 0x72, 0xBD, 0x92, +0xC5, 0x92, 0xBD, 0x73, 0xCD, 0xF4, 0xB5, 0x32, +0x94, 0x6F, 0xB5, 0x33, 0xAD, 0x12, 0x94, 0x4F, +0xB5, 0x73, 0xC5, 0xD5, 0xBD, 0x94, 0x9C, 0xB0, +0x7B, 0x8C, 0x83, 0xED, 0x8B, 0xED, 0x94, 0x6E, +0xBD, 0x93, 0xC5, 0xB4, 0xD6, 0x56, 0xC5, 0xB4, +0xA4, 0xD0, 0xA4, 0xD1, 0xBD, 0x73, 0xBD, 0x52, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x32, 0xAD, 0x11, +0xBD, 0x72, 0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x73, +0xC5, 0x93, 0xC5, 0x93, 0xBD, 0x52, 0xBD, 0x52, +0xBD, 0x52, 0xB5, 0x31, 0xC5, 0x93, 0xC5, 0x94, +0xBD, 0x73, 0xC5, 0x93, 0xC5, 0x94, 0xC5, 0xB4, +0xB5, 0x53, 0xAD, 0x12, 0x9C, 0xB0, 0xA4, 0xB0, +0xBD, 0x53, 0xB5, 0x53, 0xBD, 0x74, 0xB5, 0x33, +0xA4, 0xB0, 0x94, 0x2E, 0x8B, 0xED, 0x8B, 0xCC, +0x83, 0xCC, 0x7B, 0x8B, 0x83, 0xAC, 0x8B, 0xCC, +0x7B, 0x6B, 0x73, 0x4A, 0x83, 0xAB, 0x83, 0xEC, +0x8C, 0x0D, 0x94, 0x4E, 0x9C, 0x8F, 0x94, 0x4E, +0x8B, 0xCC, 0x83, 0xAC, 0x83, 0x8B, 0x83, 0xCC, +0x94, 0x4E, 0x9C, 0xAF, 0xA4, 0xD0, 0x9C, 0xAF, +0x94, 0x4E, 0xAD, 0x10, 0xBD, 0x93, 0xBD, 0xB3, +0xB5, 0x72, 0xBD, 0xB3, 0xC6, 0x15, 0xBD, 0xD4, +0x8C, 0x4F, 0x4A, 0x27, 0x31, 0xA6, 0x39, 0xC6, +0x39, 0xA6, 0x31, 0x85, 0x31, 0x85, 0x29, 0x45, +0x29, 0x24, 0x29, 0x04, 0x41, 0xE7, 0x5A, 0xAA, +0x4A, 0x28, 0x6A, 0xEB, 0x62, 0xCA, 0x73, 0x4C, +0x94, 0x30, 0x9C, 0x71, 0xA4, 0xD2, 0x83, 0xAE, +0x8B, 0xCE, 0xA4, 0xB0, 0x9C, 0x8F, 0x9C, 0x6F, +0xAD, 0x11, 0xBD, 0x73, 0xB5, 0x52, 0xD6, 0x56, +0xDE, 0x56, 0xB5, 0x32, 0x4A, 0x08, 0x18, 0xC4, +0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0xA3, 0x18, 0xC3, 0x29, 0x45, 0x9C, 0xD2, +0xB5, 0x53, 0xBD, 0xB4, 0xD6, 0x56, 0xCE, 0x15, +0xC5, 0xF5, 0xCE, 0x15, 0xB5, 0x52, 0xAD, 0x32, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xF4, +0xCE, 0x36, 0xC5, 0xF5, 0xAD, 0x52, 0xC5, 0xF5, +0xC5, 0xF5, 0xC5, 0xF5, 0xBD, 0xB4, 0xC5, 0xF5, +0xB5, 0x93, 0xBD, 0xF5, 0xCE, 0x15, 0xCE, 0x15, +0xA4, 0xD1, 0xB5, 0x52, 0xD6, 0x35, 0xDE, 0x55, +0xD6, 0x14, 0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x15, +0xD6, 0x15, 0xCD, 0xF4, 0xBD, 0x72, 0xDE, 0x35, +0xD6, 0x15, 0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x35, +0x84, 0xAD, 0x64, 0x0B, 0x74, 0x8D, 0x74, 0x8C, +0x53, 0x66, 0x4B, 0x66, 0x6C, 0x2A, 0x64, 0x08, +0x63, 0xE7, 0x6B, 0xE7, 0x63, 0xA6, 0x6B, 0xE7, +0x95, 0x2D, 0xA5, 0x4F, 0xBD, 0xB2, 0xC5, 0xD3, +0xCD, 0xF3, 0xC5, 0xB2, 0xC5, 0xB2, 0xD6, 0x55, +0xDE, 0x55, 0xCD, 0xD3, 0xA4, 0x8E, 0xA4, 0xAF, +0xAC, 0xCF, 0xA4, 0xCF, 0x83, 0xCC, 0x4A, 0x27, +0x39, 0xC6, 0x42, 0x28, 0x52, 0x8A, 0x52, 0xAA, +0x84, 0x10, 0x6B, 0x6D, 0x52, 0x8A, 0x8C, 0x51, +0x84, 0x30, 0x4A, 0x69, 0x7B, 0xAD, 0xCE, 0x16, +0xA4, 0xAF, 0xAC, 0xAF, 0xB5, 0x10, 0xB5, 0x30, +0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xCF, 0xAC, 0xCF, +0xA4, 0xAE, 0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, +0xA4, 0xCF, 0xA4, 0x8F, 0xA4, 0x8E, 0x9C, 0x4E, +0x9C, 0x4D, 0x9C, 0x2D, 0x9C, 0x2D, 0x9C, 0x4D, +0x9C, 0x4C, 0xA4, 0x6D, 0xAC, 0xAE, 0x9C, 0x8E, +0xAD, 0x10, 0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x32, +0xAD, 0x31, 0x9C, 0xAF, 0xAD, 0x31, 0xA4, 0xF0, +0xA4, 0xD0, 0xAD, 0x31, 0xB5, 0x52, 0xB5, 0x93, +0xB5, 0x93, 0xBD, 0xB4, 0xA5, 0x11, 0xA4, 0xF1, +0xA4, 0xD0, 0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, +0x94, 0x8F, 0x7B, 0x8C, 0x73, 0x4C, 0x73, 0x6D, +0x5A, 0xCB, 0xA5, 0x14, 0xBD, 0x96, 0xDE, 0xBB, +0xA5, 0x14, 0x94, 0x92, 0x7B, 0xAF, 0x9C, 0xB3, +0x9C, 0xF4, 0xA5, 0x14, 0x84, 0x10, 0x6B, 0x2D, +0x31, 0xA6, 0x94, 0xB3, 0xCE, 0x39, 0xB5, 0x96, +0xC5, 0xF8, 0xA4, 0xF4, 0xAD, 0x35, 0xB5, 0x76, +0xA5, 0x14, 0xCE, 0x39, 0xDE, 0xDB, 0xC6, 0x39, +0x7B, 0xEF, 0x73, 0x8E, 0xBD, 0x93, 0xCD, 0xF3, +0xCD, 0xF3, 0xD6, 0x14, 0xC5, 0x92, 0xCD, 0xB2, +0xAC, 0xEF, 0xAD, 0x30, 0xAD, 0x10, 0xA4, 0xCF, +0xB5, 0x31, 0xB5, 0x30, 0xB5, 0x10, 0xB4, 0xEF, +0x9C, 0x4D, 0xA4, 0x8E, 0x8B, 0xEC, 0xAC, 0xF0, +0xA4, 0xCF, 0x9C, 0x6E, 0x9C, 0x8F, 0xAC, 0xF0, +0x8C, 0x0D, 0x42, 0x07, 0x31, 0x85, 0x31, 0x85, +0x41, 0xE6, 0x42, 0x07, 0x42, 0x28, 0x52, 0x8A, +0x4A, 0x48, 0x4A, 0x68, 0x63, 0x0B, 0x83, 0xEF, +0x84, 0x10, 0x94, 0x92, 0xA5, 0x14, 0xBD, 0xD7, +0xCE, 0x59, 0xA4, 0xF2, 0xBD, 0x73, 0xBD, 0x72, +0xBD, 0x92, 0xBD, 0x93, 0xC5, 0xD4, 0xBD, 0xB4, +0xAD, 0x32, 0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x53, +0xB5, 0x73, 0xC5, 0xD4, 0xCD, 0xF4, 0xA4, 0xF1, +0x94, 0x6F, 0x94, 0x4F, 0x8C, 0x0E, 0xAD, 0x12, +0xC5, 0xF4, 0xCD, 0xF4, 0xCE, 0x15, 0xB5, 0x52, +0xAC, 0xF1, 0xBD, 0x73, 0xD6, 0x35, 0xD6, 0x14, +0xCD, 0xD3, 0xC5, 0x93, 0xC5, 0xB3, 0xBD, 0x72, +0xA4, 0xD0, 0x94, 0x4E, 0xA4, 0xCF, 0xAC, 0xF0, +0xAD, 0x11, 0xAD, 0x10, 0x9C, 0x6F, 0x9C, 0x6E, +0x9C, 0x6E, 0xAC, 0xD0, 0xAC, 0xF0, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x8F, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xB0, 0x9C, 0x6F, 0x9C, 0x8F, 0x9C, 0x6F, +0xA4, 0xD0, 0xA4, 0xB0, 0xAD, 0x12, 0xB5, 0x53, +0xAD, 0x12, 0xAC, 0xF1, 0xB5, 0x32, 0xAD, 0x12, +0xAD, 0x12, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x11, 0xAC, 0xF1, 0xAC, 0xF0, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x11, 0xAC, 0xD0, 0x9C, 0x8F, +0x9C, 0x90, 0x9C, 0x90, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x52, +0xB5, 0x32, 0xA4, 0xF0, 0xAC, 0xF0, 0xA4, 0xD0, +0x94, 0x6E, 0x9C, 0x6F, 0xA4, 0xF1, 0xAD, 0x12, +0xAD, 0x11, 0x83, 0xED, 0x41, 0xC6, 0x39, 0xA6, +0x31, 0x85, 0x31, 0xA6, 0x6B, 0x2C, 0x63, 0x0B, +0x39, 0x86, 0x29, 0x25, 0x31, 0x45, 0x4A, 0x08, +0x4A, 0x48, 0x4A, 0x28, 0x5A, 0x89, 0x6B, 0x0C, +0x8B, 0xEF, 0x8B, 0xEF, 0x9C, 0x70, 0x83, 0xCE, +0x73, 0x2C, 0x8B, 0xCE, 0x83, 0xCD, 0x8B, 0xEE, +0xA4, 0xB1, 0x9C, 0x91, 0x52, 0x69, 0x52, 0x48, +0x52, 0x68, 0x42, 0x07, 0x21, 0x04, 0x18, 0xC3, +0x10, 0xA3, 0x10, 0x83, 0x10, 0xA3, 0x10, 0xA3, +0x10, 0x82, 0x18, 0xC3, 0x73, 0x6C, 0xAD, 0x32, +0xB5, 0x53, 0xC5, 0xD5, 0xD6, 0x56, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xF5, 0xB5, 0x73, 0xB5, 0x93, +0xC5, 0xF4, 0xC5, 0xF4, 0xC5, 0xF4, 0xCE, 0x15, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xD4, 0xC6, 0x15, +0xC6, 0x15, 0xC5, 0xD5, 0xC5, 0xD5, 0xBD, 0xD4, +0xC5, 0xF5, 0xC6, 0x15, 0xCE, 0x35, 0xAD, 0x32, +0xA4, 0xF0, 0xC5, 0xD4, 0xD6, 0x14, 0xDE, 0x55, +0xD6, 0x14, 0xD6, 0x14, 0xDE, 0x76, 0xD6, 0x14, +0xCD, 0xF4, 0xCD, 0xD4, 0xC5, 0xB3, 0xD6, 0x35, +0xD6, 0x14, 0xD6, 0x35, 0xD6, 0x15, 0xDE, 0x35, +0x6C, 0x2A, 0x5B, 0xEA, 0x6C, 0x6B, 0x64, 0x29, +0x5B, 0xE6, 0x64, 0x08, 0x53, 0x67, 0x53, 0x88, +0x8D, 0x0E, 0x95, 0x0D, 0x74, 0x28, 0x84, 0xAB, +0xA5, 0x8F, 0xAD, 0xB1, 0xA5, 0x50, 0x94, 0xAE, +0xC6, 0x14, 0xD6, 0x75, 0xD6, 0x75, 0xDE, 0x75, +0xD6, 0x54, 0xD6, 0x14, 0xA4, 0x8E, 0x83, 0xCB, +0x9C, 0x8E, 0xA4, 0xF0, 0xAD, 0x11, 0xAD, 0x32, +0x63, 0x0B, 0x39, 0xA6, 0x42, 0x07, 0x42, 0x28, +0x63, 0x0C, 0x6B, 0x2D, 0x5A, 0xAB, 0x4A, 0x49, +0x41, 0xE7, 0x62, 0xEB, 0x9C, 0xD3, 0xEF, 0x7D, +0xDE, 0xDA, 0x8C, 0x0F, 0x8C, 0x0D, 0xA4, 0x8E, +0x94, 0x2C, 0x94, 0x2C, 0xAC, 0xAE, 0xAC, 0xAE, +0xA4, 0xAE, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x6D, +0x9C, 0x6D, 0xA4, 0x8E, 0xAC, 0xCF, 0xB4, 0xEF, +0xAC, 0xEF, 0xB4, 0xF0, 0xB5, 0x10, 0xB5, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x10, +0xAD, 0x0F, 0xAC, 0xEF, 0xB5, 0x10, 0xAC, 0xF0, +0xAC, 0xCF, 0xA4, 0xAE, 0xAC, 0xCF, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAE, 0xA4, 0xAE, 0x9C, 0x8E, +0x9C, 0x8F, 0x9C, 0x8F, 0x94, 0x6E, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x4E, 0x8C, 0x0D, +0x8C, 0x0D, 0xAC, 0xF1, 0x94, 0x4F, 0x5A, 0xCA, +0x39, 0xE7, 0x73, 0x8E, 0x94, 0x92, 0xA5, 0x14, +0x94, 0x71, 0xAD, 0x35, 0x94, 0x71, 0x63, 0x0C, +0x84, 0x10, 0xC5, 0xF7, 0x94, 0x51, 0x62, 0xEB, +0x62, 0xEC, 0x4A, 0x69, 0xB5, 0xB6, 0xC6, 0x39, +0x8C, 0x51, 0xB5, 0xB7, 0xBD, 0xF8, 0xA4, 0xF4, +0xBD, 0xB7, 0xC5, 0xF8, 0xD6, 0x9B, 0xE6, 0xFD, +0xBD, 0xD7, 0xC6, 0x17, 0xC5, 0xF5, 0xD6, 0x35, +0xD6, 0x55, 0xD6, 0x34, 0xC5, 0xB2, 0xCD, 0xD3, +0xB5, 0x30, 0xB5, 0x71, 0x9C, 0xAF, 0x8C, 0x2D, +0xB5, 0x72, 0xA4, 0xEF, 0xB5, 0x30, 0xB5, 0x10, +0x93, 0xEC, 0xA4, 0xAF, 0x9C, 0x6E, 0xBD, 0x92, +0xA4, 0xCF, 0xAC, 0xF0, 0xAD, 0x31, 0xB5, 0x51, +0xB5, 0x31, 0x73, 0x4B, 0x39, 0xA5, 0x39, 0xC6, +0x39, 0xA5, 0x39, 0xC6, 0x39, 0xA6, 0x42, 0x07, +0x4A, 0x48, 0x42, 0x28, 0x4A, 0x48, 0x63, 0x2C, +0x7B, 0xCF, 0x9C, 0xD3, 0x9C, 0xF4, 0xB5, 0xB7, +0xCE, 0x7A, 0xBD, 0xD6, 0xAD, 0x52, 0xB5, 0x51, +0xB5, 0x72, 0xC5, 0xB3, 0xC5, 0xB3, 0xC5, 0xD4, +0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x94, +0xC5, 0xD4, 0xCD, 0xF5, 0xC5, 0xD4, 0x9C, 0x90, +0x94, 0x4F, 0x8C, 0x2E, 0x94, 0x4F, 0xBD, 0x93, +0xCE, 0x35, 0xD6, 0x35, 0xD6, 0x55, 0xB5, 0x52, +0xAC, 0xF1, 0xBD, 0x73, 0xCD, 0xF4, 0xDE, 0x55, +0xDE, 0x35, 0xD6, 0x34, 0xD6, 0x35, 0xDE, 0x76, +0xD6, 0x15, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, +0xAD, 0x31, 0xB5, 0x32, 0xC5, 0xD4, 0xC5, 0xB4, +0xBD, 0x93, 0xC5, 0xB4, 0xB5, 0x52, 0x9C, 0x8F, +0x83, 0xEC, 0x8C, 0x2E, 0xB5, 0x52, 0xA4, 0xF1, +0xA4, 0xD1, 0x9C, 0x8F, 0xA4, 0xF1, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xF1, 0xAD, 0x12, 0xA4, 0xD1, 0x94, 0x4F, +0x94, 0x4F, 0x8C, 0x2E, 0x9C, 0x90, 0xA4, 0xB0, +0xB5, 0x31, 0xBD, 0x52, 0xC5, 0x92, 0xD6, 0x14, +0xDE, 0x34, 0xD5, 0xF3, 0xBD, 0x72, 0xAC, 0xF1, +0xBD, 0x73, 0xA4, 0xD1, 0xAC, 0xD0, 0xB5, 0x11, +0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x52, 0xBD, 0x52, +0xB5, 0x32, 0xBD, 0x32, 0xB5, 0x31, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x31, 0xB5, 0x32, +0xB5, 0x52, 0xBD, 0x52, 0xA4, 0xD1, 0x83, 0xCD, +0x41, 0xE6, 0x31, 0x85, 0x52, 0xAA, 0x94, 0x50, +0x94, 0x71, 0x7B, 0x8E, 0x41, 0xE8, 0x29, 0x25, +0x39, 0xC6, 0x4A, 0x08, 0x41, 0xE7, 0x4A, 0x08, +0x62, 0xCB, 0x73, 0x4C, 0x8B, 0xEF, 0x94, 0x50, +0x8B, 0xCF, 0x8B, 0xCE, 0x7B, 0x6D, 0x62, 0xCA, +0x8C, 0x2F, 0x7B, 0x8D, 0x18, 0xC3, 0x10, 0xA3, +0x10, 0xA3, 0x10, 0xA3, 0x10, 0xA3, 0x10, 0x82, +0x10, 0xA3, 0x18, 0xC3, 0x18, 0xE4, 0x18, 0xE3, +0x10, 0xA3, 0x52, 0x89, 0xA5, 0x12, 0x94, 0x4F, +0xA4, 0xB0, 0xA4, 0xF1, 0xAD, 0x52, 0xAD, 0x32, +0xB5, 0x52, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x52, +0xB5, 0x93, 0xC5, 0xD4, 0xC5, 0xF5, 0xC5, 0xF5, +0xCE, 0x36, 0xB5, 0x73, 0xCE, 0x16, 0xCE, 0x56, +0xCE, 0x15, 0xC5, 0xD5, 0xC5, 0xF5, 0xC5, 0xF5, +0xC6, 0x15, 0xCE, 0x15, 0xD6, 0x56, 0xBD, 0xD4, +0xA4, 0xD0, 0xBD, 0xB3, 0xC5, 0xB3, 0xD6, 0x14, +0xCD, 0xB3, 0xBD, 0x72, 0xCD, 0xF4, 0xD6, 0x14, +0xD5, 0xF4, 0xCD, 0xD3, 0xD6, 0x14, 0xD6, 0x15, +0xD6, 0x35, 0xCD, 0xD4, 0xD6, 0x14, 0xD6, 0x35, +0x4B, 0x46, 0x53, 0x87, 0x5C, 0x08, 0x64, 0x27, +0x64, 0x26, 0x74, 0x8A, 0x9D, 0x90, 0x8C, 0xEE, +0x84, 0xAE, 0x95, 0x2E, 0x6B, 0xA8, 0xA5, 0x8F, +0x7C, 0x4A, 0x4B, 0x25, 0x74, 0x2A, 0xB5, 0xF3, +0xD6, 0x96, 0xD6, 0x75, 0xD6, 0x54, 0xCE, 0x34, +0xCE, 0x13, 0xD6, 0x14, 0xA4, 0xAE, 0xB5, 0x72, +0xC6, 0x15, 0xCE, 0x35, 0xCE, 0x35, 0xCE, 0x35, +0xCE, 0x16, 0x8C, 0x2F, 0x39, 0xC6, 0x39, 0xC6, +0x42, 0x28, 0x52, 0x8A, 0x5A, 0xAA, 0x5A, 0xEB, +0x52, 0x8A, 0x52, 0x69, 0x9C, 0xD3, 0xE7, 0x3C, +0xEF, 0x7D, 0xD6, 0xBA, 0xC5, 0xF7, 0xAD, 0x11, +0xA4, 0xEF, 0xA4, 0xAE, 0xA4, 0x8E, 0xB5, 0x10, +0xA4, 0xAF, 0x94, 0x2D, 0xA4, 0xCF, 0xAC, 0xF0, +0xA4, 0xCF, 0xB5, 0x31, 0xBD, 0x72, 0xA4, 0xAF, +0x94, 0x0D, 0xA4, 0x8F, 0xA4, 0xAE, 0xAC, 0xEF, +0xB5, 0x30, 0xAC, 0xCF, 0xAC, 0xAE, 0xAC, 0xCF, +0xB5, 0x10, 0xAC, 0xCF, 0x94, 0x2C, 0x8B, 0xEB, +0xA4, 0x8E, 0xB5, 0x10, 0xB5, 0x0F, 0xBD, 0x30, +0xBD, 0x50, 0xBD, 0x50, 0xB5, 0x30, 0xB4, 0xEF, +0xAC, 0xCF, 0xA4, 0xAE, 0xAC, 0xCE, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xEF, 0xB4, 0xEF, 0xAC, 0xAE, +0xA4, 0xAE, 0xB4, 0xF0, 0xB5, 0x10, 0x83, 0xAC, +0x8C, 0x0D, 0x83, 0xCD, 0x52, 0x89, 0x73, 0xAE, +0x94, 0x92, 0x7B, 0xAE, 0x7B, 0xAF, 0x6B, 0x4D, +0xBD, 0xB7, 0xBD, 0xD7, 0xD6, 0xBB, 0x94, 0x92, +0x7B, 0xCF, 0x31, 0x66, 0x42, 0x08, 0x6B, 0x8E, +0xAD, 0x76, 0xCE, 0x39, 0x9C, 0xF4, 0xA5, 0x15, +0xC6, 0x19, 0xC6, 0x39, 0xC6, 0x39, 0xD6, 0xBB, +0xD6, 0xBB, 0xDE, 0xDB, 0xBD, 0xB6, 0x94, 0x2F, +0xAD, 0x31, 0xAD, 0x31, 0xBD, 0x72, 0xC5, 0x92, +0xAD, 0x10, 0xAD, 0x31, 0xB5, 0x72, 0xBD, 0x92, +0xC5, 0xF4, 0xAD, 0x30, 0xCD, 0xF3, 0xB5, 0x30, +0x93, 0xEC, 0xA4, 0x6E, 0x94, 0x4D, 0xC5, 0xD3, +0xB5, 0x52, 0xB5, 0x51, 0xA4, 0xF0, 0xBD, 0x72, +0xBD, 0x93, 0xA4, 0xD0, 0x4A, 0x48, 0x39, 0xA5, +0x31, 0x85, 0x31, 0x85, 0x39, 0xA6, 0x4A, 0x28, +0x52, 0x8A, 0x4A, 0x28, 0x4A, 0x69, 0x6B, 0x2C, +0x73, 0x8E, 0x84, 0x31, 0x9C, 0xD3, 0xAD, 0x76, +0xC6, 0x19, 0xCE, 0x38, 0xAD, 0x32, 0xA4, 0xF0, +0xBD, 0x72, 0xC5, 0xB4, 0xBD, 0x72, 0xBD, 0x73, +0xB5, 0x73, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB4, +0xCE, 0x15, 0xCE, 0x15, 0xCD, 0xF5, 0xBD, 0x73, +0xA4, 0xD1, 0x94, 0x6F, 0x9C, 0xB0, 0xC5, 0xD4, +0xD6, 0x35, 0xDE, 0x75, 0xD6, 0x14, 0xB5, 0x11, +0xAD, 0x12, 0xC5, 0xB4, 0xCD, 0xF4, 0xD6, 0x34, +0xD6, 0x34, 0xD5, 0xF3, 0xC5, 0xB2, 0xD6, 0x14, +0xC5, 0xB3, 0xB5, 0x52, 0xA4, 0xAF, 0xA4, 0xAF, +0xA4, 0xF1, 0x9C, 0xB0, 0x9C, 0xAF, 0xAD, 0x11, +0xB5, 0x31, 0xAD, 0x11, 0xAD, 0x11, 0x9C, 0xB0, +0x94, 0x4E, 0xAD, 0x11, 0xBD, 0xB4, 0xAD, 0x11, +0xAD, 0x12, 0xB5, 0x53, 0xA4, 0xF1, 0x9C, 0xB0, +0xAD, 0x12, 0x9C, 0xB0, 0xA5, 0x11, 0xA4, 0xD1, +0xAD, 0x32, 0xCD, 0xF5, 0xC5, 0xD4, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x32, 0xB5, 0x73, 0xAD, 0x32, +0xAD, 0x11, 0xCD, 0xD3, 0xDE, 0x34, 0xD6, 0x13, +0xDE, 0x33, 0xCD, 0xD2, 0xBD, 0x51, 0x9C, 0x8F, +0xB5, 0x53, 0xA4, 0x8F, 0xAC, 0xD0, 0xB5, 0x11, +0xAC, 0xAF, 0xA4, 0x6F, 0x9C, 0x4E, 0x94, 0x2E, +0x7B, 0x8B, 0x83, 0xCC, 0x94, 0x2E, 0xA4, 0x8F, +0xA4, 0x8F, 0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF1, +0xAC, 0xD0, 0xA4, 0xB0, 0x9C, 0x6F, 0x94, 0x4F, +0x83, 0xCD, 0x4A, 0x27, 0x29, 0x45, 0x31, 0xA6, +0x5A, 0xCB, 0x94, 0x51, 0x83, 0xAE, 0x5A, 0x6A, +0x4A, 0x08, 0x39, 0xC7, 0x41, 0xE7, 0x4A, 0x08, +0x41, 0xE7, 0x4A, 0x29, 0x5A, 0x8A, 0x62, 0xCB, +0x52, 0x49, 0x73, 0x4D, 0x83, 0xCE, 0x8C, 0x10, +0x6B, 0x0B, 0x52, 0x8A, 0x31, 0x87, 0x31, 0x87, +0x10, 0xA3, 0x10, 0x82, 0x10, 0xA3, 0x10, 0xA3, +0x18, 0xE4, 0x29, 0x45, 0x19, 0x04, 0x10, 0xC3, +0x18, 0xE4, 0x73, 0x8D, 0x94, 0x70, 0x94, 0x50, +0x94, 0x70, 0x94, 0x4F, 0x8C, 0x0F, 0x8C, 0x2F, +0x8C, 0x2F, 0x94, 0x70, 0x94, 0x70, 0x8C, 0x2F, +0x8C, 0x0F, 0x8C, 0x0E, 0x8C, 0x2F, 0x8C, 0x2F, +0x8C, 0x2F, 0x7B, 0xCD, 0x8C, 0x4F, 0x94, 0x70, +0x84, 0x0E, 0x84, 0x0E, 0x9C, 0xD1, 0xA4, 0xF1, +0xAD, 0x11, 0xB5, 0x73, 0xA4, 0xD1, 0x94, 0x6F, +0xA4, 0xD0, 0x94, 0x6F, 0x83, 0xAC, 0x94, 0x2E, +0x9C, 0x6F, 0xB5, 0x31, 0xCD, 0xD4, 0xCD, 0xF4, +0xCD, 0xF4, 0xCD, 0xD4, 0xDE, 0x56, 0xE6, 0xB7, +0xEE, 0xD7, 0xEE, 0xD7, 0xE6, 0x96, 0xDE, 0x75, +0x53, 0xA7, 0x63, 0xE9, 0x64, 0x29, 0x4B, 0x64, +0x64, 0x05, 0x53, 0x86, 0x74, 0x8C, 0x74, 0x4C, +0x74, 0x4A, 0x7C, 0xAA, 0x84, 0xAC, 0x9D, 0x4E, +0x53, 0x66, 0x74, 0x6A, 0xBE, 0x33, 0xC6, 0x14, +0xC5, 0xF4, 0xCE, 0x54, 0xC6, 0x13, 0xCE, 0x13, +0xC5, 0xD3, 0xCD, 0xF3, 0xA4, 0x8E, 0xC5, 0xF3, +0xCE, 0x35, 0xC5, 0xF4, 0xC5, 0xF4, 0xC5, 0xF4, +0xC5, 0xD4, 0xCE, 0x15, 0xAD, 0x53, 0x4A, 0x48, +0x29, 0x45, 0x31, 0xA6, 0x39, 0xC6, 0x4A, 0x49, +0x42, 0x07, 0x4A, 0x69, 0x52, 0x8A, 0x5A, 0xEB, +0x7B, 0xEF, 0xD6, 0xBB, 0xF7, 0x9E, 0xCE, 0x37, +0xAD, 0x52, 0xBD, 0x92, 0xAC, 0xF0, 0xBD, 0x92, +0xB5, 0x72, 0xB5, 0x72, 0xAD, 0x31, 0xB5, 0x73, +0xC5, 0xD4, 0xCE, 0x35, 0xC5, 0xF4, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xD4, 0xBD, 0xB3, 0xCE, 0x35, +0xB5, 0x51, 0xBD, 0x72, 0xBD, 0x72, 0xB5, 0x31, +0xBD, 0x72, 0xAC, 0xEF, 0x94, 0x2C, 0x9C, 0x8E, +0x9C, 0x6D, 0x9C, 0x4D, 0x9C, 0x8E, 0xC5, 0x92, +0xD5, 0xF3, 0xD6, 0x13, 0xCD, 0xF3, 0xC5, 0xB2, +0xB5, 0x31, 0xAD, 0x10, 0xAD, 0x31, 0xB5, 0x10, +0xBD, 0x71, 0xBD, 0x92, 0xB5, 0x30, 0xAC, 0xEF, +0xAC, 0xCF, 0xBD, 0x71, 0xBD, 0x30, 0xA4, 0xAE, +0xA4, 0xCF, 0x9C, 0xB0, 0x83, 0xCD, 0x5A, 0xA9, +0x5A, 0xCA, 0x4A, 0x48, 0x6B, 0x0C, 0x73, 0x8E, +0xC6, 0x39, 0xBD, 0xD7, 0x7B, 0xEF, 0x94, 0x92, +0xBD, 0xF7, 0x84, 0x30, 0x31, 0x86, 0x42, 0x49, +0x9C, 0xF3, 0xAD, 0x55, 0xAD, 0x55, 0xBD, 0xF8, +0xBD, 0xB7, 0xC6, 0x19, 0xCE, 0x39, 0xCE, 0x7A, +0xAD, 0x76, 0xC6, 0x19, 0xBD, 0xF7, 0x8C, 0x30, +0x8C, 0x0F, 0x94, 0x2E, 0x94, 0x0D, 0x8B, 0xEC, +0x83, 0x8B, 0x7B, 0x6A, 0x83, 0xCC, 0x83, 0xCC, +0x83, 0xAC, 0x8B, 0xEC, 0x94, 0x2D, 0x73, 0x29, +0x83, 0xAB, 0x94, 0x0C, 0x73, 0x29, 0xA4, 0xD0, +0x9C, 0x8F, 0xA4, 0xD0, 0xB5, 0x72, 0xB5, 0x72, +0xB5, 0x31, 0xAD, 0x31, 0x7B, 0xCD, 0x42, 0x07, +0x39, 0xC6, 0x42, 0x07, 0x4A, 0x28, 0x4A, 0x28, +0x5A, 0xAA, 0x5A, 0xCA, 0x5A, 0xAA, 0x73, 0x8D, +0x73, 0x8E, 0x7C, 0x10, 0x84, 0x51, 0x9C, 0xD4, +0xB5, 0xD7, 0xC6, 0x38, 0xBD, 0xB5, 0xAD, 0x32, +0xC5, 0xB3, 0xC5, 0xD4, 0xBD, 0x93, 0xB5, 0x73, +0xB5, 0x73, 0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0xD4, +0xC5, 0xF4, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x73, +0xC5, 0xB4, 0xBD, 0x93, 0xB5, 0x93, 0xC5, 0xF4, +0xD6, 0x14, 0xD6, 0x35, 0xC5, 0xD3, 0xB5, 0x31, +0xAD, 0x11, 0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x34, +0xD6, 0x14, 0xC5, 0x92, 0xBD, 0x92, 0xD6, 0x14, +0xC5, 0x93, 0xAD, 0x11, 0xA4, 0xF0, 0x9C, 0x8F, +0x94, 0x6E, 0x8C, 0x2D, 0x94, 0x8F, 0x9C, 0xAF, +0xA5, 0x11, 0xBD, 0x92, 0xBD, 0x93, 0xA4, 0xF1, +0xA4, 0xF1, 0xBD, 0x93, 0xBD, 0xB4, 0xAD, 0x32, +0xAD, 0x53, 0xBD, 0xB4, 0xAD, 0x52, 0xB5, 0x53, +0xBD, 0xB4, 0xAD, 0x32, 0x9C, 0xB0, 0xA4, 0xD1, +0xB5, 0x52, 0xC5, 0xD4, 0xBD, 0x93, 0xC5, 0xD4, +0xB5, 0x73, 0xA5, 0x12, 0xAD, 0x32, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x52, 0xC5, 0x92, 0xC5, 0x91, +0xC5, 0xB1, 0xBD, 0x51, 0xB5, 0x31, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x11, 0xAC, 0xCF, 0x9C, 0x6E, +0x9C, 0x6E, 0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x11, +0xA4, 0xD0, 0x9C, 0xB0, 0xA4, 0xD0, 0xB5, 0x31, +0xAC, 0xF1, 0xA4, 0xD0, 0xA4, 0xAF, 0xBD, 0x73, +0xBD, 0x93, 0xC5, 0xF5, 0xBD, 0x73, 0x9C, 0x90, +0x9C, 0xB0, 0x9C, 0x6F, 0x6B, 0x2B, 0x31, 0x65, +0x29, 0x25, 0x31, 0x65, 0x4A, 0x28, 0x62, 0xEB, +0x7B, 0x8E, 0x7B, 0xAE, 0x62, 0xCB, 0x4A, 0x08, +0x4A, 0x08, 0x41, 0xC7, 0x4A, 0x08, 0x62, 0xAA, +0x52, 0x69, 0x49, 0xE8, 0x73, 0x0C, 0xAC, 0xD2, +0xAC, 0xD2, 0x62, 0xCB, 0x20, 0xE4, 0x21, 0x05, +0x21, 0x04, 0x21, 0x04, 0x21, 0x25, 0x29, 0x45, +0x21, 0x25, 0x18, 0xE4, 0x19, 0x04, 0x18, 0xE4, +0x4A, 0x69, 0xA4, 0xF2, 0xAD, 0x33, 0xAD, 0x33, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x32, 0xB5, 0x73, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, +0xB5, 0x53, 0xB5, 0x73, 0xAD, 0x53, 0xB5, 0x53, +0xAD, 0x33, 0xAD, 0x33, 0xA5, 0x12, 0xA5, 0x12, +0xA5, 0x12, 0xA5, 0x13, 0xA4, 0xF2, 0xA4, 0xF2, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xD1, 0xA4, 0xF2, +0xA4, 0xF2, 0xA4, 0xF2, 0xA4, 0xF2, 0x9C, 0xB1, +0x94, 0x50, 0x8C, 0x2E, 0x8C, 0x0E, 0x8C, 0x2E, +0x8C, 0x0E, 0x8C, 0x0D, 0x94, 0x4E, 0x9C, 0x8F, +0xA4, 0xAF, 0xA4, 0xCF, 0x9C, 0x6E, 0x9C, 0x6E, +0x4B, 0x27, 0x7C, 0xAC, 0x74, 0x4A, 0x43, 0x03, +0x84, 0xEC, 0x8D, 0x0F, 0x63, 0xEB, 0x74, 0x4C, +0x64, 0x28, 0x6C, 0x47, 0x95, 0x2E, 0x6B, 0xE9, +0x64, 0x07, 0x7C, 0xAB, 0xB6, 0x13, 0xBD, 0xF4, +0xBD, 0xB3, 0xBD, 0xD3, 0xC5, 0xD3, 0xC5, 0xD3, +0xC5, 0xD3, 0xCE, 0x14, 0x9C, 0x4D, 0xAD, 0x10, +0x9C, 0xAF, 0xAD, 0x52, 0xC5, 0xF5, 0xC6, 0x15, +0xC5, 0xF4, 0xBD, 0xB4, 0xD6, 0x56, 0xC5, 0xF6, +0x5A, 0xEA, 0x29, 0x44, 0x31, 0x85, 0x31, 0xA6, +0x42, 0x07, 0x63, 0x2C, 0x6B, 0x4D, 0x4A, 0x49, +0x41, 0xE8, 0x73, 0x8E, 0xA5, 0x34, 0x4A, 0x49, +0x6B, 0x4C, 0xAD, 0x11, 0xAC, 0xF0, 0xBD, 0x93, +0xB5, 0x73, 0xBD, 0x92, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0xD4, 0xC5, 0xF4, 0x9C, 0x8F, 0xB5, 0x52, +0xC5, 0xF4, 0xBD, 0xB3, 0xB5, 0x52, 0xC5, 0xD4, +0xBD, 0xB3, 0xBD, 0x92, 0xB5, 0x31, 0xBD, 0x92, +0xB5, 0x30, 0xA4, 0xAE, 0xAD, 0x30, 0xB5, 0x51, +0xBD, 0x92, 0xAC, 0xCF, 0x9C, 0x8E, 0xBD, 0x92, +0xC5, 0xD2, 0xA4, 0xCF, 0xCD, 0xF4, 0xCD, 0xF3, +0xCE, 0x14, 0xBD, 0xD3, 0xC5, 0xF4, 0xCD, 0xD4, +0xC5, 0xD3, 0xCE, 0x14, 0xC5, 0xB3, 0xBD, 0xB3, +0xBD, 0x72, 0xC5, 0xB2, 0xC5, 0xB2, 0xBD, 0x92, +0xBD, 0x92, 0xB5, 0x73, 0x9C, 0xD0, 0x8C, 0x4F, +0x73, 0x6C, 0x39, 0xA6, 0x52, 0xAA, 0x5A, 0xCB, +0x8C, 0x51, 0xBD, 0xB6, 0x73, 0x8E, 0xB5, 0x76, +0xDE, 0xDB, 0xE7, 0x3C, 0x9C, 0xD3, 0x39, 0xE7, +0x5A, 0xCB, 0xAD, 0x76, 0xC6, 0x19, 0xB5, 0x97, +0xAD, 0x76, 0xB5, 0x76, 0xB5, 0x76, 0x8C, 0x52, +0x73, 0x8F, 0xD6, 0x7A, 0xDE, 0xFB, 0xC5, 0xF7, +0xC5, 0x95, 0xBD, 0x32, 0xBD, 0x52, 0xC5, 0x72, +0xBD, 0x31, 0xB5, 0x31, 0xB5, 0x31, 0xB5, 0x11, +0xB4, 0xF0, 0xAC, 0xCF, 0xAC, 0xAF, 0xAC, 0xD0, +0xB4, 0xF0, 0xB5, 0x10, 0xA4, 0xCF, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x4D, 0x94, 0x0C, 0x83, 0xCB, +0x8C, 0x0C, 0x94, 0x4D, 0x94, 0x4E, 0x6B, 0x2A, +0x31, 0xA5, 0x42, 0x07, 0x42, 0x07, 0x42, 0x07, +0x4A, 0x48, 0x52, 0x89, 0x52, 0xAA, 0x52, 0xAA, +0x6B, 0x4D, 0x7B, 0xF0, 0x94, 0x92, 0x9C, 0xF4, +0xAD, 0x55, 0xAD, 0x55, 0xCE, 0x58, 0xB5, 0x74, +0xB5, 0x52, 0xB5, 0x32, 0xA4, 0xF1, 0xA4, 0xD0, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0xD4, +0xC5, 0xF4, 0xC5, 0xD4, 0xB5, 0x72, 0xC5, 0xB3, +0xCD, 0xF4, 0xCE, 0x35, 0xCE, 0x15, 0xCD, 0xF4, +0xD6, 0x35, 0xD6, 0x55, 0xCE, 0x14, 0xB5, 0x31, +0xAC, 0xF1, 0xBD, 0xB3, 0xBD, 0x52, 0xCD, 0xD3, +0xD6, 0x14, 0xCD, 0xD3, 0xCD, 0xF4, 0xD6, 0x35, +0xD6, 0x14, 0xC5, 0xB3, 0xC5, 0x93, 0xC5, 0xB3, +0xAD, 0x31, 0x9C, 0x8F, 0xAD, 0x11, 0xB5, 0x72, +0xBD, 0x93, 0xCD, 0xF4, 0xCE, 0x14, 0xBD, 0x92, +0xBD, 0xB2, 0xC5, 0xD3, 0xC5, 0xF4, 0xAD, 0x32, +0xAD, 0x32, 0xC5, 0xD4, 0xBD, 0x94, 0xBD, 0x94, +0xC5, 0xD5, 0xBD, 0xB4, 0xAD, 0x12, 0x9C, 0xB0, +0xBD, 0xB4, 0xC5, 0xD4, 0xB5, 0x52, 0xBD, 0xB4, +0xB5, 0x73, 0xA5, 0x12, 0xB5, 0x53, 0xB5, 0x93, +0xBD, 0x94, 0xB5, 0x53, 0xBD, 0x72, 0xCD, 0xF3, +0xC5, 0x92, 0xA4, 0xD0, 0xB5, 0x52, 0xB5, 0x52, +0xB5, 0x32, 0x9C, 0x4E, 0x94, 0x0D, 0x9C, 0x4E, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xD0, +0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0xD0, +0x9C, 0x6F, 0xA4, 0xB0, 0xBD, 0x93, 0xB5, 0x53, +0x9C, 0x8F, 0x9C, 0xB0, 0xA4, 0xB0, 0x9C, 0xB0, +0xBD, 0x93, 0xC5, 0xD4, 0xCD, 0xF4, 0x83, 0xCC, +0x41, 0xE6, 0x29, 0x44, 0x29, 0x44, 0x39, 0xC6, +0x52, 0x69, 0x7B, 0x8E, 0xA4, 0xD3, 0x83, 0xEF, +0x4A, 0x28, 0x52, 0x29, 0x52, 0x29, 0x52, 0x49, +0x62, 0xEB, 0x5A, 0x8A, 0x4A, 0x08, 0x7B, 0x8D, +0x94, 0x50, 0xA4, 0xD3, 0x73, 0x4D, 0x20, 0xE4, +0x18, 0xE4, 0x19, 0x04, 0x21, 0x25, 0x21, 0x25, +0x21, 0x04, 0x18, 0xE4, 0x18, 0xC4, 0x5A, 0xCB, +0x84, 0x0E, 0x8C, 0x2F, 0x94, 0x6F, 0xA4, 0xF2, +0xB5, 0x74, 0xCD, 0xF6, 0xB5, 0x73, 0x8C, 0x2F, +0x94, 0x4F, 0xB5, 0x74, 0x9C, 0x70, 0x9C, 0x90, +0x9C, 0xB0, 0x9C, 0x90, 0x94, 0x70, 0x83, 0xEE, +0x8C, 0x0E, 0x94, 0x50, 0xA4, 0xF2, 0xCE, 0x57, +0xBD, 0xB4, 0x9C, 0x90, 0xAD, 0x12, 0xAD, 0x33, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x32, +0xAD, 0x12, 0xB5, 0x32, 0xB5, 0x73, 0xB5, 0x32, +0xBD, 0x74, 0xB5, 0x53, 0xAD, 0x12, 0xB5, 0x32, +0xB5, 0x53, 0xB5, 0x53, 0xAD, 0x32, 0xB5, 0x32, +0xB5, 0x32, 0xAD, 0x11, 0xAC, 0xF1, 0xAC, 0xF1, +0x32, 0x24, 0x5B, 0x88, 0x6B, 0xC9, 0x42, 0xA4, +0x7C, 0xAD, 0xA5, 0x93, 0xB6, 0x36, 0x74, 0x4C, +0x64, 0x27, 0x63, 0xE5, 0x74, 0x68, 0x74, 0x6A, +0x6C, 0x69, 0x7C, 0xAC, 0xBE, 0x54, 0xBD, 0xD3, +0xB5, 0xB2, 0xBD, 0xD3, 0xC5, 0xF4, 0xBD, 0xD4, +0xC6, 0x14, 0xD6, 0x55, 0xA4, 0x8E, 0x8C, 0x0C, +0x6B, 0x2A, 0xBD, 0xB4, 0xC6, 0x15, 0xC5, 0xF4, +0xC6, 0x15, 0xC5, 0xF5, 0xC5, 0xF5, 0xD6, 0x77, +0xCE, 0x36, 0x7B, 0x8C, 0x31, 0x85, 0x31, 0x85, +0x42, 0x07, 0x4A, 0x48, 0x42, 0x07, 0x42, 0x08, +0x52, 0x8A, 0x42, 0x28, 0x52, 0x6A, 0x73, 0x8E, +0x41, 0xC7, 0x39, 0xC7, 0xB5, 0x95, 0xB5, 0x93, +0xAD, 0x11, 0xBD, 0xD4, 0xB5, 0x72, 0xB5, 0x72, +0xC5, 0xF4, 0xBD, 0x93, 0xB5, 0x93, 0xCE, 0x15, +0xC5, 0xF4, 0xB5, 0x93, 0xB5, 0x52, 0xBD, 0xD4, +0xBD, 0xB3, 0xB5, 0x51, 0xAD, 0x31, 0xA4, 0xEF, +0xAD, 0x10, 0xA4, 0xCF, 0xAC, 0xEF, 0xB5, 0x30, +0xC5, 0x71, 0x9C, 0x6D, 0xA4, 0xCF, 0xBD, 0xB3, +0xCD, 0xF4, 0x83, 0xED, 0xC5, 0xD4, 0xC5, 0xD3, +0xC5, 0xF4, 0xBD, 0xD3, 0xCE, 0x15, 0xCE, 0x35, +0xC5, 0xD3, 0xC5, 0xF4, 0xBD, 0xB3, 0xC5, 0xD4, +0xAD, 0x11, 0xBD, 0x93, 0xBD, 0x92, 0xB5, 0x71, +0xB5, 0x51, 0xC5, 0xD4, 0xA5, 0x11, 0xAD, 0x11, +0x9C, 0x8F, 0x8C, 0x0D, 0x73, 0x6B, 0x52, 0x68, +0x5A, 0xCA, 0x7B, 0xAE, 0x83, 0xEF, 0xB5, 0x76, +0xC6, 0x18, 0xB5, 0x96, 0xB5, 0x96, 0x7B, 0xCE, +0x42, 0x08, 0x6B, 0x2D, 0xC6, 0x39, 0x9C, 0xB3, +0x52, 0x8B, 0x39, 0xE8, 0xA5, 0x15, 0xCE, 0x7A, +0x9C, 0xD3, 0x52, 0x8A, 0x8C, 0x51, 0xDE, 0xBA, +0xEE, 0xFB, 0xD6, 0x17, 0x8B, 0xCE, 0x8B, 0xED, +0x7B, 0x6B, 0x7B, 0x8B, 0x83, 0xAB, 0x7B, 0x8B, +0x83, 0xAC, 0x83, 0x8C, 0x7B, 0x6B, 0x8B, 0xED, +0xAD, 0x10, 0xAC, 0xF0, 0xA4, 0xAF, 0xBD, 0x51, +0xC5, 0xB3, 0xC5, 0x92, 0xB5, 0x31, 0xAC, 0xEF, +0xA4, 0xCF, 0xA4, 0xCF, 0xA4, 0xCF, 0x9C, 0x6F, +0x4A, 0x27, 0x39, 0xA5, 0x39, 0xA6, 0x31, 0x85, +0x42, 0x27, 0x52, 0xA9, 0x4A, 0x89, 0x52, 0xAA, +0x63, 0x2C, 0x73, 0x8E, 0x94, 0xB3, 0x8C, 0x72, +0x8C, 0x52, 0x9C, 0xF4, 0xCE, 0x59, 0xB5, 0x75, +0x94, 0x70, 0x94, 0x4F, 0x8C, 0x0E, 0x8C, 0x0E, +0x8C, 0x2F, 0x94, 0x4F, 0x9C, 0x6F, 0x9C, 0xAF, +0x9C, 0xB0, 0x9C, 0x8F, 0x94, 0x6E, 0x9C, 0x8F, +0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x11, 0xBD, 0x72, +0xBD, 0x72, 0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x11, +0xAC, 0xF1, 0xAD, 0x31, 0xCE, 0x15, 0xD6, 0x35, +0xD6, 0x34, 0xD6, 0x14, 0xDE, 0x76, 0xD6, 0x35, +0xDE, 0x55, 0xD6, 0x14, 0xCD, 0xF4, 0xDE, 0xB7, +0xCD, 0xF4, 0xBD, 0xB3, 0xCD, 0xF4, 0xCE, 0x14, +0xD6, 0x35, 0xD6, 0x14, 0xD6, 0x34, 0xD6, 0x34, +0xDE, 0x55, 0xD6, 0x14, 0xCE, 0x15, 0xB5, 0x53, +0xB5, 0x52, 0xC5, 0xD4, 0xB5, 0x93, 0xBD, 0xB4, +0xBD, 0xB4, 0xBD, 0x94, 0xAD, 0x12, 0x83, 0xED, +0x9C, 0xD1, 0xCE, 0x36, 0xB5, 0x73, 0xBD, 0xB4, +0xB5, 0x73, 0xAD, 0x12, 0xBD, 0xB4, 0xBD, 0xB4, +0xBD, 0x94, 0xB5, 0x53, 0xBD, 0x93, 0xC5, 0xF3, +0xBD, 0x92, 0xA4, 0xD0, 0x9C, 0xAF, 0xAC, 0xF1, +0xAC, 0xF1, 0x94, 0x4E, 0x94, 0x2D, 0x94, 0x4E, +0x9C, 0x4E, 0x94, 0x4E, 0x9C, 0x6E, 0xAC, 0xF1, +0xB5, 0x32, 0xA4, 0xB0, 0x9C, 0x4E, 0x9C, 0x8F, +0x9C, 0x6F, 0xA4, 0xD0, 0xC5, 0xD4, 0xB5, 0x52, +0x9C, 0x6E, 0xA4, 0xAF, 0x9C, 0x8F, 0x9C, 0x4F, +0x9C, 0x8F, 0xAC, 0xF0, 0xBD, 0x92, 0xA4, 0xAF, +0x94, 0x4F, 0x63, 0x0A, 0x39, 0xA6, 0x29, 0x44, +0x31, 0x65, 0x39, 0xC7, 0x4A, 0x49, 0x63, 0x0C, +0x4A, 0x49, 0x62, 0xEB, 0x94, 0x51, 0x7B, 0xCF, +0x39, 0xA6, 0x62, 0xCB, 0x5A, 0x8A, 0x4A, 0x29, +0x5A, 0xAA, 0x9C, 0x71, 0xBD, 0x75, 0x83, 0xAE, +0x31, 0x66, 0x18, 0xC4, 0x18, 0xE4, 0x18, 0xE4, +0x18, 0xE3, 0x18, 0xE4, 0x5A, 0xCA, 0xD6, 0x76, +0xEF, 0x18, 0xDE, 0xB7, 0xCD, 0xF5, 0xBD, 0x94, +0xAD, 0x53, 0xBD, 0xB4, 0xC5, 0xF5, 0x94, 0x90, +0xBD, 0xD5, 0xDE, 0xB8, 0xAD, 0x32, 0x94, 0x70, +0x8C, 0x4F, 0xA4, 0xF2, 0xA5, 0x12, 0xAD, 0x33, +0xB5, 0x94, 0xB5, 0x74, 0xBD, 0x94, 0xD6, 0x56, +0xDE, 0xB8, 0x94, 0x70, 0xB5, 0x53, 0xB5, 0x32, +0xAD, 0x11, 0xC5, 0xD3, 0xCD, 0xD4, 0xCD, 0xD4, +0xC5, 0xB3, 0xCD, 0xF4, 0xCE, 0x14, 0xBD, 0x93, +0xBD, 0x72, 0xBD, 0x73, 0xD6, 0x35, 0xD6, 0x14, +0xBD, 0x92, 0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x14, +0xDE, 0x55, 0xD6, 0x35, 0xD6, 0x14, 0xCD, 0xF4, +0x63, 0xCB, 0x4A, 0xE6, 0x74, 0x0A, 0x4A, 0xC5, +0x63, 0xCA, 0x9D, 0x52, 0xA5, 0x73, 0x5B, 0x48, +0x64, 0x08, 0x4B, 0x23, 0x63, 0xE7, 0x6C, 0x69, +0x7C, 0xCB, 0x7C, 0x8B, 0x8C, 0xAD, 0x9D, 0x0D, +0xA5, 0x4D, 0xAD, 0x6F, 0xA4, 0xCF, 0xA4, 0xCF, +0xAD, 0x30, 0xBD, 0x91, 0xA4, 0xAE, 0x94, 0x0C, +0xAD, 0x52, 0xD6, 0x96, 0xDE, 0xB7, 0xD6, 0x76, +0xD6, 0x76, 0xD6, 0x97, 0xD6, 0x76, 0xD6, 0x97, +0xD6, 0x97, 0xC5, 0xF4, 0x94, 0x6F, 0x4A, 0x67, +0x39, 0xC6, 0x41, 0xE7, 0x39, 0xE7, 0x52, 0xAA, +0x73, 0x8E, 0x4A, 0x69, 0x5A, 0xCA, 0x73, 0x6D, +0x83, 0xAE, 0x73, 0xAE, 0xEF, 0x7C, 0xEF, 0x5B, +0xBD, 0xB5, 0xAD, 0x32, 0xAD, 0x31, 0xAD, 0x11, +0xC5, 0xD4, 0xB5, 0x93, 0xBD, 0xB3, 0xBD, 0xB4, +0xB5, 0x72, 0xB5, 0x72, 0xAD, 0x31, 0xAD, 0x31, +0xA4, 0xF0, 0xA4, 0xEF, 0xA4, 0xCF, 0x94, 0x6D, +0xA4, 0xEF, 0xA4, 0xEF, 0xC5, 0x91, 0xCD, 0xD2, +0xD6, 0x34, 0x9C, 0x6D, 0xAD, 0x11, 0xC5, 0xF4, +0xCE, 0x55, 0xB5, 0x93, 0xAD, 0x52, 0xB5, 0x93, +0xBD, 0xB3, 0xB5, 0x52, 0xB5, 0x92, 0xBD, 0xD3, +0xBD, 0xB3, 0xC5, 0xD4, 0xBD, 0xD4, 0xC6, 0x15, +0xB5, 0x93, 0xC5, 0xD4, 0xBD, 0x92, 0xAD, 0x51, +0x94, 0x4E, 0xA4, 0xF0, 0xA4, 0xF1, 0xAD, 0x31, +0xBD, 0x71, 0xDE, 0x54, 0xCD, 0xD3, 0xB5, 0x52, +0x6A, 0xEA, 0x4A, 0x28, 0x7B, 0xCF, 0xA5, 0x14, +0x7B, 0xAF, 0x83, 0xF0, 0xAD, 0x75, 0xC5, 0xF7, +0x52, 0x8A, 0x42, 0x49, 0x73, 0xAF, 0xB5, 0x96, +0xA5, 0x14, 0x73, 0x8E, 0xAD, 0x76, 0xAD, 0x35, +0x52, 0x6A, 0x5A, 0xAB, 0xA5, 0x14, 0xDE, 0x9A, +0xF7, 0x3C, 0xEF, 0x1C, 0xB5, 0x75, 0x7B, 0xAD, +0x7B, 0xAC, 0x8C, 0x0E, 0x8C, 0x2E, 0x83, 0xED, +0x7B, 0xCD, 0x83, 0xCD, 0x8C, 0x2E, 0x8C, 0x2E, +0x94, 0x6F, 0x7B, 0xAC, 0x7B, 0xAB, 0xA4, 0xAF, +0x9C, 0x6E, 0x9C, 0x8E, 0xAC, 0xCF, 0xB5, 0x31, +0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xB0, +0x7B, 0x8C, 0x41, 0xE6, 0x39, 0xC6, 0x39, 0xC6, +0x41, 0xE7, 0x52, 0xA9, 0x42, 0x28, 0x52, 0x8A, +0x5A, 0xEB, 0x63, 0x2C, 0x6B, 0x4D, 0x73, 0x6E, +0x7B, 0xAF, 0x9C, 0xF4, 0xBD, 0xF8, 0xCE, 0x59, +0xB5, 0x54, 0xAD, 0x12, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xB1, 0x9C, 0x6F, 0x9C, 0x90, 0xA4, 0xD0, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xD0, +0x9C, 0x6F, 0x9C, 0x6F, 0x9C, 0x6F, 0xA4, 0xB0, +0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x52, +0xBD, 0x73, 0xB5, 0x52, 0xA4, 0xB0, 0xA4, 0x8F, +0x9C, 0x8F, 0x9C, 0x6E, 0xA4, 0xD0, 0xB5, 0x52, +0xC5, 0xD3, 0xC5, 0xB3, 0xBD, 0x92, 0xCD, 0xF4, +0xC5, 0xB3, 0xC5, 0xB3, 0xCE, 0x14, 0xD6, 0x55, +0xD6, 0x34, 0xD6, 0x35, 0xD6, 0x34, 0xDE, 0x75, +0xDE, 0x76, 0xDE, 0x55, 0xCD, 0xF4, 0xA4, 0xF1, +0xAC, 0xF1, 0xBD, 0x93, 0xB5, 0x53, 0xBD, 0x94, +0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0xB4, 0xAD, 0x53, +0xA4, 0xF1, 0xC5, 0xF5, 0xB5, 0x93, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x53, 0xBD, 0xB5, 0xBD, 0xB4, +0xBD, 0xB4, 0xAD, 0x12, 0xBD, 0x93, 0xBD, 0xB3, +0xC5, 0xB3, 0xAD, 0x31, 0xA4, 0xF0, 0xAD, 0x11, +0xAD, 0x32, 0xA4, 0xF0, 0x9C, 0x8E, 0xA4, 0xD0, +0x9C, 0x6E, 0xA4, 0xD0, 0xAC, 0xF0, 0xB5, 0x31, +0xB5, 0x31, 0xA4, 0xD0, 0xA4, 0x8F, 0x9C, 0x8F, +0xA4, 0xD0, 0x9C, 0x6E, 0x94, 0x2D, 0x9C, 0x8F, +0x94, 0x6E, 0x94, 0x4E, 0xAC, 0xF1, 0xAC, 0xF1, +0xAC, 0xF0, 0xA4, 0xD0, 0xBD, 0x72, 0xAC, 0xF0, +0xAC, 0xF0, 0xB5, 0x52, 0x83, 0xEE, 0x39, 0xC6, +0x29, 0x44, 0x29, 0x44, 0x29, 0x45, 0x29, 0x45, +0x29, 0x65, 0x41, 0xE7, 0x6B, 0x2D, 0x7B, 0xCF, +0x4A, 0x49, 0x62, 0xEB, 0x5A, 0x8A, 0x52, 0x6A, +0x41, 0xE8, 0x5A, 0xAB, 0x83, 0xAE, 0xA4, 0xD3, +0x94, 0x51, 0x41, 0xE8, 0x10, 0x82, 0x10, 0xA3, +0x21, 0x04, 0x52, 0x68, 0xD6, 0x55, 0xEF, 0x18, +0xEE, 0xD7, 0xE6, 0xD7, 0xE6, 0xB7, 0xDE, 0xB8, +0xCE, 0x57, 0xC6, 0x16, 0xC6, 0x16, 0xC6, 0x16, +0xCE, 0x77, 0xD6, 0x97, 0xCE, 0x57, 0xBD, 0xF6, +0xCE, 0x37, 0xD6, 0x98, 0xDE, 0xB8, 0xDE, 0xB8, +0xDE, 0xB8, 0xDE, 0xB8, 0xE6, 0xD9, 0xE6, 0xB8, +0xDE, 0xB8, 0xA4, 0xF2, 0xBD, 0xB4, 0xD6, 0x34, +0xD6, 0x34, 0xDE, 0x74, 0xDE, 0x75, 0xDE, 0x75, +0xDE, 0x55, 0xDE, 0x75, 0xE6, 0x96, 0xD6, 0x34, +0xDE, 0x55, 0xDE, 0x55, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x75, 0xE6, 0x95, 0xE6, 0x95, 0xEE, 0xB6, +0xE6, 0x95, 0xE6, 0xB5, 0xE6, 0xB6, 0xEE, 0xD6, +0x74, 0x2C, 0x53, 0x47, 0x63, 0xC8, 0x6C, 0x09, +0x5B, 0x89, 0x74, 0x2C, 0x74, 0x0B, 0x53, 0x27, +0x6C, 0x29, 0x43, 0x03, 0x53, 0x65, 0x53, 0xA7, +0x6C, 0x69, 0x74, 0x89, 0x8C, 0xEA, 0x95, 0x49, +0x9D, 0x6A, 0x9C, 0xCA, 0x94, 0x8B, 0x84, 0x2A, +0x9C, 0xEE, 0xAD, 0x0F, 0xA4, 0x8D, 0x94, 0x2C, +0x8B, 0xCB, 0x8C, 0x0C, 0x94, 0x2D, 0x94, 0x4D, +0x9C, 0x6D, 0x9C, 0x6E, 0xA4, 0xF0, 0xAC, 0xF0, +0x94, 0x2D, 0x83, 0xCC, 0x9C, 0x6E, 0x9C, 0x6F, +0x52, 0x47, 0x39, 0xC6, 0x42, 0x07, 0x4A, 0x48, +0x52, 0xAA, 0x52, 0x89, 0x4A, 0x49, 0x41, 0xE7, +0x63, 0x0C, 0x63, 0x0C, 0xBD, 0xD7, 0xEF, 0x5D, +0xEF, 0x7D, 0xDE, 0xBA, 0x94, 0x91, 0x6B, 0x2B, +0x9C, 0xD0, 0xBD, 0xB4, 0xC5, 0xF4, 0xBD, 0xD4, +0xBD, 0xB3, 0xB5, 0x93, 0xAD, 0x52, 0xB5, 0x72, +0xAD, 0x31, 0xA5, 0x10, 0x8C, 0x0C, 0x94, 0x4D, +0xA4, 0xAE, 0xC5, 0xB1, 0xD6, 0x12, 0xD6, 0x12, +0xDE, 0x54, 0x8B, 0xCB, 0x8C, 0x2D, 0xAD, 0x31, +0xB5, 0x92, 0xA5, 0x11, 0xA5, 0x11, 0x9C, 0xD1, +0xAD, 0x52, 0xA5, 0x11, 0xB5, 0xB3, 0xAD, 0x52, +0xB5, 0x72, 0xBD, 0xB3, 0xBD, 0xD3, 0xBD, 0xD4, +0xC5, 0xF4, 0xC5, 0xF4, 0xBD, 0x92, 0xA4, 0xF0, +0x9C, 0xB0, 0x8C, 0x2E, 0x83, 0xED, 0x94, 0x6E, +0xB5, 0x30, 0xDE, 0x34, 0xC5, 0x91, 0xC5, 0xB2, +0xA4, 0xAF, 0x8C, 0x0D, 0x6B, 0x2B, 0x84, 0x10, +0x73, 0xAF, 0xA5, 0x14, 0x9C, 0xF3, 0xB5, 0x75, +0xA5, 0x14, 0x52, 0x8A, 0x39, 0xE8, 0x73, 0xAF, +0xC6, 0x18, 0xA5, 0x14, 0xBD, 0xF7, 0xBD, 0xD7, +0x9C, 0xB2, 0xC5, 0xD7, 0xDE, 0xDA, 0xE6, 0xBA, +0xF7, 0x5D, 0xEE, 0xFB, 0xDE, 0x79, 0x94, 0x70, +0x9C, 0x90, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x12, +0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xF1, +0xBD, 0xB4, 0xAD, 0x12, 0x8C, 0x2E, 0x9C, 0xB0, +0x9C, 0xAF, 0x9C, 0x8F, 0xAC, 0xF0, 0xBD, 0x72, +0xB5, 0x52, 0x94, 0x6F, 0xB5, 0x93, 0xC5, 0xF5, +0xB5, 0x53, 0x52, 0x48, 0x39, 0xA5, 0x39, 0xC6, +0x31, 0x85, 0x42, 0x28, 0x42, 0x28, 0x5A, 0xEB, +0x6B, 0x4C, 0x63, 0x0C, 0x63, 0x2C, 0x7B, 0xAF, +0x8C, 0x72, 0xA5, 0x35, 0xB5, 0xB7, 0xC6, 0x18, +0xCE, 0x17, 0x9C, 0x91, 0xAC, 0xF1, 0xC5, 0xD5, +0xBD, 0xB4, 0xAD, 0x32, 0xBD, 0x93, 0xAC, 0xF1, +0xA4, 0xD0, 0xAC, 0xF1, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x12, 0xAC, 0xF1, 0xA4, 0xD0, 0xAC, 0xF1, +0xA4, 0x90, 0xA4, 0xD0, 0xA4, 0xF0, 0xAC, 0xF0, +0xAC, 0xF1, 0xAD, 0x12, 0xB5, 0x52, 0xB5, 0x32, +0xB5, 0x52, 0xB5, 0x12, 0xB5, 0x32, 0xA4, 0x8F, +0x8B, 0xED, 0xA4, 0xD0, 0xB5, 0x31, 0xB5, 0x31, +0xAD, 0x10, 0xAD, 0x11, 0xA4, 0xD0, 0xAC, 0xF0, +0xA4, 0xD0, 0xAC, 0xF0, 0xAD, 0x10, 0xB5, 0x11, +0xB5, 0x10, 0xAD, 0x10, 0xB5, 0x11, 0xB5, 0x31, +0xB5, 0x72, 0xB5, 0x52, 0xA4, 0xF1, 0xA4, 0xD0, +0x9C, 0xB0, 0xAD, 0x11, 0xAD, 0x32, 0xAD, 0x11, +0x9C, 0xD0, 0xA4, 0xF1, 0xA4, 0xD1, 0x9C, 0xB0, +0x94, 0x90, 0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x32, 0x9C, 0xB1, 0xA4, 0xF1, 0xAD, 0x32, +0xBD, 0x93, 0xAC, 0xF0, 0xB5, 0x52, 0xAD, 0x11, +0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x10, 0xBD, 0x93, +0xAC, 0xF0, 0xB5, 0x32, 0xBD, 0x73, 0xB5, 0x31, +0xC5, 0xB3, 0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0x6F, 0xA4, 0xB0, 0xAC, 0xF1, +0xA4, 0xD0, 0x9C, 0xAF, 0xB5, 0x52, 0xB5, 0x11, +0xAC, 0xF1, 0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xF0, +0xB5, 0x52, 0xBD, 0x73, 0xBD, 0xD4, 0xA4, 0xD1, +0x5A, 0xCA, 0x31, 0x85, 0x29, 0x24, 0x21, 0x03, +0x29, 0x24, 0x29, 0x65, 0x29, 0x65, 0x39, 0xC7, +0x41, 0xE7, 0x4A, 0x28, 0x5A, 0xAB, 0x52, 0x49, +0x4A, 0x29, 0x4A, 0x08, 0x83, 0xAF, 0x83, 0xAE, +0xB5, 0x34, 0xA4, 0xD3, 0x41, 0xE8, 0x18, 0xC4, +0x63, 0x0B, 0xAC, 0xF1, 0xF7, 0x18, 0xE6, 0xD7, +0xE6, 0xD6, 0xE6, 0xB6, 0xDE, 0x96, 0xE6, 0xD8, +0xE6, 0xD8, 0xDE, 0xB8, 0xDE, 0xB8, 0xDE, 0xB8, +0xDE, 0xB8, 0xDE, 0x97, 0xDE, 0x97, 0xDE, 0x98, +0xDE, 0xD8, 0xDE, 0xD8, 0xDE, 0xB7, 0xDE, 0xB8, +0xE6, 0xD8, 0xE6, 0xF8, 0xE6, 0xF8, 0xE6, 0xD8, +0xDE, 0xB8, 0xAD, 0x12, 0xA4, 0xD0, 0xE6, 0xB6, +0xE6, 0x95, 0xE6, 0x74, 0xE6, 0x75, 0xDE, 0x75, +0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x55, 0xDE, 0x75, +0xDE, 0x75, 0xDE, 0x75, 0xE6, 0x95, 0xE6, 0x95, +0xEE, 0xB5, 0xEE, 0xB5, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x54, 0xDE, 0x54, 0xDE, 0x34, 0xDE, 0x34, +0x6C, 0x0A, 0x6C, 0x2A, 0x6C, 0x4A, 0x63, 0xE9, +0x6B, 0xEA, 0x8C, 0xCE, 0x42, 0x85, 0x3A, 0x84, +0x53, 0x86, 0x74, 0x68, 0x53, 0xA6, 0x43, 0x45, +0x64, 0x68, 0x5C, 0x25, 0x95, 0x6A, 0xA5, 0xAA, +0x9D, 0x69, 0x84, 0x88, 0x7C, 0x48, 0x8C, 0xEC, +0xAD, 0x6F, 0xCD, 0xF3, 0xCD, 0xD3, 0xCD, 0xD2, +0xC5, 0x92, 0xAC, 0xEF, 0xB5, 0x30, 0xC5, 0x92, +0xCD, 0xF3, 0xD5, 0xF4, 0xD5, 0xF3, 0xCD, 0xB2, +0xCD, 0xD3, 0xCD, 0xD2, 0xA4, 0x8E, 0x9C, 0x6D, +0xB5, 0x52, 0x6B, 0x2A, 0x41, 0xE7, 0x4A, 0x48, +0x52, 0x89, 0x52, 0x69, 0x42, 0x28, 0x39, 0xC6, +0x41, 0xE7, 0x41, 0xE7, 0x39, 0xC7, 0x7B, 0xF0, +0xC6, 0x18, 0xEF, 0x7D, 0xEF, 0x3D, 0xAD, 0x34, +0x8C, 0x0E, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, +0xBD, 0x93, 0xA4, 0xF0, 0xA4, 0xF0, 0xAD, 0x31, +0xAD, 0x10, 0xA4, 0xF0, 0x94, 0x6E, 0x94, 0x4D, +0xA4, 0xAE, 0xDE, 0x74, 0xE6, 0x74, 0xDE, 0x33, +0xD6, 0x13, 0x8C, 0x0C, 0x94, 0x4E, 0x9C, 0xAF, +0x9C, 0xB0, 0x8C, 0x4E, 0x8C, 0x4E, 0x94, 0x90, +0x9C, 0xB0, 0x8C, 0x4E, 0xA5, 0x32, 0xB5, 0x73, +0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x72, 0xBD, 0xB3, +0xBD, 0xD4, 0xBD, 0x93, 0xB5, 0x72, 0x9C, 0xAF, +0xAD, 0x10, 0xA5, 0x11, 0xA4, 0xF0, 0xAD, 0x10, +0xAD, 0x0F, 0xDE, 0x34, 0xCD, 0xD2, 0xD5, 0xF3, +0xAC, 0xAE, 0x8B, 0xEC, 0x9C, 0x8F, 0x73, 0x6C, +0x8C, 0x30, 0x7B, 0xCF, 0x7B, 0xAF, 0x94, 0x72, +0xB5, 0x75, 0xB5, 0x75, 0x42, 0x07, 0x4A, 0x49, +0x7B, 0xAE, 0x6B, 0x4D, 0x9C, 0xD3, 0xAD, 0x14, +0xCD, 0xF7, 0xBD, 0x75, 0xC5, 0xF7, 0xD6, 0x38, +0xCE, 0x18, 0xE6, 0xBA, 0xCE, 0x17, 0xB5, 0x34, +0xBD, 0xB4, 0xB5, 0x73, 0xAD, 0x12, 0xB5, 0x53, +0xB5, 0x93, 0xB5, 0x73, 0xAD, 0x32, 0x9C, 0x8F, +0xAD, 0x32, 0xA4, 0xD1, 0x94, 0x90, 0xA4, 0xF1, +0xB5, 0x73, 0xAC, 0xF0, 0xAD, 0x10, 0xCD, 0xF4, +0xC6, 0x14, 0xA4, 0xD0, 0x6B, 0x6B, 0xA5, 0x11, +0xC5, 0xD4, 0x7B, 0xCD, 0x41, 0xE6, 0x39, 0xC6, +0x31, 0x85, 0x39, 0xC6, 0x4A, 0x28, 0x4A, 0x69, +0x4A, 0x69, 0x5A, 0xCA, 0x63, 0x2D, 0x73, 0x8F, +0x84, 0x31, 0x94, 0x93, 0x9C, 0xD3, 0xB5, 0x76, +0xA5, 0x14, 0xAD, 0x13, 0xA4, 0xF1, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x73, 0xCE, 0x36, +0xC5, 0xF5, 0xC5, 0xF5, 0xC5, 0xD4, 0xC5, 0xF5, +0xCD, 0xF5, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0xB4, 0xB5, 0x32, 0xB5, 0x32, 0xA4, 0xD0, +0xB5, 0x32, 0xBD, 0x94, 0xCE, 0x15, 0xBD, 0xB3, +0xCE, 0x15, 0xA4, 0xB0, 0xC5, 0x93, 0xDE, 0x76, +0xCE, 0x14, 0xBD, 0x72, 0xB5, 0x31, 0xA4, 0xD0, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0xB5, 0x32, +0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x31, 0xB5, 0x32, +0xBD, 0x72, 0xB5, 0x52, 0xAC, 0xD0, 0xB5, 0x31, +0xBD, 0x72, 0xAD, 0x11, 0xA4, 0xB0, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xF1, 0x9C, 0x90, 0xA4, 0xD0, +0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x11, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD1, 0xA4, 0xF1, +0xA4, 0xF2, 0x9C, 0xB1, 0x9C, 0xB0, 0x94, 0x4F, +0x94, 0x4E, 0x94, 0x4E, 0x8C, 0x0D, 0x94, 0x4E, +0xA4, 0xB0, 0xA4, 0xB0, 0xB5, 0x11, 0xAC, 0xD0, +0xB5, 0x11, 0xAC, 0xD0, 0xAC, 0xF0, 0xB5, 0x32, +0xBD, 0x52, 0xA4, 0xD0, 0xA4, 0x8F, 0xA4, 0xD0, +0xA4, 0xAF, 0xA4, 0xD0, 0xAD, 0x11, 0xAC, 0xF0, +0xB5, 0x31, 0xB5, 0x52, 0xBD, 0x72, 0xC5, 0x93, +0xCD, 0xF4, 0xC5, 0xB3, 0xBD, 0x93, 0xBD, 0x72, +0xC5, 0x93, 0xAC, 0xF1, 0xC5, 0xB4, 0xC5, 0xF5, +0xC5, 0xD5, 0x73, 0x6C, 0x39, 0xC6, 0x29, 0x44, +0x29, 0x45, 0x29, 0x65, 0x29, 0x44, 0x29, 0x65, +0x31, 0xA6, 0x29, 0x45, 0x42, 0x28, 0x62, 0xEB, +0x5A, 0xAA, 0x4A, 0x49, 0x4A, 0x08, 0x7B, 0x8E, +0x83, 0xAE, 0xB5, 0x33, 0x7B, 0x8E, 0x5A, 0x8A, +0x94, 0x50, 0xBD, 0x53, 0xF7, 0x18, 0xEE, 0xD7, +0xE6, 0xB6, 0xDE, 0x75, 0xD6, 0x35, 0xDE, 0x56, +0xDE, 0x97, 0xE6, 0xD8, 0xE6, 0xD8, 0xDE, 0xB7, +0xE6, 0xF8, 0xE6, 0xF8, 0xE6, 0xD8, 0xE6, 0xF8, +0xE6, 0xD8, 0xE6, 0xD8, 0xDE, 0xD7, 0xDE, 0xD7, +0xE6, 0xD8, 0xDE, 0x97, 0xD6, 0x56, 0xE6, 0xF8, +0xDE, 0xB8, 0xA4, 0xF1, 0xE6, 0x96, 0xEE, 0xD6, +0xE6, 0x74, 0xDE, 0x33, 0xD6, 0x13, 0xD5, 0xF3, +0xD6, 0x34, 0xD6, 0x54, 0xD6, 0x34, 0xD6, 0x13, +0xD6, 0x13, 0xDE, 0x34, 0xE6, 0x74, 0xE6, 0x75, +0xDE, 0x53, 0xE6, 0x53, 0xE6, 0x74, 0xE6, 0x53, +0xDE, 0x53, 0xDE, 0x33, 0xDE, 0x34, 0xDE, 0x54, +0x5B, 0x88, 0x5B, 0xE9, 0x53, 0x87, 0x4B, 0x46, +0x6C, 0x29, 0x74, 0x6A, 0x64, 0x08, 0x53, 0x86, +0x53, 0xC6, 0x6C, 0x68, 0x5C, 0x07, 0x3A, 0xE3, +0x53, 0xE6, 0x74, 0xA8, 0xA5, 0xEB, 0x7C, 0xA6, +0x63, 0xE3, 0x74, 0x46, 0x7C, 0x87, 0x8C, 0xEA, +0xAD, 0x4E, 0xC5, 0xB1, 0xCD, 0xD2, 0xC5, 0x91, +0xD6, 0x13, 0xCD, 0xD2, 0xB5, 0x30, 0xB5, 0x30, +0xC5, 0x92, 0xC5, 0x71, 0xD5, 0xF3, 0xD5, 0xF3, +0xD5, 0xD3, 0xD6, 0x13, 0xCD, 0xB2, 0xD6, 0x14, +0xBD, 0xB3, 0x62, 0xEA, 0x4A, 0x27, 0x31, 0xA6, +0x42, 0x07, 0x39, 0xE6, 0x39, 0xA6, 0x4A, 0x28, +0x5A, 0xAA, 0x4A, 0x48, 0x39, 0xC7, 0x42, 0x08, +0x42, 0x08, 0x73, 0x8E, 0xB5, 0x96, 0x7B, 0xAE, +0xAD, 0x13, 0x94, 0x70, 0x8C, 0x0E, 0x8B, 0xEC, +0x94, 0x0D, 0x8B, 0xEC, 0x94, 0x2C, 0x9C, 0x8E, +0x9C, 0x6D, 0x94, 0x2C, 0x8B, 0xEB, 0x8B, 0xEB, +0x9C, 0x6D, 0xAC, 0xEE, 0xBD, 0x2F, 0xBD, 0x2F, +0xBD, 0x30, 0xA4, 0xAE, 0x8B, 0xEC, 0x7B, 0x6A, +0x6B, 0x09, 0x62, 0xE9, 0x63, 0x09, 0x7B, 0xAC, +0x7B, 0xAC, 0x6B, 0x4B, 0xA4, 0xD1, 0xBD, 0xD4, +0xBD, 0xB3, 0xBD, 0x92, 0xB5, 0x72, 0xBD, 0xB3, +0xB5, 0x92, 0xA4, 0xF0, 0xAD, 0x10, 0x9C, 0x8E, +0x9C, 0x8E, 0x9C, 0x8E, 0x94, 0x6D, 0xB5, 0x51, +0xAC, 0xEF, 0xDE, 0x54, 0xDE, 0x34, 0xDE, 0x34, +0xAC, 0xAE, 0x9C, 0x2D, 0xAC, 0xCF, 0xB5, 0x31, +0xA4, 0xF1, 0x8C, 0x30, 0x31, 0x66, 0x62, 0xEB, +0x94, 0x71, 0xAD, 0x34, 0x6B, 0x4C, 0x42, 0x28, +0x52, 0x8A, 0x73, 0x8E, 0x7B, 0xCF, 0x9C, 0x92, +0x83, 0xCF, 0x73, 0x6D, 0xB5, 0x96, 0xBD, 0xD6, +0xEF, 0x1B, 0xDE, 0x9A, 0xAD, 0x35, 0xAD, 0x55, +0xB5, 0x95, 0xBD, 0xD6, 0x94, 0x90, 0x94, 0x70, +0xAD, 0x53, 0xA4, 0xF2, 0x9C, 0xD1, 0x94, 0x4F, +0x8C, 0x2F, 0xCE, 0x38, 0xE6, 0xFB, 0xBD, 0xB5, +0xAD, 0x31, 0x9C, 0x8F, 0xAC, 0xF0, 0xCE, 0x14, +0xCE, 0x35, 0xBD, 0xD4, 0xA4, 0xF1, 0x8C, 0x2E, +0xAD, 0x31, 0x94, 0x70, 0x4A, 0x28, 0x31, 0xA5, +0x39, 0xC6, 0x42, 0x07, 0x42, 0x28, 0x4A, 0x49, +0x42, 0x28, 0x52, 0xAA, 0x63, 0x0C, 0x6B, 0x4D, +0x6B, 0x6E, 0x73, 0xAF, 0x84, 0x11, 0xA5, 0x35, +0xAD, 0x75, 0xDE, 0x9A, 0xB5, 0x54, 0xCE, 0x16, +0xBD, 0x93, 0xAC, 0xF1, 0x94, 0x6F, 0xCE, 0x36, +0xD6, 0x76, 0xD6, 0x56, 0xCE, 0x15, 0xC5, 0xF4, +0xBD, 0x73, 0xAC, 0xF1, 0xA4, 0xB0, 0xAD, 0x32, +0xB5, 0x73, 0xBD, 0x93, 0xD6, 0x36, 0xCD, 0xF4, +0xBD, 0x73, 0xCD, 0xF4, 0xC5, 0x93, 0xB5, 0x72, +0xC5, 0xB3, 0xAD, 0x11, 0xC5, 0xB3, 0xDE, 0x55, +0xCD, 0xD4, 0xBD, 0x72, 0xC5, 0xD4, 0xC5, 0xB3, +0xC5, 0x93, 0xC5, 0x93, 0xC5, 0xB3, 0xCD, 0xD4, +0xCD, 0xD4, 0xD6, 0x15, 0xAD, 0x11, 0xAD, 0x11, +0xBD, 0x93, 0xB5, 0x72, 0xB5, 0x73, 0xB5, 0x73, +0x9C, 0x8F, 0xA4, 0xF1, 0xAD, 0x32, 0xBD, 0x94, +0xAD, 0x32, 0xA4, 0xD1, 0xAD, 0x11, 0x9C, 0xB0, +0x73, 0x6B, 0x7B, 0xAC, 0x83, 0xCD, 0x94, 0x6F, +0x9C, 0x6F, 0x9C, 0x90, 0xA4, 0xF1, 0xB5, 0x53, +0xB5, 0x53, 0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x52, +0xB5, 0x31, 0xAD, 0x31, 0xAD, 0x11, 0xAC, 0xD0, +0xA4, 0xD0, 0xA4, 0x8F, 0x9C, 0x4E, 0x9C, 0x4E, +0x9C, 0x4E, 0x9C, 0x4E, 0xA4, 0xB0, 0xAC, 0xD0, +0xA4, 0xAF, 0xAC, 0xD0, 0xA4, 0xD0, 0xAC, 0xD0, +0xAC, 0xF0, 0xAC, 0xD0, 0xAC, 0xD0, 0xA4, 0xAF, +0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0x8F, +0xA4, 0x8F, 0x9C, 0x6E, 0xAC, 0xD0, 0xA4, 0x8F, +0x94, 0x2E, 0x94, 0x2E, 0x9C, 0x8F, 0xAD, 0x11, +0xAD, 0x32, 0xA4, 0xD0, 0x73, 0x6B, 0x42, 0x07, +0x31, 0x85, 0x29, 0x65, 0x29, 0x44, 0x31, 0x85, +0x42, 0x07, 0x42, 0x07, 0x4A, 0x28, 0x39, 0xC6, +0x62, 0xEB, 0x6B, 0x0C, 0x49, 0xE7, 0x5A, 0x8A, +0x83, 0xAE, 0x83, 0x8D, 0x73, 0x6D, 0x73, 0x2C, +0x73, 0x2C, 0x6A, 0xEA, 0xBD, 0x73, 0xCD, 0xF4, +0xC5, 0xB3, 0xC5, 0x93, 0xAC, 0xF1, 0xC5, 0xB4, +0xBD, 0x93, 0xCE, 0x15, 0xD6, 0x56, 0xD6, 0x35, +0xE6, 0xB7, 0xDE, 0x97, 0xDE, 0xB7, 0xE6, 0xB8, +0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0xD8, 0xE6, 0xB7, +0xE6, 0xF8, 0xDE, 0x97, 0xDE, 0x77, 0xE6, 0xF8, +0xDE, 0xB7, 0xA4, 0xD0, 0xF7, 0x18, 0xEE, 0xD6, +0xE6, 0x75, 0xDE, 0x33, 0xD5, 0xF3, 0xD6, 0x14, +0xDE, 0x55, 0xDE, 0x54, 0xDE, 0x55, 0xE6, 0x75, +0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, +0xDE, 0x33, 0xDE, 0x33, 0xDE, 0x13, 0xE6, 0x54, +0xDE, 0x33, 0xDE, 0x33, 0xE6, 0x74, 0xE6, 0x95, +0x21, 0xE3, 0x4B, 0x27, 0x32, 0xC4, 0x3A, 0xC4, +0x53, 0xA6, 0x43, 0x24, 0x43, 0x44, 0x3B, 0x04, +0x64, 0x08, 0x3B, 0x03, 0x53, 0xC6, 0x43, 0x45, +0x5B, 0xC7, 0x9D, 0xCE, 0x63, 0xC6, 0x6C, 0x08, +0x8C, 0xEC, 0xB5, 0xF0, 0xCE, 0x51, 0xC5, 0xF0, +0xBD, 0x8F, 0xBD, 0x70, 0xBD, 0x30, 0xB5, 0x0F, +0xCD, 0xB2, 0xCD, 0xB2, 0xBD, 0x71, 0xC5, 0x92, +0xCD, 0xB2, 0xCD, 0xD3, 0xD6, 0x14, 0xD5, 0xF3, +0xD5, 0xF3, 0xD5, 0xD3, 0xD6, 0x13, 0xD6, 0x14, +0x6A, 0xEA, 0x7B, 0xCD, 0x73, 0x6B, 0x4A, 0x27, +0x39, 0x85, 0x31, 0xA6, 0x31, 0xA6, 0x41, 0xE7, +0x52, 0x89, 0x62, 0xEB, 0x52, 0x89, 0x63, 0x0B, +0x73, 0x4D, 0x7B, 0x8E, 0x8C, 0x51, 0x73, 0x6E, +0xC6, 0x38, 0xEF, 0x3C, 0xB5, 0x75, 0x8C, 0x0E, +0x9C, 0x8F, 0xA4, 0xAF, 0x8B, 0xEC, 0x83, 0xCB, +0x8C, 0x0C, 0xA4, 0xAE, 0xB4, 0xEF, 0xB5, 0x10, +0xBD, 0x51, 0xC5, 0x91, 0xC5, 0x71, 0xAC, 0xCE, +0xB4, 0xEF, 0xBD, 0x50, 0xBD, 0x31, 0xAC, 0xAF, +0x9C, 0x6E, 0xA4, 0xAE, 0xAC, 0xCF, 0xA4, 0xAE, +0x9C, 0x4D, 0x94, 0x2D, 0x94, 0x2D, 0x94, 0x2D, +0x9C, 0x4D, 0xA4, 0xAE, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x8E, 0x9C, 0x8E, 0xA4, 0xAE, 0xA4, 0xAE, +0xAC, 0xCF, 0xA4, 0xAE, 0x94, 0x0C, 0x9C, 0x6D, +0xA4, 0x8D, 0xCD, 0xF2, 0xCD, 0xF3, 0xBD, 0x51, +0x8B, 0xCB, 0x8B, 0xEC, 0xAC, 0xCE, 0xAC, 0xEF, +0xAD, 0x10, 0x6B, 0x0A, 0x39, 0xA6, 0x31, 0xA6, +0x6B, 0x2C, 0x8C, 0x30, 0x73, 0x6C, 0x5A, 0xCB, +0x6B, 0x6D, 0x6B, 0x2C, 0x7B, 0xAE, 0x8C, 0x30, +0x94, 0x30, 0x94, 0x30, 0x73, 0x4D, 0x94, 0x71, +0xE6, 0xFB, 0x94, 0x92, 0x6B, 0x2D, 0xA5, 0x14, +0x5A, 0xAB, 0x94, 0x91, 0x84, 0x0F, 0x8C, 0x50, +0x94, 0x91, 0x9C, 0xB2, 0x94, 0x51, 0x9C, 0x91, +0xC6, 0x18, 0xEF, 0x5D, 0xCE, 0x59, 0x9C, 0xD2, +0xA4, 0xF1, 0xA4, 0xCF, 0xB5, 0x10, 0xCE, 0x14, +0xC5, 0xD3, 0x9C, 0xD0, 0xB5, 0x52, 0xAD, 0x72, +0xB5, 0x73, 0xB5, 0x74, 0x6B, 0x2B, 0x39, 0xC6, +0x42, 0x07, 0x5A, 0xAA, 0x52, 0xAA, 0x52, 0x8A, +0x63, 0x0B, 0x6B, 0x6D, 0x73, 0x8D, 0x5A, 0xCB, +0x52, 0x8A, 0x6B, 0x4D, 0x7B, 0xF0, 0x8C, 0x92, +0xA5, 0x35, 0xC6, 0x38, 0xBD, 0xF6, 0xCE, 0x16, +0xCE, 0x15, 0xAD, 0x32, 0xA4, 0xD1, 0xD6, 0x56, +0xDE, 0x97, 0xDE, 0x76, 0xD6, 0x76, 0xCE, 0x35, +0xBD, 0x93, 0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xF1, +0xA4, 0xF1, 0xB5, 0x73, 0xCE, 0x15, 0xCD, 0xF4, +0xB5, 0x52, 0xAD, 0x31, 0xAC, 0xF0, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x11, 0xBD, 0x93, 0xCD, 0xD3, +0xC5, 0x92, 0xB5, 0x31, 0xC5, 0xB3, 0xC5, 0xB3, +0xBD, 0x52, 0xBD, 0x72, 0xB5, 0x51, 0xBD, 0x72, +0xC5, 0xB3, 0xCD, 0xF4, 0xB5, 0x32, 0x9C, 0x6F, +0xA4, 0xF1, 0xB5, 0x52, 0xC5, 0xD4, 0xD6, 0x57, +0xBD, 0xD5, 0xBD, 0xD4, 0xBD, 0xB4, 0xBD, 0x94, +0xBD, 0xB4, 0xC5, 0xD4, 0xB5, 0x52, 0xA4, 0xD1, +0x7B, 0xAC, 0x7B, 0xCD, 0x7B, 0xCC, 0x8C, 0x0E, +0x9C, 0x6F, 0x8C, 0x2E, 0x83, 0xED, 0x83, 0xAC, +0x83, 0x8C, 0x83, 0xAC, 0x7B, 0x8B, 0x83, 0xAC, +0x8B, 0xED, 0x9C, 0x6E, 0xA4, 0xB0, 0x9C, 0x6E, +0xA4, 0x8F, 0xA4, 0x8F, 0x94, 0x0D, 0x94, 0x2E, +0x83, 0xAB, 0x83, 0xAB, 0xA4, 0xB0, 0x9C, 0x6F, +0x8B, 0xED, 0x83, 0xAC, 0x8B, 0xED, 0x9C, 0x4E, +0x94, 0x2E, 0x9C, 0x4E, 0xA4, 0x8F, 0xA4, 0x8F, +0x9C, 0x4E, 0xAC, 0xD0, 0xAD, 0x11, 0xAC, 0xF0, +0xB5, 0x32, 0xAC, 0xF0, 0xAC, 0xF0, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x94, 0xBD, 0xB4, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x94, 0xA4, 0xF2, +0x5A, 0xCA, 0x31, 0xA6, 0x29, 0x65, 0x31, 0x85, +0x39, 0xC6, 0x41, 0xE7, 0x4A, 0x68, 0x42, 0x07, +0x31, 0xA6, 0x52, 0x69, 0x5A, 0xAA, 0x6B, 0x0C, +0x5A, 0xAA, 0x4A, 0x28, 0x52, 0x49, 0x62, 0x8A, +0x8B, 0xCE, 0x62, 0xAA, 0x62, 0x89, 0x94, 0x4F, +0xA4, 0xB0, 0xAD, 0x11, 0x94, 0x4F, 0x9C, 0x90, +0x94, 0x6F, 0xA4, 0xD0, 0xB5, 0x52, 0xB5, 0x32, +0xBD, 0x73, 0xA4, 0xD0, 0x9C, 0xB0, 0xC5, 0xD5, +0xBD, 0x52, 0xBD, 0x73, 0xBD, 0x93, 0xBD, 0x93, +0xCE, 0x15, 0xDE, 0x97, 0xE6, 0xD8, 0xE6, 0xD8, +0xDE, 0x77, 0xAC, 0xF1, 0xF7, 0x18, 0xEE, 0xD6, +0xDE, 0x54, 0xDE, 0x54, 0xE6, 0x55, 0xD6, 0x13, +0xE6, 0x96, 0xDE, 0x34, 0xE6, 0x96, 0xEE, 0xB6, +0xDE, 0x75, 0xEE, 0xD6, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x95, 0xE6, 0x74, 0xDE, 0x54, 0xEE, 0xB5, +0xE6, 0x75, 0xDE, 0x54, 0xDE, 0x34, 0xE6, 0x95, +0x21, 0xC4, 0x43, 0x27, 0x6C, 0x4B, 0x43, 0x05, +0x4B, 0x05, 0x53, 0x66, 0x5B, 0xC8, 0x43, 0x05, +0x64, 0x09, 0x22, 0x21, 0x3B, 0x03, 0x4B, 0x45, +0x7C, 0xAB, 0x7C, 0x6A, 0xA5, 0xD1, 0xC6, 0xD5, +0xCE, 0xD6, 0xE7, 0x17, 0xD6, 0x54, 0xC5, 0x70, +0xB5, 0x0F, 0xC5, 0x91, 0xB5, 0x30, 0xB4, 0xEF, +0xBD, 0x71, 0xC5, 0x92, 0xC5, 0x92, 0xCD, 0xD3, +0xCD, 0xF3, 0xD6, 0x14, 0xCD, 0xD3, 0xCD, 0xD2, +0xD5, 0xF3, 0xDE, 0x34, 0xD6, 0x14, 0xDE, 0x35, +0xDE, 0x56, 0xDE, 0x96, 0xAC, 0xEF, 0xAC, 0xCF, +0x94, 0x2E, 0x73, 0x6C, 0x39, 0xA6, 0x29, 0x44, +0x39, 0xC6, 0x4A, 0x68, 0x52, 0x89, 0x52, 0x69, +0x73, 0x8D, 0x83, 0xEF, 0x94, 0x71, 0x73, 0x6D, +0x9C, 0xD3, 0xEF, 0x5D, 0xF7, 0x9E, 0xD6, 0x79, +0x84, 0x0E, 0x8C, 0x2E, 0x8B, 0xEE, 0x8C, 0x2E, +0x8C, 0x2E, 0x8C, 0x0D, 0xAC, 0xCF, 0xAC, 0xAF, +0xC5, 0x72, 0xCD, 0xF3, 0xC5, 0xB2, 0xAC, 0xCF, +0xA4, 0xAE, 0xA4, 0xAF, 0xAC, 0xF0, 0xAC, 0xAF, +0xA4, 0x8E, 0xAC, 0xAF, 0xB5, 0x10, 0xCD, 0xD3, +0xBD, 0x51, 0xB5, 0x10, 0xBD, 0x30, 0xB5, 0x30, +0xB5, 0x30, 0xB5, 0x30, 0xB5, 0x10, 0xBD, 0x51, +0xB5, 0x30, 0xB5, 0x10, 0xA4, 0x6D, 0xAC, 0xAE, +0xC5, 0x71, 0xBD, 0x50, 0xA4, 0x8E, 0xA4, 0x6D, +0xAC, 0xCE, 0xB4, 0xCE, 0xA4, 0x8E, 0xA4, 0x8E, +0x8B, 0xCB, 0x94, 0x2D, 0xAC, 0xEF, 0xB5, 0x0F, +0xAC, 0xCF, 0xB5, 0x10, 0x6B, 0x0A, 0x41, 0xE7, +0x52, 0x89, 0x4A, 0x49, 0x42, 0x28, 0x31, 0x86, +0x52, 0x8A, 0x62, 0xEB, 0x73, 0x4D, 0x83, 0xEF, +0xCE, 0x17, 0xCD, 0xD6, 0xA4, 0xB2, 0x73, 0x4D, +0xC5, 0xF7, 0xAD, 0x75, 0xAD, 0x55, 0xB5, 0x75, +0x94, 0x72, 0xAD, 0x75, 0x94, 0x71, 0xAD, 0x55, +0xAD, 0x55, 0xC6, 0x18, 0xB5, 0x76, 0x94, 0x92, +0xBD, 0xB6, 0xCE, 0x59, 0xAD, 0x55, 0x8C, 0x30, +0xBD, 0xB4, 0xB5, 0x31, 0xAC, 0xF0, 0xBD, 0xB3, +0xC5, 0xF4, 0xB5, 0x52, 0xB5, 0x72, 0xBD, 0xD4, +0xBD, 0xD4, 0xAD, 0x52, 0x9C, 0xD1, 0x4A, 0x48, +0x5A, 0xCA, 0x73, 0x6D, 0x73, 0xAE, 0x7B, 0xAE, +0x83, 0xEF, 0x5A, 0xCB, 0x4A, 0x49, 0x52, 0x8A, +0x52, 0x8A, 0x6B, 0x4D, 0x7B, 0xAF, 0x84, 0x31, +0xA5, 0x14, 0xAD, 0x76, 0xCE, 0x58, 0xCE, 0x37, +0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x32, 0xD6, 0x76, +0xDE, 0x96, 0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x56, +0xBD, 0x73, 0xAD, 0x11, 0xAD, 0x11, 0x9C, 0xD0, +0x94, 0x8F, 0xC5, 0xB4, 0xCE, 0x15, 0xC5, 0xB3, +0xAD, 0x31, 0x9C, 0x8F, 0xA4, 0xF0, 0xBD, 0xB3, +0xBD, 0x93, 0xAD, 0x11, 0xC5, 0xB3, 0xC5, 0xB3, +0xBD, 0x51, 0xB5, 0x11, 0xBD, 0x73, 0xBD, 0x31, +0xB4, 0xF0, 0xBD, 0x52, 0xB5, 0x11, 0xBD, 0x52, +0xCD, 0xD3, 0xCD, 0xF4, 0xB5, 0x32, 0xAD, 0x11, +0xBD, 0x94, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0xB4, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x93, 0xBD, 0x94, +0xB5, 0x52, 0xC5, 0xF5, 0xB5, 0x53, 0xAD, 0x32, +0x94, 0x6F, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xB0, +0xB5, 0x73, 0xA4, 0xF1, 0x94, 0x6F, 0x83, 0xCC, +0x7B, 0x8B, 0x7B, 0x8C, 0x7B, 0xAC, 0x83, 0xCD, +0x83, 0xCD, 0x83, 0xAC, 0xA4, 0xAF, 0xB5, 0x31, +0xBD, 0x52, 0xBD, 0x72, 0xAC, 0xF1, 0xAC, 0xF1, +0xA4, 0x8F, 0x9C, 0x4E, 0xB5, 0x32, 0x94, 0x2E, +0x7B, 0x8C, 0x7B, 0xAC, 0x83, 0xCD, 0x9C, 0x6E, +0x8C, 0x0D, 0x8B, 0xCC, 0x8B, 0xED, 0x94, 0x0D, +0x94, 0x0D, 0xAC, 0xD0, 0xB5, 0x31, 0xB5, 0x31, +0xAC, 0xF0, 0x8B, 0xCD, 0x83, 0xAC, 0x9C, 0x6F, +0xAD, 0x11, 0xB5, 0x52, 0xA4, 0xD1, 0xC5, 0xB4, +0xB5, 0x52, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x12, +0x9C, 0x90, 0x7B, 0xCD, 0x39, 0xC6, 0x31, 0x85, +0x29, 0x65, 0x39, 0xA6, 0x42, 0x28, 0x42, 0x28, +0x4A, 0x28, 0x4A, 0x28, 0x4A, 0x49, 0x7B, 0xAE, +0x83, 0xCE, 0x73, 0x2C, 0x5A, 0x69, 0x7B, 0x6D, +0xB5, 0x13, 0x94, 0x2F, 0x62, 0xCA, 0x62, 0xCA, +0x8C, 0x0E, 0xB5, 0x52, 0xBD, 0xB3, 0xAD, 0x12, +0xBD, 0x94, 0xBD, 0x73, 0xB5, 0x32, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x73, 0xB5, 0x53, 0xB5, 0x53, +0xA4, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xD1, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF2, 0xAD, 0x12, +0xAC, 0xF2, 0xA4, 0xD1, 0xB5, 0x32, 0xB5, 0x11, +0xAC, 0xD0, 0xC5, 0x72, 0xCD, 0xD3, 0xCD, 0xD3, +0xCD, 0xD3, 0xC5, 0x92, 0xCD, 0xD3, 0xCD, 0xF4, +0xD6, 0x14, 0xD5, 0xF4, 0xCD, 0xB3, 0xCD, 0xB3, +0xD6, 0x14, 0xDE, 0x34, 0xDE, 0x54, 0xE6, 0x75, +0xE6, 0x95, 0xEE, 0xD6, 0xE6, 0x95, 0xD5, 0xF3, +0x5B, 0x0B, 0x2A, 0x04, 0x32, 0x85, 0x42, 0xE5, +0x32, 0x63, 0x3A, 0x64, 0x3A, 0x65, 0x3A, 0x44, +0x53, 0x28, 0x53, 0x67, 0x4B, 0x45, 0x43, 0x04, +0x74, 0x2A, 0xA5, 0x8F, 0xA5, 0x6F, 0xA5, 0x70, +0xBE, 0x34, 0xE7, 0x18, 0xDE, 0xD7, 0xD6, 0x34, +0xB5, 0x0F, 0xCD, 0xD3, 0xBD, 0x50, 0xBD, 0x51, +0xBD, 0x72, 0xBD, 0x92, 0xBD, 0x92, 0xBD, 0x72, +0xC5, 0x92, 0xCD, 0xB2, 0xCD, 0xB2, 0xCD, 0xB2, +0xCD, 0xD2, 0xDE, 0x34, 0xC5, 0x71, 0xCD, 0xB2, +0xCD, 0xF4, 0xDE, 0x35, 0xB5, 0x0F, 0xAC, 0xEE, +0xAC, 0xF0, 0xBD, 0xD4, 0x9C, 0xD1, 0x52, 0x89, +0x29, 0x64, 0x31, 0x85, 0x39, 0xC6, 0x4A, 0x69, +0x39, 0xA6, 0x42, 0x07, 0x52, 0x89, 0x4A, 0x28, +0x5A, 0xCB, 0xCE, 0x38, 0xE7, 0x1C, 0x8C, 0x30, +0x29, 0x25, 0x29, 0x24, 0x39, 0xE7, 0x94, 0x91, +0x9C, 0xD1, 0x8C, 0x2E, 0xAC, 0xCF, 0xC5, 0x92, +0xD6, 0x35, 0xBD, 0x51, 0xB5, 0x31, 0xBD, 0x72, +0xBD, 0x52, 0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x72, +0xBD, 0x72, 0xC5, 0x93, 0xC5, 0xB3, 0xCD, 0xD3, +0xC5, 0x92, 0xBD, 0x71, 0xD5, 0xF3, 0xBD, 0x51, +0xB5, 0x51, 0xBD, 0x51, 0xB5, 0x31, 0xBD, 0x52, +0xC5, 0x92, 0xDE, 0x35, 0xAC, 0xAF, 0xB4, 0xEF, +0xD5, 0xF3, 0xDD, 0xF3, 0xCD, 0xB2, 0xC5, 0x51, +0xC5, 0x51, 0xCD, 0x92, 0xCD, 0xB2, 0xBD, 0x31, +0xBD, 0x31, 0xAC, 0xCF, 0xA4, 0x6D, 0xA4, 0x8E, +0xAC, 0xCF, 0xC5, 0x71, 0xB4, 0xF0, 0x73, 0x4B, +0x83, 0xCE, 0x73, 0x6D, 0x42, 0x08, 0x39, 0xA7, +0x62, 0xEC, 0x73, 0x8E, 0x94, 0x92, 0xA4, 0xF3, +0xC5, 0xF7, 0xDE, 0x59, 0xA4, 0x92, 0xB5, 0x34, +0x6B, 0x0B, 0x52, 0x69, 0x4A, 0x69, 0x6B, 0x4D, +0x73, 0x8E, 0xBD, 0xB6, 0xB5, 0x96, 0xAD, 0x34, +0xC5, 0xF7, 0xB5, 0x75, 0xA5, 0x14, 0x62, 0xCB, +0x7B, 0xAF, 0xBD, 0xB6, 0x94, 0x92, 0x8C, 0x0E, +0x9C, 0x8E, 0xA4, 0xAE, 0xAD, 0x10, 0xAC, 0xF0, +0xAD, 0x10, 0xA5, 0x10, 0xAC, 0xF0, 0xAD, 0x11, +0xAD, 0x31, 0xA4, 0xF1, 0xB5, 0x73, 0x83, 0xEE, +0x63, 0x0B, 0x5A, 0xCA, 0x5A, 0xCA, 0x52, 0x89, +0x4A, 0x28, 0x4A, 0x69, 0x4A, 0x69, 0x4A, 0x69, +0x41, 0xE7, 0x5A, 0xCB, 0x63, 0x0C, 0x73, 0xAE, +0x8C, 0x31, 0x9C, 0xF4, 0xBD, 0xF8, 0xD6, 0xBA, +0xB5, 0x74, 0xAD, 0x32, 0x9C, 0x8F, 0xC5, 0xF4, +0xCE, 0x55, 0xD6, 0x55, 0xD6, 0x56, 0xCE, 0x15, +0xB5, 0x73, 0xB5, 0x72, 0xB5, 0x52, 0xA4, 0xD1, +0x9C, 0xD0, 0xBD, 0xD4, 0xD6, 0x35, 0xBD, 0x93, +0xA4, 0xB0, 0x94, 0x6F, 0x9C, 0xB0, 0xAD, 0x31, +0xBD, 0xB3, 0xB5, 0x32, 0xC5, 0xB4, 0xCD, 0xD3, +0xBD, 0x51, 0xB5, 0x32, 0xC5, 0x73, 0xC5, 0x52, +0xC5, 0x52, 0xBD, 0x52, 0xB5, 0x11, 0xBD, 0x72, +0xC5, 0xD3, 0xCD, 0xF4, 0xB5, 0x11, 0xB5, 0x53, +0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, +0xB5, 0x73, 0xAD, 0x52, 0xA5, 0x11, 0xBD, 0xB4, +0xBD, 0xD4, 0xCE, 0x36, 0xB5, 0x52, 0xB5, 0x73, +0xA4, 0xD0, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x52, +0xBD, 0x94, 0xBD, 0x93, 0xA4, 0xD1, 0x8C, 0x2E, +0x7B, 0xAC, 0x73, 0x2A, 0x73, 0x2A, 0x8C, 0x2E, +0x94, 0x4F, 0x94, 0x2E, 0x9C, 0x6F, 0xAC, 0xF0, +0xC5, 0x92, 0xBD, 0x72, 0xB5, 0x11, 0xB5, 0x10, +0x9C, 0x4E, 0x8B, 0xCC, 0xBD, 0x52, 0x94, 0x4E, +0x83, 0xED, 0x94, 0x4F, 0x9C, 0x90, 0xB5, 0x52, +0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x11, 0xB5, 0x52, +0xA4, 0xD0, 0xB5, 0x11, 0xBD, 0x72, 0xC5, 0xB2, +0xB5, 0x31, 0xA4, 0xD0, 0x94, 0x2E, 0xA4, 0xD0, +0xBD, 0x73, 0xAD, 0x11, 0xBD, 0x93, 0xBD, 0xB3, +0xAD, 0x11, 0xB5, 0x73, 0xAD, 0x11, 0xAD, 0x32, +0xAD, 0x11, 0xCE, 0x36, 0x9C, 0xB1, 0x52, 0x89, +0x39, 0xA6, 0x39, 0xC6, 0x39, 0xA6, 0x42, 0x07, +0x4A, 0x48, 0x4A, 0x68, 0x52, 0x89, 0x4A, 0x28, +0x73, 0x8D, 0x94, 0x51, 0x73, 0x2C, 0x52, 0x48, +0x9C, 0x50, 0x94, 0x2F, 0x83, 0xAE, 0x73, 0x4C, +0x8C, 0x0E, 0xAD, 0x10, 0xBD, 0x93, 0xBD, 0x73, +0xE6, 0x97, 0xC5, 0xB4, 0xBD, 0x93, 0xC5, 0xB4, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, 0xB5, 0x52, +0xCD, 0xF5, 0xCE, 0x15, 0xCD, 0xF5, 0xCD, 0xD5, +0xC5, 0xD5, 0xCD, 0xF5, 0xCD, 0xD5, 0xC5, 0xD5, +0xC5, 0xB5, 0xC5, 0xB4, 0xBD, 0x94, 0xB5, 0x53, +0xB5, 0x53, 0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x12, +0xB5, 0x12, 0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xB0, 0x9C, 0x70, 0x9C, 0x70, 0x94, 0x4F, +0x94, 0x4E, 0x94, 0x4E, 0x9C, 0x4F, 0x9C, 0x8F, +0xAC, 0xF0, 0xB5, 0x31, 0xBD, 0x32, 0xAD, 0x11, +0x6B, 0xCD, 0x19, 0x42, 0x32, 0x65, 0x6C, 0x0A, +0x3A, 0x44, 0x53, 0x08, 0x42, 0x86, 0x6B, 0xCB, +0x6B, 0xEB, 0x5B, 0x47, 0x7C, 0x4B, 0x9D, 0x4F, +0xB5, 0xF2, 0xC6, 0x54, 0xCE, 0x54, 0x9C, 0xCD, +0xC5, 0xF3, 0xDE, 0x75, 0xBD, 0x72, 0xA4, 0x8E, +0xBD, 0x91, 0xCD, 0xD3, 0xBD, 0x51, 0xA4, 0xAE, +0xBD, 0x72, 0xB5, 0x30, 0xB5, 0x30, 0xB5, 0x51, +0xBD, 0x51, 0xCD, 0xD3, 0xD5, 0xF3, 0xBD, 0x51, +0xC5, 0x92, 0xD6, 0x14, 0xAC, 0xEF, 0xC5, 0xB2, +0xD6, 0x34, 0xDE, 0x34, 0xBD, 0x30, 0xB4, 0xCE, +0xA4, 0xCF, 0xBD, 0xB4, 0xB5, 0x53, 0xB5, 0x53, +0x7B, 0x8D, 0x39, 0xC6, 0x29, 0x44, 0x39, 0xC6, +0x41, 0xE6, 0x39, 0xA6, 0x31, 0x85, 0x5A, 0xEB, +0x62, 0xEC, 0x4A, 0x49, 0x5A, 0xEB, 0x83, 0xEF, +0x73, 0x8E, 0x4A, 0x48, 0x31, 0xA6, 0x6B, 0x4C, +0xAD, 0x53, 0x94, 0x70, 0xA4, 0x8F, 0xB5, 0x31, +0xAC, 0xF0, 0xB5, 0x31, 0xBD, 0x72, 0xA4, 0xF0, +0xA4, 0xD0, 0xA4, 0xD0, 0xB5, 0x31, 0xB5, 0x31, +0xBD, 0x72, 0xBD, 0x73, 0xBD, 0xB3, 0xBD, 0x92, +0xC5, 0xB3, 0xBD, 0x51, 0xB5, 0x31, 0xAC, 0xD0, +0xAC, 0xF1, 0xAD, 0x11, 0xA4, 0xD0, 0xB5, 0x31, +0xBD, 0x72, 0xD5, 0xF4, 0xAC, 0x8E, 0xAC, 0x8E, +0xC5, 0x51, 0xCD, 0x92, 0xD5, 0xD3, 0xDE, 0x14, +0xDD, 0xF3, 0xD5, 0xF3, 0xCD, 0xB2, 0xBD, 0x51, +0xBD, 0x71, 0xD5, 0xD3, 0xCD, 0xB2, 0xCD, 0x91, +0xCD, 0x92, 0xCD, 0xD2, 0xC5, 0x92, 0x8C, 0x0D, +0x6B, 0x2B, 0x6B, 0x4C, 0x39, 0xC6, 0x31, 0x66, +0x4A, 0x49, 0x4A, 0x69, 0x5A, 0xEB, 0x83, 0xEF, +0x9C, 0x92, 0x94, 0x51, 0x8C, 0x10, 0xBD, 0x54, +0xAC, 0xB2, 0x6A, 0xCB, 0x39, 0xA7, 0x73, 0x8E, +0x8C, 0x51, 0xBD, 0xB7, 0xAD, 0x55, 0x7B, 0xCF, +0xA4, 0xF3, 0x7B, 0xCF, 0x4A, 0x49, 0x5A, 0xCB, +0x7B, 0xAF, 0xCE, 0x18, 0xC5, 0xF7, 0xA4, 0xD1, +0x94, 0x2D, 0x9C, 0x4D, 0x9C, 0x6E, 0x8C, 0x0C, +0x8C, 0x0D, 0x94, 0x2D, 0xA4, 0xD0, 0x9C, 0x8F, +0xA4, 0xAF, 0xAD, 0x11, 0xB5, 0x31, 0x9C, 0xB0, +0x4A, 0x07, 0x42, 0x27, 0x42, 0x07, 0x41, 0xE7, +0x52, 0x69, 0x52, 0x89, 0x4A, 0x48, 0x4A, 0x49, +0x39, 0xC6, 0x42, 0x28, 0x63, 0x0C, 0x6B, 0x6E, +0x73, 0xAF, 0x8C, 0x72, 0xAD, 0x76, 0xC6, 0x18, +0xBD, 0xB6, 0xAD, 0x12, 0xA5, 0x11, 0xBD, 0xB4, +0xC5, 0xF5, 0xC6, 0x15, 0xC6, 0x15, 0xC6, 0x15, +0xBD, 0xD4, 0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x73, +0xAD, 0x32, 0xC5, 0xD5, 0xCE, 0x15, 0xCE, 0x15, +0xC5, 0xD4, 0xBD, 0xB4, 0x9C, 0xB0, 0xAD, 0x31, +0xBD, 0x92, 0xAD, 0x11, 0xCD, 0xD4, 0xCD, 0xF3, +0xC5, 0x71, 0xBD, 0x72, 0xC5, 0x72, 0xBD, 0x31, +0xC5, 0x52, 0xC5, 0x93, 0xAC, 0xAF, 0xB5, 0x51, +0xC5, 0x93, 0xD6, 0x35, 0xAD, 0x11, 0xB5, 0x52, +0xC5, 0xF5, 0xBD, 0xD4, 0xBD, 0xB4, 0xB5, 0x94, +0xB5, 0x93, 0xBD, 0x94, 0xB5, 0xB4, 0xBD, 0xD4, +0xC5, 0xF5, 0xCE, 0x15, 0xB5, 0x32, 0xBD, 0x73, +0xAD, 0x32, 0xB5, 0x32, 0xA4, 0xF1, 0xAD, 0x12, +0xB5, 0x53, 0xB5, 0x73, 0x9C, 0xB0, 0x94, 0x70, +0x8C, 0x2F, 0x94, 0x70, 0x8C, 0x2E, 0xA4, 0xD1, +0x8C, 0x0E, 0x9C, 0x90, 0x94, 0x6E, 0xA4, 0xB0, +0xAC, 0xD0, 0xAC, 0xF0, 0x94, 0x4E, 0x83, 0xAC, +0x7B, 0x6B, 0x8B, 0xCD, 0xBD, 0x53, 0x94, 0x2E, +0x8C, 0x2E, 0x94, 0x6F, 0xA4, 0xF1, 0xB5, 0x72, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xB3, 0xC5, 0xD4, +0xB5, 0x32, 0xB5, 0x51, 0xCD, 0xF4, 0xCE, 0x14, +0xBD, 0x72, 0xAD, 0x11, 0x83, 0xCD, 0xBD, 0x93, +0xBD, 0xB4, 0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x52, +0xAC, 0xF1, 0xBD, 0xB3, 0xAD, 0x31, 0xAD, 0x32, +0xAD, 0x11, 0xCE, 0x35, 0xC5, 0xF5, 0xB5, 0x94, +0x63, 0x2B, 0x31, 0xA6, 0x31, 0xA5, 0x31, 0x85, +0x42, 0x07, 0x4A, 0x68, 0x52, 0x8A, 0x42, 0x28, +0x4A, 0x48, 0x63, 0x0B, 0x7B, 0x6D, 0x6A, 0xEB, +0x52, 0x28, 0x93, 0xEF, 0x9C, 0x70, 0x8B, 0xEE, +0x94, 0x6E, 0x9C, 0x8D, 0xA4, 0xEF, 0x9C, 0x6F, +0xDE, 0x56, 0xDE, 0x55, 0xDE, 0x35, 0xCD, 0xD4, +0xCD, 0xD4, 0xC5, 0xB3, 0xC5, 0x93, 0xCD, 0xD4, +0xD6, 0x35, 0xDE, 0x56, 0xDE, 0x76, 0xDE, 0x56, +0xCD, 0xD4, 0xC5, 0xD5, 0xCE, 0x15, 0xD6, 0x16, +0xDE, 0x77, 0xD6, 0x56, 0xD6, 0x36, 0xD6, 0x16, +0xCD, 0xD5, 0xD6, 0x16, 0xB5, 0x52, 0x9C, 0x90, +0xA4, 0xF1, 0xB5, 0x74, 0xB5, 0x32, 0xB5, 0x53, +0xBD, 0x94, 0xBD, 0x53, 0xB5, 0x33, 0xBD, 0x74, +0xCD, 0xF5, 0xD6, 0x36, 0xC5, 0xD5, 0xCE, 0x15, +0xD6, 0x76, 0xC5, 0xB4, 0xC5, 0xB4, 0xC5, 0xD5, +0x53, 0x0A, 0x29, 0xA4, 0x42, 0xA6, 0x6B, 0xC9, +0x31, 0xC3, 0x42, 0x46, 0x31, 0xE4, 0x52, 0xE9, +0x6B, 0xAC, 0x84, 0x8F, 0x7C, 0x4D, 0x84, 0x8E, +0x9D, 0x30, 0xA5, 0x31, 0xAD, 0x71, 0xA4, 0xCE, +0xC5, 0x91, 0xD6, 0x13, 0xBD, 0x50, 0x9C, 0x2D, +0xB5, 0x30, 0xBD, 0x72, 0x9C, 0x4D, 0xAC, 0xCF, +0xC5, 0xB2, 0xBD, 0x92, 0x9C, 0x8E, 0xCD, 0xD3, +0xB5, 0x31, 0xC5, 0xD3, 0xCD, 0xB3, 0xB5, 0x30, +0xD5, 0xF4, 0xD6, 0x14, 0xBD, 0x51, 0xCD, 0xF4, +0xDE, 0x76, 0xE6, 0x96, 0xBD, 0x10, 0xAC, 0xAE, +0xAC, 0xF0, 0xBD, 0x93, 0xAD, 0x52, 0xB5, 0x74, +0xAD, 0x32, 0x9C, 0x90, 0x52, 0x89, 0x31, 0x65, +0x31, 0xA5, 0x31, 0x65, 0x31, 0x86, 0x4A, 0x69, +0x63, 0x0C, 0x52, 0x8A, 0x42, 0x28, 0x7B, 0xCF, +0xA4, 0xD2, 0x94, 0x50, 0x73, 0x6D, 0x42, 0x28, +0x73, 0xAE, 0xC5, 0xF6, 0xB5, 0x32, 0xA4, 0xAF, +0x9C, 0x6F, 0xA4, 0xD0, 0xAD, 0x11, 0xA4, 0xF1, +0x9C, 0xAF, 0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x32, 0xB5, 0x52, +0xB5, 0x52, 0xAD, 0x11, 0xAD, 0x10, 0xA4, 0xF0, +0xA4, 0xD0, 0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, +0xAC, 0xF0, 0xC5, 0x92, 0xAC, 0xCF, 0xB5, 0x10, +0xCD, 0x92, 0xCD, 0x92, 0xCD, 0x91, 0xCD, 0x92, +0xC5, 0x71, 0xC5, 0x71, 0xD5, 0xD3, 0xCD, 0x92, +0xC5, 0x71, 0xD5, 0xF3, 0xD5, 0xF3, 0xD5, 0xF3, +0xDE, 0x13, 0xD5, 0xF3, 0xCD, 0xB2, 0x9C, 0x4E, +0x6B, 0x0A, 0x6B, 0x0B, 0x39, 0xA6, 0x41, 0xE8, +0x73, 0xAF, 0x5A, 0xCB, 0x52, 0x8A, 0x73, 0x4D, +0x6B, 0x4D, 0x73, 0x8E, 0x9C, 0xB2, 0xA4, 0xB2, +0x93, 0xCE, 0x8B, 0xAE, 0x73, 0x2C, 0x6B, 0x0B, +0x52, 0x49, 0x8C, 0x51, 0x84, 0x30, 0x52, 0x6A, +0x62, 0xEB, 0x6B, 0x4D, 0x9C, 0xF3, 0xCE, 0x59, +0xDE, 0xBB, 0xCE, 0x18, 0xCD, 0xF7, 0xAD, 0x13, +0x83, 0xCD, 0x7B, 0xAC, 0x7B, 0xAC, 0x94, 0x4F, +0xAD, 0x11, 0x9C, 0x8F, 0x9C, 0x8F, 0x7B, 0xAC, +0x62, 0xE9, 0x62, 0xC9, 0x73, 0x4B, 0x73, 0x6B, +0x62, 0xCA, 0x31, 0x64, 0x39, 0xA6, 0x39, 0xC6, +0x4A, 0x68, 0x52, 0x69, 0x4A, 0x68, 0x52, 0x89, +0x42, 0x28, 0x4A, 0x49, 0x63, 0x0C, 0x6B, 0x4E, +0x73, 0x8F, 0x84, 0x31, 0x9C, 0xF4, 0xB5, 0x96, +0xAD, 0x34, 0x9C, 0xB1, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0xB0, 0x9C, 0x90, 0x9C, 0x90, 0xA4, 0xF1, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x94, 0xBD, 0x73, +0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x52, 0xC5, 0xF4, +0xD6, 0x56, 0xB5, 0x31, 0xC5, 0x73, 0xC5, 0xB3, +0xC5, 0x92, 0xD5, 0xF4, 0xD6, 0x14, 0xD5, 0xF4, +0xD5, 0xF4, 0xD6, 0x15, 0xB4, 0xF0, 0xAC, 0xCF, +0xBD, 0x72, 0xDE, 0x76, 0xAD, 0x11, 0xB5, 0x73, +0xD6, 0x77, 0xBD, 0xF5, 0xC5, 0xF5, 0xBD, 0xD4, +0xCE, 0x15, 0xBD, 0x93, 0xBD, 0xD4, 0xCE, 0x56, +0xBD, 0xD4, 0xC5, 0xD4, 0xAD, 0x32, 0xB5, 0x72, +0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xD0, 0xA4, 0xF1, +0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xB0, 0x9C, 0x90, +0x9C, 0x90, 0x9C, 0x90, 0x94, 0x6F, 0xA4, 0xD1, +0x94, 0x6F, 0xA4, 0xD1, 0xA4, 0xD0, 0xAD, 0x11, +0xA4, 0xD0, 0xA4, 0xD0, 0x62, 0xE9, 0x6B, 0x0A, +0x7B, 0x8C, 0xA4, 0x90, 0xBD, 0x53, 0x8C, 0x0E, +0x94, 0x6F, 0x9C, 0x90, 0xAD, 0x32, 0xBD, 0x93, +0xC5, 0xD4, 0xC5, 0xF4, 0xCD, 0xF4, 0xCD, 0xF4, +0xBD, 0x93, 0xB5, 0x51, 0xB5, 0x72, 0xBD, 0x92, +0xC5, 0xB3, 0xAC, 0xF1, 0x8C, 0x2E, 0xBD, 0xB4, +0xBD, 0x93, 0xAD, 0x11, 0xA4, 0xF0, 0xB5, 0x52, +0xA4, 0xF0, 0xC5, 0xD4, 0xAD, 0x11, 0xA4, 0xD0, +0xB5, 0x72, 0xCE, 0x15, 0xBD, 0xB3, 0xB5, 0x94, +0xB5, 0x74, 0x73, 0xAD, 0x42, 0x07, 0x31, 0xA6, +0x39, 0xC6, 0x42, 0x28, 0x52, 0x89, 0x52, 0x69, +0x4A, 0x69, 0x62, 0xEB, 0x8B, 0xEF, 0x73, 0x2C, +0x73, 0x2C, 0x73, 0x0B, 0x94, 0x0F, 0x83, 0x8C, +0x62, 0xC8, 0x83, 0xEB, 0xB5, 0x91, 0x7B, 0x6B, +0xAC, 0xD0, 0xE6, 0x96, 0xE6, 0x96, 0xE6, 0xB7, +0xE6, 0x76, 0xE6, 0x76, 0xDE, 0x56, 0xDE, 0x76, +0xE6, 0x76, 0xE6, 0x97, 0xE6, 0xB7, 0xE6, 0xB8, +0xDE, 0x77, 0xDE, 0x77, 0xD6, 0x56, 0xDE, 0x77, +0xDE, 0x97, 0xDE, 0x77, 0xDE, 0x57, 0xD6, 0x56, +0xDE, 0x56, 0xDE, 0x97, 0xDE, 0x77, 0xA4, 0xD1, +0x9C, 0x90, 0x9C, 0x90, 0x94, 0x50, 0x7B, 0xAD, +0x9C, 0x90, 0xC5, 0xB4, 0xD6, 0x15, 0xD6, 0x36, +0x9C, 0x70, 0xB5, 0x53, 0xDE, 0x76, 0xDE, 0x77, +0x9C, 0x90, 0x7B, 0x8C, 0x83, 0xCD, 0x94, 0x2F, +0x6B, 0x8B, 0x4A, 0x87, 0x53, 0x08, 0x52, 0xC7, +0x39, 0xE5, 0x52, 0xC8, 0x63, 0x6A, 0x73, 0xED, +0x73, 0xED, 0x84, 0x90, 0x9D, 0x53, 0x84, 0xAF, +0x9D, 0x51, 0x8C, 0xAE, 0x9C, 0xEF, 0xAC, 0xEF, +0xAC, 0xEE, 0xB5, 0x0F, 0xB4, 0xEF, 0xA4, 0x8E, +0x9C, 0x6D, 0xAC, 0xCF, 0xA4, 0xAE, 0xA4, 0x8E, +0xAC, 0xCF, 0xA4, 0x8E, 0x94, 0x0C, 0x9C, 0x4D, +0x9C, 0x6D, 0xA4, 0xAE, 0xA4, 0x6D, 0xA4, 0x8E, +0xB5, 0x10, 0xBD, 0x51, 0xB4, 0xEF, 0xBD, 0x31, +0xCD, 0xF4, 0xD6, 0x34, 0xC5, 0x71, 0xAC, 0xAE, +0xA4, 0xAE, 0xAD, 0x10, 0xA5, 0x11, 0xB5, 0x93, +0xBD, 0x94, 0xB5, 0x93, 0xAD, 0x32, 0x73, 0x6B, +0x31, 0x85, 0x31, 0x65, 0x31, 0x65, 0x42, 0x07, +0x4A, 0x48, 0x4A, 0x69, 0x63, 0x0C, 0x42, 0x28, +0x9C, 0xD2, 0xA4, 0xD2, 0x94, 0x70, 0x94, 0xB2, +0x84, 0x10, 0x94, 0x92, 0xE7, 0x1B, 0xAD, 0x12, +0x7B, 0x6B, 0xA4, 0xD0, 0xBD, 0x93, 0xA4, 0xD0, +0x9C, 0x8F, 0x94, 0x6F, 0x8C, 0x2E, 0x94, 0x4F, +0x94, 0x4F, 0x9C, 0x6F, 0xA4, 0xF1, 0xAD, 0x32, +0xB5, 0x72, 0xAD, 0x11, 0xAD, 0x11, 0xA4, 0xAF, +0xA4, 0xD0, 0xA4, 0xD1, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0xB5, 0x31, 0xB4, 0xEF, 0xC5, 0x72, +0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x30, 0xBD, 0x10, +0xC5, 0x51, 0xBD, 0x30, 0xCD, 0x92, 0xB4, 0xF0, +0xB5, 0x10, 0xCD, 0xB2, 0xD5, 0xF3, 0xD5, 0xF3, +0xDE, 0x34, 0xDE, 0x54, 0xBD, 0x51, 0x8B, 0xED, +0x73, 0x6D, 0x94, 0x71, 0x94, 0x92, 0xBD, 0xB7, +0xBD, 0xD7, 0x63, 0x2C, 0x4A, 0x49, 0x5A, 0xAA, +0x5A, 0xCB, 0x62, 0xEB, 0x8C, 0x30, 0x94, 0x50, +0x9C, 0x91, 0x94, 0x0F, 0x94, 0x0F, 0xAC, 0xB2, +0x9C, 0x91, 0x9C, 0xB2, 0x83, 0xEF, 0x73, 0x6E, +0x8C, 0x51, 0xBD, 0xF7, 0xD6, 0x9A, 0xDE, 0xDB, +0xBD, 0xF7, 0xE6, 0xFB, 0xEF, 0x3C, 0xD6, 0x59, +0xAC, 0xF2, 0x9C, 0x90, 0x9C, 0x90, 0x94, 0x6F, +0x9C, 0x90, 0x9C, 0x6F, 0x8C, 0x2E, 0x7B, 0xAC, +0x7B, 0xAD, 0x7B, 0xAD, 0x94, 0x4F, 0x9C, 0xB0, +0x9C, 0xD1, 0x62, 0xEA, 0x39, 0xC6, 0x39, 0xA5, +0x41, 0xE6, 0x39, 0xC6, 0x39, 0xE7, 0x42, 0x28, +0x4A, 0x29, 0x52, 0xAA, 0x63, 0x2C, 0x63, 0x0C, +0x5A, 0xCC, 0x73, 0xAF, 0x7C, 0x10, 0x8C, 0x51, +0xAD, 0x34, 0xB5, 0x74, 0xBD, 0xB4, 0xAD, 0x12, +0xB5, 0x53, 0xBD, 0x94, 0xB5, 0x52, 0xB5, 0x52, +0xAD, 0x32, 0xA4, 0xF1, 0xAD, 0x11, 0xB5, 0x52, +0xAC, 0xF1, 0xA4, 0xD0, 0x9C, 0x90, 0x9C, 0xB0, +0xA4, 0xB0, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xD0, +0xA4, 0xF0, 0xAC, 0xF1, 0xAC, 0xD0, 0xA4, 0xAF, +0x9C, 0x6E, 0xA4, 0x8F, 0xAC, 0xCF, 0xAC, 0xD0, +0xAC, 0xF0, 0xAC, 0xD0, 0x9C, 0x6E, 0x9C, 0x6E, +0x9C, 0x6E, 0xAD, 0x11, 0x94, 0x4E, 0x94, 0x2E, +0x9C, 0xB0, 0xAD, 0x32, 0xA4, 0xF1, 0x94, 0x4E, +0x9C, 0x90, 0x8C, 0x2E, 0x94, 0x6F, 0xB5, 0x93, +0xC6, 0x15, 0xC5, 0xF5, 0xA4, 0xD0, 0x83, 0xED, +0x7B, 0xAC, 0x83, 0xED, 0xAD, 0x11, 0xA4, 0xF1, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x32, 0xAD, 0x11, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x73, 0xA5, 0x11, +0xAD, 0x32, 0xB5, 0x32, 0xAC, 0xF1, 0xB5, 0x52, +0xA4, 0xAF, 0xA4, 0xD0, 0x6B, 0x0A, 0x94, 0x4F, +0x9C, 0x8F, 0xA4, 0x90, 0xBD, 0x73, 0x8C, 0x0D, +0x9C, 0x90, 0xA4, 0xD0, 0xB5, 0x73, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xF4, 0xC5, 0xD3, +0xBD, 0x93, 0xB5, 0x51, 0xBD, 0x92, 0xB5, 0x72, +0xBD, 0x93, 0xC5, 0xB4, 0xAD, 0x11, 0xC5, 0xD4, +0xB5, 0x73, 0xAD, 0x11, 0xB5, 0x52, 0xBD, 0xB4, +0xAD, 0x11, 0xC5, 0xD4, 0xAC, 0xF1, 0xA4, 0xD1, +0xBD, 0x93, 0xCE, 0x15, 0xB5, 0x93, 0xAD, 0x73, +0xAD, 0x32, 0xB5, 0x73, 0x83, 0xEE, 0x42, 0x27, +0x39, 0xC6, 0x42, 0x07, 0x42, 0x28, 0x4A, 0x69, +0x4A, 0x49, 0x4A, 0x28, 0x5A, 0xAA, 0x83, 0xCE, +0x73, 0x0C, 0x73, 0x0B, 0x8B, 0xAD, 0x73, 0x2B, +0x5A, 0xC8, 0x5B, 0x27, 0x9D, 0x0E, 0xB5, 0xB2, +0xB5, 0x70, 0xBD, 0xD0, 0xBD, 0xF1, 0xEF, 0x17, +0xEE, 0xD7, 0xDE, 0x76, 0xEE, 0xD7, 0xEE, 0xD7, +0xE6, 0x97, 0xE6, 0xB7, 0xDE, 0x97, 0xE6, 0xB8, +0xDE, 0xB8, 0xE6, 0xB8, 0xE6, 0xB8, 0xE6, 0xB8, +0xDE, 0x98, 0xDE, 0x98, 0xDE, 0x77, 0xDE, 0x97, +0xDE, 0x97, 0xEE, 0xF8, 0xEE, 0xF8, 0xAD, 0x12, +0xAD, 0x33, 0xC5, 0xD5, 0xC5, 0xF5, 0xBD, 0xB5, +0x9C, 0xB1, 0xB5, 0x12, 0xD6, 0x15, 0xC5, 0xB4, +0x7B, 0xAC, 0x94, 0x70, 0x8C, 0x2F, 0xAD, 0x32, +0x8C, 0x2F, 0x8C, 0x2F, 0x9C, 0x91, 0x9C, 0xB1, +0x8C, 0x6F, 0x5A, 0xC8, 0x52, 0xC8, 0x5B, 0x2A, +0x84, 0x4F, 0x7C, 0x2E, 0x8C, 0x6E, 0x73, 0xCC, +0x73, 0xCD, 0x6B, 0xAC, 0x52, 0xE9, 0x4A, 0xA8, +0x94, 0xF0, 0x84, 0x2C, 0x94, 0x4D, 0xA4, 0xAE, +0xA4, 0x8E, 0xB4, 0xEF, 0xAC, 0xCE, 0xAC, 0xCF, +0xBD, 0x71, 0xB5, 0x0F, 0xAC, 0xAE, 0xAC, 0xAE, +0xAC, 0xCF, 0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x8E, +0xA4, 0x8E, 0xAC, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xEF, 0xB4, 0xEF, 0xAC, 0xCF, +0xAC, 0xAE, 0xAC, 0x8D, 0xAC, 0xAE, 0xAC, 0xAE, +0xA4, 0x8E, 0x9C, 0x4D, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x4E, 0x8C, 0x0D, 0x8C, 0x2D, 0x94, 0x4E, +0x8B, 0xEC, 0x62, 0xA8, 0x31, 0x84, 0x31, 0xA5, +0x39, 0xC6, 0x4A, 0x48, 0x63, 0x0C, 0x52, 0xAA, +0x52, 0xAA, 0x83, 0xCF, 0x84, 0x0F, 0x7B, 0xAE, +0x73, 0x6D, 0x73, 0x8E, 0xD6, 0xBA, 0xEF, 0x1B, +0xB5, 0x33, 0x8B, 0xAD, 0xB4, 0xF1, 0x94, 0x4F, +0x8C, 0x0E, 0x8C, 0x2E, 0x8C, 0x0E, 0x8C, 0x2F, +0x9C, 0x90, 0xA4, 0xD1, 0x94, 0x6F, 0x94, 0x6F, +0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xB0, 0x94, 0x4E, +0x9C, 0xB0, 0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x31, 0xC5, 0x72, 0xCD, 0xB3, +0xC5, 0x51, 0xC5, 0x51, 0xBD, 0x31, 0xAC, 0xAF, +0xB4, 0xF0, 0xC5, 0x51, 0xCD, 0x72, 0xBD, 0x31, +0xBD, 0x51, 0xCD, 0x92, 0xD5, 0xD3, 0xCD, 0x92, +0xD5, 0xF3, 0xDE, 0x55, 0xA4, 0xB0, 0xB5, 0x95, +0xBD, 0xD6, 0xC5, 0xF7, 0xB5, 0xB6, 0x6B, 0x4D, +0x6B, 0x4D, 0x42, 0x08, 0x29, 0x45, 0x31, 0xA6, +0x42, 0x07, 0x42, 0x08, 0x7B, 0xAE, 0x8C, 0x30, +0xAD, 0x14, 0x8B, 0xEF, 0x9C, 0x50, 0xA4, 0xD2, +0xB5, 0x34, 0xCE, 0x18, 0xCE, 0x38, 0xCE, 0x38, +0xAD, 0x34, 0xD6, 0x79, 0x9C, 0xD3, 0xAD, 0x14, +0x94, 0x72, 0xAD, 0x55, 0xCE, 0x59, 0xF7, 0x5C, +0xBD, 0xB5, 0xAC, 0xF2, 0xAC, 0xF1, 0x9C, 0x8F, +0xA4, 0xD0, 0x94, 0x6F, 0x7B, 0xAC, 0x8C, 0x0E, +0x83, 0xCD, 0x8C, 0x2E, 0x9C, 0xB1, 0xAD, 0x12, +0x9C, 0xB0, 0x8C, 0x2E, 0x42, 0x06, 0x31, 0x85, +0x39, 0xC6, 0x39, 0xC6, 0x39, 0xE6, 0x39, 0xE7, +0x42, 0x08, 0x52, 0xAA, 0x5A, 0xCB, 0x63, 0x2D, +0x63, 0x0D, 0x6B, 0x6E, 0x73, 0x8E, 0x84, 0x30, +0xA5, 0x34, 0xB5, 0x75, 0xC5, 0xD6, 0xC5, 0xB4, +0xCE, 0x36, 0xBD, 0xB4, 0xBD, 0x94, 0xBD, 0x93, +0xBD, 0x73, 0xB5, 0x52, 0xC5, 0xD4, 0xDE, 0x97, +0xDE, 0x97, 0xBD, 0x93, 0xAC, 0xF1, 0xCD, 0xF5, +0xC5, 0xB4, 0xAC, 0xF1, 0x9C, 0x4F, 0x8C, 0x0E, +0x8C, 0x0D, 0x8C, 0x0E, 0x9C, 0x8F, 0xAD, 0x32, +0xBD, 0x73, 0xAC, 0xF1, 0xA4, 0x90, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x11, +0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0xB0, 0xAC, 0xD1, +0xA4, 0xD1, 0x9C, 0xB0, 0x94, 0x4E, 0x9C, 0x8F, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x90, +0x9C, 0x8F, 0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xD1, +0xA4, 0xD1, 0x94, 0x4F, 0x83, 0xED, 0x83, 0xCD, +0x8B, 0xCD, 0x83, 0xCD, 0x8B, 0xED, 0x83, 0xCD, +0x83, 0xCD, 0x8C, 0x0E, 0x8C, 0x2E, 0x8C, 0x0E, +0x94, 0x2E, 0x9C, 0xB0, 0xAD, 0x11, 0xB5, 0x52, +0xA4, 0xF1, 0x83, 0xED, 0x6B, 0x2A, 0x94, 0x2E, +0x9C, 0x8F, 0x94, 0x2E, 0xBD, 0x53, 0x8B, 0xED, +0x9C, 0x6F, 0x9C, 0xB0, 0xAD, 0x32, 0xB5, 0x73, +0xB5, 0x52, 0xB5, 0x72, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x93, 0xB5, 0x72, 0xBD, 0xB3, 0xBD, 0x93, +0xBD, 0x93, 0xC5, 0xB4, 0xAD, 0x11, 0xBD, 0xB4, +0xBD, 0x94, 0xBD, 0x93, 0xC5, 0xF5, 0xBD, 0x93, +0xB5, 0x53, 0xBD, 0xB3, 0xA4, 0xF0, 0xAD, 0x32, +0xBD, 0x93, 0xC5, 0xD4, 0xA5, 0x11, 0xAD, 0x73, +0xA4, 0xF2, 0xB5, 0x73, 0xBD, 0xD4, 0xB5, 0x52, +0x52, 0x67, 0x31, 0x85, 0x31, 0x85, 0x39, 0xE6, +0x42, 0x27, 0x4A, 0x68, 0x4A, 0x48, 0x8C, 0x30, +0x83, 0xAE, 0x73, 0x2C, 0x8B, 0xCE, 0x8B, 0xCD, +0x5A, 0xC7, 0x53, 0x26, 0x5B, 0x66, 0x94, 0xEE, +0x94, 0x8C, 0xA5, 0x6D, 0xAD, 0xAE, 0xD6, 0x93, +0xB5, 0xB1, 0x84, 0x2C, 0xDE, 0xB5, 0xEE, 0xF7, +0xEE, 0xD8, 0xEE, 0xF8, 0xE6, 0xB8, 0xDE, 0x97, +0xDE, 0xD8, 0xDE, 0x98, 0xDE, 0xB8, 0xDE, 0xB8, +0xE6, 0xD8, 0xE6, 0xD8, 0xDE, 0xB7, 0xDE, 0x97, +0xDE, 0xB8, 0xE6, 0xF8, 0xE6, 0xD8, 0xAD, 0x12, +0xAD, 0x12, 0xCE, 0x36, 0xD6, 0x77, 0xCE, 0x36, +0xC5, 0xD5, 0xD6, 0x36, 0xD6, 0x15, 0xCD, 0xF5, +0xB5, 0x53, 0xC6, 0x15, 0xA4, 0xD1, 0xBD, 0xD5, +0xCE, 0x37, 0xC6, 0x16, 0xCE, 0x16, 0xC5, 0xF6, +0x7C, 0x0E, 0x3A, 0x06, 0x6B, 0xAD, 0x73, 0xEE, +0x8C, 0xD1, 0x9D, 0x12, 0x8C, 0x6F, 0x94, 0x8F, +0xA5, 0x11, 0xB5, 0x52, 0xAD, 0x31, 0x94, 0x6E, +0x6B, 0x29, 0x62, 0xC8, 0x5A, 0xA8, 0x73, 0x4A, +0x62, 0xE9, 0x73, 0x6A, 0xA4, 0xD0, 0xAC, 0xD0, +0x9C, 0x6D, 0xAC, 0xCF, 0xC5, 0x92, 0xC5, 0x92, +0xC5, 0x92, 0xBD, 0x30, 0xBD, 0x51, 0xCD, 0xB2, +0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xCF, 0xB5, 0x10, +0xA4, 0x8E, 0xAC, 0xCE, 0xAC, 0x8E, 0xAC, 0xAE, +0xB4, 0xCF, 0xBD, 0x30, 0xD5, 0xD3, 0xC5, 0x51, +0xB5, 0x0F, 0xAC, 0xEF, 0xBD, 0x50, 0xBD, 0x30, +0xB5, 0x10, 0xB5, 0x30, 0xB5, 0x10, 0xB5, 0x30, +0xBD, 0x30, 0xBD, 0x30, 0x94, 0x2D, 0x52, 0x47, +0x29, 0x64, 0x39, 0xE7, 0x62, 0xEB, 0x5A, 0xCA, +0x5A, 0xCA, 0x63, 0x0C, 0x41, 0xE7, 0x41, 0xE7, +0x5A, 0xEB, 0x7B, 0xF0, 0xD6, 0x9A, 0xE7, 0x1C, +0xF7, 0x7D, 0xD6, 0x38, 0x94, 0x2F, 0xA4, 0xD1, +0x9C, 0x6F, 0x94, 0x4E, 0x8C, 0x0E, 0x8C, 0x0E, +0x94, 0x4F, 0xB5, 0x73, 0x9C, 0xB0, 0x83, 0xCD, +0x8C, 0x0E, 0x83, 0xCC, 0x73, 0x6B, 0x83, 0xCC, +0x8C, 0x0E, 0x94, 0x4F, 0x9C, 0x6F, 0xA4, 0xD0, +0xAD, 0x11, 0xBD, 0x72, 0xCD, 0xB2, 0xD5, 0xD3, +0xCD, 0xB2, 0xD5, 0xD3, 0xE6, 0x35, 0xD5, 0xB3, +0xC5, 0x51, 0xCD, 0x92, 0xC5, 0x92, 0xCD, 0xD3, +0xCD, 0x92, 0xCD, 0xB3, 0xDE, 0x34, 0xC5, 0x71, +0xBD, 0x31, 0xBD, 0x72, 0xA4, 0xD1, 0x94, 0x71, +0x73, 0x6D, 0x7B, 0xCF, 0x6B, 0x2C, 0x42, 0x28, +0x5A, 0xCB, 0x52, 0xAA, 0x4A, 0x49, 0x21, 0x04, +0x29, 0x45, 0x31, 0x65, 0x5A, 0xAA, 0x73, 0x8D, +0x8B, 0xEF, 0xA4, 0xB2, 0x94, 0x30, 0xA4, 0xD2, +0xA4, 0xD2, 0xBD, 0x95, 0xA4, 0xD3, 0xD6, 0x59, +0xD6, 0x38, 0xDE, 0x79, 0x8C, 0x10, 0xAD, 0x34, +0x73, 0xAE, 0x52, 0x8A, 0x7B, 0xAF, 0xDE, 0xDB, +0xCE, 0x38, 0x94, 0x91, 0x9C, 0xB1, 0xAC, 0xF1, +0xB5, 0x32, 0xAC, 0xF1, 0x9C, 0x8F, 0xA4, 0xD0, +0x9C, 0x90, 0x9C, 0x90, 0xD6, 0x57, 0xBD, 0xD5, +0x94, 0x50, 0x83, 0xEE, 0x63, 0x0B, 0x41, 0xE7, +0x42, 0x07, 0x39, 0xC6, 0x39, 0xE7, 0x41, 0xE7, +0x42, 0x07, 0x52, 0x8A, 0x52, 0x8A, 0x63, 0x0C, +0x6B, 0x4D, 0x63, 0x0C, 0x63, 0x2D, 0x83, 0xF0, +0x94, 0x92, 0xB5, 0x75, 0xC5, 0xD6, 0xC5, 0xD6, +0x8C, 0x50, 0x62, 0xCA, 0xB5, 0x74, 0x9C, 0x70, +0xA4, 0xD1, 0xAD, 0x11, 0xB5, 0x73, 0xD6, 0x56, +0xE6, 0xD8, 0xBD, 0x93, 0xBD, 0x73, 0xD6, 0x36, +0xC5, 0xB4, 0xB5, 0x72, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x32, 0xAD, 0x12, 0xAD, 0x11, 0xC5, 0xD4, +0xC5, 0xF5, 0xC5, 0xD4, 0xAD, 0x11, 0xA4, 0xB0, +0x94, 0x4E, 0x8C, 0x0D, 0x94, 0x4F, 0xA4, 0xB0, +0x94, 0x4F, 0xB5, 0x32, 0xC5, 0xD4, 0xBD, 0x93, +0x9C, 0x6F, 0x9C, 0x6F, 0x9C, 0xB0, 0xC5, 0xB4, +0xCD, 0xF5, 0xD6, 0x56, 0xC5, 0xD4, 0xBD, 0x73, +0xAD, 0x11, 0x9C, 0x6F, 0xB5, 0x52, 0xAD, 0x11, +0xA4, 0xF1, 0xA4, 0xB0, 0xAD, 0x11, 0xAD, 0x11, +0xAC, 0xD1, 0xAC, 0xD0, 0xA4, 0xD0, 0xA4, 0xD1, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x90, +0x9C, 0x90, 0x9C, 0x6F, 0x94, 0x2E, 0x94, 0x2E, +0x94, 0x0E, 0x9C, 0x4F, 0xA4, 0xB0, 0x9C, 0x6F, +0x94, 0x4E, 0x9C, 0x6F, 0xB5, 0x32, 0x9C, 0x6F, +0x8C, 0x2E, 0x83, 0xED, 0x94, 0x4E, 0x94, 0x6F, +0x83, 0xED, 0x94, 0x4E, 0xA4, 0xD0, 0xA4, 0xF0, +0xB5, 0x52, 0xBD, 0xB3, 0xC5, 0xD4, 0xCE, 0x15, +0xCE, 0x15, 0xCE, 0x14, 0xB5, 0x52, 0xBD, 0xB4, +0xC5, 0xD4, 0xC5, 0xB3, 0xCE, 0x36, 0xC5, 0xD4, +0xBD, 0xB4, 0xC5, 0xF4, 0x9C, 0xB0, 0x94, 0x6F, +0xA4, 0xF0, 0xA4, 0xF1, 0x94, 0x4E, 0xAD, 0x32, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0xD4, 0xDE, 0xB6, +0xBD, 0xD4, 0x52, 0x88, 0x31, 0xA5, 0x29, 0x64, +0x39, 0xC6, 0x4A, 0x48, 0x4A, 0x48, 0x62, 0xCA, +0x5A, 0xAA, 0x73, 0x2C, 0x83, 0x6D, 0x83, 0x8D, +0x5A, 0xC8, 0x42, 0xA5, 0x5B, 0x87, 0x42, 0x64, +0x84, 0x2B, 0x84, 0x8A, 0xBE, 0x50, 0x94, 0xEC, +0x74, 0x49, 0x6C, 0x09, 0xC6, 0x12, 0xD6, 0x34, +0xD6, 0x35, 0xD6, 0x36, 0xBD, 0xB4, 0xA5, 0x12, +0xAD, 0x53, 0xBD, 0xB5, 0xDE, 0xB8, 0xCE, 0x36, +0xDE, 0xB8, 0xDE, 0xD8, 0xD6, 0x77, 0xD6, 0x77, +0xDE, 0xB8, 0xE6, 0xF8, 0xDE, 0xB8, 0xAD, 0x12, +0xAD, 0x12, 0xCE, 0x36, 0xD6, 0x57, 0xC5, 0xD5, +0xBD, 0xB3, 0xD6, 0x15, 0xCD, 0xB3, 0xDE, 0x55, +0xCD, 0xD4, 0xC5, 0xD4, 0xC5, 0xD5, 0xCE, 0x36, +0xD6, 0x77, 0xD6, 0x57, 0xCE, 0x16, 0xD6, 0x77, +0x3A, 0x47, 0x74, 0x0E, 0x7C, 0x90, 0x84, 0xB1, +0x9D, 0x54, 0xA5, 0x74, 0x94, 0xB0, 0x9C, 0xD0, +0xC5, 0xF4, 0xDE, 0x76, 0xCE, 0x14, 0xB5, 0x11, +0x94, 0x4F, 0x6B, 0x0A, 0x6B, 0x0A, 0x8C, 0x2E, +0x7B, 0xCC, 0x94, 0x6F, 0xC5, 0xD5, 0xC5, 0xB3, +0xA4, 0x8E, 0xC5, 0x71, 0xD5, 0xF4, 0xDE, 0x55, +0xDE, 0x55, 0xD6, 0x14, 0xCD, 0xB2, 0xDE, 0x75, +0xDE, 0x55, 0xDE, 0x34, 0xD5, 0xF3, 0xD6, 0x14, +0xCD, 0xD3, 0xC5, 0x92, 0xCD, 0xB2, 0xD6, 0x14, +0xDE, 0x35, 0xCD, 0xB2, 0xDE, 0x34, 0xC5, 0x71, +0xB5, 0x0F, 0xC5, 0x92, 0xBD, 0x30, 0xB4, 0xEF, +0xAC, 0xAE, 0x9C, 0x2C, 0x94, 0x2C, 0x7B, 0x8A, +0x83, 0xAB, 0x94, 0x0D, 0x9C, 0x6E, 0x83, 0xAC, +0x52, 0x68, 0x42, 0x27, 0x42, 0x28, 0x39, 0xE6, +0x42, 0x07, 0x39, 0xE7, 0x42, 0x07, 0x39, 0xE7, +0x42, 0x28, 0x84, 0x10, 0xBD, 0xD7, 0xAD, 0x55, +0xD6, 0xBB, 0xEF, 0x3D, 0xE6, 0xFB, 0xBD, 0x74, +0xB5, 0x11, 0xBD, 0x52, 0xBD, 0x31, 0xB5, 0x31, +0xAC, 0xF0, 0xAC, 0xF0, 0xAC, 0xD0, 0xA4, 0xAF, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x4E, +0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x2D, 0x94, 0x4E, +0x9C, 0x6E, 0xB5, 0x10, 0xA4, 0x4D, 0x9C, 0x2C, +0x9C, 0x2C, 0xA4, 0x6D, 0xB4, 0xCF, 0xBD, 0x10, +0xBC, 0xF0, 0xB4, 0xF0, 0xB5, 0x31, 0xBD, 0x72, +0xC5, 0x72, 0xCD, 0xB3, 0xDE, 0x35, 0xE6, 0x75, +0xEE, 0x95, 0xEE, 0xB7, 0xC5, 0xB3, 0x83, 0xCD, +0x52, 0x68, 0x7B, 0xCD, 0x8C, 0x2F, 0x94, 0x71, +0x8C, 0x50, 0x8C, 0x51, 0x9C, 0xF3, 0x83, 0xEF, +0x73, 0xAE, 0x63, 0x2C, 0x42, 0x28, 0x4A, 0x48, +0x6B, 0x0B, 0x83, 0xCE, 0x9C, 0x71, 0xA4, 0xD2, +0x9C, 0x71, 0x9C, 0x91, 0xB5, 0x35, 0x8C, 0x10, +0xB5, 0x75, 0xCE, 0x38, 0x8C, 0x10, 0x5A, 0xEB, +0x39, 0xC7, 0x31, 0xA7, 0x6B, 0x2D, 0xE7, 0x3C, +0xF7, 0xBE, 0xEF, 0x3D, 0xE6, 0xDA, 0xB5, 0x53, +0xB5, 0x11, 0xC5, 0x92, 0xC5, 0x72, 0xBD, 0x72, +0xAC, 0xD0, 0x94, 0x2F, 0xB5, 0x95, 0xDE, 0xDB, +0xC6, 0x17, 0x8C, 0x30, 0x7B, 0xAD, 0x52, 0x69, +0x39, 0xE6, 0x39, 0xC6, 0x4A, 0x68, 0x4A, 0x48, +0x39, 0xE7, 0x39, 0xE7, 0x42, 0x08, 0x4A, 0x49, +0x52, 0x69, 0x4A, 0x6A, 0x6B, 0x2D, 0x6B, 0x6D, +0x7B, 0xCF, 0x83, 0xF0, 0x73, 0x8E, 0x7B, 0xEF, +0x63, 0x0C, 0x94, 0x92, 0xD6, 0x99, 0xAD, 0x13, +0x94, 0x6F, 0xA4, 0xD0, 0xA4, 0xF1, 0xC5, 0xD4, +0xDE, 0xB8, 0xB5, 0x53, 0xC5, 0xD4, 0xCD, 0xF5, +0xBD, 0x94, 0xAD, 0x11, 0xB5, 0x52, 0xAC, 0xF1, +0xAD, 0x11, 0xAD, 0x11, 0xBD, 0x73, 0xBD, 0xB4, +0xC5, 0xD4, 0xC5, 0xF4, 0xC5, 0xF5, 0xC5, 0xF5, +0xB5, 0x52, 0x9C, 0x8F, 0xAD, 0x32, 0xBD, 0x73, +0xBD, 0x93, 0xCD, 0xF5, 0xC5, 0xF5, 0xD6, 0x77, +0xC5, 0xB4, 0xAC, 0xF1, 0xC5, 0xD4, 0xBD, 0xB3, +0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x15, 0xCD, 0xF4, +0xC5, 0xB4, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x52, +0xAD, 0x12, 0xB5, 0x52, 0xC5, 0xD4, 0xCD, 0xF5, +0xC5, 0xB3, 0xD6, 0x56, 0xC5, 0xD4, 0xA4, 0xD1, +0x9C, 0x90, 0x94, 0x6F, 0x9C, 0x6F, 0xBD, 0x73, +0xAC, 0xF1, 0xA4, 0xB0, 0xC5, 0xB4, 0xCD, 0xD4, +0xCD, 0xD4, 0xCD, 0xD4, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x52, 0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x11, +0xAC, 0xF0, 0xAC, 0xF1, 0xAC, 0xF1, 0x9C, 0xB0, +0xA4, 0xD1, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x8F, +0xA4, 0xB0, 0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD0, 0x9C, 0xB0, 0x94, 0x6F, +0xA4, 0xD0, 0xAD, 0x11, 0xB5, 0x52, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x32, 0x8C, 0x2E, 0x83, 0xCD, +0x73, 0x6B, 0x6B, 0x2B, 0x73, 0x4B, 0x73, 0x6C, +0x83, 0xCD, 0x8C, 0x0E, 0x94, 0x6F, 0x9C, 0x8F, +0xA4, 0xD0, 0x83, 0xED, 0x52, 0x68, 0x42, 0x07, +0x42, 0x07, 0x39, 0xC6, 0x39, 0xE7, 0x39, 0xE7, +0x41, 0xE7, 0x5A, 0xAA, 0x7B, 0x6D, 0x83, 0xCE, +0x6A, 0xEA, 0x5A, 0xE9, 0x5B, 0x28, 0x42, 0x66, +0x52, 0xC7, 0x94, 0xEC, 0xA5, 0x8D, 0x6C, 0x08, +0x6C, 0x48, 0x6C, 0x49, 0xC6, 0x33, 0xE6, 0xB7, +0xC5, 0xB4, 0xB5, 0x73, 0xBD, 0xB5, 0xBD, 0xB5, +0xAD, 0x33, 0x9C, 0xB1, 0xB5, 0x94, 0x94, 0x70, +0x8C, 0x2F, 0x8C, 0x50, 0x94, 0x70, 0xA4, 0xF2, +0xC5, 0xF6, 0xEF, 0x3A, 0xDE, 0x97, 0xA4, 0xF1, +0xAD, 0x32, 0xCE, 0x36, 0xA4, 0xD1, 0x73, 0x4C, +0xAD, 0x11, 0xBD, 0x51, 0xBD, 0x72, 0xBD, 0x51, +0xC5, 0x93, 0xDE, 0x57, 0xD6, 0x56, 0xC5, 0xD5, +0xCE, 0x15, 0xD6, 0x36, 0xCD, 0xF5, 0xDE, 0x77, +0x53, 0x09, 0x5B, 0x2A, 0x5B, 0x4B, 0x63, 0x8C, +0x8C, 0xB0, 0x84, 0x2F, 0x8C, 0x6F, 0x9C, 0xD0, +0xA4, 0xF1, 0xC5, 0xD4, 0xBD, 0x72, 0xAC, 0xF0, +0xB5, 0x52, 0xA4, 0xB0, 0x9C, 0x8F, 0xB5, 0x52, +0xCD, 0xF5, 0xDE, 0x77, 0xE6, 0xD8, 0xE6, 0xB7, +0xAC, 0xAE, 0xDE, 0x34, 0xDE, 0x34, 0xD6, 0x14, +0xCD, 0xD3, 0xCD, 0xB2, 0xC5, 0x92, 0xC5, 0xB2, +0xDE, 0x34, 0xE6, 0x75, 0xD5, 0xF4, 0xDE, 0x75, +0xE6, 0xB6, 0xEE, 0xB7, 0xE6, 0x96, 0xDE, 0x55, +0xD5, 0xF3, 0xBD, 0x30, 0xB4, 0xEF, 0xAC, 0x8E, +0xAC, 0xAE, 0xB5, 0x10, 0xD5, 0xF3, 0xB4, 0xEF, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0xF0, 0x8C, 0x0E, +0x73, 0x6C, 0x73, 0x6B, 0x6B, 0x0A, 0x5A, 0xA9, +0x62, 0xC9, 0x52, 0x88, 0x39, 0xC6, 0x39, 0xE7, +0x31, 0xA6, 0x31, 0x65, 0x39, 0xE7, 0x39, 0xC6, +0x4A, 0x48, 0x7B, 0xEF, 0x94, 0xD3, 0x9C, 0xD4, +0xCE, 0x9B, 0xDE, 0xFC, 0xDE, 0xFB, 0xE7, 0x1B, +0xBD, 0x94, 0x8B, 0xEE, 0x94, 0x4E, 0x9C, 0x4D, +0xA4, 0xAF, 0xAC, 0xCF, 0xA4, 0x8E, 0xAC, 0xCF, +0xB4, 0xEF, 0xBD, 0x30, 0xBD, 0x31, 0xB5, 0x10, +0xB5, 0x10, 0xBD, 0x51, 0xBD, 0x30, 0xBD, 0x30, +0xB5, 0x10, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, +0xCD, 0x91, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x30, +0xBC, 0xEF, 0xAC, 0x8E, 0x9C, 0x2D, 0xB5, 0x74, +0xE6, 0xDA, 0xD6, 0x58, 0xA4, 0x90, 0x8B, 0xAC, +0x93, 0xEC, 0x9C, 0x0C, 0x94, 0x0C, 0x94, 0x0D, +0x8B, 0xCC, 0x7B, 0x6B, 0x8B, 0xEC, 0x94, 0x2E, +0x7B, 0xAC, 0x62, 0xE9, 0x5A, 0xA9, 0x62, 0xEB, +0x6B, 0x4D, 0x73, 0xAE, 0x5A, 0xAA, 0x73, 0x6D, +0x5A, 0xCA, 0x62, 0xCA, 0x62, 0xCA, 0x73, 0x2C, +0xAC, 0xD2, 0x9C, 0x71, 0xBD, 0x96, 0xAC, 0xF4, +0xA4, 0xF3, 0xCE, 0x18, 0xD6, 0x59, 0x9C, 0xB3, +0x4A, 0x49, 0x31, 0x66, 0x73, 0x8E, 0xDE, 0xBA, +0xD6, 0x9A, 0xEF, 0x3C, 0xEF, 0x1C, 0xD6, 0x58, +0x9C, 0x91, 0xCD, 0xD5, 0xC5, 0x72, 0xC5, 0x72, +0xA4, 0xB0, 0x94, 0x50, 0x6B, 0x2C, 0x94, 0x92, +0xCE, 0x59, 0xCE, 0x59, 0xA4, 0xF3, 0x73, 0x8D, +0x41, 0xE7, 0x39, 0xC6, 0x4A, 0x68, 0x42, 0x07, +0x39, 0xE7, 0x39, 0xC7, 0x39, 0xC7, 0x42, 0x08, +0x42, 0x28, 0x4A, 0x49, 0x5A, 0xCB, 0x63, 0x2D, +0x6B, 0x4D, 0x62, 0xEC, 0x5A, 0xAB, 0x52, 0xAA, +0x62, 0xEC, 0x9C, 0xF3, 0xBD, 0xD6, 0xDE, 0x99, +0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xF1, 0xC5, 0xD4, +0xE6, 0xB8, 0xAD, 0x11, 0xC5, 0xD4, 0xC5, 0xF5, +0xC5, 0xF5, 0xA4, 0xD0, 0xB5, 0x52, 0xBD, 0x73, +0xB5, 0x52, 0xB5, 0x32, 0xBD, 0x73, 0xB5, 0x52, +0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x73, +0xB5, 0x52, 0x9C, 0x6F, 0xB5, 0x52, 0xB5, 0x73, +0xBD, 0x73, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0xB4, +0xBD, 0x94, 0xA4, 0xB0, 0x9C, 0xB0, 0xBD, 0x93, +0xCD, 0xD4, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xF4, +0xCE, 0x14, 0xC5, 0xB4, 0xBD, 0xB4, 0xCE, 0x36, +0xC5, 0xD5, 0xC5, 0xF5, 0xBD, 0x72, 0xAC, 0xF1, +0xAD, 0x10, 0xB5, 0x51, 0xA4, 0xF0, 0x83, 0xCD, +0x94, 0x4F, 0x94, 0x6F, 0x83, 0xAD, 0x94, 0x4F, +0x8B, 0xED, 0xAD, 0x11, 0x9C, 0x6E, 0xA4, 0xB0, +0xAC, 0xF0, 0xB5, 0x31, 0xAC, 0xF0, 0xAD, 0x11, +0xA4, 0xAF, 0x8B, 0xEC, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x2D, 0xBD, 0x72, 0xAC, 0xF0, 0x83, 0xCC, +0x8C, 0x2D, 0x9C, 0x6F, 0xAD, 0x11, 0xD6, 0x35, +0xBD, 0x93, 0xAD, 0x11, 0xAD, 0x11, 0xB5, 0x32, +0xA4, 0xD1, 0x9C, 0x90, 0x9C, 0x8F, 0x94, 0x4F, +0x8C, 0x2E, 0x8C, 0x0E, 0x7B, 0xAD, 0x7B, 0xAC, +0x83, 0xCD, 0x83, 0xEE, 0x8B, 0xEE, 0x9C, 0x90, +0x94, 0x70, 0x9C, 0x90, 0x9C, 0xD1, 0x9C, 0xB1, +0x9C, 0x90, 0x9C, 0x90, 0x94, 0x70, 0x94, 0x70, +0x9C, 0xB1, 0xA4, 0xF2, 0xA4, 0xD1, 0x7B, 0xAD, +0x4A, 0x48, 0x39, 0xA6, 0x31, 0xA5, 0x39, 0xC6, +0x42, 0x28, 0x4A, 0x28, 0x5A, 0xCA, 0x6B, 0x2C, +0x73, 0x4C, 0x6B, 0x2B, 0x63, 0x0A, 0x5A, 0xE8, +0x7C, 0x4B, 0x74, 0x49, 0x84, 0xAA, 0x5B, 0x47, +0x63, 0xA8, 0x74, 0x09, 0x9C, 0x8F, 0x9C, 0x4F, +0x94, 0x4F, 0x94, 0x70, 0x94, 0x6F, 0x9C, 0xB0, +0x9C, 0xB1, 0xA4, 0xF2, 0x94, 0x70, 0x94, 0x70, +0xA4, 0xF2, 0xA4, 0xF2, 0xAD, 0x54, 0x9C, 0xD2, +0xA4, 0xF2, 0xE6, 0xD8, 0xC5, 0xD4, 0x9C, 0xB0, +0xBD, 0x94, 0xE6, 0xB8, 0xCD, 0xF5, 0xCD, 0xF5, +0xD6, 0x16, 0xDE, 0x35, 0xBD, 0x73, 0x8B, 0xED, +0xAC, 0xD1, 0xDE, 0x77, 0xC5, 0xD4, 0xC5, 0xB3, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x73, 0xCD, 0xD4, +0x5B, 0x2A, 0x84, 0x2E, 0x9C, 0xD0, 0x8C, 0x6E, +0xA5, 0x11, 0x84, 0x0D, 0x84, 0x0D, 0x8C, 0x4E, +0x9C, 0xAF, 0xCD, 0xF4, 0xA4, 0xCF, 0x94, 0x4D, +0x94, 0x4E, 0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x52, +0xDE, 0x77, 0xE6, 0xB7, 0xE6, 0x97, 0xDE, 0x56, +0xAC, 0xAF, 0xDE, 0x75, 0xDE, 0x55, 0xD5, 0xF3, +0xD5, 0xF4, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0xB2, +0xCD, 0xD3, 0xD6, 0x34, 0xBD, 0x51, 0xD6, 0x14, +0xDE, 0x34, 0xDE, 0x75, 0xDE, 0x54, 0xCD, 0x92, +0xC5, 0x71, 0xCD, 0xB2, 0xDE, 0x35, 0xE6, 0x76, +0xE6, 0x96, 0xDE, 0x55, 0xEE, 0x96, 0xC5, 0x51, +0x9C, 0x4D, 0xA4, 0x8F, 0xAD, 0x11, 0xA4, 0xF1, +0x9C, 0x8F, 0x94, 0x4E, 0x8C, 0x0E, 0x83, 0xED, +0x83, 0xED, 0x83, 0xCD, 0x7B, 0x8C, 0x41, 0xE6, +0x39, 0xC6, 0x31, 0x85, 0x31, 0x85, 0x31, 0x85, +0x4A, 0x48, 0x5A, 0xCA, 0x73, 0xAE, 0x94, 0xB3, +0xBE, 0x18, 0xC6, 0x3A, 0xB5, 0x97, 0xCE, 0x7A, +0x7B, 0xCF, 0x4A, 0x49, 0xA4, 0xF2, 0x9C, 0xB0, +0x9C, 0x8F, 0x9C, 0x6E, 0x8B, 0xEC, 0x7B, 0x4A, +0x7B, 0x8B, 0x8B, 0xEC, 0x83, 0xAB, 0x83, 0xCC, +0x7B, 0x6B, 0x7B, 0x6A, 0x73, 0x09, 0x83, 0x6A, +0x8B, 0xAB, 0x8B, 0xCB, 0x94, 0x0C, 0xA4, 0x8E, +0xBD, 0x30, 0xD5, 0xD3, 0xC5, 0x51, 0xBD, 0x30, +0xC5, 0x50, 0xD5, 0xD2, 0xD5, 0xD4, 0xEF, 0x1B, +0xEF, 0x3C, 0xEF, 0x5D, 0xEF, 0x1B, 0x94, 0x4F, +0xB5, 0x12, 0xBD, 0x31, 0xBD, 0x31, 0xBD, 0x31, +0xB5, 0x10, 0xBD, 0x31, 0xBD, 0x72, 0xBD, 0x52, +0xC5, 0x93, 0xC5, 0x92, 0xAD, 0x10, 0xAC, 0xF0, +0x62, 0xC9, 0x31, 0xA6, 0x42, 0x07, 0x73, 0x8D, +0x83, 0xEF, 0x52, 0x49, 0x29, 0x24, 0x5A, 0x69, +0x83, 0xAE, 0x83, 0x8E, 0x94, 0x51, 0x83, 0xEF, +0x73, 0x6E, 0x6B, 0x4D, 0xA4, 0xF4, 0xD6, 0x79, +0x8C, 0x31, 0x41, 0xE8, 0x5A, 0xCB, 0x8C, 0x31, +0xB5, 0x76, 0xDE, 0xBA, 0xE6, 0xFB, 0xE6, 0xFC, +0xD6, 0x59, 0xF7, 0x5C, 0xDE, 0x37, 0xA4, 0x6F, +0x94, 0x0D, 0xA4, 0xB0, 0x8C, 0x0F, 0x6B, 0x4C, +0x84, 0x10, 0x94, 0x92, 0xC6, 0x18, 0xC5, 0xF7, +0x5A, 0xCA, 0x39, 0xC6, 0x39, 0xE6, 0x39, 0xC6, +0x42, 0x07, 0x39, 0xC6, 0x39, 0xC6, 0x42, 0x07, +0x42, 0x08, 0x42, 0x29, 0x4A, 0x49, 0x5A, 0xCB, +0x63, 0x2D, 0x52, 0x8A, 0x39, 0xE8, 0x31, 0x86, +0x39, 0xE7, 0x5A, 0xCB, 0x84, 0x10, 0xAD, 0x34, +0xB5, 0x53, 0xA4, 0xD1, 0xA5, 0x12, 0xCE, 0x15, +0xDE, 0x97, 0xA4, 0xF0, 0xBD, 0x93, 0xC5, 0xB4, +0xBD, 0x73, 0x9C, 0xB0, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0x73, 0xB5, 0x52, 0xB5, 0x52, 0xAC, 0xF1, +0xBD, 0x94, 0xBD, 0xB4, 0xBD, 0x73, 0xB5, 0x52, +0xAD, 0x32, 0xA4, 0xD0, 0xB5, 0x32, 0xB5, 0x52, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0xB4, 0xBD, 0x94, +0xA4, 0xD0, 0x9C, 0xB0, 0xA4, 0xF1, 0xCD, 0xF4, +0xD6, 0x34, 0xD6, 0x34, 0xD6, 0x14, 0xD6, 0x35, +0xD6, 0x35, 0xC5, 0xD4, 0xB5, 0x73, 0xC5, 0xD5, +0xD6, 0x77, 0xD6, 0x56, 0xCD, 0xD4, 0xBD, 0x93, +0xBD, 0x52, 0xBD, 0x51, 0xC5, 0xB3, 0xB5, 0x53, +0xBD, 0xB5, 0xB5, 0x73, 0x9C, 0xD1, 0x9C, 0x90, +0x83, 0xED, 0xB5, 0x32, 0x83, 0xCC, 0xA4, 0xB0, +0xB5, 0x31, 0xAD, 0x11, 0xAC, 0xF0, 0xAC, 0xF0, +0xA4, 0xB0, 0xA4, 0x8F, 0x8B, 0xEC, 0x8B, 0xEC, +0xA4, 0xAF, 0xB5, 0x31, 0x9C, 0x8F, 0x94, 0x6E, +0x94, 0x4F, 0x9C, 0x6F, 0xA4, 0xB0, 0xBD, 0x72, +0xC5, 0xB3, 0xCE, 0x14, 0xCE, 0x14, 0xC5, 0x93, +0xAD, 0x32, 0x8B, 0xED, 0x94, 0x2E, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xF1, 0xB5, 0x33, +0xC5, 0xD5, 0xBD, 0x94, 0xAD, 0x12, 0xB5, 0x53, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0xB4, 0xC5, 0xB4, 0xC5, 0xD4, +0xBD, 0xD4, 0xC5, 0xF5, 0xC5, 0xD5, 0xCD, 0xF5, +0xBD, 0xB4, 0x62, 0xC9, 0x41, 0xE7, 0x39, 0xE7, +0x39, 0xE6, 0x39, 0xE6, 0x4A, 0x48, 0x5A, 0xAA, +0x73, 0x6C, 0x6B, 0x2C, 0x4A, 0x47, 0x73, 0xEC, +0x7C, 0xAB, 0x74, 0x48, 0x53, 0x05, 0x6B, 0xC9, +0x53, 0x07, 0x7C, 0x0B, 0xBD, 0x73, 0xAC, 0xF2, +0xA4, 0xD2, 0xA4, 0xF2, 0xA4, 0xB1, 0xA4, 0xD1, +0x9C, 0xB1, 0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0x91, +0x9C, 0xD1, 0x9C, 0xB1, 0x9C, 0xB1, 0x8C, 0x2F, +0x94, 0x4F, 0xA5, 0x12, 0x94, 0x50, 0x9C, 0x90, +0xAD, 0x32, 0xCD, 0xD4, 0xCD, 0xB4, 0xCD, 0xB4, +0xC5, 0x73, 0xBD, 0x32, 0xC5, 0x94, 0xC5, 0x94, +0xC5, 0xB4, 0xBD, 0x73, 0xA4, 0x8F, 0x9C, 0x8F, +0x9C, 0x6F, 0x9C, 0x8F, 0xC5, 0x93, 0xD6, 0x36, +0xA5, 0x11, 0xB5, 0x72, 0xA4, 0xCF, 0x9C, 0x8E, +0x8C, 0x4D, 0x84, 0x0D, 0x83, 0xED, 0x94, 0x6E, +0x9C, 0x8F, 0xCE, 0x14, 0xAC, 0xF0, 0xAD, 0x10, +0xB5, 0x51, 0xAD, 0x11, 0xAD, 0x11, 0xAC, 0xD0, +0xD6, 0x35, 0xD6, 0x15, 0xDE, 0x55, 0xE6, 0x75, +0xAC, 0xAE, 0xD6, 0x13, 0xD6, 0x34, 0xCD, 0xD3, +0xC5, 0x71, 0xCD, 0xD2, 0xD6, 0x13, 0xDE, 0x76, +0xD5, 0xF4, 0xCD, 0xB3, 0xC5, 0xB3, 0xD6, 0x35, +0xDE, 0x34, 0xE6, 0x75, 0xD5, 0xF3, 0xC5, 0x51, +0xBD, 0x10, 0xC5, 0x51, 0xCD, 0xD3, 0xD6, 0x14, +0xDE, 0x35, 0xE6, 0x55, 0xE6, 0x55, 0xC5, 0x31, +0x9C, 0x4D, 0x9C, 0x6E, 0xB5, 0x52, 0xAD, 0x32, +0xAD, 0x11, 0xB5, 0x31, 0xB5, 0x52, 0xBD, 0x92, +0xCD, 0xF3, 0xCD, 0xF3, 0xD6, 0x14, 0x8C, 0x0D, +0x42, 0x06, 0x31, 0xA5, 0x31, 0x85, 0x31, 0x85, +0x39, 0xE7, 0x42, 0x28, 0x5A, 0xCA, 0x63, 0x0C, +0x9C, 0xF3, 0xAD, 0x96, 0xAD, 0x76, 0xB5, 0x97, +0x7B, 0xCF, 0x7B, 0xCF, 0xCE, 0x59, 0xBD, 0xD6, +0x94, 0x70, 0x94, 0x4F, 0x94, 0x4F, 0x83, 0xAC, +0x8C, 0x0D, 0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xD0, +0x94, 0x2E, 0xA4, 0x8F, 0x8C, 0x0D, 0x9C, 0x2E, +0x94, 0x2D, 0x8C, 0x0C, 0x94, 0x4D, 0x8C, 0x0C, +0x8B, 0xEC, 0x9C, 0x4D, 0xA4, 0x8E, 0xB4, 0xCE, +0xC5, 0x50, 0xEE, 0x95, 0xE6, 0x35, 0xBD, 0x95, +0xC5, 0xF8, 0xDE, 0xFB, 0xDE, 0xBB, 0xD6, 0x79, +0xD6, 0x99, 0xB5, 0x74, 0x9C, 0xD1, 0x7B, 0xAC, +0x94, 0x6E, 0xB5, 0x52, 0xBD, 0x72, 0xAD, 0x11, +0xBD, 0x93, 0xC5, 0x93, 0xAC, 0xEF, 0xBD, 0x51, +0x83, 0xAC, 0x31, 0x65, 0x62, 0xEB, 0x6B, 0x2C, +0x63, 0x0B, 0x52, 0x69, 0x29, 0x45, 0x31, 0x45, +0x52, 0x48, 0x6B, 0x0B, 0x83, 0xAE, 0x7B, 0x8E, +0x63, 0x0B, 0x39, 0xC7, 0x83, 0xCF, 0xBD, 0x96, +0xBD, 0xB7, 0xAD, 0x55, 0x73, 0x8E, 0x6B, 0x4D, +0xAD, 0x35, 0xE7, 0x1C, 0xE7, 0x1C, 0xE6, 0xFC, +0xEF, 0x1C, 0xDE, 0x7A, 0xC5, 0xD6, 0xA4, 0x91, +0xB5, 0x12, 0x94, 0x2E, 0x94, 0x0E, 0x8B, 0xED, +0x7B, 0x6C, 0x62, 0xCA, 0x73, 0x6E, 0x8C, 0x30, +0x5A, 0xAA, 0x4A, 0x48, 0x42, 0x28, 0x42, 0x07, +0x39, 0xE7, 0x39, 0xE7, 0x42, 0x07, 0x4A, 0x49, +0x4A, 0x69, 0x52, 0x8A, 0x4A, 0x6A, 0x52, 0x8A, +0x52, 0x8A, 0x4A, 0x69, 0x39, 0xE8, 0x29, 0x45, +0x39, 0xC7, 0x52, 0x89, 0x5A, 0xAA, 0x52, 0x69, +0x8C, 0x30, 0xAD, 0x32, 0xC5, 0xD5, 0xDE, 0x77, +0xDE, 0x97, 0xAC, 0xF0, 0xC5, 0xD4, 0xD6, 0x35, +0xBD, 0x72, 0xB5, 0x52, 0xB5, 0x52, 0xB5, 0x32, +0xAD, 0x11, 0xA4, 0xD0, 0xB5, 0x52, 0xAC, 0xF1, +0xBD, 0x73, 0xC5, 0xB4, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x32, 0xAD, 0x11, 0xB5, 0x31, 0xB5, 0x52, +0xB5, 0x73, 0xBD, 0x93, 0xCE, 0x36, 0xBD, 0xB4, +0xA4, 0xB0, 0xA4, 0xD1, 0xBD, 0x73, 0xD6, 0x35, +0xDE, 0x54, 0xD6, 0x14, 0xD5, 0xF3, 0xD6, 0x14, +0xCD, 0xF4, 0xCE, 0x14, 0xAD, 0x32, 0xAD, 0x33, +0xCE, 0x15, 0xD6, 0x35, 0xBD, 0x72, 0xAC, 0xF0, +0xBD, 0x72, 0xB5, 0x10, 0xB5, 0x72, 0x94, 0x2E, +0xAD, 0x12, 0xA4, 0xF2, 0x9C, 0xD1, 0x94, 0x70, +0x8C, 0x0E, 0xB5, 0x32, 0x8C, 0x0D, 0xB5, 0x32, +0xB5, 0x31, 0xC5, 0x93, 0xBD, 0x93, 0xC5, 0xD4, +0xC5, 0xB3, 0xA4, 0xD0, 0x94, 0x2D, 0x94, 0x2D, +0x94, 0x4E, 0x9C, 0x8F, 0xA4, 0xB0, 0x8C, 0x0D, +0x8C, 0x0D, 0x8B, 0xED, 0x9C, 0x6F, 0xA4, 0xF0, +0xAD, 0x10, 0xBD, 0xB3, 0xC5, 0xD3, 0xC5, 0xB3, +0xAD, 0x11, 0xAC, 0xF2, 0xA4, 0xF1, 0xCE, 0x15, +0xDE, 0x97, 0xDE, 0x77, 0xD6, 0x56, 0xC5, 0xF5, +0xC5, 0xF5, 0xC5, 0xD5, 0xCE, 0x16, 0xD6, 0x56, +0xDE, 0x97, 0xD6, 0x56, 0xCE, 0x35, 0xD6, 0x36, +0xCE, 0x15, 0xBD, 0x94, 0xCE, 0x15, 0xDE, 0x76, +0xDE, 0x97, 0xE6, 0xD7, 0xEE, 0xF7, 0xF6, 0xF7, +0xF7, 0x38, 0xBD, 0xB3, 0x6B, 0x4B, 0x41, 0xE6, +0x31, 0x85, 0x31, 0xA5, 0x39, 0xC6, 0x42, 0x27, +0x4A, 0x28, 0x31, 0xA6, 0x4A, 0x48, 0x6B, 0xAA, +0x7C, 0xAB, 0x7C, 0xCB, 0x5B, 0x67, 0x3A, 0x04, +0x84, 0x4C, 0xA5, 0x0F, 0x8C, 0x0E, 0xA4, 0xB1, +0xA4, 0xB1, 0xAD, 0x12, 0xBD, 0x74, 0xAD, 0x12, +0xBD, 0xB4, 0xBD, 0xB4, 0xB5, 0x33, 0xBD, 0xB4, +0xBD, 0x93, 0xBD, 0xB4, 0xB5, 0x52, 0xB5, 0x53, +0xC5, 0xB4, 0xBD, 0x53, 0xBD, 0x74, 0xB5, 0x53, +0xB5, 0x32, 0xC5, 0x94, 0xBD, 0x53, 0xBD, 0x32, +0xBD, 0x73, 0xBD, 0x53, 0xB5, 0x53, 0xB5, 0x32, +0xAD, 0x32, 0xAC, 0xF1, 0xAD, 0x12, 0xAC, 0xF2, +0xA4, 0xF2, 0xA4, 0xF2, 0xA4, 0xB1, 0x9C, 0x90, +0x7B, 0xCC, 0x9C, 0xD0, 0xA4, 0xAF, 0x9C, 0x6E, +0x7B, 0xAB, 0x7B, 0x8B, 0x83, 0xEC, 0x8C, 0x2E, +0x94, 0x4E, 0xAC, 0xF0, 0xA4, 0xAE, 0x8C, 0x0C, +0x83, 0xAB, 0x83, 0xCB, 0x8C, 0x0C, 0xB5, 0x31, +0xDE, 0x76, 0xDE, 0x56, 0xE6, 0xB7, 0xEE, 0xB7, +0xB4, 0xCF, 0xDE, 0x34, 0xD6, 0x14, 0xCD, 0xB2, +0xCD, 0xD3, 0xD5, 0xF3, 0xD6, 0x14, 0xDE, 0x76, +0xD5, 0xF4, 0xDE, 0x56, 0xDE, 0x76, 0xDE, 0x75, +0xDE, 0x55, 0xDE, 0x34, 0xC5, 0x71, 0xCD, 0x92, +0xCD, 0x72, 0xC5, 0x51, 0xCD, 0xB2, 0xCD, 0xD3, +0xD5, 0xD3, 0xC5, 0x51, 0xBC, 0xEF, 0xB4, 0x8E, +0x9C, 0x4D, 0xAD, 0x11, 0xC5, 0xB3, 0xC5, 0xB3, +0xC5, 0xB3, 0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xB3, +0xD5, 0xF3, 0xCD, 0xD3, 0xCD, 0xD2, 0xD6, 0x14, +0xCD, 0xF4, 0x9C, 0x6E, 0x6B, 0x2A, 0x41, 0xE6, +0x39, 0xE6, 0x52, 0xA9, 0x52, 0x8A, 0x52, 0x8A, +0x63, 0x4C, 0x7B, 0xCF, 0x7B, 0xEF, 0x8C, 0x51, +0x8C, 0x51, 0xAD, 0x76, 0xC6, 0x18, 0xE7, 0x3C, +0xC6, 0x18, 0xA4, 0xF3, 0x9C, 0x70, 0x7B, 0x8C, +0x83, 0xEC, 0xBD, 0xB3, 0xBD, 0xB4, 0xAD, 0x32, +0x94, 0x4E, 0x94, 0x4E, 0x8B, 0xED, 0x9C, 0x8F, +0x9C, 0x8F, 0xA4, 0xAF, 0xA4, 0xD0, 0x9C, 0x6E, +0x8B, 0xED, 0x94, 0x0D, 0xA4, 0x6E, 0xB4, 0xEF, +0xB4, 0xCE, 0xCD, 0x91, 0xDE, 0x14, 0xAC, 0xB0, +0x84, 0x10, 0xC6, 0x38, 0xB5, 0x76, 0xAD, 0x55, +0xF7, 0x7D, 0xDE, 0xBA, 0xB5, 0x54, 0x8C, 0x50, +0x7B, 0xCD, 0x8C, 0x4F, 0x84, 0x0E, 0x84, 0x0E, +0xB5, 0x93, 0x9C, 0x8F, 0xA4, 0xAE, 0xA4, 0xAF, +0x94, 0x2E, 0x5A, 0x89, 0x5A, 0xEB, 0x5A, 0xAA, +0x5A, 0xCA, 0x4A, 0x28, 0x52, 0x8A, 0x52, 0x48, +0x52, 0x28, 0x41, 0xE7, 0x62, 0xEA, 0x52, 0x89, +0x52, 0x69, 0x7B, 0x6D, 0x73, 0x6D, 0x9C, 0x72, +0xBD, 0x96, 0xA4, 0xF3, 0xAD, 0x35, 0xA5, 0x14, +0xC6, 0x38, 0xE6, 0xFC, 0xC5, 0xD7, 0xC5, 0xF8, +0xD6, 0x79, 0xDE, 0xBA, 0x9C, 0xB2, 0x7B, 0x4D, +0xB5, 0x13, 0xAC, 0xD1, 0xAC, 0xF0, 0xB5, 0x31, +0xB5, 0x31, 0xAD, 0x11, 0x8B, 0xEE, 0x62, 0xCA, +0x4A, 0x48, 0x63, 0x0B, 0x4A, 0x68, 0x42, 0x48, +0x42, 0x07, 0x42, 0x48, 0x42, 0x28, 0x52, 0x89, +0x52, 0x8A, 0x52, 0xAA, 0x52, 0x8A, 0x63, 0x0C, +0x5A, 0xCB, 0x52, 0x8A, 0x42, 0x08, 0x31, 0x86, +0x29, 0x65, 0x39, 0xC6, 0x39, 0xE7, 0x83, 0xEF, +0x9C, 0x90, 0xAC, 0xF1, 0xCE, 0x16, 0xD6, 0x56, +0xCE, 0x15, 0xAC, 0xF0, 0xC5, 0xB4, 0xD6, 0x35, +0xCD, 0xF4, 0xC5, 0xF4, 0xC5, 0xB4, 0xCD, 0xF5, +0xBD, 0xB3, 0xBD, 0x72, 0xC5, 0xD4, 0xC5, 0xB3, +0xCE, 0x15, 0xD6, 0x56, 0xCE, 0x35, 0xC5, 0xD4, +0xBD, 0xB3, 0xBD, 0x93, 0xC5, 0xB3, 0xBD, 0x93, +0xC5, 0xB4, 0xC5, 0xD4, 0xC5, 0xF4, 0xBD, 0xB4, +0xA4, 0xD0, 0xAD, 0x32, 0xC5, 0xF4, 0xDE, 0x55, +0xDE, 0x75, 0xDE, 0x14, 0xDE, 0x14, 0xD6, 0x14, +0xCD, 0xD3, 0xCD, 0xF4, 0xB5, 0x52, 0xB5, 0x73, +0xD6, 0x36, 0xD6, 0x35, 0xAC, 0xD0, 0xAC, 0xCF, +0xAC, 0xF0, 0xA4, 0xCF, 0xB5, 0x51, 0x8C, 0x0E, +0x94, 0x4F, 0x94, 0x6F, 0x8C, 0x4F, 0x8C, 0x2E, +0x94, 0x70, 0xB5, 0x53, 0x8B, 0xED, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, +0xC5, 0xB3, 0x9C, 0x8F, 0xBD, 0x72, 0xA4, 0xF0, +0xA4, 0xAF, 0x8C, 0x0D, 0x94, 0x4E, 0xA4, 0xB0, +0xAD, 0x11, 0x8C, 0x0D, 0x9C, 0x8F, 0x9C, 0xAF, +0x94, 0x4E, 0x94, 0x4E, 0x94, 0x6E, 0xA4, 0xCF, +0xA4, 0xD0, 0xAD, 0x33, 0xB5, 0x73, 0xD6, 0x56, +0xDE, 0x96, 0xDE, 0xB7, 0xDE, 0x97, 0xD6, 0x77, +0xD6, 0x77, 0xD6, 0x77, 0xDE, 0x77, 0xE6, 0xB7, +0xDE, 0xB7, 0xDE, 0x97, 0xDE, 0x96, 0xDE, 0x96, +0xDE, 0x96, 0xD6, 0x56, 0xD6, 0x56, 0xE6, 0xB7, +0xE6, 0xD7, 0xE6, 0xD6, 0xE6, 0xB6, 0xEE, 0xD6, +0xEE, 0xF7, 0xCE, 0x14, 0xAD, 0x52, 0x84, 0x0E, +0x31, 0xA5, 0x31, 0xA6, 0x39, 0xE6, 0x31, 0xA5, +0x39, 0xC6, 0x42, 0x28, 0x4A, 0x48, 0x63, 0x4A, +0x53, 0x27, 0x74, 0x8A, 0x6C, 0x49, 0x5B, 0x48, +0x4A, 0x86, 0x8C, 0x6C, 0x73, 0x4A, 0x6B, 0x0B, +0xA4, 0xD2, 0xA4, 0xB1, 0xB5, 0x53, 0xA4, 0xD1, +0xBD, 0x93, 0xDE, 0xB7, 0xA5, 0x31, 0xA5, 0x50, +0x8C, 0xCD, 0x94, 0xED, 0xA5, 0x4F, 0xB5, 0x70, +0xCE, 0x14, 0xC5, 0xB3, 0xBD, 0x73, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xAD, 0x11, 0xB5, 0x12, +0xB5, 0x12, 0xA4, 0xB0, 0x94, 0x2E, 0xAC, 0xF1, +0xB5, 0x12, 0xAC, 0xB0, 0xAC, 0xF1, 0xB5, 0x12, +0xAC, 0xF2, 0xAC, 0xF2, 0xAC, 0xF2, 0xB5, 0x33, +0x8C, 0xB1, 0x94, 0xD1, 0x8C, 0x4E, 0x8C, 0x0C, +0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, 0x83, 0xCB, +0x83, 0xAB, 0x83, 0xAB, 0x83, 0xAB, 0x83, 0x8B, +0x7B, 0x6A, 0x7B, 0x6A, 0x83, 0xAB, 0x8B, 0xEB, +0x9C, 0x4D, 0x9C, 0x6E, 0xA4, 0xAF, 0xA4, 0x8E, +0x9C, 0x4D, 0xC5, 0x71, 0xBD, 0x30, 0xB5, 0x10, +0xAC, 0xEF, 0xAC, 0xEF, 0xAC, 0xAE, 0xBD, 0x31, +0xC5, 0x92, 0xBD, 0x51, 0xBD, 0x30, 0xC5, 0x72, +0xD5, 0xD3, 0xDE, 0x35, 0xDE, 0x14, 0xD5, 0xD3, +0xE6, 0x55, 0xE6, 0x75, 0xEE, 0x76, 0xE6, 0x75, +0xE6, 0x55, 0xD5, 0xB3, 0xE6, 0x14, 0xC5, 0x51, +0xA4, 0x8E, 0xC5, 0xD3, 0xC5, 0xD3, 0xC5, 0x93, +0xC5, 0xB3, 0xC5, 0xB3, 0xB5, 0x10, 0xBD, 0x30, +0xCD, 0xB2, 0xCD, 0xB2, 0xD5, 0xF3, 0xDE, 0x14, +0xE6, 0x55, 0xD6, 0x14, 0xD5, 0xF4, 0xAC, 0xF0, +0x6B, 0x09, 0x52, 0x89, 0x39, 0xE7, 0x39, 0xE7, +0x42, 0x27, 0x52, 0xAA, 0x63, 0x2C, 0x6B, 0x6D, +0x7B, 0xAF, 0xAD, 0x55, 0xBD, 0xF8, 0xCE, 0x7A, +0xD6, 0xBA, 0xDE, 0xDB, 0xB5, 0x75, 0x7B, 0xAD, +0x7B, 0x8C, 0xAD, 0x32, 0xBD, 0xB4, 0xAC, 0xF1, +0x8B, 0xED, 0x83, 0xCC, 0x8C, 0x0D, 0x9C, 0x8F, +0xA4, 0xAF, 0x9C, 0x8F, 0xA4, 0xD0, 0xB5, 0x12, +0xB5, 0x32, 0xB5, 0x11, 0xA4, 0x8E, 0xB4, 0xEF, +0xBD, 0x0F, 0xD5, 0xF3, 0xD5, 0xF3, 0xCD, 0xB3, +0x73, 0x4C, 0x8C, 0x51, 0x83, 0xF0, 0x9C, 0xB3, +0xDE, 0xBB, 0xD6, 0xBA, 0xA5, 0x13, 0xA5, 0x13, +0x8C, 0x70, 0x84, 0x2E, 0x94, 0x90, 0xAD, 0x53, +0xBD, 0xD4, 0xAD, 0x10, 0xAC, 0xCF, 0xB5, 0x52, +0xB5, 0x52, 0x9C, 0x90, 0x42, 0x07, 0x5A, 0xAA, +0x5A, 0xAA, 0x39, 0xC6, 0x52, 0x69, 0x7B, 0x8D, +0x83, 0xAE, 0x39, 0xA6, 0x29, 0x65, 0x31, 0x85, +0x62, 0xEB, 0x83, 0xEF, 0x94, 0x30, 0x94, 0x51, +0x8C, 0x0F, 0x73, 0x6E, 0x9C, 0xB3, 0xC6, 0x17, +0xC5, 0xF8, 0xB5, 0x96, 0xC5, 0xD7, 0xE6, 0xFC, +0xEF, 0x3C, 0xFF, 0xBE, 0xF7, 0x5C, 0xAC, 0xD3, +0x94, 0x0F, 0x83, 0xAD, 0x94, 0x2E, 0x94, 0x4E, +0x9C, 0x6F, 0x94, 0x4E, 0xA4, 0xAF, 0xB5, 0x52, +0x5A, 0xAA, 0x7B, 0xEE, 0x52, 0xAA, 0x4A, 0x68, +0x42, 0x27, 0x4A, 0x89, 0x4A, 0x89, 0x42, 0x48, +0x42, 0x28, 0x4A, 0x48, 0x42, 0x28, 0x4A, 0x49, +0x4A, 0x69, 0x52, 0x8A, 0x42, 0x29, 0x42, 0x08, +0x42, 0x08, 0x31, 0x86, 0x63, 0x0C, 0x9C, 0x91, +0x9C, 0x6F, 0x9C, 0x6F, 0x94, 0x2E, 0x8C, 0x0E, +0x9C, 0x4F, 0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, +0x9C, 0x4E, 0x94, 0x4E, 0x8B, 0xED, 0x8C, 0x0E, +0x94, 0x2E, 0x8C, 0x0E, 0x94, 0x4E, 0xA4, 0xD1, +0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, +0xBD, 0x73, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x15, +0xD6, 0x15, 0xCD, 0xF5, 0xC5, 0xD4, 0xC5, 0xD4, +0x9C, 0xB0, 0xA4, 0xD0, 0xB5, 0x52, 0xC5, 0xD3, +0xD6, 0x34, 0xDE, 0x54, 0xDE, 0x55, 0xDE, 0x54, +0xDE, 0x14, 0xCD, 0xD3, 0xAD, 0x11, 0xAD, 0x32, +0xD6, 0x35, 0xD6, 0x14, 0xB5, 0x10, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x10, 0xAD, 0x11, 0x8C, 0x0D, +0x83, 0xEE, 0x83, 0xEE, 0x83, 0xEE, 0x7B, 0xAD, +0xA4, 0xF1, 0xB5, 0x32, 0x8C, 0x0D, 0xB5, 0x52, +0xB5, 0x72, 0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, +0xCD, 0xF4, 0xBD, 0x93, 0xAD, 0x11, 0xC5, 0xD4, +0xBD, 0x93, 0xA4, 0xD0, 0xA4, 0xF1, 0xBD, 0xB3, +0xBD, 0x93, 0xB5, 0x52, 0xAD, 0x32, 0x9C, 0x8F, +0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x2D, 0x94, 0x2E, +0x9C, 0xB0, 0xB5, 0x53, 0xB5, 0x33, 0xCE, 0x15, +0xDE, 0x76, 0xDE, 0x96, 0xDE, 0x97, 0xDE, 0x97, +0xDE, 0x97, 0xDE, 0x97, 0xE6, 0xB7, 0xDE, 0x76, +0xE6, 0xD7, 0xDE, 0xB6, 0xDE, 0x96, 0xDE, 0x96, +0xDE, 0x76, 0xDE, 0xB6, 0xDE, 0xB7, 0xDE, 0xB6, +0xDE, 0x96, 0xE6, 0xB6, 0xE6, 0x96, 0xE6, 0x95, +0xE6, 0xB6, 0xC5, 0xD4, 0xAD, 0x12, 0xC5, 0xD4, +0xA4, 0xF1, 0x39, 0xA5, 0x39, 0xA6, 0x39, 0xC6, +0x39, 0xC6, 0x31, 0x85, 0x31, 0xA5, 0x52, 0x88, +0x4A, 0x86, 0x8D, 0x0E, 0x7C, 0xCB, 0x74, 0x8B, +0x7C, 0x8C, 0x7C, 0x6C, 0x84, 0x4C, 0x5A, 0xE9, +0x52, 0x89, 0x8C, 0x0E, 0xAC, 0xF2, 0xB5, 0x53, +0xE6, 0xF8, 0xE6, 0xD7, 0xA5, 0x90, 0x8D, 0x4D, +0x7C, 0xAA, 0x6C, 0x48, 0x74, 0x68, 0x95, 0x0B, +0xAD, 0xAE, 0xAD, 0x30, 0xB5, 0x72, 0xC5, 0xB3, +0xBD, 0x52, 0xA4, 0xB0, 0xBD, 0x52, 0xC5, 0x93, +0xBD, 0x52, 0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0x8F, +0x94, 0x0D, 0x8B, 0xAC, 0x83, 0x8B, 0xB4, 0xF1, +0xC5, 0x73, 0xC5, 0x73, 0xC5, 0xB4, 0xAC, 0xF2, +0x8C, 0xB1, 0x73, 0xCE, 0x5B, 0x09, 0x83, 0xEC, +0x94, 0x4E, 0x94, 0x2D, 0x94, 0x2D, 0x9C, 0x6E, +0x9C, 0x6E, 0x9C, 0x4E, 0x9C, 0x8F, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0x8E, 0xA4, 0x8E, +0xA4, 0xAE, 0xAC, 0xCF, 0xA4, 0x8E, 0xAC, 0xAF, +0xAC, 0xAE, 0xAC, 0xAE, 0xA4, 0x8E, 0xA4, 0x8E, +0xA4, 0x8E, 0xA4, 0x6E, 0x9C, 0x6D, 0x9C, 0x4D, +0x9C, 0x6D, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0x8E, +0x9C, 0x2D, 0x9C, 0x4D, 0xAC, 0x8E, 0xAC, 0x8E, +0xA4, 0x4D, 0xA4, 0x6E, 0xBD, 0x10, 0xC5, 0x51, +0xCD, 0x92, 0xD5, 0xB3, 0xDD, 0xF4, 0xBD, 0x10, +0xA4, 0x8D, 0xC5, 0x92, 0xC5, 0x92, 0xCD, 0xD3, +0xCD, 0xF4, 0xCD, 0xB3, 0xAC, 0xAE, 0xBD, 0x50, +0xD5, 0xF3, 0xD5, 0xD3, 0xDE, 0x14, 0xDE, 0x14, +0xDE, 0x13, 0xD5, 0xF3, 0xD6, 0x13, 0xDE, 0x34, +0xD5, 0xF3, 0x9C, 0x6E, 0x4A, 0x27, 0x31, 0xA5, +0x39, 0xC6, 0x42, 0x28, 0x4A, 0x48, 0x52, 0x8A, +0x63, 0x0C, 0x84, 0x30, 0x9C, 0xF4, 0xAD, 0x76, +0xC6, 0x19, 0xD6, 0x9B, 0xE7, 0x1C, 0xDE, 0xDB, +0xC6, 0x18, 0xAD, 0x13, 0xB5, 0x73, 0x9C, 0xB0, +0x7B, 0x8C, 0x7B, 0x8C, 0x8C, 0x0E, 0x9C, 0x4E, +0xA4, 0xAF, 0x9C, 0x6E, 0x9C, 0x8F, 0xBD, 0x73, +0xC5, 0x93, 0xC5, 0xB3, 0xB4, 0xF0, 0xAC, 0xCE, +0xAC, 0xCE, 0xD5, 0xF3, 0xDD, 0xF3, 0xE6, 0x55, +0xA4, 0x90, 0x5A, 0x8A, 0x9C, 0xD3, 0xCE, 0x59, +0xEF, 0x3D, 0xE7, 0x3D, 0xCE, 0x59, 0xB5, 0x95, +0xB5, 0x74, 0x9C, 0xF2, 0x94, 0xB1, 0xAD, 0x33, +0xAD, 0x52, 0xA4, 0x8E, 0xAC, 0xCF, 0xBD, 0x72, +0xB5, 0x31, 0xBD, 0x72, 0x8C, 0x0E, 0x4A, 0x28, +0x4A, 0x28, 0x29, 0x44, 0x31, 0x65, 0x52, 0x69, +0x83, 0xAD, 0x52, 0x69, 0x52, 0x69, 0x31, 0x65, +0x39, 0xC6, 0x4A, 0x28, 0x73, 0x6C, 0x73, 0x6D, +0x52, 0x69, 0x73, 0x6E, 0x84, 0x30, 0x9C, 0xB2, +0xB5, 0x76, 0xCE, 0x59, 0xE6, 0xDB, 0xE6, 0xDB, +0xE6, 0xFB, 0xEF, 0x3C, 0xE6, 0xFB, 0xD6, 0x18, +0xA4, 0xB3, 0xCE, 0x17, 0xB5, 0x54, 0x94, 0x50, +0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xD0, 0xB5, 0x53, +0x5A, 0xAA, 0x8C, 0x50, 0x63, 0x0B, 0x4A, 0x69, +0x42, 0x07, 0x42, 0x07, 0x42, 0x27, 0x39, 0xE6, +0x42, 0x07, 0x4A, 0x48, 0x39, 0xE7, 0x39, 0xC7, +0x42, 0x28, 0x42, 0x28, 0x42, 0x08, 0x39, 0xC7, +0x39, 0xC7, 0x73, 0x6E, 0xBD, 0xB6, 0xAD, 0x33, +0xB5, 0x54, 0xBD, 0x94, 0xB5, 0x73, 0xAD, 0x12, +0xAD, 0x12, 0xB5, 0x52, 0xA4, 0xD0, 0x9C, 0x8F, +0x94, 0x2E, 0x9C, 0x90, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x8F, 0x9C, 0x6F, +0x9C, 0x6F, 0x9C, 0x6F, 0x9C, 0x8F, 0x9C, 0x8F, +0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x8F, 0x9C, 0x8F, +0xA4, 0x90, 0x9C, 0x4F, 0x8C, 0x0E, 0x9C, 0x8F, +0xA4, 0xAF, 0xA4, 0xD0, 0x9C, 0x6F, 0x8C, 0x0D, +0x8C, 0x0D, 0x9C, 0x4E, 0x9C, 0x4D, 0x9C, 0x4D, +0xAC, 0xAF, 0xAC, 0xCF, 0xA4, 0xD0, 0xAC, 0xF1, +0xB5, 0x11, 0xB5, 0x31, 0xA4, 0x8E, 0x9C, 0x6E, +0xAC, 0xCF, 0xA4, 0x8E, 0x8B, 0xEC, 0x7B, 0x6B, +0x83, 0xCD, 0x7B, 0x8C, 0x6B, 0x4B, 0x6B, 0x2B, +0xAC, 0xF1, 0xB5, 0x32, 0x83, 0xED, 0x8C, 0x0E, +0x94, 0x4E, 0xAD, 0x11, 0x9C, 0xB0, 0x9C, 0xAF, +0xAD, 0x11, 0x83, 0xCC, 0x9C, 0x6F, 0xAC, 0xF1, +0xAD, 0x31, 0xA4, 0xB0, 0xB5, 0x52, 0xC5, 0xD4, +0xB5, 0x73, 0xB5, 0x73, 0xC5, 0xB4, 0x9C, 0xB0, +0x8C, 0x2E, 0x94, 0x6F, 0x83, 0xED, 0x83, 0xED, +0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x12, 0xBD, 0x72, +0xDE, 0x55, 0xD6, 0x55, 0xDE, 0x76, 0xDE, 0x96, +0xDE, 0x96, 0xDE, 0x97, 0xE6, 0x97, 0xE6, 0xB6, +0xE6, 0xD7, 0xE6, 0xB6, 0xE6, 0xB6, 0xDE, 0x75, +0xD6, 0x34, 0xDE, 0x76, 0xDE, 0xB6, 0xD6, 0x75, +0xD6, 0x35, 0xDE, 0x96, 0xE6, 0x96, 0xE6, 0x95, +0xE6, 0x96, 0xC5, 0xD4, 0xAC, 0xF1, 0xD6, 0x36, +0xDE, 0xB7, 0xAD, 0x32, 0x4A, 0x27, 0x39, 0xA6, +0x31, 0x85, 0x31, 0x65, 0x29, 0x44, 0x31, 0xA5, +0x73, 0xEC, 0xA5, 0xB1, 0x85, 0x2D, 0x84, 0xED, +0x85, 0x0D, 0x84, 0xED, 0x6C, 0x29, 0x94, 0xEE, +0x6B, 0x6B, 0x6A, 0xEA, 0x8B, 0xEE, 0xAC, 0xF1, +0xCE, 0x34, 0xD6, 0x95, 0x84, 0xAC, 0x8D, 0x2D, +0x95, 0x6D, 0x6C, 0x27, 0x6C, 0x47, 0x7C, 0xC9, +0x8D, 0x2B, 0x84, 0xAC, 0x9D, 0x0F, 0xC5, 0xD3, +0xCD, 0xB3, 0xC5, 0x73, 0xC5, 0x93, 0xB5, 0x11, +0x94, 0x0E, 0xA4, 0x6F, 0xA4, 0x6F, 0x9C, 0x2E, +0x8B, 0xAC, 0x83, 0x8C, 0x94, 0x0E, 0xBD, 0x32, +0xD5, 0xF5, 0xD5, 0xD4, 0x9C, 0x4F, 0x94, 0x50, +0x7B, 0xEF, 0x39, 0xE7, 0x42, 0x28, 0x4A, 0x68, +0x62, 0xEA, 0x6B, 0x2A, 0x83, 0xED, 0x94, 0x4E, +0x9C, 0x8F, 0x94, 0x4E, 0xA4, 0xD0, 0x94, 0x4E, +0x8C, 0x0D, 0x94, 0x2D, 0x9C, 0x6E, 0xA4, 0xAE, +0xD6, 0x14, 0xC5, 0xB2, 0x94, 0x2D, 0x9C, 0x6E, +0x8B, 0xEC, 0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, +0xAC, 0xAF, 0xAC, 0xCF, 0xB4, 0xF0, 0xB5, 0x10, +0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, 0xB4, 0xEF, +0xB4, 0xEF, 0xB4, 0xEF, 0xA4, 0x8E, 0xA4, 0x8E, +0xA4, 0x8E, 0xAC, 0xCF, 0xAC, 0xCF, 0xAC, 0xAE, +0xAC, 0xAE, 0xAC, 0xAE, 0xB4, 0xCE, 0xB4, 0xEF, +0xB4, 0xEF, 0xAC, 0xCE, 0xAC, 0x8D, 0xA4, 0x8D, +0xA4, 0x6D, 0xA4, 0x6D, 0xA4, 0x4C, 0xA4, 0x6D, +0xAC, 0x8E, 0xAC, 0x8E, 0xAC, 0xCE, 0xB4, 0xEF, +0xB4, 0xEF, 0xBD, 0x30, 0xC5, 0x50, 0xCD, 0x71, +0xCD, 0x92, 0xCD, 0x92, 0xB4, 0xF0, 0x7B, 0x8B, +0x41, 0xE6, 0x39, 0xC6, 0x42, 0x28, 0x42, 0x07, +0x4A, 0x48, 0x63, 0x2C, 0x7B, 0xF0, 0x94, 0xB3, +0xAD, 0x56, 0xBD, 0xD8, 0xC6, 0x39, 0xDE, 0xDC, +0xF7, 0x7E, 0xEF, 0x3C, 0xBD, 0xB6, 0xA4, 0xB1, +0x73, 0x2B, 0x73, 0x4B, 0x8B, 0xED, 0x94, 0x2E, +0xA4, 0xD0, 0x9C, 0x8F, 0xA4, 0xB0, 0xC5, 0xD4, +0xD6, 0x14, 0xD6, 0x14, 0xC5, 0x71, 0xB4, 0xCF, +0xAC, 0xAE, 0xD5, 0xD2, 0xE6, 0x34, 0xDD, 0xF3, +0xCD, 0xB3, 0x5A, 0xCA, 0xA5, 0x14, 0xDE, 0xBB, +0xE6, 0xFC, 0xBD, 0xD8, 0xDE, 0xBB, 0xCE, 0x59, +0xB5, 0x75, 0xAD, 0x53, 0xA5, 0x33, 0xB5, 0x73, +0xB5, 0x73, 0xA4, 0x8E, 0xAC, 0xCF, 0xC5, 0xB3, +0xB5, 0x31, 0xBD, 0x52, 0xBD, 0x93, 0x7B, 0xAD, +0x31, 0x64, 0x21, 0x03, 0x18, 0xC3, 0x39, 0xA6, +0x62, 0xEA, 0x52, 0x69, 0x62, 0xEB, 0x6B, 0x2B, +0x73, 0x2B, 0x5A, 0x89, 0x4A, 0x68, 0x73, 0x6C, +0x83, 0xEF, 0x83, 0xEF, 0x73, 0x6D, 0x7B, 0xCF, +0x94, 0x72, 0x94, 0xB3, 0xBD, 0xD7, 0xD6, 0x7A, +0xDE, 0xBB, 0xCE, 0x39, 0xDE, 0x9A, 0xEE, 0xFC, +0xDE, 0x9A, 0xD6, 0x59, 0xEE, 0xFB, 0xE6, 0xDA, +0xAD, 0x13, 0xA4, 0xB1, 0x9C, 0x70, 0x9C, 0xB0, +0x5A, 0x89, 0x6B, 0x2C, 0x73, 0xAD, 0x52, 0x89, +0x4A, 0x48, 0x39, 0xE7, 0x39, 0xE6, 0x42, 0x28, +0x39, 0xE7, 0x42, 0x28, 0x42, 0x08, 0x42, 0x08, +0x39, 0xE7, 0x39, 0xE7, 0x39, 0xE8, 0x42, 0x07, +0x63, 0x2C, 0xA5, 0x34, 0xBD, 0xD7, 0xA4, 0xF2, +0xB5, 0x33, 0xBD, 0xB4, 0xC5, 0xF5, 0xC5, 0xB4, +0x9C, 0x6F, 0x73, 0x4B, 0x83, 0xAC, 0x8C, 0x0E, +0x8B, 0xED, 0x8B, 0xED, 0x94, 0x4F, 0x8C, 0x2E, +0xA4, 0xB0, 0xA4, 0xD1, 0x94, 0x6F, 0x8C, 0x2E, +0x8C, 0x0E, 0x94, 0x4F, 0xA4, 0xD0, 0xA4, 0xF1, +0xAD, 0x32, 0xBD, 0x93, 0xB5, 0x52, 0xA4, 0xF1, +0xAC, 0xF1, 0xA4, 0xD0, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xB0, 0xAD, 0x11, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xB0, 0xB5, 0x11, 0xB5, 0x32, 0xBD, 0x52, +0xB5, 0x11, 0xB5, 0x11, 0xA4, 0x90, 0xB4, 0xF1, +0xAC, 0xD0, 0xAC, 0xB0, 0xAC, 0xD0, 0xA4, 0x8F, +0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0x8F, 0x9C, 0x8F, +0xA4, 0x90, 0x94, 0x0E, 0x8C, 0x0E, 0x7B, 0xAC, +0x9C, 0x6F, 0xA4, 0xD0, 0x94, 0x4F, 0x8C, 0x0E, +0x8B, 0xED, 0x8B, 0xED, 0x8C, 0x0D, 0x83, 0xCD, +0x83, 0xCD, 0x7B, 0x6B, 0x83, 0xAC, 0x83, 0xCC, +0x83, 0xCC, 0x83, 0xCC, 0x8C, 0x0E, 0x94, 0x4E, +0x8C, 0x2E, 0x8C, 0x2E, 0x9C, 0x8F, 0x8C, 0x0E, +0x83, 0xCC, 0x83, 0xED, 0x83, 0xCD, 0x8C, 0x2E, +0xB5, 0x32, 0xB5, 0x73, 0xBD, 0x93, 0xD6, 0x56, +0xDE, 0x96, 0xE6, 0xD7, 0xE6, 0xD7, 0xE6, 0xD7, +0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0xB6, +0xE6, 0xD7, 0xE6, 0xD6, 0xE6, 0xD6, 0xE6, 0xD7, +0xE6, 0xB6, 0xE6, 0xD7, 0xDE, 0x96, 0xDE, 0x76, +0xDE, 0x75, 0xDE, 0x75, 0xE6, 0xB6, 0xE6, 0xB6, +0xE6, 0xB6, 0xC5, 0xF4, 0xB5, 0x32, 0xDE, 0x76, +0xDE, 0x75, 0xE6, 0xB7, 0xC5, 0xB4, 0x73, 0x4B, +0x39, 0xC6, 0x31, 0x85, 0x31, 0x85, 0x29, 0x64, +0x3A, 0x25, 0x5B, 0xA9, 0x7C, 0xCC, 0x8D, 0x2E, +0x8D, 0x6F, 0x7C, 0xCC, 0x6C, 0x6A, 0x74, 0x2A, +0x94, 0xAE, 0x7B, 0x8B, 0x62, 0xA8, 0x9C, 0xB0, +0x9C, 0xAF, 0xB5, 0x71, 0x9D, 0x0E, 0x84, 0xAA, +0x95, 0x8C, 0x74, 0x89, 0x64, 0x06, 0x6C, 0x68, +0x7C, 0xEA, 0x8D, 0x6E, 0x95, 0x4F, 0xC6, 0x13, +0xDE, 0x35, 0xD5, 0xD4, 0xCD, 0x93, 0xC5, 0x93, +0xC5, 0xB4, 0xCD, 0xB4, 0xD5, 0xD3, 0xDE, 0x15, +0xDE, 0x35, 0xDE, 0x16, 0xE6, 0x56, 0xDE, 0x15, +0xCD, 0x93, 0xDE, 0x57, 0xCD, 0xF7, 0xBD, 0x96, +0x5A, 0xCA, 0x42, 0x07, 0x4A, 0x69, 0x52, 0xA9, +0x6B, 0x2B, 0x73, 0x8C, 0xA4, 0xF0, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x93, 0x8C, 0x2D, +0x8C, 0x2D, 0xA4, 0xF1, 0xAC, 0xF0, 0xA4, 0x8E, +0xDE, 0x55, 0xB5, 0x31, 0x8C, 0x0C, 0x94, 0x4E, +0x8C, 0x0E, 0xC5, 0xB4, 0xC5, 0xB3, 0xBD, 0x52, +0xB5, 0x10, 0x94, 0x0C, 0x9C, 0x4D, 0xC5, 0x92, +0xC5, 0xB3, 0xBD, 0x72, 0xBD, 0x72, 0xAC, 0xD0, +0x8C, 0x0C, 0x9C, 0x8E, 0xAC, 0xF0, 0xAD, 0x10, +0xAC, 0xEF, 0xA4, 0xAE, 0xAC, 0xCE, 0xA4, 0x8D, +0xB5, 0x10, 0xAC, 0xCE, 0xAC, 0xAE, 0xA4, 0x8D, +0xA4, 0x6D, 0xAC, 0xAE, 0xBD, 0x30, 0xB5, 0x0F, +0xAC, 0xCE, 0xAC, 0xCE, 0xAC, 0xCE, 0xAC, 0xAE, +0xB4, 0xEF, 0xB4, 0xEF, 0xB4, 0xEE, 0xB4, 0xCE, +0xB4, 0xEF, 0xBD, 0x0F, 0xBD, 0x0F, 0xBC, 0xEF, +0xB4, 0xEE, 0xAC, 0xAE, 0xA4, 0x8D, 0xAC, 0xAE, +0x9C, 0x4D, 0x6A, 0xE9, 0x39, 0xC6, 0x39, 0xA6, +0x39, 0xE7, 0x42, 0x28, 0x52, 0xCB, 0x73, 0xAF, +0x84, 0x11, 0x9C, 0xD4, 0xB5, 0xD8, 0xCE, 0x7A, +0xD6, 0xBB, 0xDE, 0xDB, 0xE6, 0xDC, 0xD6, 0x59, +0xA4, 0xD2, 0x83, 0xAD, 0x83, 0xAC, 0x8B, 0xED, +0x8B, 0xED, 0x94, 0x2E, 0xA4, 0x8F, 0xCD, 0xF4, +0xC5, 0x93, 0xC5, 0x92, 0xBD, 0x31, 0xB4, 0xEF, +0xAC, 0xCE, 0xE6, 0x54, 0xEE, 0x55, 0xE6, 0x14, +0xBD, 0x11, 0x73, 0x4B, 0x8C, 0x71, 0xC6, 0x18, +0xAD, 0x76, 0xC6, 0x39, 0xEF, 0x5E, 0xDE, 0xFC, +0xBD, 0xF7, 0xBD, 0xB5, 0xC5, 0xD5, 0xCE, 0x56, +0xD6, 0x56, 0xBD, 0x51, 0xAC, 0xF0, 0xCD, 0xD3, +0xC5, 0xB3, 0xC5, 0xB3, 0xCD, 0xB3, 0xBD, 0x72, +0x8C, 0x2E, 0x5A, 0xA9, 0x63, 0x0A, 0x6B, 0x2B, +0x31, 0x65, 0x39, 0xA6, 0x52, 0x69, 0x5A, 0xCA, +0x6B, 0x2B, 0x62, 0xCA, 0x31, 0x65, 0x4A, 0x07, +0x7B, 0xAD, 0xA4, 0xD2, 0x8C, 0x30, 0x73, 0x8E, +0x84, 0x10, 0x9C, 0xB3, 0xB5, 0x96, 0xAD, 0x55, +0xDE, 0xBB, 0xE6, 0xDB, 0xD6, 0x59, 0xCE, 0x18, +0xF7, 0x5D, 0xEE, 0xFB, 0xD6, 0x58, 0xDE, 0x79, +0xF7, 0x3B, 0xC5, 0xB6, 0x73, 0x4D, 0x8C, 0x2F, +0x6B, 0x0B, 0x42, 0x08, 0x73, 0x8C, 0x52, 0xA9, +0x4A, 0x48, 0x42, 0x07, 0x3A, 0x07, 0x4A, 0x69, +0x42, 0x48, 0x31, 0xA6, 0x31, 0xA6, 0x4A, 0x49, +0x5A, 0xCB, 0x52, 0x69, 0x52, 0x6A, 0x63, 0x2C, +0x7B, 0xCF, 0x9C, 0xD3, 0xA5, 0x14, 0xA5, 0x34, +0x8C, 0x50, 0x9C, 0xB1, 0xBD, 0xD4, 0xCE, 0x16, +0xB5, 0x73, 0xA4, 0xD1, 0xAD, 0x32, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF1, 0xC5, 0xF5, 0xBD, 0xB4, +0xA4, 0xD1, 0x94, 0x4F, 0x94, 0x4F, 0x94, 0x90, +0x9C, 0x90, 0x9C, 0xB0, 0x9C, 0xB0, 0xAD, 0x33, +0xBD, 0x94, 0xCE, 0x36, 0xCE, 0x15, 0xC5, 0xF4, +0xC5, 0xF4, 0xB5, 0x73, 0xB5, 0x53, 0xAD, 0x32, +0xAC, 0xF1, 0xAD, 0x11, 0x9C, 0xB0, 0x94, 0x4E, +0x8C, 0x2E, 0x9C, 0x8F, 0x9C, 0x2E, 0x8B, 0xCD, +0x83, 0x8C, 0x94, 0x2E, 0xAC, 0xD0, 0xCD, 0xD4, +0xCD, 0xD4, 0xC5, 0x93, 0xCD, 0xF4, 0xCD, 0xD4, +0xCD, 0xB3, 0xBD, 0x72, 0xB5, 0x10, 0xBD, 0x52, +0xC5, 0x72, 0xBD, 0x52, 0xBD, 0x52, 0xB5, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xD0, 0xB5, 0x11, +0xB5, 0x11, 0xB5, 0x12, 0xB5, 0x32, 0xB5, 0x12, +0xB5, 0x11, 0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xA4, 0xB0, 0x9C, 0x90, +0xA4, 0xB0, 0xAC, 0xF1, 0xA4, 0xD1, 0x9C, 0x6F, +0x8C, 0x0E, 0x83, 0xCD, 0x83, 0xED, 0x94, 0x2E, +0x94, 0x4F, 0xA4, 0xD1, 0x9C, 0x90, 0xBD, 0x93, +0xCE, 0x14, 0xDE, 0x76, 0xDE, 0x76, 0xD6, 0x56, +0xD6, 0x56, 0xDE, 0x76, 0xDE, 0x96, 0xDE, 0x96, +0xDE, 0x96, 0xE6, 0xB6, 0xE6, 0xB6, 0xEE, 0xD6, +0xEE, 0xD7, 0xEE, 0xF8, 0xE6, 0xD7, 0xE6, 0xD7, +0xE6, 0xF7, 0xEE, 0xF7, 0xEE, 0xF7, 0xEE, 0xF7, +0xF7, 0x18, 0xCE, 0x14, 0xC5, 0xB4, 0xEF, 0x18, +0xE6, 0x96, 0xE6, 0xB6, 0xEE, 0xD7, 0xEE, 0xF8, +0xAD, 0x11, 0x39, 0xC6, 0x31, 0x85, 0x31, 0x85, +0x29, 0x64, 0x32, 0x25, 0x4B, 0x27, 0x74, 0x8B, +0x85, 0x0C, 0x74, 0x8A, 0x6C, 0x6A, 0x21, 0xA2, +0x5A, 0xE9, 0x9C, 0xEF, 0xA5, 0x0F, 0x73, 0x8A, +0x62, 0xE9, 0x73, 0x6B, 0x8C, 0x6E, 0x7C, 0x4B, +0x84, 0xCA, 0x74, 0xA9, 0x63, 0xE8, 0x53, 0x67, +0x7C, 0xAB, 0x7C, 0xCC, 0x8D, 0x0E, 0xCE, 0x33, +0xD6, 0x14, 0xCD, 0xB3, 0xCD, 0xB4, 0xCD, 0xD4, +0xD5, 0xF5, 0xCD, 0x93, 0xCD, 0xB3, 0xE6, 0x56, +0xE6, 0x56, 0xD5, 0xF5, 0xAC, 0xF2, 0x9C, 0x50, +0xB5, 0x13, 0xBD, 0x54, 0xB5, 0x34, 0xA4, 0xB2, +0x39, 0xE7, 0x4A, 0x49, 0x52, 0x89, 0x5A, 0xAA, +0x5A, 0xCA, 0x6B, 0x4B, 0x9C, 0xB0, 0xAD, 0x32, +0xAD, 0x11, 0xAD, 0x11, 0xAD, 0x31, 0x94, 0x2E, +0x83, 0xCD, 0xAD, 0x32, 0xB5, 0x11, 0xA4, 0x8D, +0xD6, 0x34, 0xB5, 0x11, 0x8B, 0xEC, 0x8C, 0x2E, +0x94, 0x4F, 0xD6, 0x56, 0xBD, 0x52, 0xB5, 0x10, +0xA4, 0xAE, 0x83, 0xAA, 0x8C, 0x0C, 0xA4, 0xAF, +0xAD, 0x10, 0xBD, 0x92, 0xD6, 0x56, 0xC5, 0xB3, +0x7B, 0xAB, 0xAD, 0x11, 0xC5, 0xD4, 0xBD, 0xD3, +0xC5, 0xF4, 0xB5, 0x31, 0xA4, 0x8D, 0x9C, 0x4D, +0xC5, 0x92, 0xBD, 0x71, 0xAC, 0xEF, 0x9C, 0x4D, +0x94, 0x2C, 0x83, 0xCC, 0x7B, 0x6A, 0x83, 0xEB, +0x83, 0xCB, 0x83, 0xAB, 0x94, 0x0C, 0x73, 0x49, +0x83, 0xCB, 0x83, 0xCA, 0x94, 0x2C, 0x9C, 0x6D, +0x9C, 0x6D, 0x94, 0x2C, 0x94, 0x0C, 0xA4, 0x8E, +0xB4, 0xEF, 0xBD, 0x30, 0xB5, 0x10, 0xBD, 0x30, +0xC5, 0x92, 0xAC, 0xCF, 0x8B, 0xEC, 0x4A, 0x27, +0x31, 0xA6, 0x31, 0xA6, 0x3A, 0x07, 0x52, 0x8A, +0x5A, 0xCC, 0x84, 0x31, 0xA5, 0x15, 0xA5, 0x35, +0xA5, 0x35, 0xB5, 0x97, 0xE7, 0x1D, 0xEF, 0x5D, +0xE6, 0xFC, 0xAC, 0xF3, 0x94, 0x4F, 0x9C, 0x4E, +0x94, 0x0D, 0x8B, 0xCC, 0x8B, 0xAB, 0x8B, 0xAB, +0x83, 0x8B, 0x83, 0x8B, 0x8B, 0xCB, 0x9C, 0x2C, +0x8B, 0xAA, 0x8B, 0xAB, 0x9C, 0x2C, 0xAC, 0x8E, +0x9C, 0x2D, 0x9C, 0x8F, 0x8C, 0x2E, 0x8C, 0x70, +0xA5, 0x14, 0xDE, 0xBB, 0xE7, 0x3D, 0xDE, 0xDC, +0xE7, 0x3D, 0xB5, 0x95, 0xC5, 0xD5, 0xCE, 0x36, +0xC5, 0xF4, 0xA4, 0x8F, 0x9C, 0x4D, 0xAD, 0x10, +0xD6, 0x15, 0xD6, 0x15, 0xD5, 0xF4, 0xC5, 0xB3, +0xC5, 0x72, 0xC5, 0xB4, 0xD6, 0x35, 0xAD, 0x31, +0x41, 0xC6, 0x39, 0xA6, 0x29, 0x44, 0x39, 0xE7, +0x4A, 0x28, 0x5A, 0x89, 0x62, 0xEB, 0x52, 0x89, +0x42, 0x07, 0x62, 0xCA, 0x9C, 0x71, 0x94, 0x71, +0x6B, 0x4D, 0x8C, 0x51, 0xB5, 0x75, 0xB5, 0x76, +0xAD, 0x35, 0xC5, 0xF8, 0xBD, 0x96, 0xDE, 0xDB, +0xF7, 0x7D, 0xF7, 0x5D, 0xCD, 0xF7, 0xC5, 0xB6, +0xE6, 0xBA, 0xEE, 0x9A, 0xDE, 0x59, 0xBD, 0x75, +0xB5, 0x55, 0x39, 0xE7, 0x42, 0x07, 0x5A, 0xEA, +0x52, 0xA9, 0x4A, 0x48, 0x4A, 0x68, 0x42, 0x07, +0x39, 0xC6, 0x31, 0x85, 0x39, 0xE7, 0x42, 0x28, +0x4A, 0x89, 0x4A, 0x69, 0x52, 0xAA, 0x63, 0x2C, +0x6B, 0x8E, 0x73, 0xAF, 0x9C, 0xD3, 0xBD, 0xF7, +0xB5, 0x96, 0x8C, 0x50, 0xAD, 0x32, 0xBD, 0xB4, +0xB5, 0x52, 0xAD, 0x12, 0xB5, 0x33, 0xB5, 0x32, +0xAD, 0x12, 0xB5, 0x32, 0xBD, 0x94, 0xC5, 0xF5, +0x94, 0x6F, 0x9C, 0xB1, 0xBD, 0xD5, 0xB5, 0x94, +0xBD, 0xD5, 0xBD, 0x94, 0x9C, 0x90, 0xAD, 0x12, +0xBD, 0xD4, 0xD6, 0x55, 0xCE, 0x34, 0xD6, 0x75, +0xD6, 0x55, 0xB5, 0x73, 0x8C, 0x4F, 0x9C, 0xD0, +0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x52, 0xA4, 0xF1, +0x9C, 0xB0, 0xAC, 0xF1, 0x83, 0x8C, 0x73, 0x2A, +0x83, 0xAC, 0x9C, 0x6F, 0xB5, 0x11, 0xA4, 0x6E, +0xBD, 0x52, 0xAC, 0xF0, 0xA4, 0xAF, 0xAC, 0xF0, +0xB5, 0x30, 0xBD, 0x51, 0xC5, 0x51, 0xC5, 0x92, +0xCD, 0xD3, 0xCD, 0xD3, 0xCD, 0xB2, 0xCD, 0xD3, +0xBD, 0x72, 0xAC, 0xD0, 0x94, 0x2D, 0x8B, 0xED, +0x8B, 0xAC, 0x9C, 0x6F, 0x8C, 0x0E, 0x8C, 0x0D, +0x94, 0x2E, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x6F, 0xAC, 0xF1, 0xA4, 0x8F, 0x9C, 0x8F, +0xA4, 0xB0, 0xA4, 0xB0, 0xA4, 0xB0, 0xAD, 0x11, +0xAD, 0x12, 0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, +0x9C, 0x6F, 0x94, 0x2E, 0x94, 0x4F, 0x9C, 0x6F, +0xAD, 0x12, 0xA4, 0xD1, 0x9C, 0xB1, 0xAC, 0xF2, +0xAD, 0x32, 0xB5, 0x32, 0xAD, 0x32, 0xAD, 0x11, +0xAD, 0x32, 0xB5, 0x32, 0xB5, 0x52, 0xBD, 0x72, +0xBD, 0x93, 0xC5, 0xB3, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xB3, 0xBD, 0x93, +0xBD, 0x73, 0xAC, 0xF1, 0xB5, 0x52, 0xDE, 0x96, +0xDE, 0x55, 0xD6, 0x35, 0xD6, 0x35, 0xDE, 0x96, +0xDE, 0x76, 0x7B, 0xCD, 0x31, 0xA5, 0x31, 0x85, +0x4A, 0x67, 0x6C, 0x0B, 0x7C, 0xAC, 0x85, 0x0D, +0x6C, 0x6A, 0x6C, 0x49, 0x5B, 0x88, 0x19, 0x22, +0x31, 0xC5, 0x63, 0x49, 0xB5, 0xB0, 0x62, 0xE8, +0x29, 0x24, 0x41, 0xE6, 0x5A, 0x88, 0x5A, 0xE8, +0x74, 0x09, 0x7C, 0x8A, 0x6C, 0x0A, 0x42, 0x67, +0xAD, 0x91, 0xCE, 0x53, 0x9D, 0x2F, 0xD6, 0x75, +0xD5, 0xF4, 0xCD, 0xB3, 0xD5, 0xF5, 0xDE, 0x36, +0xDE, 0x36, 0xC5, 0x73, 0xD5, 0xD5, 0xCD, 0xB4, +0xCD, 0x94, 0xC5, 0x95, 0xCD, 0xF7, 0xCE, 0x18, +0xB5, 0x55, 0xAC, 0xF3, 0xB5, 0x34, 0xAD, 0x14, +0x31, 0xA7, 0x42, 0x28, 0x4A, 0x48, 0x52, 0xAA, +0x5A, 0xAA, 0x63, 0x0A, 0x8C, 0x6F, 0xA4, 0xF1, +0xA4, 0xD0, 0x9C, 0xB0, 0xA4, 0xF0, 0x8C, 0x2E, +0x7B, 0xAC, 0xAD, 0x32, 0xA4, 0xCF, 0x9C, 0x8E, +0xD6, 0x35, 0xBD, 0x71, 0x94, 0x4E, 0x8C, 0x2E, +0x94, 0x6F, 0xCD, 0xF5, 0xA4, 0xAF, 0x83, 0xAB, +0xA4, 0xAF, 0x9C, 0x6E, 0x94, 0x4E, 0x8C, 0x2E, +0xA4, 0xD0, 0xCE, 0x15, 0xD6, 0x76, 0xBD, 0xB4, +0x94, 0x4E, 0xB5, 0x93, 0xCE, 0x15, 0xBD, 0xB4, +0xCE, 0x15, 0xB5, 0x51, 0x9C, 0x6D, 0x9C, 0x8E, +0xB5, 0x71, 0xBD, 0x92, 0xC5, 0xD3, 0xC5, 0xD4, +0xC5, 0xD3, 0xBD, 0xB3, 0xB5, 0x93, 0x9C, 0xAF, +0x7B, 0xAB, 0x9C, 0xAF, 0xA4, 0xAF, 0xA4, 0xF0, +0xB5, 0x52, 0xAD, 0x31, 0xAD, 0x10, 0xB5, 0x31, +0x9C, 0x8F, 0x7B, 0x8B, 0x7B, 0xAB, 0x9C, 0x6E, +0xC5, 0x72, 0xB4, 0xEF, 0x9C, 0x6C, 0xBD, 0x51, +0xC5, 0x71, 0xAC, 0xAF, 0x9C, 0x4D, 0xA4, 0x8F, +0x52, 0x47, 0x31, 0xA5, 0x31, 0xA5, 0x42, 0x28, +0x4A, 0x69, 0x63, 0x0C, 0x7B, 0xCF, 0x6B, 0x4D, +0x73, 0x8E, 0xB5, 0xB7, 0xCE, 0x7A, 0xCE, 0x5A, +0xE6, 0xFC, 0xD6, 0x7A, 0xCE, 0x18, 0xBD, 0x74, +0xC5, 0x93, 0xB5, 0x31, 0xA4, 0x8E, 0xA4, 0x8E, +0xAC, 0xCF, 0xB4, 0xF0, 0xAC, 0xAE, 0xAC, 0xAE, +0xAC, 0xCF, 0x9C, 0x4D, 0x9C, 0x2D, 0xA4, 0x4D, +0x9C, 0x4D, 0x9C, 0x4E, 0x9C, 0x8F, 0x6B, 0x4C, +0x9C, 0xD3, 0xA5, 0x14, 0xD6, 0x9A, 0xC6, 0x19, +0xE7, 0x1C, 0xCE, 0x59, 0x83, 0xCE, 0x8B, 0xED, +0x94, 0x0D, 0x9C, 0x4D, 0xA4, 0x6E, 0x94, 0x0D, +0x83, 0xAB, 0x83, 0x8B, 0x83, 0xAB, 0x8B, 0xEC, +0x9C, 0x2D, 0xA4, 0x6E, 0xA4, 0xAF, 0x94, 0x2D, +0x8B, 0xED, 0x6A, 0xE9, 0x31, 0xA5, 0x39, 0xC5, +0x42, 0x06, 0x52, 0x68, 0x6B, 0x2B, 0x6B, 0x2C, +0x9C, 0xB2, 0x94, 0x50, 0x62, 0xCA, 0x83, 0xEF, +0x9C, 0xD2, 0x63, 0x0C, 0x73, 0xAF, 0x94, 0xB2, +0x9C, 0xB2, 0x94, 0x92, 0xAD, 0x55, 0xCE, 0x39, +0xEF, 0x5D, 0xD6, 0x79, 0xC5, 0xF7, 0xCE, 0x18, +0xBD, 0xB6, 0xD6, 0x39, 0xE6, 0x9A, 0xFF, 0x5D, +0xC5, 0xD7, 0x6A, 0xEC, 0x4A, 0x08, 0x5A, 0xCA, +0x52, 0x89, 0x42, 0x28, 0x42, 0x27, 0x39, 0xE7, +0x39, 0xC6, 0x31, 0x85, 0x31, 0xA6, 0x39, 0xC6, +0x4A, 0x69, 0x5A, 0xEB, 0x5A, 0xCA, 0x5A, 0xCA, +0x6B, 0x6D, 0x84, 0x30, 0xAD, 0x55, 0xB5, 0x96, +0xBD, 0xD7, 0xB5, 0x74, 0xB5, 0x74, 0xBD, 0xB4, +0xB5, 0x52, 0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x32, +0xB5, 0x53, 0xB5, 0x73, 0xBD, 0x93, 0xC5, 0xF5, +0xAD, 0x32, 0xA5, 0x12, 0xBD, 0xB4, 0xC5, 0xF5, +0xC5, 0xF5, 0xBD, 0xB4, 0xA4, 0xD1, 0xAD, 0x53, +0xBD, 0x93, 0xCE, 0x14, 0xCE, 0x34, 0xD6, 0x55, +0xCE, 0x35, 0xA4, 0xF1, 0xB5, 0x74, 0xB5, 0x94, +0xAD, 0x32, 0xB5, 0x94, 0xBD, 0x94, 0xA5, 0x11, +0x9C, 0x8F, 0xAC, 0xF1, 0x94, 0x0D, 0x83, 0x8C, +0x94, 0x2D, 0xBD, 0x32, 0xB4, 0xF0, 0xAC, 0xAF, +0xBD, 0x32, 0x9C, 0x8F, 0xA4, 0xB0, 0xB5, 0x31, +0xCD, 0xB3, 0xD5, 0xD3, 0xCD, 0xB2, 0xCD, 0xB3, +0xCD, 0xD3, 0xCD, 0xB2, 0xC5, 0x51, 0xA4, 0x8F, +0x8B, 0xCC, 0x8B, 0xED, 0x94, 0x2D, 0x94, 0x2D, +0x8B, 0xCC, 0xA4, 0x90, 0x9C, 0x8F, 0xAC, 0xF0, +0xBD, 0x72, 0xBD, 0x93, 0xB5, 0x52, 0xA4, 0xD0, +0xA4, 0xB0, 0xA4, 0xF0, 0xA4, 0xAF, 0xA4, 0xB0, +0xAC, 0xF1, 0xA4, 0xD0, 0x9C, 0x6F, 0x9C, 0x6F, +0xB5, 0x12, 0xAD, 0x11, 0xA4, 0xB0, 0x9C, 0x6F, +0x83, 0xCD, 0x7B, 0x8B, 0xB5, 0x32, 0xCD, 0xF4, +0xBD, 0x93, 0x94, 0x6F, 0xA4, 0xD0, 0xC5, 0xD5, +0xBD, 0x73, 0xB5, 0x32, 0xCD, 0xD4, 0xD6, 0x35, +0xD6, 0x36, 0xB5, 0x52, 0xB5, 0x32, 0xB5, 0x32, +0xB5, 0x32, 0xC5, 0xB4, 0xBD, 0x94, 0xBD, 0x73, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x32, 0xAC, 0xF1, 0xA4, 0xD1, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0xD0, 0x8C, 0x2E, 0x4A, 0x68, +0x5B, 0x08, 0x6C, 0x2A, 0x6C, 0x4A, 0x53, 0xA8, +0x3A, 0xA5, 0x32, 0x44, 0x29, 0xC3, 0x21, 0x83, +0x4A, 0xE7, 0x4A, 0xE7, 0x7B, 0xEB, 0x8C, 0x6E, +0x42, 0x07, 0x29, 0x44, 0x39, 0xA6, 0x52, 0x67, +0x5B, 0x28, 0x53, 0x08, 0x42, 0xA7, 0x3A, 0x07, +0x73, 0x8B, 0xCE, 0x14, 0xBD, 0x92, 0xCD, 0xF3, +0xCD, 0xF4, 0xBD, 0xB3, 0xE6, 0xD8, 0xEE, 0xD9, +0xDE, 0x57, 0xE6, 0xB9, 0xE6, 0xD9, 0xD6, 0x77, +0xD6, 0x78, 0xD6, 0x17, 0xAD, 0x13, 0xBD, 0x75, +0xC5, 0xB6, 0xBD, 0x96, 0xC5, 0xB6, 0xBD, 0x96, +0x31, 0x86, 0x39, 0xE7, 0x42, 0x28, 0x4A, 0x28, +0x52, 0x69, 0x5A, 0xEA, 0x7B, 0xCD, 0x94, 0x90, +0x94, 0x90, 0x94, 0x70, 0x94, 0x70, 0x83, 0xEE, +0x83, 0xEE, 0xBD, 0xB4, 0xAC, 0xD0, 0xA4, 0x8E, +0xD6, 0x14, 0xCD, 0xD3, 0xA4, 0xB0, 0x94, 0x6F, +0x94, 0x6F, 0xBD, 0x93, 0xBD, 0x72, 0xB5, 0x52, +0xCE, 0x15, 0xBD, 0x93, 0xC5, 0xD4, 0x9C, 0x90, +0xB5, 0x53, 0xCE, 0x15, 0xC5, 0xF4, 0xB5, 0x52, +0xA4, 0xD0, 0xC5, 0xF5, 0xCE, 0x35, 0xCE, 0x56, +0xC5, 0xD4, 0xB5, 0x31, 0xAC, 0xCF, 0xA4, 0xAE, +0xBD, 0x72, 0xBD, 0x93, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xB3, 0xCE, 0x35, 0xCE, 0x35, 0xAD, 0x11, +0x63, 0x09, 0xBD, 0xD4, 0xD6, 0x76, 0xCE, 0x55, +0xD6, 0x55, 0xD6, 0x76, 0xD6, 0x76, 0xCE, 0x35, +0xBD, 0x93, 0xC5, 0xD4, 0xD6, 0x56, 0xCE, 0x14, +0xDE, 0x55, 0xB5, 0x10, 0xAC, 0xAE, 0xEE, 0xB6, +0xEE, 0xD7, 0xEE, 0xB6, 0xE6, 0x76, 0xE6, 0x55, +0xCD, 0x93, 0x72, 0xE9, 0x31, 0x84, 0x39, 0xC6, +0x42, 0x07, 0x4A, 0x48, 0x5A, 0xAB, 0x5A, 0xCB, +0x73, 0xAF, 0xAD, 0x76, 0xB5, 0xD8, 0xC6, 0x19, +0xD6, 0x9B, 0xE7, 0x1D, 0xEF, 0x5D, 0xCE, 0x59, +0x9C, 0x91, 0x94, 0x0D, 0xA4, 0xAE, 0xAC, 0xCF, +0xC5, 0xB2, 0xC5, 0x71, 0xBD, 0x71, 0xC5, 0x92, +0x9C, 0x2D, 0x83, 0x49, 0x9C, 0x2D, 0xB5, 0x11, +0xAC, 0xAF, 0x94, 0x0D, 0x9C, 0x6E, 0x6B, 0x2B, +0x8C, 0x71, 0x9C, 0xD3, 0xD6, 0xBA, 0xCE, 0x59, +0xBD, 0xD7, 0xEF, 0x3D, 0xC6, 0x17, 0x94, 0x2F, +0x9C, 0x4E, 0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, +0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x31, 0xBD, 0x31, +0xBD, 0x51, 0x83, 0xAC, 0x29, 0x23, 0x6B, 0x2A, +0x8C, 0x4E, 0x63, 0x09, 0x52, 0x89, 0x42, 0x07, +0x5A, 0xCA, 0x8B, 0xEE, 0x6B, 0x0B, 0x31, 0x85, +0x6B, 0x2C, 0x6B, 0x2C, 0x62, 0xEC, 0x5A, 0xAB, +0x7B, 0xEF, 0x94, 0xB2, 0x9C, 0xB3, 0xA5, 0x35, +0xA5, 0x14, 0xC5, 0xF8, 0xEF, 0x5D, 0xE6, 0xFB, +0xDE, 0x9A, 0xCE, 0x18, 0xDE, 0x9A, 0xF7, 0x3C, +0xF7, 0x3D, 0xD6, 0x18, 0xA4, 0xD3, 0xA4, 0xB2, +0x62, 0xCA, 0x42, 0x07, 0x42, 0x07, 0x42, 0x07, +0x42, 0x27, 0x39, 0xE7, 0x39, 0xE7, 0x42, 0x07, +0x4A, 0x28, 0x52, 0x89, 0x52, 0xAA, 0x5A, 0xEB, +0x6B, 0x6D, 0x84, 0x10, 0xA5, 0x14, 0xB5, 0x96, +0xA5, 0x14, 0xB5, 0xB5, 0xAD, 0x53, 0xC5, 0xD4, +0xC5, 0xB4, 0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x73, 0xB5, 0x73, 0xC5, 0xB4, +0xAD, 0x32, 0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x32, +0xAD, 0x12, 0xAD, 0x53, 0xA4, 0xD1, 0xAD, 0x53, +0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xF3, 0xD6, 0x55, +0xCE, 0x14, 0x9C, 0xB0, 0xAD, 0x33, 0xC5, 0xF5, +0xB5, 0x73, 0xAD, 0x32, 0xAD, 0x12, 0xA4, 0xD1, +0x9C, 0x8F, 0xA4, 0xB0, 0x9C, 0x4E, 0xA4, 0x6F, +0xB4, 0xF0, 0xC5, 0x52, 0xAC, 0x8F, 0xB4, 0xF1, +0xC5, 0x93, 0xA4, 0x8F, 0xA4, 0xD0, 0xAC, 0xF0, +0xCD, 0xB2, 0xD5, 0xD3, 0xCD, 0xB3, 0xCD, 0xB2, +0xD5, 0xD3, 0xCD, 0x92, 0xBD, 0x31, 0x8B, 0xEC, +0x7B, 0x8C, 0x7B, 0xAC, 0x83, 0xCD, 0x83, 0xAB, +0x8B, 0xCC, 0xA4, 0xD0, 0xAD, 0x31, 0xB5, 0x72, +0xB5, 0x72, 0xB5, 0x72, 0xB5, 0x52, 0xB5, 0x52, +0xAD, 0x11, 0xA4, 0xF0, 0xA4, 0xD0, 0xB5, 0x32, +0xBD, 0x73, 0xB5, 0x72, 0xB5, 0x52, 0xA4, 0xF0, +0xBD, 0x72, 0xBD, 0x92, 0xC5, 0xB3, 0xA4, 0xF0, +0x83, 0xCD, 0xBD, 0xB3, 0xB5, 0x31, 0xDE, 0x75, +0xCE, 0x14, 0x8C, 0x2E, 0xB5, 0x31, 0xC5, 0x93, +0x94, 0x4F, 0x73, 0x4B, 0xBD, 0x73, 0xD6, 0x14, +0xAD, 0x11, 0x94, 0x4F, 0x94, 0x4E, 0x94, 0x2E, +0x9C, 0x6F, 0xBD, 0x72, 0x83, 0xCC, 0x94, 0x4E, +0x94, 0x6F, 0xBD, 0x73, 0xBD, 0x73, 0xA4, 0xB0, +0xAD, 0x11, 0xB5, 0x11, 0xBD, 0x73, 0xC5, 0xB4, +0xDE, 0x77, 0xC5, 0xD4, 0x94, 0x2F, 0xD6, 0x77, +0xE6, 0xD7, 0xEE, 0xF8, 0xDE, 0xB7, 0xBD, 0xF4, +0x84, 0x6E, 0x74, 0x6C, 0x6C, 0x4A, 0x4B, 0x47, +0x32, 0x85, 0x3A, 0x65, 0x53, 0x28, 0x7C, 0xAD, +0x53, 0x66, 0x5B, 0xE9, 0x42, 0xA6, 0x9D, 0x10, +0x73, 0xAC, 0x52, 0x68, 0x39, 0xA6, 0x52, 0x68, +0x52, 0x87, 0x29, 0x84, 0x3A, 0x06, 0x4A, 0x48, +0x42, 0x07, 0x8C, 0x0E, 0xA4, 0xD0, 0xD6, 0x56, +0xA5, 0x11, 0xA5, 0x72, 0x95, 0x0F, 0xAD, 0x72, +0xEF, 0x3A, 0xC5, 0xF5, 0x94, 0xF0, 0x8C, 0xEF, +0x9D, 0x31, 0xAD, 0x93, 0x8C, 0x0F, 0xBD, 0x96, +0xBD, 0xB6, 0xB5, 0x34, 0xAD, 0x34, 0xA4, 0xD2, +0x29, 0x45, 0x29, 0x86, 0x39, 0xC7, 0x39, 0xE7, +0x39, 0xE7, 0x42, 0x28, 0x52, 0xA9, 0x63, 0x0B, +0x6B, 0x2B, 0x6B, 0x2B, 0x6B, 0x2B, 0x6B, 0x4B, +0x83, 0xCD, 0xB5, 0x73, 0xB5, 0x10, 0x9C, 0x6D, +0xD6, 0x14, 0xC5, 0x92, 0xA4, 0xAF, 0x94, 0x6F, +0x9C, 0x90, 0xCE, 0x35, 0xCD, 0xF4, 0xCE, 0x15, +0xD6, 0x56, 0xBD, 0xD3, 0xCE, 0x15, 0xA4, 0xD1, +0xCE, 0x16, 0xB5, 0x73, 0xA4, 0xF1, 0xAD, 0x32, +0x94, 0x6F, 0xB5, 0x73, 0xCE, 0x15, 0xCE, 0x35, +0xBD, 0x93, 0xB5, 0x31, 0xAC, 0xCF, 0x9C, 0x4D, +0xBD, 0x93, 0xBD, 0x92, 0xBD, 0x92, 0xBD, 0x72, +0xB5, 0x51, 0xB5, 0x72, 0xBD, 0xB3, 0x94, 0x8F, +0x73, 0x8C, 0xB5, 0xB4, 0xCE, 0x35, 0xCE, 0x35, +0xCE, 0x14, 0xCE, 0x34, 0xCE, 0x35, 0xCE, 0x35, +0xCE, 0x35, 0xD6, 0x76, 0xDE, 0x96, 0xD6, 0x76, +0xCD, 0xF3, 0xBD, 0x72, 0xB4, 0xCF, 0xE6, 0xB6, +0xE6, 0xB6, 0xEE, 0xB6, 0xEE, 0x96, 0xD5, 0xD3, +0xD5, 0x72, 0xE6, 0x35, 0xB5, 0x11, 0x52, 0x47, +0x39, 0xC6, 0x39, 0xE6, 0x4A, 0x69, 0x4A, 0x28, +0x5A, 0xCB, 0x8C, 0x51, 0x9C, 0xF4, 0xB5, 0xD8, +0xB5, 0x97, 0xDE, 0xDC, 0xE6, 0xFC, 0xE7, 0x1D, +0xC5, 0xF8, 0xA4, 0xF2, 0xA4, 0x8F, 0xBD, 0x51, +0xE6, 0x75, 0xE6, 0x55, 0xDE, 0x55, 0xCD, 0xD3, +0xA4, 0x6E, 0xAC, 0x8F, 0xCD, 0x93, 0xD5, 0xF4, +0xBD, 0x72, 0xCD, 0xD3, 0xCD, 0xD4, 0xA4, 0xD0, +0x8C, 0x2F, 0x7B, 0xEF, 0xC6, 0x39, 0xCE, 0x59, +0xCE, 0x59, 0xE6, 0xFC, 0xEF, 0x5D, 0xA4, 0xD3, +0x7B, 0x8C, 0x73, 0x6B, 0x73, 0x6B, 0x6B, 0x2A, +0x73, 0x2A, 0x73, 0x4B, 0x7B, 0x8B, 0x83, 0xCC, +0x8C, 0x0D, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x2D, +0x9C, 0x6E, 0x5A, 0x88, 0x29, 0x24, 0x8C, 0x0E, +0xA4, 0xF0, 0xAD, 0x31, 0x94, 0x4F, 0x41, 0xE6, +0x39, 0xC6, 0x31, 0xA5, 0x21, 0x24, 0x39, 0xE7, +0x31, 0x65, 0x4A, 0x48, 0x63, 0x0B, 0x62, 0xEB, +0x7B, 0xCF, 0x7B, 0xAE, 0x8C, 0x31, 0x84, 0x10, +0x94, 0xB3, 0x94, 0x72, 0xB5, 0x76, 0xDE, 0xBB, +0xF7, 0x7E, 0xEF, 0x3C, 0xC5, 0xD8, 0xBD, 0xB6, +0xDE, 0x79, 0xEF, 0x1B, 0xF7, 0x5C, 0xCD, 0xF6, +0x9C, 0x91, 0x52, 0x48, 0x39, 0xE7, 0x39, 0xE6, +0x39, 0xE7, 0x42, 0x07, 0x42, 0x07, 0x4A, 0x48, +0x4A, 0x69, 0x4A, 0x69, 0x52, 0xAA, 0x63, 0x0C, +0x6B, 0x4D, 0x84, 0x10, 0x83, 0xF0, 0x8C, 0x51, +0x9C, 0xD3, 0xBD, 0xF7, 0xAD, 0x12, 0xC5, 0xB4, +0xC5, 0xB4, 0xC5, 0x93, 0xCD, 0xF4, 0xCD, 0xF5, +0xC5, 0xB4, 0xAD, 0x32, 0xBD, 0x93, 0xB5, 0x53, +0xB5, 0x73, 0xAD, 0x12, 0xA4, 0xF1, 0xA5, 0x11, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0xB0, 0xA4, 0xF1, +0xB5, 0x73, 0xC5, 0xB3, 0xCD, 0xF4, 0xCE, 0x35, +0xC5, 0xF4, 0x94, 0x6F, 0x94, 0x90, 0xB5, 0x74, +0xB5, 0x94, 0xAD, 0x12, 0xAD, 0x53, 0x9C, 0xD0, +0x94, 0x4E, 0xA4, 0xD0, 0x9C, 0x4E, 0xA4, 0x8F, +0xBD, 0x11, 0xBD, 0x31, 0xA4, 0x8F, 0xB5, 0x11, +0xB5, 0x32, 0x9C, 0x90, 0xA4, 0xD0, 0xAC, 0xF0, +0xCD, 0x92, 0xCD, 0x92, 0xCD, 0x92, 0xCD, 0xB2, +0xD5, 0xD3, 0xCD, 0xB2, 0xB5, 0x10, 0x7B, 0xAC, +0x73, 0x6C, 0x7B, 0x8C, 0x7B, 0xAC, 0x7B, 0x8C, +0x83, 0xAC, 0xAC, 0xF1, 0xA4, 0xF0, 0xBD, 0x92, +0xBD, 0x72, 0xAD, 0x31, 0xAD, 0x11, 0xA4, 0xF0, +0x9C, 0x8F, 0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x52, +0xB5, 0x52, 0xBD, 0xB3, 0xC5, 0xD3, 0xB5, 0x51, +0xC5, 0xB3, 0xC5, 0x92, 0xC5, 0x93, 0xB5, 0x31, +0xC5, 0x93, 0xDE, 0x55, 0x93, 0xEC, 0xCD, 0xD4, +0xCD, 0xF4, 0x9C, 0x8F, 0xCE, 0x15, 0xD6, 0x36, +0xC5, 0xB4, 0xCD, 0xF6, 0xCE, 0x15, 0xDE, 0x56, +0xCE, 0x15, 0xBD, 0x53, 0x9C, 0x90, 0x8C, 0x0E, +0x9C, 0x90, 0xAD, 0x12, 0xB5, 0x32, 0xBD, 0x73, +0xC5, 0x94, 0xD6, 0x36, 0xD6, 0x35, 0xD6, 0x35, +0xDE, 0x76, 0xE6, 0x76, 0xE6, 0x76, 0xDE, 0x56, +0xDE, 0x76, 0xD6, 0x36, 0xB5, 0x12, 0xCE, 0x16, +0xB5, 0x32, 0x9C, 0x90, 0xA4, 0xF1, 0xA5, 0x11, +0x95, 0x30, 0x8D, 0x2E, 0x8D, 0x2E, 0x74, 0x6B, +0x53, 0x88, 0x5B, 0xE9, 0x85, 0x0E, 0x85, 0x0D, +0x5B, 0xE8, 0x74, 0x8B, 0x6B, 0xCA, 0x84, 0x6C, +0xBD, 0xF2, 0x73, 0xAB, 0x42, 0x27, 0x52, 0xA7, +0x52, 0xC8, 0x31, 0xC5, 0x29, 0x44, 0x42, 0x68, +0x5A, 0xEA, 0x73, 0x8C, 0xBD, 0xF4, 0xEF, 0x7A, +0xD6, 0xF8, 0x84, 0xCF, 0x42, 0xE5, 0x53, 0x87, +0x84, 0xED, 0x74, 0x6B, 0x8D, 0x4F, 0xAE, 0x12, +0xAE, 0x33, 0xBE, 0x75, 0xBD, 0xF5, 0x94, 0x50, +0x8C, 0x10, 0x83, 0xCE, 0x7B, 0xAD, 0x73, 0x4C, +0x31, 0xA6, 0x39, 0xE7, 0x4A, 0x48, 0x52, 0x69, +0x5A, 0xA9, 0x5A, 0xAA, 0x5A, 0xA9, 0x5A, 0xA9, +0x62, 0xEA, 0x63, 0x0A, 0x63, 0x0A, 0x62, 0xEA, +0x73, 0x4B, 0xA4, 0xD0, 0xA4, 0xAF, 0x9C, 0x4D, +0xBD, 0x71, 0xB5, 0x10, 0xB5, 0x11, 0xAC, 0xD1, +0xAC, 0xF1, 0xD6, 0x36, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xD4, 0x94, 0x6E, 0xAD, 0x11, 0x9C, 0xB0, +0xBD, 0xD4, 0xDE, 0xD8, 0xBD, 0x93, 0xC5, 0xD4, +0xC6, 0x15, 0xCE, 0x35, 0xAD, 0x52, 0xCE, 0x15, +0xBD, 0xB3, 0xAD, 0x10, 0xA4, 0x8E, 0x9C, 0x4D, +0xBD, 0x92, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x93, +0xC5, 0xD4, 0xBD, 0x93, 0xC5, 0xD4, 0xB5, 0x73, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0xB3, 0xBD, 0x92, +0xBD, 0x92, 0xC5, 0xF4, 0xC5, 0xD3, 0xBD, 0x93, +0xBD, 0x93, 0xC5, 0xB3, 0xCE, 0x34, 0xCE, 0x14, +0xD6, 0x14, 0xBD, 0x51, 0xB4, 0xEF, 0xEE, 0xB6, +0xE6, 0x75, 0xE6, 0x75, 0xEE, 0x95, 0xDD, 0xD3, +0xDD, 0xB3, 0xE6, 0x14, 0xF6, 0xD7, 0xDE, 0x55, +0x7B, 0x8C, 0x39, 0xA6, 0x39, 0xC6, 0x39, 0xC6, +0x4A, 0x48, 0x5A, 0xCB, 0x73, 0xAF, 0x94, 0xB3, +0xA5, 0x56, 0xB5, 0xD8, 0xBD, 0xF9, 0xCE, 0x7A, +0xDE, 0xBB, 0xEF, 0x5C, 0xB5, 0x54, 0xCD, 0xD4, +0xD5, 0xF4, 0xE6, 0x55, 0xDE, 0x34, 0xBD, 0x72, +0xBD, 0x52, 0xDE, 0x55, 0xE6, 0x96, 0xE6, 0x96, +0xDE, 0x35, 0xD6, 0x14, 0xDE, 0x14, 0xE6, 0x96, +0xDE, 0x55, 0x9C, 0x6F, 0x94, 0x50, 0xB5, 0x96, +0xB5, 0x76, 0xCE, 0x39, 0xDE, 0xDB, 0xDE, 0x9A, +0xAD, 0x33, 0xAD, 0x53, 0xAD, 0x12, 0x9C, 0xB1, +0x8C, 0x0E, 0x7B, 0xAD, 0x73, 0x4B, 0x6B, 0x4B, +0x6B, 0x4B, 0x6B, 0x2B, 0x5A, 0xA9, 0x52, 0x89, +0x7B, 0xAD, 0x31, 0x64, 0x41, 0xE7, 0x52, 0x68, +0x52, 0x88, 0x73, 0x6B, 0x9C, 0x90, 0x73, 0x4C, +0x41, 0xE6, 0x31, 0x85, 0x4A, 0x28, 0x5A, 0xCA, +0x5A, 0xCA, 0x42, 0x27, 0x42, 0x07, 0x5A, 0xCA, +0x6B, 0x4C, 0x5A, 0xCA, 0x6B, 0x4C, 0x73, 0x8E, +0x8C, 0x31, 0x9C, 0xD3, 0x73, 0x8F, 0x9C, 0xF4, +0xC6, 0x18, 0xDE, 0xBA, 0xD6, 0x7A, 0xBD, 0x96, +0xD6, 0x59, 0xDE, 0x79, 0xFF, 0xDE, 0xEF, 0x3C, +0xCD, 0xF7, 0xA4, 0xD3, 0x4A, 0x28, 0x42, 0x28, +0x39, 0xC6, 0x39, 0xC6, 0x31, 0xA6, 0x42, 0x48, +0x52, 0x89, 0x52, 0xAA, 0x5A, 0xEB, 0x52, 0xCA, +0x63, 0x0C, 0x6B, 0x4D, 0x73, 0x6E, 0x94, 0xB3, +0xB5, 0x96, 0xC6, 0x18, 0xB5, 0x75, 0x9C, 0x91, +0x9C, 0x8F, 0x9C, 0x8F, 0x9C, 0x8F, 0xA4, 0xB0, +0x9C, 0x6F, 0x9C, 0x8F, 0xA4, 0xD0, 0x9C, 0x90, +0xAD, 0x12, 0xBD, 0x73, 0xBD, 0xB4, 0xAD, 0x32, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xF1, 0xB5, 0x73, +0xD6, 0x56, 0xD6, 0x76, 0xD6, 0x55, 0xD6, 0x55, +0xC5, 0xF4, 0x9C, 0x90, 0x94, 0x70, 0x9C, 0xD1, +0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, 0x9C, 0xB0, +0x8C, 0x0D, 0xAC, 0xF1, 0x9C, 0x4E, 0xAC, 0xD0, +0xBD, 0x32, 0xC5, 0x73, 0xAC, 0xB0, 0xA4, 0x6F, +0x94, 0x4F, 0x8C, 0x2E, 0x9C, 0x6F, 0xAC, 0xF1, +0xC5, 0x92, 0xCD, 0x92, 0xCD, 0x92, 0xCD, 0x92, +0xC5, 0x71, 0xBD, 0x30, 0xAC, 0xCF, 0x73, 0x8B, +0x73, 0x4B, 0x73, 0x4B, 0x73, 0x4B, 0x7B, 0x6C, +0x8B, 0xED, 0xAC, 0xF1, 0x9C, 0xB0, 0xB5, 0x31, +0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0xAD, 0x32, 0xB5, 0x72, 0xBD, 0x93, +0xBD, 0x73, 0xB5, 0x52, 0xBD, 0x92, 0xA4, 0xF0, +0xAC, 0xF0, 0xB5, 0x51, 0xBD, 0x72, 0xB5, 0x51, +0xC5, 0x71, 0xD5, 0xF3, 0xBD, 0x31, 0xB5, 0x31, +0xC5, 0x93, 0x9C, 0x90, 0xD6, 0x36, 0xDE, 0x77, +0xD6, 0x56, 0xDE, 0x77, 0xDE, 0x97, 0xE6, 0xB8, +0xDE, 0x77, 0xE6, 0x98, 0xC5, 0xB4, 0xB5, 0x53, +0xDE, 0x98, 0xE6, 0xB8, 0xD6, 0x56, 0xE6, 0x97, +0xEE, 0xD9, 0xE6, 0xB7, 0xEE, 0xF7, 0xE6, 0xB7, +0xE6, 0x76, 0xE6, 0x75, 0xDE, 0x75, 0xDE, 0x55, +0xDE, 0x55, 0xD6, 0x15, 0x9C, 0xB0, 0xAD, 0x33, +0xC5, 0xF6, 0xC5, 0xF6, 0xCE, 0x37, 0xBD, 0xD3, +0x8C, 0xEF, 0x8D, 0x2F, 0x7C, 0xCC, 0x6C, 0x4A, +0x74, 0x6B, 0x7C, 0xED, 0x95, 0x6F, 0x64, 0x29, +0x64, 0x49, 0x5B, 0xC8, 0x32, 0x04, 0x52, 0xE7, +0x84, 0x4B, 0x9D, 0x50, 0x53, 0x07, 0x3A, 0x85, +0x42, 0xC5, 0x53, 0x07, 0x4A, 0xC8, 0x63, 0x6A, +0x7C, 0x8E, 0x74, 0x0C, 0xB5, 0xF4, 0xD7, 0x18, +0x9D, 0x71, 0x4B, 0x27, 0x43, 0x05, 0x3A, 0xE4, +0x42, 0xE5, 0x4B, 0x46, 0x6C, 0x2A, 0x9D, 0xD1, +0xB6, 0x75, 0xB6, 0x95, 0xA5, 0x92, 0x63, 0x0A, +0x62, 0xCA, 0x83, 0xCE, 0x8C, 0x0F, 0x8C, 0x0F, +0x5A, 0xCA, 0x6B, 0x0B, 0x6B, 0x4B, 0x7B, 0x8C, +0x83, 0xCD, 0x83, 0xED, 0x8C, 0x0D, 0x8C, 0x0D, +0x8B, 0xED, 0x8B, 0xEC, 0x8C, 0x0D, 0x94, 0x2D, +0x94, 0x4E, 0x94, 0x4D, 0x94, 0x2C, 0x94, 0x2C, +0x94, 0x0C, 0x94, 0x2C, 0x94, 0x2D, 0x9C, 0x4E, +0x8C, 0x0C, 0x94, 0x2D, 0x94, 0x0C, 0x94, 0x0C, +0x94, 0x2D, 0x94, 0x4D, 0x9C, 0x6E, 0x94, 0x2D, +0x94, 0x4E, 0xAD, 0x31, 0xB5, 0x73, 0xB5, 0x52, +0xAD, 0x11, 0xA5, 0x11, 0xAC, 0xF0, 0xB5, 0x51, +0x9C, 0x6E, 0x94, 0x0C, 0xA4, 0x8E, 0xAC, 0xCF, +0xB5, 0x72, 0xC5, 0xD3, 0xBD, 0xD3, 0xBD, 0xB3, +0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x93, +0xAD, 0x31, 0xB5, 0x72, 0xB5, 0x72, 0xBD, 0x92, +0xBD, 0x92, 0xB5, 0x92, 0xAD, 0x11, 0xA4, 0xF0, +0xA4, 0xD0, 0xB5, 0x72, 0xC5, 0xD3, 0xC5, 0xD3, +0xC5, 0xB2, 0xBD, 0x30, 0xBD, 0x30, 0xEE, 0xD7, +0xE6, 0x95, 0xE6, 0x75, 0xE6, 0x55, 0xE6, 0x14, +0xE5, 0xF3, 0xEE, 0x55, 0xEE, 0x95, 0xEE, 0xB6, +0xE6, 0x96, 0xAC, 0xD0, 0x4A, 0x27, 0x31, 0xA6, +0x39, 0xE7, 0x39, 0xE7, 0x4A, 0x69, 0x6B, 0x4D, +0x84, 0x51, 0x8C, 0x93, 0xB5, 0x97, 0xC6, 0x19, +0xDE, 0xFC, 0xEF, 0x3D, 0xB5, 0x96, 0xD6, 0x79, +0xC5, 0xD6, 0xCD, 0xF4, 0xD6, 0x14, 0xC5, 0x93, +0xD6, 0x15, 0xD6, 0x35, 0xDE, 0x35, 0xDE, 0x34, +0xDE, 0x34, 0xDE, 0x34, 0xD5, 0xF3, 0xD5, 0xB2, +0xD5, 0xF3, 0xD5, 0xF3, 0xB5, 0x31, 0x73, 0x6C, +0xAD, 0x55, 0xDE, 0xDB, 0xE6, 0xFC, 0xEF, 0x5D, +0xD6, 0x79, 0xB5, 0x33, 0xB5, 0x93, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x12, 0x9C, 0xB1, 0x9C, 0x90, +0x9C, 0xB0, 0x94, 0x8F, 0x8C, 0x2E, 0x8C, 0x2F, +0x4A, 0x27, 0x4A, 0x48, 0x8C, 0x2F, 0x8C, 0x4F, +0x9C, 0xD1, 0xAD, 0x12, 0xAD, 0x32, 0x9C, 0xAF, +0xA4, 0xD0, 0x73, 0x6B, 0x63, 0x0A, 0x52, 0x68, +0x5A, 0xAA, 0x5A, 0xA9, 0x31, 0xA5, 0x39, 0xA6, +0x42, 0x07, 0x4A, 0x48, 0x6B, 0x4C, 0x73, 0x6D, +0x6B, 0x2C, 0x83, 0xF0, 0x83, 0xF0, 0x7B, 0xF0, +0x7B, 0xCF, 0x8C, 0x51, 0x94, 0xB3, 0xAD, 0x35, +0xE6, 0xDB, 0xDE, 0x9A, 0xEF, 0x1B, 0xEF, 0x5C, +0xC5, 0xD7, 0xDE, 0xBA, 0xAD, 0x34, 0x42, 0x08, +0x31, 0xA6, 0x39, 0xC6, 0x39, 0xE6, 0x39, 0xC6, +0x3A, 0x07, 0x4A, 0x48, 0x42, 0x48, 0x52, 0x8A, +0x5B, 0x0B, 0x6B, 0x6E, 0x7B, 0xD0, 0x9C, 0xB3, +0xAD, 0x76, 0xBD, 0xD7, 0xAD, 0x55, 0xC5, 0xD6, +0xCE, 0x17, 0xC5, 0x94, 0xBD, 0x94, 0xC5, 0xB4, +0xC5, 0x94, 0xBD, 0x93, 0xBD, 0x73, 0xB5, 0x32, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xD1, 0xA4, 0xD0, +0xA4, 0xD0, 0xA4, 0xD1, 0xA4, 0xD1, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x52, 0xB5, 0x52, 0xB5, 0x11, +0xBD, 0x72, 0xA4, 0xF1, 0xAD, 0x12, 0xAC, 0xF2, +0xA4, 0xD1, 0x9C, 0xD1, 0x94, 0x4F, 0x8C, 0x0D, +0x94, 0x4F, 0xA4, 0xD0, 0x94, 0x0E, 0x93, 0xED, +0x94, 0x0D, 0xB5, 0x11, 0xBD, 0x52, 0xBD, 0x52, +0xB5, 0x32, 0xAD, 0x31, 0xB5, 0x52, 0xBD, 0x52, +0xC5, 0x72, 0xD5, 0xD3, 0xD5, 0xD2, 0xCD, 0xB2, +0xCD, 0x92, 0xC5, 0x72, 0x94, 0x4E, 0x6B, 0x2B, +0x62, 0xEA, 0x63, 0x0A, 0x63, 0x0A, 0x73, 0x4B, +0x94, 0x0D, 0xAD, 0x11, 0xA4, 0xD0, 0xBD, 0x72, +0xAD, 0x10, 0xAD, 0x11, 0xAD, 0x31, 0xB5, 0x72, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x52, +0xB5, 0x52, 0xB5, 0x52, 0xBD, 0x92, 0xB5, 0x51, +0x9C, 0x8E, 0xB5, 0x31, 0xC5, 0xB3, 0xBD, 0x92, +0xBD, 0x71, 0xBD, 0x51, 0xCD, 0xB3, 0xB5, 0x31, +0xB5, 0x52, 0x9C, 0x90, 0xD6, 0x56, 0xDE, 0x76, +0xE6, 0x97, 0xE6, 0xD8, 0xBD, 0xB4, 0x94, 0x50, +0x9C, 0x91, 0xB5, 0x54, 0xBD, 0x95, 0xC5, 0xD6, +0xC5, 0xF5, 0xD6, 0x16, 0xDE, 0x56, 0xCE, 0x15, +0xBD, 0x94, 0xC5, 0xD5, 0xE6, 0x96, 0xDE, 0x35, +0xE6, 0x96, 0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x34, +0xD6, 0x14, 0xB5, 0x32, 0xB5, 0x74, 0xCE, 0x58, +0xC5, 0xF7, 0x9C, 0xB2, 0xE6, 0xD8, 0xE6, 0xD7, +0xB5, 0xD2, 0x8D, 0x2E, 0x7C, 0xCD, 0x85, 0x0D, +0x8D, 0x2E, 0x8D, 0x4F, 0x95, 0x70, 0x64, 0x09, +0x4B, 0x67, 0x21, 0xA3, 0x19, 0x03, 0x29, 0x64, +0x21, 0x63, 0x63, 0x8A, 0x7C, 0xAC, 0x5B, 0xC9, +0x32, 0x84, 0x42, 0xA6, 0x7C, 0x6C, 0x74, 0x4C, +0x9D, 0xB1, 0xA5, 0xD2, 0x8C, 0xEE, 0x6C, 0x2B, +0x2A, 0x24, 0x53, 0x88, 0x53, 0xA7, 0x4B, 0x66, +0x53, 0x87, 0x63, 0xA8, 0x8C, 0xEE, 0x74, 0x4C, +0x7C, 0x8D, 0x85, 0x2F, 0x84, 0xEE, 0x9C, 0xF0, +0xC5, 0xB5, 0xAC, 0xF2, 0x83, 0x8D, 0x7B, 0x4C, +0x63, 0x0A, 0x7B, 0x8C, 0x83, 0xCD, 0x83, 0xCD, +0x94, 0x6F, 0xB5, 0x52, 0xBD, 0xD3, 0xC5, 0xF4, +0xBD, 0x92, 0xA4, 0x8E, 0x94, 0x0C, 0xA4, 0xCF, +0xB5, 0x31, 0xC5, 0x93, 0xB5, 0x10, 0xAC, 0xCF, +0xB4, 0xEF, 0xAC, 0xAF, 0xB4, 0xEF, 0xAC, 0xCF, +0x9C, 0x6E, 0x9C, 0x4D, 0xA4, 0xAE, 0xB5, 0x0F, +0xAC, 0xEF, 0xB5, 0x10, 0xAC, 0xEF, 0xAC, 0xCF, +0xAC, 0xCF, 0xA4, 0x8E, 0x9C, 0x6D, 0x9C, 0x4D, +0x94, 0x2D, 0x94, 0x2C, 0x8B, 0xEC, 0x8B, 0xCB, +0x94, 0x0C, 0x94, 0x2D, 0x9C, 0x2D, 0x8B, 0xEB, +0x8B, 0xCB, 0x83, 0xAB, 0x83, 0xAB, 0x83, 0xAB, +0x83, 0xCC, 0x83, 0xCB, 0x83, 0xCC, 0x94, 0x0D, +0x9C, 0x8E, 0x94, 0x2D, 0x8C, 0x0C, 0x9C, 0x6E, +0x94, 0x2D, 0x83, 0xCB, 0x7B, 0x8B, 0x83, 0xED, +0x94, 0x6E, 0xBD, 0x93, 0xCE, 0x14, 0xD6, 0x35, +0xD6, 0x55, 0xBD, 0x51, 0xC5, 0x70, 0xF6, 0xF7, +0xEE, 0xB6, 0xE6, 0x75, 0xDD, 0xF4, 0xDD, 0x93, +0xDD, 0xB3, 0xEE, 0x55, 0xE6, 0x75, 0xE6, 0x75, +0xE6, 0x75, 0xEE, 0x96, 0xD5, 0xF4, 0x73, 0x2A, +0x41, 0xE6, 0x39, 0xC6, 0x39, 0xE7, 0x4A, 0x28, +0x5A, 0xCB, 0x73, 0xAF, 0x9C, 0xF4, 0xAD, 0x97, +0xC6, 0x5A, 0xD6, 0x7B, 0xB5, 0x97, 0xC6, 0x39, +0xE7, 0x3C, 0xEF, 0x3B, 0xDE, 0xB8, 0xCD, 0xD4, +0xCD, 0xD3, 0xCD, 0xD3, 0xD5, 0xF4, 0xDE, 0x55, +0xE6, 0x75, 0xE6, 0x54, 0xE6, 0x34, 0xE6, 0x14, +0xE6, 0x34, 0xE6, 0x34, 0xE6, 0x35, 0x8B, 0xED, +0x9C, 0xF3, 0xC6, 0x18, 0xD6, 0x9A, 0xE6, 0xFC, +0xEF, 0x5D, 0xBD, 0xD6, 0xB5, 0x73, 0xB5, 0x52, +0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xF1, 0xA4, 0xF1, +0xAD, 0x12, 0xAD, 0x32, 0xAD, 0x53, 0x84, 0x0F, +0x31, 0x85, 0x9C, 0xD1, 0xB5, 0x53, 0xAD, 0x32, +0xA4, 0xF2, 0x9C, 0xD1, 0xB5, 0x73, 0xBD, 0x72, +0xB5, 0x10, 0x83, 0xAC, 0x73, 0x8C, 0x84, 0x0E, +0x52, 0x68, 0x5A, 0xA9, 0x42, 0x27, 0x39, 0xC6, +0x39, 0xA6, 0x42, 0x07, 0x4A, 0x48, 0x6B, 0x2C, +0x6B, 0x4D, 0x5A, 0xCB, 0x5A, 0xEB, 0x73, 0x6E, +0x7B, 0xAF, 0x6B, 0x4E, 0x9C, 0x92, 0xAD, 0x34, +0x9C, 0xB3, 0x9C, 0xB2, 0x9C, 0xB2, 0xBD, 0x75, +0x8C, 0x10, 0xAD, 0x34, 0xD6, 0xBA, 0x5A, 0xCB, +0x42, 0x07, 0x31, 0xC6, 0x39, 0xC6, 0x39, 0xE7, +0x42, 0x28, 0x42, 0x27, 0x4A, 0x48, 0x5A, 0xEB, +0x63, 0x4D, 0x7B, 0xCF, 0x8C, 0x51, 0x94, 0x72, +0x9C, 0xD3, 0xA5, 0x35, 0xBD, 0xF8, 0xCE, 0x39, +0xC5, 0xF7, 0xAD, 0x12, 0xB5, 0x12, 0xAC, 0xF1, +0xB5, 0x32, 0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x53, +0xBD, 0x73, 0xC5, 0xD4, 0xCD, 0xF5, 0xC5, 0xD4, +0xC5, 0xB4, 0xC5, 0xD4, 0xC5, 0xB4, 0xBD, 0x73, +0xB5, 0x52, 0xB5, 0x11, 0xC5, 0x93, 0xBD, 0x53, +0xB5, 0x52, 0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD5, 0xC5, 0xB4, 0xB5, 0x53, +0xB5, 0x53, 0xAC, 0xF1, 0x9C, 0x6F, 0x9C, 0x70, +0x9C, 0x6F, 0xA4, 0xB0, 0xA4, 0xAF, 0xB5, 0x11, +0xB5, 0x11, 0xAC, 0xCF, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xCF, 0xBD, 0x31, 0xBD, 0x30, 0xBD, 0x10, +0xBD, 0x30, 0xB5, 0x10, 0x8B, 0xED, 0x73, 0x4B, +0x73, 0x6C, 0x73, 0x4B, 0x73, 0x2B, 0x7B, 0x6B, +0x94, 0x2D, 0xAD, 0x11, 0x9C, 0x8F, 0xC5, 0xD4, +0xC5, 0xD4, 0xBD, 0x93, 0xBD, 0x73, 0xBD, 0x93, +0xBD, 0x93, 0xBD, 0x92, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x72, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x92, +0x94, 0x6D, 0xBD, 0x92, 0xD6, 0x14, 0xCD, 0xF4, +0xCD, 0xD3, 0xCD, 0xD4, 0xDE, 0x55, 0xB5, 0x51, +0xA4, 0xD0, 0x9C, 0x90, 0xD6, 0x36, 0xEE, 0xD7, +0xE6, 0xB7, 0xEE, 0xF8, 0x8C, 0x2F, 0x5A, 0xCB, +0x6B, 0x4C, 0x94, 0xB2, 0x9C, 0xB2, 0xC5, 0xD6, +0xE6, 0xB9, 0xDE, 0x99, 0xE6, 0xB9, 0xC5, 0xF6, +0x8C, 0x10, 0x9C, 0xD2, 0xBD, 0x73, 0xB5, 0x31, +0xAC, 0xF1, 0xB5, 0x11, 0xD6, 0x15, 0xDE, 0x55, +0xCD, 0xB3, 0xCE, 0x16, 0xC5, 0xF7, 0x9C, 0xF3, +0xAD, 0x13, 0xE6, 0xD9, 0xE6, 0xB7, 0xE6, 0xB6, +0xE7, 0x17, 0xCE, 0x95, 0x8D, 0x0E, 0x85, 0x0E, +0x85, 0x2E, 0x8D, 0x6F, 0x85, 0x0E, 0x74, 0x8B, +0x32, 0x65, 0x29, 0x84, 0x21, 0x44, 0x29, 0x85, +0x29, 0xA5, 0x29, 0xA4, 0x5B, 0xA9, 0x6C, 0x8B, +0x5B, 0xE9, 0x32, 0x84, 0x63, 0xCA, 0x42, 0xC6, +0x32, 0x65, 0x5B, 0xAA, 0x74, 0x6C, 0x6C, 0x4B, +0x43, 0x07, 0x5B, 0xE9, 0x5C, 0x09, 0x5B, 0xE8, +0x63, 0xE9, 0x5B, 0x89, 0x5B, 0x29, 0x5B, 0x29, +0x52, 0xC8, 0x7C, 0x4E, 0xA5, 0x91, 0xAD, 0x92, +0xA5, 0x11, 0x8C, 0x0E, 0x7B, 0x4C, 0x73, 0x0A, +0x6B, 0x0B, 0x6B, 0x2B, 0x6B, 0x6B, 0x83, 0xED, +0x8C, 0x2E, 0x94, 0x8E, 0xA5, 0x10, 0xB5, 0x51, +0xB5, 0x51, 0xB5, 0x31, 0xC5, 0xB3, 0xDE, 0x96, +0xC5, 0xF4, 0xBD, 0xB3, 0xC5, 0xB3, 0xBD, 0x91, +0xDE, 0x75, 0xD6, 0x34, 0xD6, 0x14, 0xCD, 0xF3, +0xD6, 0x14, 0xAC, 0xAF, 0xBD, 0x71, 0xEE, 0xB6, +0xD5, 0xF3, 0xCD, 0xD2, 0xC5, 0x91, 0xCD, 0xD2, +0xDE, 0x54, 0xDE, 0x34, 0xD5, 0xF3, 0xD6, 0x34, +0xCD, 0xB2, 0xB5, 0x10, 0xC5, 0x71, 0xC5, 0x71, +0xB5, 0x10, 0xD5, 0xF3, 0xCD, 0xD2, 0xC5, 0x92, +0xBD, 0x30, 0xBD, 0x51, 0xC5, 0x71, 0xBD, 0x30, +0xB5, 0x10, 0xB5, 0x10, 0xAC, 0xCF, 0xAC, 0xAF, +0xAC, 0xAE, 0xAC, 0xAE, 0xAC, 0xCF, 0xAC, 0xAE, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x6E, 0x9C, 0x6E, +0x94, 0x4D, 0x94, 0x0C, 0x94, 0x2D, 0x9C, 0x6E, +0xA4, 0xAE, 0xA4, 0x6D, 0xA4, 0x4C, 0xBD, 0x30, +0xBD, 0x51, 0xBD, 0x31, 0xB4, 0xAF, 0xA4, 0x2D, +0xAC, 0x8E, 0xBD, 0x10, 0xBD, 0x10, 0xBD, 0x10, +0xD5, 0xF4, 0xDE, 0x14, 0xDE, 0x34, 0xB5, 0x10, +0x83, 0xAB, 0x4A, 0x06, 0x42, 0x07, 0x42, 0x07, +0x42, 0x28, 0x5A, 0xCB, 0x73, 0xAE, 0x94, 0xB3, +0xAD, 0x96, 0x9C, 0xF4, 0xB5, 0xB7, 0xE7, 0x1C, +0xD6, 0x9A, 0xBD, 0xF7, 0xC6, 0x38, 0xCE, 0x17, +0xCD, 0xF5, 0xDE, 0x35, 0xE6, 0x96, 0xEE, 0x96, +0xEE, 0x75, 0xEE, 0x75, 0xE6, 0x54, 0xE6, 0x34, +0xDE, 0x13, 0xDD, 0xF3, 0xE6, 0x55, 0xB4, 0xF0, +0x7B, 0xAD, 0xA5, 0x14, 0xCE, 0x5A, 0xD6, 0x9A, +0xDE, 0xBB, 0xCE, 0x58, 0x9C, 0xD1, 0xAD, 0x12, +0xA4, 0xF1, 0xA4, 0xD1, 0xA4, 0xF1, 0x9C, 0xD1, +0x9C, 0xD1, 0xA4, 0xD1, 0xA4, 0xF1, 0x52, 0x68, +0x6B, 0x2C, 0xB5, 0x74, 0xAD, 0x32, 0xA5, 0x12, +0xA4, 0xF1, 0x9C, 0xB0, 0xAD, 0x52, 0xBD, 0x72, +0xB5, 0x10, 0x8C, 0x0D, 0x83, 0xCC, 0xAD, 0x31, +0x9C, 0x8F, 0x73, 0x6B, 0x4A, 0x27, 0x31, 0x85, +0x39, 0xE6, 0x42, 0x07, 0x52, 0x69, 0x4A, 0x48, +0x5A, 0xAA, 0x5A, 0xAA, 0x5A, 0xAB, 0x5A, 0xCB, +0x7B, 0xCF, 0x84, 0x10, 0xBD, 0x96, 0xC5, 0xD7, +0xB5, 0x34, 0xAD, 0x14, 0x94, 0x71, 0xAD, 0x13, +0x94, 0x51, 0x52, 0x8A, 0xAD, 0x35, 0xAD, 0x55, +0x42, 0x07, 0x31, 0xA6, 0x31, 0xC6, 0x39, 0xE7, +0x42, 0x27, 0x4A, 0x48, 0x52, 0x89, 0x63, 0x0C, +0x73, 0x8E, 0x73, 0x8E, 0x7B, 0xEF, 0x73, 0x8E, +0x7B, 0xF0, 0x94, 0x92, 0xB5, 0x76, 0xAD, 0x55, +0xAD, 0x55, 0x94, 0x2F, 0xAC, 0xF1, 0x83, 0xEE, +0x83, 0xEE, 0x6B, 0x4C, 0x63, 0x0A, 0x63, 0x0A, +0x6B, 0x4B, 0x6B, 0x2B, 0x6B, 0x2B, 0x6B, 0x2B, +0x73, 0x6C, 0x7B, 0xAD, 0x8C, 0x0E, 0x94, 0x4F, +0x9C, 0x6F, 0xA4, 0xD0, 0xC5, 0xD4, 0xDE, 0x97, +0xD6, 0x56, 0xAC, 0xF1, 0xA4, 0xD0, 0xA4, 0xAF, +0x9C, 0x8F, 0xAC, 0xF0, 0xB5, 0x32, 0xB5, 0x52, +0xAD, 0x11, 0xA4, 0xB0, 0xB4, 0xF0, 0xB5, 0x10, +0xAC, 0xF0, 0xAC, 0xF1, 0xAC, 0xD0, 0xB5, 0x11, +0xB5, 0x32, 0xB5, 0x11, 0xAC, 0xF0, 0xA4, 0xAF, +0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xD0, 0xAC, 0xD0, +0xAC, 0xF0, 0xAC, 0xF1, 0xB4, 0xF1, 0xAC, 0xF1, +0xA4, 0xB0, 0x9C, 0x6F, 0x8B, 0xEE, 0x8C, 0x0D, +0xA4, 0xB0, 0xAD, 0x12, 0xA4, 0xB0, 0x94, 0x4E, +0x8B, 0xED, 0x8B, 0xED, 0x8C, 0x0D, 0x8B, 0xED, +0x8C, 0x0D, 0x8C, 0x0D, 0x94, 0x2E, 0x94, 0x2E, +0x8C, 0x0D, 0x83, 0xED, 0x83, 0xEC, 0x94, 0x2D, +0x9C, 0xAF, 0xA4, 0xD0, 0xB5, 0x11, 0xBD, 0x72, +0xB5, 0x11, 0xA4, 0xAF, 0xBD, 0x92, 0xC5, 0xD3, +0x9C, 0x8F, 0x9C, 0x90, 0xC5, 0xD4, 0xF7, 0x18, +0xE6, 0xB7, 0xE6, 0x96, 0x9C, 0x70, 0x62, 0xCA, +0x5A, 0x89, 0x6B, 0x4C, 0x7B, 0xAE, 0xBD, 0x75, +0xCE, 0x17, 0xAD, 0x14, 0x8C, 0x51, 0x83, 0xEF, +0xBD, 0x96, 0xDE, 0xBA, 0xE6, 0xBA, 0xCD, 0xD6, +0xB5, 0x54, 0xA4, 0xB1, 0x8C, 0x0F, 0xAD, 0x13, +0xCE, 0x17, 0xA5, 0x14, 0x73, 0xAF, 0xD6, 0x78, +0xEF, 0x19, 0xEE, 0xD7, 0xE6, 0xB6, 0xE6, 0xB6, +0xE6, 0xD6, 0xE6, 0xF7, 0xCE, 0x95, 0x95, 0x2F, +0x85, 0x0E, 0x8D, 0x6F, 0x74, 0xCC, 0x74, 0x8B, +0x32, 0x04, 0x3A, 0x27, 0x3A, 0x07, 0x31, 0xC6, +0x31, 0xA5, 0x31, 0xE6, 0x32, 0x24, 0x5B, 0xE8, +0x64, 0x2A, 0x4B, 0x47, 0x32, 0x24, 0x42, 0x85, +0x29, 0xE3, 0x19, 0xA2, 0x3A, 0x85, 0x74, 0xAC, +0x53, 0x88, 0x53, 0xA8, 0x5B, 0xC8, 0x43, 0x05, +0x3A, 0xA4, 0x3A, 0x85, 0x5B, 0x28, 0x7C, 0x4D, +0x7C, 0x4D, 0xA5, 0x72, 0x9C, 0xF0, 0x94, 0x6F, +0x8C, 0x0E, 0x6B, 0x0A, 0x5A, 0x48, 0x6A, 0xA9, +0x62, 0xEA, 0x73, 0x8C, 0x7B, 0xAC, 0x94, 0x8F, +0x9C, 0xD0, 0x9C, 0xCF, 0x9C, 0xCF, 0xAD, 0x10, +0xA4, 0xF0, 0xA4, 0xF0, 0x94, 0x6E, 0xC5, 0xD4, +0xAD, 0x32, 0xB5, 0x52, 0xAD, 0x10, 0xAD, 0x10, +0xD6, 0x14, 0xCD, 0xF3, 0xCD, 0xF3, 0xBD, 0x91, +0xDE, 0x96, 0xAC, 0xAE, 0xC5, 0x71, 0xE6, 0x95, +0xE6, 0x74, 0xE6, 0x74, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x95, 0xE6, 0x75, 0xDE, 0x34, 0xE6, 0x95, +0xDE, 0x75, 0xD6, 0x13, 0xE6, 0x54, 0xE6, 0x74, +0xD6, 0x13, 0xEE, 0xB5, 0xE6, 0x74, 0xE6, 0x95, +0xE6, 0x54, 0xD5, 0xF2, 0xE6, 0x95, 0xC5, 0x70, +0xCD, 0xB1, 0xB5, 0x0F, 0xB4, 0xEF, 0xDE, 0x34, +0xCD, 0x92, 0xBD, 0x30, 0xB5, 0x30, 0xB5, 0x0F, +0xBD, 0x50, 0xBD, 0x30, 0xB5, 0x0F, 0xBD, 0x30, +0xBD, 0x10, 0xBD, 0x30, 0xBD, 0x30, 0xB5, 0x10, +0xB4, 0xEF, 0xBD, 0x30, 0xBD, 0x30, 0xB4, 0xCF, +0xAC, 0xAE, 0xAC, 0x8E, 0x9C, 0x4D, 0x9C, 0x4D, +0x9C, 0x4D, 0x9C, 0x4D, 0x9C, 0x4D, 0x9C, 0x2D, +0x93, 0xEB, 0x8B, 0xCB, 0x8B, 0xCB, 0x8B, 0xAA, +0x8B, 0xAA, 0x7B, 0x4A, 0x52, 0x47, 0x39, 0xC6, +0x39, 0xE7, 0x42, 0x28, 0x52, 0xAA, 0x6B, 0x8E, +0x84, 0x31, 0x94, 0xB3, 0xBD, 0xD7, 0xC6, 0x18, +0x84, 0x10, 0x8C, 0x51, 0x8C, 0x51, 0x73, 0x8E, +0xAC, 0xF2, 0xC5, 0x93, 0xCD, 0xB3, 0xDE, 0x34, +0xE6, 0x34, 0xE6, 0x54, 0xEE, 0x95, 0xEE, 0xB5, +0xEE, 0x95, 0xEE, 0x75, 0xE6, 0x34, 0xB4, 0xCF, +0xA4, 0xB0, 0x84, 0x10, 0xBD, 0xF7, 0xC6, 0x38, +0x94, 0x92, 0xB5, 0x96, 0xC5, 0xF8, 0xB5, 0x55, +0xAD, 0x33, 0xB5, 0x73, 0xAD, 0x32, 0xA4, 0xD1, +0xA4, 0xD1, 0x9C, 0xB0, 0x7B, 0xCD, 0x29, 0x44, +0x9C, 0xB1, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x32, +0x9C, 0xD1, 0x9C, 0xD0, 0x9C, 0xB0, 0xAC, 0xF0, +0xAC, 0xCF, 0xAC, 0xF0, 0xAC, 0xF0, 0xB5, 0x52, +0xBD, 0x72, 0xB5, 0x31, 0x83, 0xCD, 0x4A, 0x27, +0x42, 0x07, 0x4A, 0x28, 0x52, 0x69, 0x5A, 0xAA, +0x73, 0x8D, 0x5A, 0xCA, 0x5A, 0xCA, 0x52, 0x89, +0x6B, 0x4D, 0xA4, 0xD3, 0xAD, 0x14, 0xB5, 0x34, +0xD6, 0x18, 0xD6, 0x18, 0xC5, 0x96, 0x94, 0x71, +0x9C, 0xB3, 0x73, 0x8E, 0xB5, 0xB6, 0xBD, 0xD6, +0x52, 0xAA, 0x39, 0xC6, 0x31, 0xA6, 0x39, 0xC6, +0x42, 0x07, 0x42, 0x28, 0x5A, 0xCA, 0x73, 0xAE, +0x6B, 0x2C, 0x52, 0xAA, 0x52, 0xAA, 0x63, 0x0C, +0x6B, 0x6D, 0x8C, 0x51, 0x84, 0x31, 0xA5, 0x14, +0xB5, 0x96, 0xA4, 0xF3, 0xAD, 0x33, 0x9C, 0x90, +0xBD, 0x94, 0xB5, 0x73, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xAD, 0x32, 0x9C, 0xB1, 0x8C, 0x4F, +0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x2F, 0x9C, 0x90, +0x8C, 0x2F, 0xA4, 0xF1, 0xBD, 0x94, 0xBD, 0xD4, +0xD6, 0x77, 0xA4, 0xF1, 0x9C, 0xAF, 0xA4, 0xD0, +0xA4, 0xD0, 0x8C, 0x0D, 0x8C, 0x0D, 0x94, 0x6E, +0xB5, 0x31, 0x94, 0x2D, 0xBD, 0x30, 0xCD, 0xD2, +0xCD, 0xB2, 0xAC, 0xB0, 0xB5, 0x32, 0x9C, 0x8F, +0x94, 0x0D, 0xA4, 0xCF, 0xAD, 0x11, 0xAC, 0xF0, +0xAC, 0xF1, 0x9C, 0x4E, 0x9C, 0x6F, 0xB5, 0x32, +0xC5, 0xD4, 0xBD, 0x72, 0xC5, 0xB4, 0xC5, 0xD4, +0xCD, 0xF5, 0xCE, 0x15, 0xCD, 0xD4, 0xBD, 0x93, +0x9C, 0x8F, 0xAD, 0x11, 0xBD, 0x52, 0xBD, 0x52, +0xB5, 0x32, 0xB5, 0x32, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xF1, 0xAD, 0x12, +0xAD, 0x12, 0xA4, 0xD1, 0xA4, 0xB0, 0xA4, 0x90, +0x9C, 0x8F, 0x9C, 0x6F, 0x94, 0x4F, 0x8C, 0x0E, +0x94, 0x0E, 0x94, 0x0E, 0x94, 0x2E, 0x94, 0x0D, +0x83, 0xCD, 0x8C, 0x0E, 0x94, 0x2F, 0xAD, 0x11, +0xB5, 0x12, 0xB5, 0x31, 0xB5, 0x32, 0xAC, 0xF2, +0x8C, 0x2F, 0x5A, 0xCA, 0x5A, 0xAA, 0x9C, 0x92, +0x94, 0x51, 0x9C, 0xB2, 0x7B, 0xCE, 0x5A, 0xCB, +0xC5, 0xF7, 0xCE, 0x38, 0xD6, 0x59, 0xD6, 0x79, +0xEF, 0x3C, 0xDE, 0xBA, 0xD6, 0xBA, 0xE6, 0xFC, +0xC6, 0x18, 0x9C, 0xD3, 0xAD, 0x54, 0xDE, 0x97, +0xEE, 0xD7, 0xEE, 0xF7, 0xEE, 0xF7, 0xEE, 0xF7, +0xEE, 0xF7, 0xEE, 0xF7, 0xF7, 0x17, 0xCE, 0x75, +0x84, 0xEE, 0x95, 0x6F, 0x7C, 0xCD, 0x5B, 0xA9, +0x31, 0xC5, 0x42, 0x07, 0x42, 0x28, 0x52, 0x89, +0x52, 0xAA, 0x42, 0x47, 0x29, 0xE5, 0x4B, 0x47, +0x6C, 0x8B, 0x63, 0xEA, 0x52, 0xC6, 0x7C, 0x09, +0x53, 0x46, 0x2A, 0x44, 0x19, 0xA2, 0x4B, 0x27, +0x64, 0x09, 0x32, 0xA3, 0x32, 0xC4, 0x3A, 0xC3, +0x3A, 0xC4, 0x4B, 0x46, 0x74, 0x8B, 0x8D, 0x2D, +0x84, 0xCC, 0x6C, 0x09, 0x6B, 0xA9, 0x6B, 0x49, +0x62, 0xA9, 0x49, 0xC6, 0x52, 0x27, 0x7B, 0x4B, +0x6B, 0x4B, 0x7B, 0xAC, 0x83, 0xED, 0x9C, 0xD0, +0xAD, 0x32, 0xAD, 0x31, 0xA5, 0x10, 0xAD, 0x31, +0x9C, 0xAF, 0x94, 0x6E, 0x84, 0x0D, 0xAD, 0x32, +0xB5, 0x53, 0xA5, 0x11, 0xA5, 0x10, 0xB5, 0x71, +0xCD, 0xF3, 0xCD, 0xF3, 0xC5, 0x92, 0xAC, 0xEF, +0xCE, 0x14, 0xA4, 0x8E, 0xBD, 0x50, 0xE6, 0x75, +0xE6, 0x74, 0xEE, 0xB5, 0xE6, 0x74, 0xE6, 0x74, +0xE6, 0x74, 0xE6, 0xB6, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x95, 0xDE, 0x54, 0xE6, 0x74, 0xDE, 0x54, +0xDE, 0x13, 0xDE, 0x33, 0xD5, 0xF2, 0xDE, 0x33, +0xDE, 0x13, 0xD5, 0xD2, 0xE6, 0x74, 0xE6, 0x53, +0xE6, 0x95, 0xAC, 0xCE, 0xCD, 0x92, 0xCD, 0x72, +0xB4, 0xEF, 0xAC, 0xCF, 0xB5, 0x30, 0xC5, 0x72, +0xD5, 0xD3, 0xC5, 0x71, 0xB4, 0xEF, 0xC5, 0x71, +0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x71, +0xC5, 0x91, 0xCD, 0x92, 0xCD, 0x91, 0xC5, 0x51, +0xCD, 0xB2, 0xD6, 0x14, 0xBD, 0x51, 0xBD, 0x31, +0xDE, 0x14, 0xAC, 0xAE, 0xCD, 0xB2, 0xEE, 0x95, +0xDE, 0x34, 0xDE, 0x34, 0xCD, 0xD3, 0xBD, 0x51, +0xCD, 0xB3, 0xD5, 0xF4, 0xCD, 0xD4, 0x94, 0x2D, +0x41, 0xE6, 0x42, 0x28, 0x52, 0x89, 0x63, 0x0C, +0x63, 0x2C, 0x73, 0xAF, 0x94, 0xB3, 0x73, 0x6E, +0x7B, 0xCF, 0x6B, 0x4D, 0x7B, 0xAE, 0x73, 0xAE, +0x9C, 0xB2, 0xEF, 0x1B, 0xBD, 0x54, 0x94, 0x0D, +0x9C, 0x0C, 0xA4, 0x4D, 0xA4, 0x4D, 0xA4, 0x6D, +0xAC, 0x8E, 0xAC, 0xAE, 0xB4, 0xCF, 0xB4, 0xEF, +0xB5, 0x31, 0x8C, 0x0E, 0x8C, 0x51, 0xA5, 0x14, +0xBD, 0xD7, 0xDE, 0xFC, 0xE7, 0x1C, 0xC6, 0x18, +0xBD, 0xB5, 0xBD, 0x74, 0xBD, 0x72, 0xB5, 0x72, +0xC5, 0xD4, 0xB5, 0x53, 0x6B, 0x4B, 0x4A, 0x48, +0xBD, 0xD4, 0xD6, 0x56, 0xCD, 0xF4, 0xB5, 0x32, +0x94, 0x4E, 0x8C, 0x2E, 0x8C, 0x2E, 0xB5, 0x31, +0xAC, 0xEF, 0xC5, 0xB3, 0xB5, 0x51, 0xB5, 0x51, +0xBD, 0x72, 0xC5, 0xD4, 0xBD, 0x93, 0xAD, 0x32, +0x63, 0x0A, 0x52, 0x88, 0x4A, 0x68, 0x52, 0x69, +0x63, 0x0B, 0x6B, 0x2B, 0x63, 0x0B, 0x42, 0x07, +0x52, 0x68, 0x83, 0xAE, 0xAD, 0x14, 0x9C, 0x72, +0xDE, 0x59, 0xEE, 0xDB, 0xA4, 0x92, 0x8B, 0xEF, +0x9C, 0xB2, 0xAD, 0x55, 0xAD, 0x54, 0xC5, 0xF7, +0xC5, 0xF7, 0x5A, 0xCB, 0x39, 0xE7, 0x39, 0xE7, +0x41, 0xE7, 0x4A, 0x48, 0x63, 0x2C, 0x5A, 0xCA, +0x4A, 0x69, 0x52, 0x89, 0x52, 0xCA, 0x63, 0x2C, +0x73, 0x6E, 0x73, 0xAF, 0x8C, 0x72, 0xAD, 0x55, +0xBD, 0xD7, 0xCE, 0x38, 0x94, 0x70, 0x9C, 0xB1, +0xCE, 0x36, 0xCE, 0x15, 0xC5, 0xF5, 0xC5, 0xF5, +0xCE, 0x15, 0xCE, 0x15, 0xCD, 0xF5, 0xC5, 0xD4, +0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0x93, +0xAD, 0x32, 0xC5, 0xD4, 0xC5, 0xF5, 0xC5, 0xD4, +0xCE, 0x15, 0xA4, 0xD0, 0xAD, 0x11, 0xBD, 0xB3, +0xB5, 0x72, 0x9C, 0xAF, 0x9C, 0x8F, 0x94, 0x6E, +0xA4, 0xCF, 0xAC, 0xCF, 0xAC, 0xEF, 0xC5, 0x70, +0xC5, 0x91, 0xAC, 0xF0, 0xB5, 0x52, 0x9C, 0xAF, +0x9C, 0xAF, 0xAD, 0x11, 0xAC, 0xF0, 0xAD, 0x11, +0xAD, 0x11, 0xAC, 0xF1, 0x9C, 0xAF, 0x9C, 0xAF, +0xA4, 0xF0, 0x9C, 0xAF, 0xA4, 0xB0, 0xA4, 0xB0, +0xA4, 0xD0, 0xB5, 0x52, 0xBD, 0x73, 0xB5, 0x31, +0xAD, 0x10, 0xB5, 0x31, 0xAC, 0xF0, 0xC5, 0x92, +0xD6, 0x14, 0x9C, 0x8F, 0xA4, 0xB0, 0xAD, 0x11, +0xB5, 0x52, 0xB5, 0x32, 0xA4, 0xB0, 0xAD, 0x11, +0xBD, 0x93, 0xAD, 0x12, 0xBD, 0x93, 0xC5, 0xB4, +0xB5, 0x52, 0xAC, 0xF1, 0xA4, 0xF1, 0x8C, 0x0E, +0x9C, 0x90, 0xAC, 0xF1, 0xAC, 0xD1, 0xAC, 0xF1, +0xAD, 0x11, 0xAD, 0x32, 0xAD, 0x12, 0xAD, 0x12, +0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x33, 0xB5, 0x33, +0xAD, 0x32, 0xA4, 0xD2, 0x9C, 0xD2, 0xB5, 0x54, +0x41, 0xC7, 0x52, 0x69, 0x52, 0x89, 0x52, 0x69, +0x73, 0x8D, 0x73, 0x8E, 0x84, 0x10, 0xAD, 0x34, +0xA5, 0x14, 0xB5, 0x76, 0xDE, 0xDB, 0xE7, 0x3C, +0xE7, 0x1C, 0xE6, 0xFC, 0xC5, 0xD6, 0xB5, 0x53, +0xCD, 0xF5, 0xBD, 0x93, 0xBD, 0x73, 0xBD, 0x52, +0xBD, 0x52, 0xC5, 0x93, 0xCD, 0xF4, 0xCE, 0x35, +0x9D, 0x0F, 0x8D, 0x50, 0x9D, 0x91, 0x73, 0xEC, +0x39, 0xE6, 0x42, 0x48, 0x52, 0xCA, 0x42, 0x07, +0x52, 0xCA, 0x4A, 0xA9, 0x42, 0x88, 0x53, 0x88, +0x85, 0x0D, 0x4B, 0x27, 0x29, 0x82, 0x4A, 0xC5, +0x6C, 0x49, 0x4B, 0x67, 0x4B, 0x47, 0x32, 0xA4, +0x32, 0xA4, 0x2A, 0x42, 0x2A, 0x62, 0x3A, 0xE4, +0x43, 0x45, 0x6C, 0x6A, 0x74, 0xCB, 0x6C, 0x49, +0x4B, 0x65, 0x3A, 0xE3, 0x4B, 0x05, 0x63, 0x88, +0x6B, 0x09, 0x7B, 0x2B, 0x7B, 0x4C, 0x73, 0x0C, +0x6B, 0x4B, 0x7B, 0xCD, 0x7B, 0xED, 0xA4, 0xF1, +0xAD, 0x52, 0xAD, 0x32, 0xAD, 0x51, 0xB5, 0x72, +0xAD, 0x11, 0xAD, 0x52, 0xAD, 0x73, 0xAD, 0x52, +0xAD, 0x32, 0xBD, 0xD4, 0xAD, 0x31, 0xAD, 0x31, +0xCD, 0xF3, 0xCD, 0xD3, 0xBD, 0x72, 0xAD, 0x11, +0xCE, 0x14, 0xA4, 0x8E, 0xBD, 0x50, 0xE6, 0x74, +0xDE, 0x13, 0xE6, 0x74, 0xDE, 0x54, 0xE6, 0x54, +0xDE, 0x54, 0xE6, 0x75, 0xD6, 0x13, 0xE6, 0x75, +0xE6, 0xB6, 0xE6, 0x75, 0xDE, 0x33, 0xDE, 0x33, +0xDE, 0x33, 0xCD, 0xB1, 0xD5, 0xD1, 0xE6, 0x74, +0xEE, 0x95, 0xE6, 0x74, 0xDE, 0x13, 0xD5, 0xF2, +0xDE, 0x13, 0xB4, 0xCE, 0xBD, 0x30, 0xE6, 0x55, +0xCD, 0xB3, 0xC5, 0x52, 0xC5, 0x71, 0xBD, 0x51, +0xBD, 0x31, 0xB4, 0xEF, 0xBD, 0x10, 0xBD, 0x10, +0xBD, 0x30, 0xC5, 0x71, 0xC5, 0x71, 0xBD, 0x30, +0xBD, 0x10, 0xC5, 0x71, 0xBD, 0x30, 0xAC, 0xCF, +0xB4, 0xEF, 0xC5, 0x71, 0xE6, 0x95, 0xE6, 0x55, +0xE6, 0x75, 0xB4, 0xCF, 0xB4, 0xEF, 0xCD, 0xB2, +0xEE, 0x95, 0xCD, 0xB2, 0xBD, 0x51, 0xCD, 0xB3, +0xD5, 0xF4, 0xD5, 0xF4, 0xD6, 0x14, 0xDE, 0x34, +0xB5, 0x10, 0x5A, 0xA8, 0x4A, 0x48, 0x4A, 0x48, +0x42, 0x28, 0x4A, 0x69, 0x52, 0x8A, 0x42, 0x07, +0x4A, 0x69, 0x39, 0xC7, 0x52, 0x8A, 0x73, 0x8E, +0xAD, 0x55, 0xDE, 0xBA, 0xE6, 0xFB, 0xD6, 0x78, +0xBD, 0x74, 0xA4, 0x8F, 0xA4, 0x6E, 0x93, 0xEC, +0x9C, 0x4D, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0xB4, 0xF0, 0xAC, 0xF1, 0x83, 0xCE, 0x94, 0xB3, +0xCE, 0x59, 0xC6, 0x38, 0xE7, 0x1D, 0xE7, 0x3D, +0xC5, 0xD7, 0x8C, 0x0E, 0x94, 0x2D, 0x9C, 0x4D, +0x9C, 0x6E, 0xA5, 0x11, 0x52, 0x68, 0x73, 0x4B, +0xAC, 0xF0, 0xA4, 0x8E, 0xA4, 0xAF, 0xA4, 0xAF, +0x9C, 0x6F, 0x94, 0x4E, 0x83, 0xCB, 0xA4, 0x8E, +0xA4, 0x6D, 0x94, 0x2D, 0x9C, 0x4E, 0x9C, 0x6E, +0xAC, 0xF0, 0xBD, 0x93, 0xAD, 0x11, 0xA4, 0xCF, +0x8C, 0x2D, 0x8C, 0x2E, 0x52, 0x88, 0x4A, 0x27, +0x52, 0x69, 0x63, 0x0A, 0x73, 0x6C, 0x62, 0xCA, +0x4A, 0x07, 0x5A, 0x69, 0x83, 0x8E, 0x8C, 0x10, +0xA4, 0xF3, 0xA4, 0xD2, 0x83, 0xAF, 0x9C, 0x92, +0xAC, 0xF3, 0x83, 0xCF, 0x9C, 0xD3, 0xF7, 0x7D, +0xEF, 0x1B, 0x9C, 0xB3, 0x41, 0xE7, 0x42, 0x07, +0x39, 0xE7, 0x52, 0x89, 0x42, 0x27, 0x39, 0xA6, +0x39, 0xC6, 0x4A, 0x69, 0x5A, 0xCA, 0x62, 0xEB, +0x6B, 0x4D, 0x6B, 0x6D, 0x8C, 0x72, 0xA5, 0x35, +0xB5, 0x96, 0xCE, 0x79, 0xC5, 0xF6, 0xA4, 0xD1, +0xD6, 0x36, 0xCD, 0xF5, 0xC5, 0xD4, 0xCE, 0x14, +0xCE, 0x35, 0xCE, 0x15, 0xCE, 0x15, 0xCD, 0xF4, +0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0xB3, 0xBD, 0x73, +0xC5, 0xF5, 0xC5, 0xD4, 0xCD, 0xF4, 0xC5, 0xF4, +0xCE, 0x36, 0xA4, 0xF1, 0xB5, 0x73, 0xC5, 0xD3, +0xB5, 0x72, 0xBD, 0xB3, 0xAD, 0x11, 0xAD, 0x51, +0xAD, 0x31, 0xB5, 0x30, 0xB5, 0x50, 0xBD, 0x50, +0xCD, 0xB2, 0xA4, 0xAF, 0xAD, 0x11, 0x9C, 0xAF, +0x9C, 0xAF, 0xA4, 0xCF, 0xA4, 0xD0, 0xAD, 0x11, +0xB5, 0x72, 0xB5, 0x52, 0xAD, 0x11, 0xAD, 0x11, +0xB5, 0x73, 0xB5, 0x32, 0xB5, 0x32, 0xAD, 0x11, +0xA4, 0xD0, 0x9C, 0x8F, 0x8B, 0xED, 0xA4, 0xAF, +0xB5, 0x52, 0xB5, 0x31, 0xB5, 0x30, 0xCD, 0xB2, +0xCD, 0xD3, 0xB5, 0x12, 0xAD, 0x12, 0xC5, 0xD4, +0xCE, 0x15, 0xBD, 0xB4, 0xAD, 0x52, 0xBD, 0x93, +0xE6, 0xB7, 0xE6, 0xD7, 0xCE, 0x14, 0xE6, 0xB7, +0xE6, 0xB7, 0xD6, 0x56, 0xB5, 0x72, 0x8B, 0xED, +0xA4, 0x90, 0xBD, 0x93, 0xBD, 0x93, 0xC5, 0xF5, +0xBD, 0xB3, 0xBD, 0x93, 0xB5, 0x72, 0xBD, 0x93, +0xB5, 0x52, 0x8C, 0x0E, 0x9C, 0x70, 0xCE, 0x36, +0xC5, 0xF5, 0xC5, 0xD5, 0xB5, 0x94, 0x8C, 0x30, +0x84, 0x10, 0x9C, 0xD2, 0xA4, 0xD2, 0x9C, 0xB1, +0xB5, 0x53, 0x52, 0xA9, 0x4A, 0x28, 0x73, 0x8E, +0x5A, 0xCB, 0x73, 0xAF, 0x8C, 0x72, 0x8C, 0x52, +0x94, 0x93, 0xD6, 0xBB, 0xE6, 0xFB, 0xB5, 0x75, +0xB5, 0x75, 0xA4, 0xD2, 0xB5, 0x53, 0xAC, 0xF2, +0xA4, 0xB1, 0x9C, 0x70, 0x9C, 0x70, 0x9C, 0x90, +0xA5, 0x31, 0x9D, 0x92, 0x8C, 0xD0, 0x7B, 0xEE, +0x63, 0x2C, 0x5B, 0x0B, 0x52, 0xA9, 0x39, 0xE6, +0x31, 0x85, 0x31, 0xA5, 0x31, 0xC5, 0x53, 0x48, +0x85, 0x0D, 0x32, 0x44, 0x3A, 0x65, 0x63, 0xC9, +0x6C, 0x6A, 0x6C, 0x69, 0x64, 0x29, 0x5B, 0xE8, +0x43, 0x05, 0x4B, 0x67, 0x2A, 0x83, 0x43, 0x25, +0x53, 0xE7, 0x5C, 0x08, 0x4B, 0x65, 0x32, 0xC3, +0x32, 0xA2, 0x3A, 0xA3, 0x3A, 0xC4, 0x53, 0x66, +0x8C, 0x8D, 0x94, 0x6F, 0xAD, 0x34, 0xCE, 0x18, +0x83, 0xEE, 0x84, 0x0E, 0x84, 0x0E, 0x9C, 0xB0, +0xAD, 0x52, 0xAD, 0x52, 0xAD, 0x51, 0xAD, 0x52, +0xAD, 0x31, 0xAD, 0x52, 0xB5, 0x93, 0xAD, 0x52, +0xAD, 0x52, 0xC5, 0xF5, 0xA5, 0x11, 0xB5, 0x72, +0xC5, 0xD4, 0xCE, 0x14, 0xC5, 0xD3, 0xB5, 0x51, +0xBD, 0x92, 0xA4, 0x8D, 0xBD, 0x50, 0xE6, 0x95, +0xBD, 0x2F, 0xC5, 0x71, 0xDE, 0x34, 0xDE, 0x33, +0xD6, 0x33, 0xE6, 0x75, 0xE6, 0x95, 0xE6, 0x95, +0xE6, 0x95, 0xDE, 0x54, 0xDE, 0x13, 0xDE, 0x33, +0xDE, 0x53, 0xE6, 0x74, 0xC5, 0x91, 0xE6, 0x54, +0xE6, 0x95, 0xDE, 0x53, 0xD6, 0x12, 0xDE, 0x33, +0xE6, 0x74, 0xB4, 0xEE, 0xD6, 0x14, 0xD5, 0xF4, +0xCD, 0x92, 0xC5, 0x92, 0xC5, 0x51, 0xBD, 0x31, +0xB5, 0x10, 0x9C, 0x4D, 0xBD, 0x51, 0xBD, 0x31, +0xBD, 0x31, 0xBD, 0x10, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xCF, 0xB4, 0xF0, 0xB4, 0xEF, 0xB4, 0xCF, +0xBD, 0x30, 0xCD, 0xD3, 0xDE, 0x55, 0xE6, 0x75, +0xE6, 0x75, 0xAC, 0xCE, 0xBD, 0x30, 0xD5, 0xF3, +0xEE, 0xF7, 0xDE, 0x34, 0xCD, 0xB2, 0xCD, 0xD3, +0xD5, 0xF3, 0xD6, 0x14, 0xDE, 0x34, 0xDE, 0x34, +0xEE, 0xB6, 0xCD, 0xF4, 0x62, 0xE9, 0x31, 0x85, +0x31, 0x86, 0x39, 0xC7, 0x42, 0x07, 0x42, 0x28, +0x52, 0x69, 0x63, 0x2C, 0x73, 0xAE, 0x94, 0x71, +0x9C, 0xB3, 0xCE, 0x39, 0xCE, 0x59, 0xDE, 0xFB, +0xEF, 0x3C, 0xD6, 0x58, 0x94, 0x70, 0x8C, 0x30, +0x8C, 0x2F, 0x7B, 0x8C, 0x5A, 0xC9, 0x5A, 0xA8, +0x6B, 0x0A, 0x73, 0x4B, 0x5A, 0xA9, 0x84, 0x30, +0xCE, 0x7A, 0xD6, 0x7A, 0xD6, 0x9B, 0xDE, 0xFC, +0xE6, 0xFC, 0x7B, 0xAE, 0x7B, 0x8C, 0x94, 0x0D, +0x94, 0x2E, 0x8C, 0x4F, 0x39, 0xA5, 0x73, 0x8C, +0x94, 0x4D, 0x9C, 0x4D, 0xA4, 0x8E, 0xAC, 0xCF, +0xB4, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAF, +0x9C, 0x8E, 0x94, 0x4D, 0x9C, 0x4E, 0xA4, 0xAF, +0xA4, 0xCF, 0xA4, 0x8F, 0x94, 0x2D, 0x6B, 0x0A, +0x4A, 0x06, 0x62, 0xEA, 0x5A, 0xCA, 0x63, 0x0B, +0x4A, 0x28, 0x39, 0x85, 0x5A, 0xAA, 0x83, 0xEF, +0x94, 0x71, 0x73, 0x4D, 0x6B, 0x0C, 0x8C, 0x10, +0x8C, 0x10, 0x8B, 0xF0, 0x7B, 0xAE, 0x94, 0x92, +0xE6, 0xFB, 0xE7, 0x1B, 0x7B, 0xCF, 0x31, 0xA6, +0x39, 0xE7, 0x42, 0x28, 0x39, 0xE7, 0x42, 0x07, +0x41, 0xE7, 0x42, 0x28, 0x52, 0xAA, 0x5A, 0xCA, +0x6B, 0x4D, 0x84, 0x10, 0x84, 0x31, 0x9C, 0xD3, +0xAD, 0x56, 0xBD, 0xF8, 0xC5, 0xF7, 0xA4, 0xF2, +0xB5, 0x73, 0xC5, 0xB4, 0xB5, 0x72, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0x93, 0xB5, 0x73, 0xBD, 0x93, +0xB5, 0x52, 0xB5, 0x73, 0xBD, 0x93, 0xB5, 0x73, +0xBD, 0xB3, 0xC5, 0xD4, 0xCE, 0x35, 0xC6, 0x14, +0xC5, 0xF5, 0xA4, 0xD1, 0xBD, 0x93, 0xCE, 0x15, +0xB5, 0x51, 0x9C, 0xAF, 0x7B, 0xAB, 0xAD, 0x31, +0xBD, 0x92, 0xC5, 0xD3, 0xCD, 0xF3, 0xD6, 0x12, +0xDE, 0x54, 0x9C, 0x8F, 0xA4, 0xD0, 0x9C, 0xB0, +0xAD, 0x11, 0xAD, 0x31, 0xA4, 0xF0, 0xAD, 0x11, +0xB5, 0x52, 0xB5, 0x73, 0xB5, 0x73, 0xBD, 0x73, +0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x93, 0xB5, 0x52, +0xAD, 0x52, 0xB5, 0x52, 0x94, 0x6F, 0xA4, 0xB0, +0xB5, 0x32, 0xBD, 0x72, 0xBD, 0x71, 0xBD, 0x71, +0xCD, 0xB2, 0xB5, 0x32, 0xB5, 0x53, 0xD6, 0x76, +0xD6, 0x55, 0xC5, 0xF4, 0xBD, 0x93, 0xC5, 0xF5, +0xDE, 0x96, 0xCE, 0x14, 0xB5, 0x31, 0xC5, 0x92, +0xD5, 0xF3, 0xD6, 0x35, 0xA4, 0xD0, 0x9C, 0xB0, +0x9C, 0x90, 0xCE, 0x36, 0xD6, 0x76, 0xCE, 0x35, +0xCE, 0x14, 0xCD, 0xF3, 0xCE, 0x14, 0xCE, 0x14, +0xD6, 0x35, 0x94, 0x6F, 0xB5, 0x73, 0xB5, 0x74, +0xAD, 0x53, 0xBD, 0xB4, 0xCE, 0x57, 0xC6, 0x15, +0xB5, 0x94, 0x94, 0x90, 0x8C, 0x2F, 0x9C, 0x90, +0xBD, 0xB4, 0xB5, 0x94, 0xBD, 0xB4, 0xBD, 0xB5, +0xAD, 0x54, 0x8C, 0x50, 0x52, 0xAA, 0x42, 0x09, +0x4A, 0x4B, 0xAD, 0x56, 0xDE, 0xBB, 0xCE, 0x18, +0xBD, 0x96, 0xC5, 0xD6, 0xB5, 0x54, 0xA4, 0xD1, +0xAD, 0x12, 0xA5, 0x12, 0xAD, 0x12, 0xAD, 0x12, +0x9C, 0xD1, 0x84, 0x2E, 0x6B, 0x6C, 0x4A, 0x89, +0x41, 0xE7, 0x31, 0x85, 0x29, 0x85, 0x21, 0x24, +0x21, 0x44, 0x21, 0x44, 0x32, 0x06, 0x5B, 0x89, +0x64, 0x2A, 0x64, 0x2A, 0x95, 0x6F, 0x7C, 0xCC, +0x4B, 0x67, 0x6C, 0x6A, 0x7C, 0xCB, 0x6C, 0x6A, +0x4B, 0x87, 0x64, 0x2A, 0x3A, 0xC5, 0x32, 0x84, +0x3A, 0xE5, 0x43, 0x25, 0x4B, 0x86, 0x3A, 0xE4, +0x43, 0x25, 0x63, 0xA8, 0x53, 0x27, 0x42, 0xA4, +0x5B, 0x88, 0x6B, 0x4A, 0x9C, 0xD2, 0x8C, 0x71, +0x7B, 0xAD, 0x7B, 0xAD, 0x6B, 0x2B, 0x63, 0x2A, +0x94, 0x6E, 0x9C, 0xD0, 0x8C, 0x4E, 0x94, 0x8F, +0xA4, 0xD0, 0xAD, 0x32, 0xB5, 0x73, 0xB5, 0x73, +0xB5, 0x73, 0xBD, 0xB4, 0xAD, 0x32, 0xBD, 0xD4, +0xC5, 0xD3, 0xC5, 0xD3, 0xAD, 0x30, 0x9C, 0x8E, +0x9C, 0x6E, 0xA4, 0xAE, 0xBD, 0x50, 0xEE, 0xB5, +0xE6, 0x95, 0xE6, 0x95, 0xE6, 0x75, 0xD5, 0xF2, +0xDE, 0x54, 0xDE, 0x74, 0xE6, 0x75, 0xE6, 0xB6, +0xE6, 0x95, 0xDE, 0x54, 0xDE, 0x33, 0xD5, 0xD2, +0xCD, 0x91, 0xCD, 0xB1, 0xC5, 0x70, 0xD5, 0xD2, +0xDE, 0x33, 0xDE, 0x13, 0xCD, 0xB1, 0xD5, 0xD2, +0xB4, 0xCE, 0xA4, 0x4C, 0xDE, 0x14, 0xD5, 0xD3, +0xCD, 0x92, 0xD5, 0xF4, 0xD5, 0xF4, 0xCD, 0xB3, +0xD5, 0xF4, 0xC5, 0x93, 0xCD, 0xB3, 0xD5, 0xF4, +0xCD, 0xD3, 0xC5, 0x92, 0xC5, 0x52, 0xC5, 0x72, +0xC5, 0x52, 0xBD, 0x51, 0xC5, 0x72, 0xCD, 0x93, +0xC5, 0x72, 0xC5, 0x72, 0xCD, 0xD3, 0xE6, 0x96, +0xDE, 0x14, 0xA4, 0x8D, 0xDE, 0x13, 0xE6, 0x54, +0xEE, 0xB6, 0xEE, 0xB6, 0xEE, 0xB6, 0xEE, 0x96, +0xE6, 0x95, 0xEE, 0x95, 0xEE, 0x95, 0xDE, 0x54, +0xE6, 0x75, 0xF6, 0xD7, 0xEE, 0xB7, 0xB5, 0x31, +0x5A, 0x88, 0x39, 0xC6, 0x39, 0xC6, 0x31, 0xA6, +0x39, 0xE7, 0x52, 0xAA, 0x5A, 0xEB, 0x7B, 0xCF, +0x8C, 0x72, 0x9C, 0xD3, 0xA5, 0x14, 0xC6, 0x39, +0xAD, 0x55, 0xD6, 0x9A, 0xE7, 0x3C, 0xD6, 0x9A, +0xC6, 0x17, 0xB5, 0x74, 0x94, 0xB1, 0x84, 0x0F, +0x84, 0x0E, 0x84, 0x2F, 0x73, 0x8D, 0x73, 0xAE, +0xA5, 0x35, 0xCE, 0x7A, 0xD6, 0xBB, 0xE7, 0x1D, +0xDE, 0xFC, 0xB5, 0x76, 0x83, 0xEF, 0x73, 0x8D, +0x94, 0x70, 0x73, 0x6C, 0x39, 0xC6, 0x8C, 0x2F, +0x8C, 0x2E, 0x83, 0xEE, 0x8C, 0x0E, 0x83, 0xCC, +0x83, 0xAC, 0x83, 0xAB, 0x7B, 0x8B, 0x7B, 0x8B, +0x7B, 0x8B, 0x83, 0xCC, 0x94, 0x2E, 0xA4, 0xCF, +0x8C, 0x0C, 0xA4, 0x6E, 0xA4, 0x8E, 0xA4, 0xAF, +0xA4, 0xAF, 0xAC, 0xAF, 0xAC, 0xEF, 0xB5, 0x10, +0x94, 0x2E, 0x5A, 0xA8, 0x52, 0x68, 0x52, 0x69, +0x42, 0x07, 0x4A, 0x48, 0x6B, 0x2C, 0x5A, 0xAA, +0x52, 0x49, 0x52, 0x69, 0x62, 0xCB, 0x83, 0xAE, +0xA4, 0xD2, 0x9C, 0x92, 0x9C, 0xB2, 0x83, 0xCF, +0x94, 0x92, 0xCE, 0x57, 0x83, 0xEF, 0x5A, 0xCA, +0x39, 0xE7, 0x31, 0xA6, 0x31, 0xA6, 0x39, 0xE6, +0x39, 0xE7, 0x42, 0x27, 0x52, 0x89, 0x63, 0x0B, +0x63, 0x0C, 0x6B, 0x6D, 0x73, 0xAF, 0x8C, 0x92, +0xA5, 0x35, 0xAD, 0x56, 0xA5, 0x14, 0xB5, 0x75, +0xB5, 0x94, 0xA4, 0xD1, 0xAD, 0x32, 0xB5, 0x53, +0x9C, 0x90, 0xB5, 0x73, 0xAD, 0x11, 0xA4, 0xF1, +0x9C, 0x90, 0x9C, 0xB0, 0xA4, 0xF1, 0xAD, 0x11, +0xB5, 0x52, 0xBD, 0x93, 0xC5, 0xF4, 0xCE, 0x35, +0xC5, 0xB4, 0xAC, 0xF1, 0xBD, 0xB3, 0xC5, 0xF3, +0xB5, 0x92, 0x94, 0x4E, 0x94, 0x6E, 0xAD, 0x31, +0xB5, 0x92, 0xBD, 0xB2, 0xBD, 0x71, 0xBD, 0x70, +0xD6, 0x13, 0xA4, 0xD0, 0xAD, 0x11, 0xA4, 0xF0, +0xAD, 0x32, 0xA4, 0xF1, 0xB5, 0x72, 0xBD, 0xB4, +0xBD, 0xB3, 0xC5, 0xD4, 0xC5, 0xD4, 0xC5, 0xD4, +0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0x93, 0xBD, 0xB3, +0xC5, 0xD4, 0xC5, 0xD4, 0xBD, 0x93, 0xC5, 0xF5, +0xBD, 0x93, 0xB5, 0x52, 0xB5, 0x51, 0xBD, 0x51, +0xC5, 0x92, 0xB5, 0x31, 0xBD, 0x93, 0xC5, 0xF4, +0xCE, 0x14, 0xC5, 0xD4, 0xB5, 0x93, 0xCE, 0x15, +0xC5, 0xD4, 0xB5, 0x31, 0xDE, 0x35, 0xC5, 0x71, +0xCD, 0x92, 0xCD, 0xD3, 0xB5, 0x52, 0xB5, 0x53, +0xBD, 0xB4, 0xC5, 0xF4, 0xC5, 0xD3, 0xBD, 0xB3, +0xCD, 0xF4, 0xCD, 0xF3, 0xD6, 0x14, 0xD6, 0x14, +0xCD, 0xF4, 0x9C, 0xB0, 0xA5, 0x12, 0xA4, 0xF1, +0xB5, 0x53, 0xBD, 0xB4, 0xC6, 0x15, 0xC5, 0xD4, +0xC5, 0xF5, 0xAD, 0x53, 0xA4, 0xD1, 0xB5, 0x74, +0xBD, 0xD5, 0xBD, 0xF5, 0xCE, 0x56, 0xCE, 0x36, +0xBD, 0xD5, 0x94, 0x70, 0x6B, 0x4C, 0x39, 0xC7, +0x4A, 0x4A, 0xB5, 0x76, 0xAD, 0x55, 0xBD, 0x96, +0xC6, 0x18, 0xAD, 0x54, 0xB5, 0x54, 0xBD, 0xB5, +0xC5, 0xF6, 0xAD, 0x53, 0x8C, 0x50, 0x6B, 0x4C, +0x63, 0x0B, 0x7B, 0xAD, 0x73, 0x6D, 0x42, 0x08, +0x42, 0x28, 0x39, 0xC6, 0x39, 0xE7, 0x29, 0x64, +0x21, 0x44, 0x21, 0x44, 0x53, 0x49, 0x6C, 0x6B, +0x74, 0xCB, 0x85, 0x2E, 0x95, 0xB0, 0x6C, 0x6B, +0x21, 0xE3, 0x21, 0xC3, 0x4B, 0x47, 0x53, 0x87, +0x43, 0x26, 0x43, 0x26, 0x3A, 0xE6, 0x19, 0xC3, +0x21, 0xE3, 0x3A, 0xE5, 0x64, 0x2A, 0x53, 0xE8, +0x5C, 0x09, 0x6C, 0x2A, 0x5B, 0x68, 0x42, 0x85, +0x53, 0x06, 0x5B, 0xA8, 0x5B, 0x88, 0x4B, 0x08, +0x7B, 0xCD, 0x8C, 0x0E, 0x8C, 0x2F, 0x8C, 0x0E, +0x8C, 0x0D, 0x8C, 0x0E, 0x94, 0x2E, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x4E, 0x8C, 0x2D, 0x84, 0x0D, +0x83, 0xED, 0x84, 0x0D, 0x8C, 0x2E, 0x9C, 0x8F, +0x94, 0x6E, 0x94, 0x2D, 0x8C, 0x0C, 0x8B, 0xEC, +0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0x8D, 0xDE, 0x33, +0xE6, 0x95, 0xE6, 0x95, 0xE6, 0x75, 0xE6, 0x75, +0xEE, 0xB6, 0xE6, 0xB5, 0xE6, 0xB6, 0xE6, 0xB6, +0xEE, 0xD6, 0xEE, 0xB6, 0xE6, 0x95, 0xE6, 0x74, +0xD6, 0x13, 0xC5, 0x91, 0xCD, 0xD2, 0xD6, 0x13, +0xEE, 0xB6, 0xD5, 0xF3, 0xC5, 0x71, 0xC5, 0x71, +0xBD, 0x0F, 0xA4, 0x6D, 0xCD, 0xB2, 0xCD, 0xB2, +0xCD, 0xB2, 0xDE, 0x14, 0xD5, 0xF4, 0xD6, 0x14, +0xC5, 0x92, 0xC5, 0x93, 0xAC, 0xD0, 0xD5, 0xF4, +0xCD, 0xD4, 0xCD, 0xD3, 0xCD, 0xB3, 0xCD, 0xB3, +0xCD, 0xB3, 0xCD, 0x93, 0xC5, 0x92, 0xCD, 0xB3, +0xCD, 0xB3, 0xD5, 0xD3, 0xCD, 0xB2, 0xDE, 0x14, +0xD5, 0xF3, 0xA4, 0x8D, 0xDE, 0x34, 0xE6, 0x75, +0xEE, 0xB6, 0xEE, 0x96, 0xEE, 0x95, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x95, +0xE6, 0x75, 0xE6, 0x95, 0xEE, 0xD6, 0xEE, 0xD6, +0xE6, 0x75, 0x9C, 0x6E, 0x4A, 0x07, 0x39, 0xA6, +0x39, 0xE7, 0x42, 0x07, 0x42, 0x07, 0x5A, 0xCB, +0x63, 0x2D, 0x7B, 0xF0, 0x8C, 0x72, 0xAD, 0x55, +0xC6, 0x19, 0xAD, 0x56, 0xCE, 0x7A, 0xE7, 0x1C, +0xEF, 0x3C, 0xCE, 0x38, 0x9C, 0xD2, 0x8C, 0x50, +0x9C, 0xD1, 0xA5, 0x12, 0xA5, 0x12, 0x9C, 0xD1, +0x73, 0xAE, 0xAD, 0x76, 0xC6, 0x3A, 0xEF, 0x5E, +0xF7, 0x9E, 0xE7, 0x3D, 0xB5, 0x75, 0xAD, 0x33, +0xA4, 0xF2, 0x4A, 0x48, 0x73, 0x8D, 0xBD, 0xD5, +0xBD, 0xB4, 0xB5, 0x74, 0xAD, 0x53, 0xA4, 0xF1, +0xAD, 0x32, 0xB5, 0x53, 0xAD, 0x32, 0xA4, 0xF1, +0xB5, 0x53, 0xBD, 0xB4, 0xB5, 0x53, 0xAD, 0x31, +0x9C, 0x8F, 0x9C, 0x6E, 0x8C, 0x0C, 0x94, 0x4E, +0x94, 0x2E, 0x9C, 0x8F, 0xA4, 0xD0, 0xA4, 0xCF, +0xC5, 0xD4, 0xBD, 0x92, 0x63, 0x0A, 0x4A, 0x27, +0x4A, 0x27, 0x5A, 0xAA, 0x63, 0x0B, 0x5A, 0xCA, +0x52, 0x89, 0x52, 0x49, 0x6B, 0x2C, 0x7B, 0x8E, +0x83, 0xCF, 0x73, 0x4D, 0x94, 0x51, 0xBD, 0x95, +0x94, 0x71, 0x62, 0xEB, 0xB5, 0x96, 0x9C, 0xB2, +0x4A, 0x28, 0x42, 0x28, 0x3A, 0x07, 0x31, 0xA5, +0x39, 0xC6, 0x39, 0xE7, 0x42, 0x28, 0x4A, 0x49, +0x4A, 0x49, 0x63, 0x0C, 0x73, 0xAF, 0x84, 0x51, +0x9D, 0x15, 0xB5, 0x96, 0xAD, 0x76, 0xC5, 0xF7, +0xCE, 0x78, 0xAD, 0x55, 0x73, 0x8D, 0x9C, 0x91, +0x52, 0x68, 0x94, 0x70, 0x9C, 0x90, 0x9C, 0xB0, +0x9C, 0x90, 0x9C, 0x6F, 0xA4, 0xB1, 0xA4, 0xD1, +0xA4, 0xB0, 0xBD, 0xB4, 0xC5, 0xF4, 0xC5, 0xD4, +0xC5, 0xD4, 0xA4, 0xB0, 0xAD, 0x11, 0xC6, 0x14, +0xCE, 0x55, 0xC5, 0xF4, 0xCE, 0x35, 0xD6, 0x55, +0xD6, 0x55, 0xD6, 0x54, 0xD6, 0x13, 0xD6, 0x13, +0xDE, 0x74, 0xA4, 0xAF, 0xA4, 0xF1, 0xA4, 0xF0, +0xAD, 0x31, 0xB5, 0x52, 0xBD, 0x93, 0xB5, 0x72, +0xBD, 0xB3, 0xBD, 0xD4, 0xC5, 0xD4, 0xBD, 0xB4, +0xC5, 0xF5, 0xC5, 0xF4, 0xC5, 0xD4, 0xC5, 0xF5, +0xBD, 0x93, 0xB5, 0x32, 0xAD, 0x11, 0xC5, 0xF4, +0xB5, 0x52, 0xBD, 0x73, 0xBD, 0x72, 0xC5, 0x92, +0xC5, 0x92, 0xB5, 0x11, 0xB5, 0x52, 0xC5, 0xF4, +0xC5, 0xF4, 0xBD, 0x93, 0xB5, 0x73, 0xBD, 0x93, +0xB5, 0x72, 0xA4, 0xAF, 0xD6, 0x14, 0xD5, 0xB2, +0xCD, 0x72, 0xCD, 0xF3, 0xC5, 0xD4, 0xC5, 0xD4, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xB3, 0xCE, 0x14, +0xCE, 0x14, 0xCD, 0xF3, 0xD6, 0x34, 0xD6, 0x55, +0xC5, 0xB3, 0x9C, 0xB1, 0x9C, 0xD1, 0x94, 0x90, +0xA4, 0xF2, 0xB5, 0x53, 0xB5, 0x93, 0xB5, 0x93, +0xB5, 0x73, 0xB5, 0x73, 0xA5, 0x12, 0xC6, 0x15, +0xC5, 0xF5, 0xCE, 0x36, 0xDE, 0x97, 0xC5, 0xF5, +0x9C, 0xD1, 0x83, 0xEE, 0xC5, 0xD5, 0x7B, 0xCE, +0x42, 0x08, 0x9C, 0xB3, 0x9C, 0xD3, 0xBD, 0xD7, +0xB5, 0x75, 0xBD, 0x96, 0xA4, 0xF3, 0x7B, 0xEF, +0x63, 0x0C, 0x5A, 0xCB, 0x9C, 0xD1, 0xC5, 0xF5, +0xE6, 0xB8, 0xD6, 0x16, 0xAC, 0xF2, 0x94, 0x92, +0x73, 0xAE, 0x39, 0xE7, 0x42, 0x48, 0x42, 0x07, +0x31, 0xC6, 0x31, 0xA5, 0x74, 0x4C, 0x85, 0x0D, +0x95, 0xB0, 0xA6, 0x11, 0x9D, 0xD0, 0x5B, 0xC8, +0x32, 0x65, 0x2A, 0x04, 0x3A, 0xC5, 0x5B, 0xC8, +0x5B, 0xC8, 0x4B, 0x47, 0x4B, 0x67, 0x32, 0x85, +0x2A, 0x44, 0x32, 0x84, 0x5B, 0xE9, 0x5C, 0x09, +0x5C, 0x29, 0x64, 0x08, 0x64, 0x08, 0x7C, 0x6B, +0xC6, 0x33, 0x95, 0x0E, 0x5B, 0xA7, 0x5B, 0xC7, +0x73, 0x6B, 0x8C, 0x2E, 0x9C, 0x6F, 0x9C, 0x6F, +0xAD, 0x12, 0x9C, 0x6F, 0x94, 0x4E, 0x9C, 0x8F, +0x9C, 0x8F, 0xA4, 0xF1, 0xB5, 0x52, 0xBD, 0x73, +0xAC, 0xF1, 0xA4, 0xB0, 0xA4, 0xD0, 0xA4, 0xAF, +0xA4, 0xAF, 0xA4, 0xAE, 0xAC, 0xCF, 0xA4, 0xAE, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0x6D, 0x9C, 0x4C, +0x9C, 0x6D, 0xA4, 0xAE, 0xAC, 0xCE, 0xAC, 0xCF, +0xB4, 0xEF, 0xB5, 0x30, 0xBD, 0x50, 0xBD, 0x71, +0xC5, 0xB2, 0xCD, 0xD2, 0xD5, 0xF3, 0xD5, 0xF3, +0xD6, 0x14, 0xD6, 0x34, 0xD6, 0x34, 0xDE, 0x55, +0xE6, 0x96, 0xEE, 0xB6, 0xE6, 0x95, 0xC5, 0x51, +0xCD, 0xD2, 0xAC, 0xAE, 0xE6, 0x96, 0xCD, 0xD3, +0xDE, 0x35, 0xD5, 0xF4, 0xDE, 0x35, 0xD6, 0x14, +0x9C, 0x4D, 0xC5, 0x93, 0xCD, 0xD4, 0xD5, 0xF4, +0xCD, 0xD4, 0xD5, 0xF4, 0xD5, 0xD4, 0xD5, 0xD4, +0xD5, 0xD4, 0xD5, 0xD4, 0xD5, 0xF4, 0xD5, 0xF4, +0xD5, 0xF4, 0xDE, 0x14, 0xD5, 0xF4, 0xD5, 0xF3, +0xDE, 0x34, 0xA4, 0x6D, 0xDE, 0x54, 0xE6, 0x95, +0xEE, 0x95, 0xEE, 0x95, 0xEE, 0x95, 0xE6, 0x95, +0xDE, 0x13, 0xEE, 0x95, 0xE6, 0x95, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x75, 0xEE, 0xB6, 0xDE, 0x33, +0xE6, 0x95, 0xF6, 0xD7, 0xCD, 0xD3, 0x7B, 0x6B, +0x41, 0xE6, 0x31, 0x85, 0x31, 0xA6, 0x42, 0x08, +0x5A, 0xCB, 0x5B, 0x0C, 0x73, 0x8E, 0x7B, 0xF0, +0x94, 0xB3, 0xB5, 0xB7, 0xCE, 0x5A, 0xCE, 0x7A, +0xDE, 0xDC, 0xEF, 0x5D, 0xE7, 0x1C, 0xAD, 0x75, +0x94, 0x91, 0x9C, 0xF2, 0xB5, 0x53, 0xB5, 0x74, +0x7B, 0xEE, 0x84, 0x51, 0xC6, 0x39, 0xDE, 0xDC, +0xBE, 0x18, 0xC6, 0x19, 0xCE, 0x59, 0xAD, 0x54, +0x94, 0x70, 0x39, 0xC6, 0x94, 0x90, 0xA5, 0x12, +0xAD, 0x52, 0xB5, 0x73, 0xB5, 0x73, 0xAD, 0x52, +0xA5, 0x11, 0xB5, 0x73, 0xBD, 0xB4, 0xBD, 0x93, +0xB5, 0x94, 0xAD, 0x73, 0xAD, 0x32, 0xA4, 0xF1, +0xAD, 0x32, 0xA4, 0xAF, 0x7B, 0x6B, 0x6B, 0x6C, +0x73, 0x6C, 0x73, 0x8D, 0x83, 0xEE, 0x7B, 0xEE, +0x9C, 0xB0, 0xAD, 0x32, 0x9C, 0xB0, 0x6B, 0x4B, +0x52, 0x68, 0x4A, 0x68, 0x4A, 0x48, 0x52, 0x89, +0x7B, 0x8D, 0x6B, 0x2C, 0x5A, 0x8A, 0x83, 0xEF, +0x83, 0xCE, 0x83, 0xAE, 0x9C, 0x71, 0xBD, 0x75, +0xCD, 0xD7, 0xA4, 0xB2, 0xA4, 0xB2, 0x73, 0x6D, +0x5A, 0xEA, 0x42, 0x07, 0x3A, 0x07, 0x31, 0xA6, +0x39, 0xE7, 0x42, 0x28, 0x52, 0xAA, 0x4A, 0x69, +0x52, 0xAA, 0x63, 0x2C, 0x73, 0xAF, 0x84, 0x11, +0x94, 0xB3, 0xA5, 0x15, 0x8C, 0x72, 0xB5, 0x96, +0xC6, 0x17, 0xC5, 0xF7, 0x84, 0x10, 0x73, 0x6D, +0x4A, 0x48, 0xAD, 0x33, 0xCD, 0xF6, 0xAD, 0x32, +0xAC, 0xF1, 0xA4, 0xD1, 0xA4, 0xB0, 0xA4, 0xB0, +0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x90, 0x94, 0x6F, +0x9C, 0x8F, 0xA4, 0xB0, 0x9C, 0x6F, 0x94, 0x2E, +0x8C, 0x2E, 0x94, 0x4E, 0x94, 0x4E, 0x94, 0x4E, +0x9C, 0x6E, 0x9C, 0x8E, 0x9C, 0x8F, 0xA4, 0xCF, +0x9C, 0xAF, 0x94, 0x2E, 0x8C, 0x2E, 0x8C, 0x0D, +0x8C, 0x0D, 0x8C, 0x2E, 0x8C, 0x0D, 0x83, 0xCC, +0x8C, 0x2E, 0x94, 0x6F, 0x9C, 0xB0, 0xA4, 0xF1, +0xA4, 0xF1, 0x9C, 0xB0, 0xA4, 0xD0, 0xAD, 0x32, +0xB5, 0x72, 0xBD, 0x93, 0xAD, 0x31, 0xA4, 0xD0, +0xC5, 0xB4, 0xC5, 0xB4, 0xCD, 0xF3, 0xC5, 0x92, +0xCD, 0xB3, 0xAD, 0x11, 0x9C, 0xAF, 0xCE, 0x35, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xF5, 0xC5, 0xF5, +0xBD, 0xB4, 0xBD, 0x92, 0xCD, 0xB3, 0xD5, 0xD3, +0xBD, 0x51, 0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xD4, +0xCE, 0x14, 0xCD, 0xF4, 0xC5, 0xF4, 0xCE, 0x14, +0xC5, 0xB3, 0xD6, 0x55, 0xD6, 0x55, 0xDE, 0x75, +0xC5, 0xD3, 0xA4, 0xF2, 0xA4, 0xF2, 0x94, 0x70, +0x9C, 0xD1, 0xAD, 0x53, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x74, 0xAD, 0x33, 0xA4, 0xF2, 0xAD, 0x32, +0xB5, 0x93, 0xC5, 0xF5, 0xD6, 0x76, 0xCE, 0x56, +0xD6, 0x57, 0xD6, 0x77, 0xEF, 0x1A, 0xC5, 0xF6, +0xAD, 0x75, 0xD6, 0x79, 0xB5, 0x96, 0xA5, 0x14, +0x83, 0xF0, 0x63, 0x0C, 0x5A, 0xCB, 0x5A, 0xEC, +0x8C, 0x72, 0xC6, 0x17, 0xDE, 0xB8, 0xDE, 0x97, +0xE6, 0xB8, 0xB5, 0x12, 0xD6, 0x38, 0xDE, 0xDB, +0xA5, 0x34, 0x42, 0x07, 0x42, 0x07, 0x3A, 0x07, +0x21, 0x64, 0x21, 0x64, 0x7C, 0x8D, 0x74, 0xAC, +0x6C, 0x6B, 0x7C, 0xED, 0x8D, 0x4E, 0x4B, 0x67, +0x3A, 0x85, 0x21, 0xC3, 0x43, 0x06, 0x63, 0xE9, +0x2A, 0x44, 0x2A, 0x44, 0x5B, 0xC9, 0x5B, 0xA9, +0x32, 0x65, 0x2A, 0x04, 0x3A, 0xC5, 0x4B, 0x67, +0x53, 0xA8, 0x53, 0xA7, 0x53, 0xA6, 0x84, 0x8C, +0xEF, 0x38, 0xE7, 0x17, 0x7C, 0x4B, 0x53, 0x86, +0x62, 0xEA, 0x5A, 0x89, 0x83, 0xCD, 0x94, 0x2E, +0x94, 0x4F, 0x52, 0x68, 0x5A, 0x88, 0x7B, 0x8C, +0x83, 0xAC, 0x73, 0x4B, 0x94, 0x6F, 0xDE, 0x77, +0xCE, 0x15, 0x9C, 0x4E, 0xAC, 0xD0, 0xA4, 0x6E, +0xA4, 0x6E, 0xA4, 0xAF, 0xC5, 0xB2, 0xC5, 0xB2, +0xC5, 0x92, 0xCD, 0xF3, 0xCD, 0xB3, 0xCD, 0xD3, +0xCD, 0xD3, 0xC5, 0xB2, 0xC5, 0xB2, 0xC5, 0xB2, +0xC5, 0x91, 0xB5, 0x30, 0xB5, 0x10, 0xBD, 0x71, +0xB4, 0xF0, 0xAC, 0xCF, 0xB4, 0xEF, 0xAC, 0xCF, +0xA4, 0x8E, 0xA4, 0x6D, 0xA4, 0x6E, 0xA4, 0x6E, +0xA4, 0x6D, 0xA4, 0x6D, 0xA4, 0x6D, 0xAC, 0x8E, +0xA4, 0x8D, 0xA4, 0x8E, 0xB5, 0x0F, 0xAC, 0xAE, +0xA4, 0x8E, 0x9C, 0x2C, 0x94, 0x2C, 0x9C, 0x2D, +0x9C, 0x4D, 0x8B, 0xCB, 0x94, 0x0C, 0x9C, 0x2D, +0x9C, 0x2D, 0xA4, 0x6E, 0xAC, 0xAF, 0xB4, 0xCF, +0xBD, 0x31, 0xC5, 0x72, 0xBD, 0x51, 0xCD, 0xD4, +0xCD, 0xB3, 0xCD, 0xD3, 0xCD, 0xF3, 0xD5, 0xF4, +0xE6, 0x95, 0xAC, 0x8E, 0xE6, 0x95, 0xF6, 0xF6, +0xEE, 0xD6, 0xEE, 0xD6, 0xEE, 0xD6, 0xEE, 0xB6, +0xEE, 0xB6, 0xEE, 0xD6, 0xDE, 0x34, 0xE6, 0x75, +0xEE, 0x95, 0xEE, 0x95, 0xE6, 0x75, 0xE6, 0x54, +0xE6, 0x74, 0xE6, 0x74, 0xEE, 0x95, 0xEE, 0x96, +0xB5, 0x10, 0x62, 0xA9, 0x39, 0xA5, 0x31, 0xA6, +0x31, 0xC6, 0x3A, 0x07, 0x4A, 0x69, 0x52, 0xAB, +0x6B, 0x4D, 0x84, 0x51, 0xAD, 0x96, 0xC6, 0x3A, +0xCE, 0x7A, 0xDE, 0xDB, 0xAD, 0x55, 0xBD, 0xB7, +0xE7, 0x3C, 0xCE, 0x59, 0xBD, 0x95, 0xB5, 0x75, +0x8C, 0x50, 0x8C, 0x30, 0x9C, 0xB3, 0xA5, 0x35, +0xD6, 0x9A, 0xD6, 0xBB, 0xEF, 0x3D, 0xD6, 0x79, +0x73, 0x6D, 0x5A, 0xA9, 0xBD, 0xB4, 0xC5, 0xF4, +0xC5, 0xD4, 0xCD, 0xF4, 0xC5, 0xB4, 0xBD, 0xB3, +0xBD, 0x93, 0x94, 0x6F, 0x94, 0x8F, 0x9C, 0xB0, +0xAD, 0x32, 0xBD, 0x73, 0xC5, 0xD4, 0xC5, 0xB3, +0xB5, 0x52, 0xA4, 0x8F, 0x73, 0x2A, 0x6B, 0x4C, +0x5A, 0xEB, 0x63, 0x0B, 0x63, 0x2C, 0x6B, 0x6C, +0x7B, 0xEE, 0x8C, 0x4F, 0x8C, 0x4F, 0x8C, 0x2F, +0x83, 0xEE, 0x52, 0x48, 0x4A, 0x68, 0x62, 0xEA, +0x63, 0x0B, 0x62, 0xEB, 0x4A, 0x28, 0x52, 0x89, +0x7B, 0x8E, 0x6A, 0xEB, 0x8C, 0x10, 0xAC, 0xF3, +0xCE, 0x17, 0xB5, 0x54, 0xBD, 0x95, 0x9C, 0x72, +0x94, 0x71, 0x4A, 0x89, 0x39, 0xE6, 0x39, 0xE7, +0x31, 0xA5, 0x31, 0xA5, 0x42, 0x28, 0x42, 0x28, +0x5A, 0xEB, 0x6B, 0x6D, 0x6B, 0x6E, 0x7B, 0xF0, +0x7C, 0x10, 0x7B, 0xF0, 0xA5, 0x14, 0xAD, 0x76, +0xC6, 0x18, 0xC6, 0x18, 0xA5, 0x14, 0x63, 0x0C, +0x4A, 0x48, 0x8C, 0x0F, 0xCE, 0x16, 0xC5, 0xF6, +0xB5, 0x53, 0xBD, 0xB4, 0xBD, 0x73, 0xBD, 0xB4, +0xAD, 0x12, 0x8C, 0x0E, 0x94, 0x4F, 0xA4, 0xAF, +0xAC, 0xF1, 0xC5, 0x93, 0xBD, 0x53, 0xBD, 0x53, +0xB5, 0x52, 0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, +0x9C, 0x70, 0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0xB0, 0xAD, 0x11, 0xB5, 0x32, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xF1, 0xAD, 0x12, 0xAD, 0x11, +0xAC, 0xF1, 0xAC, 0xD1, 0xA4, 0xB0, 0xA4, 0x90, +0x9C, 0x6F, 0x9C, 0x4F, 0x9C, 0x4F, 0x9C, 0x4F, +0x8B, 0xED, 0x8C, 0x0E, 0x8C, 0x0E, 0x8C, 0x0D, +0x94, 0x4E, 0x94, 0x2E, 0x94, 0x2E, 0x94, 0x2D, +0x94, 0x0D, 0x94, 0x4F, 0x8C, 0x0E, 0x94, 0x6F, +0xAC, 0xF1, 0xB5, 0x52, 0xAD, 0x12, 0xBD, 0x93, +0xC5, 0xB4, 0xC5, 0xD4, 0xDE, 0x55, 0xE6, 0x96, +0xD6, 0x35, 0xD6, 0x56, 0xC5, 0xD3, 0xCE, 0x15, +0xD6, 0x56, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x35, +0xCD, 0xF4, 0xCE, 0x14, 0xDE, 0x55, 0xD6, 0x55, +0xCD, 0xD4, 0xAD, 0x12, 0x9C, 0xF1, 0x8C, 0x4F, +0xA5, 0x12, 0xB5, 0x73, 0xB5, 0x74, 0xBD, 0x94, +0xB5, 0x73, 0xAD, 0x33, 0xAD, 0x53, 0xAD, 0x53, +0xB5, 0x73, 0xBD, 0xB4, 0xCE, 0x36, 0xCE, 0x56, +0xD6, 0x77, 0xD6, 0x98, 0xCE, 0x37, 0xB5, 0x74, +0x9C, 0xD2, 0x7B, 0xCF, 0x7B, 0xCE, 0x83, 0xEE, +0x73, 0x6D, 0x7B, 0xAE, 0x73, 0x4D, 0x6B, 0x2C, +0x73, 0x8E, 0xB5, 0x75, 0xAD, 0x53, 0xDE, 0xB9, +0xD6, 0x78, 0x84, 0x10, 0x94, 0x92, 0x94, 0x92, +0x84, 0x10, 0x42, 0x28, 0x31, 0xA5, 0x39, 0xC6, +0x31, 0xC6, 0x21, 0x64, 0x53, 0x29, 0x6C, 0x8B, +0x53, 0xC8, 0x53, 0xC8, 0x4B, 0x67, 0x2A, 0x03, +0x19, 0x41, 0x19, 0x62, 0x4B, 0x06, 0x4B, 0x66, +0x5B, 0xC9, 0x19, 0x82, 0x53, 0x49, 0x7C, 0xCD, +0x5B, 0xA9, 0x63, 0xEA, 0x63, 0xE9, 0x5B, 0xE9, +0x6C, 0x6A, 0x4B, 0x86, 0x43, 0x04, 0x8C, 0xCC, +0xDE, 0xF5, 0xAD, 0xD0, 0x7C, 0xAA, 0x4B, 0x24, +0x52, 0x89, 0x39, 0xC6, 0x52, 0xA9, 0x5A, 0xA9, +0x5A, 0xA9, 0x52, 0x48, 0x7B, 0xCD, 0xC5, 0xF4, +0xD6, 0x56, 0xB5, 0x32, 0x83, 0xED, 0xA4, 0xD0, +0xC5, 0xB4, 0x9C, 0x2E, 0xA4, 0x6E, 0xB4, 0xD0, +0x8B, 0xCC, 0x73, 0x2A, 0x7B, 0x6B, 0x83, 0xAC, +0x9C, 0x6E, 0xD6, 0x14, 0xCD, 0xB3, 0xCD, 0xB2, +0xBD, 0x72, 0xAC, 0xF0, 0xE6, 0x96, 0xDE, 0x54, +0xE6, 0x75, 0xC5, 0x92, 0x94, 0x0C, 0xBD, 0x51, +0xBD, 0x51, 0xA4, 0x6E, 0xAC, 0xAF, 0xBD, 0x51, +0xB4, 0xEF, 0xAC, 0xAE, 0xC5, 0x71, 0xE6, 0x96, +0xCD, 0xD3, 0xC5, 0x72, 0xC5, 0x92, 0xD6, 0x14, +0xD5, 0xF3, 0xC5, 0x71, 0xC5, 0x71, 0xC5, 0x91, +0xC5, 0x91, 0xBD, 0x51, 0xBD, 0x51, 0xAC, 0xEF, +0xAC, 0xEF, 0xB5, 0x10, 0xB5, 0x10, 0xB5, 0x30, +0xBD, 0x30, 0xB4, 0xEF, 0xAC, 0xAE, 0xAC, 0xCF, +0xA4, 0x8E, 0xA4, 0x6E, 0xA4, 0x6E, 0xAC, 0xCF, +0x9C, 0x2D, 0x8B, 0xEB, 0x8B, 0xCB, 0xB5, 0x10, +0xCD, 0xB2, 0xAC, 0x8D, 0xBD, 0x30, 0xC5, 0x71, +0xCD, 0x91, 0xCD, 0xB2, 0xCD, 0x71, 0xCD, 0xB2, +0xD5, 0xF3, 0xD5, 0xD2, 0xC5, 0x30, 0xCD, 0x92, +0xD5, 0xD2, 0xDE, 0x34, 0xDE, 0x34, 0xDE, 0x33, +0xDE, 0x33, 0xE6, 0x54, 0xE6, 0x53, 0xEE, 0x95, +0xF6, 0xB6, 0xE6, 0x55, 0x8B, 0xED, 0x39, 0xC6, +0x31, 0xA5, 0x31, 0xC6, 0x39, 0xE7, 0x42, 0x08, +0x52, 0xAA, 0x6B, 0x6D, 0x84, 0x30, 0x9D, 0x14, +0xAD, 0x55, 0xAD, 0x55, 0x6B, 0x4D, 0xB5, 0xB7, +0xDE, 0xDB, 0xEF, 0x5D, 0xEF, 0x7D, 0xDE, 0xBA, +0xBD, 0x95, 0xA4, 0xD3, 0x84, 0x10, 0x94, 0xB3, +0xEF, 0x5D, 0xDE, 0xDB, 0xD6, 0x7A, 0xEF, 0x3D, +0x73, 0x8E, 0x94, 0x6F, 0xCE, 0x35, 0xDE, 0x75, +0xD6, 0x34, 0xCD, 0xF4, 0xD6, 0x14, 0xCD, 0xF4, +0xCD, 0xF4, 0xC5, 0xD4, 0xC5, 0xD4, 0xCE, 0x15, +0xCE, 0x15, 0xCE, 0x14, 0xCD, 0xF4, 0xD6, 0x14, +0xB5, 0x30, 0xA4, 0x8E, 0x8B, 0xCD, 0x63, 0x2C, +0x5A, 0xEB, 0x63, 0x0B, 0x63, 0x4C, 0x73, 0x8D, +0x73, 0xAE, 0x7B, 0xEF, 0x84, 0x0F, 0x84, 0x2F, +0x84, 0x2F, 0x7B, 0xCE, 0x62, 0xEA, 0x52, 0x69, +0x52, 0x69, 0x52, 0x68, 0x62, 0xEB, 0x62, 0xCA, +0x7B, 0x8D, 0x7B, 0x8E, 0x73, 0x4C, 0x8C, 0x0F, +0xA4, 0xD2, 0x8C, 0x10, 0xA4, 0xD3, 0xB5, 0x76, +0xCE, 0x38, 0x8C, 0x51, 0x39, 0xE7, 0x3A, 0x07, +0x29, 0x65, 0x39, 0xC6, 0x42, 0x07, 0x39, 0xE7, +0x52, 0xCA, 0x63, 0x2C, 0x63, 0x0C, 0x73, 0xAF, +0x7B, 0xF0, 0x94, 0x93, 0xA5, 0x35, 0xA5, 0x15, +0xBD, 0xF8, 0xB5, 0xB6, 0xB5, 0x96, 0x5A, 0xCB, +0x39, 0xA6, 0x5A, 0xCA, 0x5A, 0xAA, 0x84, 0x0F, +0xB5, 0x74, 0xC6, 0x16, 0xA5, 0x12, 0xA4, 0xD2, +0xDE, 0x98, 0xC5, 0xB5, 0xB4, 0xF1, 0xAC, 0xD0, +0xB4, 0xD0, 0xCD, 0x92, 0xCD, 0x72, 0xCD, 0xB3, +0xC5, 0x93, 0x9C, 0x6F, 0xA4, 0xD1, 0xA4, 0xF2, +0x9C, 0x90, 0x94, 0x2F, 0x83, 0xED, 0x83, 0xED, +0x83, 0xCD, 0xA4, 0xB0, 0xAD, 0x11, 0xB5, 0x11, +0xB5, 0x31, 0xB5, 0x11, 0xB5, 0x31, 0xBD, 0x72, +0xCD, 0xD4, 0xC5, 0xB3, 0xCD, 0xB3, 0xCD, 0xB4, +0xCD, 0xD4, 0xC5, 0x73, 0xC5, 0x93, 0xC5, 0xB4, +0xC5, 0x93, 0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x73, +0xBD, 0x73, 0xB5, 0x33, 0xAC, 0xF1, 0xAD, 0x11, +0xB5, 0x32, 0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x12, +0xAC, 0xF1, 0xA4, 0xD0, 0x9C, 0x90, 0x9C, 0x90, +0x9C, 0x6F, 0x9C, 0x6F, 0x9C, 0x8F, 0x9C, 0x6F, +0x9C, 0x6F, 0x94, 0x2E, 0x8C, 0x2E, 0x94, 0x6F, +0xA4, 0xF1, 0xA4, 0xB0, 0xB5, 0x52, 0xBD, 0xB3, +0xBD, 0x73, 0xC5, 0xB3, 0xCD, 0xF4, 0xC5, 0xD3, +0xAC, 0xF0, 0xA4, 0xF1, 0x94, 0x90, 0x8C, 0x4F, +0xA4, 0xF2, 0xAD, 0x33, 0xA5, 0x32, 0xA4, 0xF2, +0xA4, 0xF2, 0xA4, 0xF2, 0xB5, 0x94, 0xC5, 0xD5, +0xCE, 0x57, 0xD6, 0x98, 0xD6, 0x57, 0xC5, 0xF6, +0xAD, 0x54, 0x94, 0x91, 0x7B, 0xEF, 0x8C, 0x50, +0xA4, 0xF2, 0x9C, 0xD2, 0x8C, 0x4F, 0x9C, 0xB1, +0x8B, 0xEE, 0x5A, 0x68, 0x5A, 0x68, 0x6B, 0x0B, +0x62, 0xCA, 0x7B, 0xAE, 0x73, 0x8D, 0xA5, 0x12, +0x94, 0x91, 0x52, 0x69, 0x39, 0xE7, 0x31, 0x86, +0x42, 0x28, 0x31, 0xC6, 0x31, 0xA5, 0x21, 0x44, +0x19, 0x23, 0x21, 0x44, 0x21, 0xA4, 0x5B, 0xC9, +0x5B, 0xE9, 0x3A, 0xE5, 0x4B, 0x27, 0x6B, 0xEB, +0x63, 0xCA, 0x74, 0x6C, 0x5C, 0x08, 0x5C, 0x28, +0x7C, 0xEC, 0x32, 0x65, 0x19, 0x83, 0x53, 0x49, +0x63, 0xEB, 0x84, 0xCD, 0x95, 0x4F, 0x7C, 0xAC, +0x6C, 0x2A, 0x43, 0x26, 0x4B, 0x65, 0x6C, 0x28, +0x85, 0x0A, 0x6C, 0x86, 0x4B, 0xA3, 0x43, 0x23, +0x52, 0x89, 0x42, 0x08, 0x42, 0x48, 0x52, 0x89, +0x5A, 0xCA, 0x62, 0xEB, 0xAD, 0x11, 0xD6, 0x35, +0xDE, 0x35, 0xDE, 0x55, 0xD6, 0x15, 0xCD, 0xF4, +0xCD, 0xF5, 0x9C, 0x4E, 0x9C, 0x2D, 0xCD, 0x72, +0xCD, 0xD4, 0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x35, +0xD6, 0x14, 0xE6, 0x96, 0xDE, 0x76, 0xDE, 0x55, +0xDE, 0x76, 0xD6, 0x35, 0xDE, 0x55, 0xDE, 0x34, +0xD6, 0x13, 0xCD, 0xF4, 0xC5, 0xD4, 0xAD, 0x11, +0xBD, 0x72, 0xC5, 0xD4, 0xD6, 0x35, 0xEE, 0x97, +0xBD, 0x51, 0xA4, 0x6D, 0x94, 0x0C, 0xAC, 0xD0, +0x9C, 0x4D, 0x83, 0x8A, 0x8B, 0xCB, 0xAC, 0x8F, +0xA4, 0x4E, 0x93, 0xCB, 0x93, 0xEC, 0x93, 0xEC, +0x8B, 0xCB, 0x7B, 0x6A, 0x83, 0xAB, 0x94, 0x0C, +0x94, 0x2D, 0x8B, 0xEC, 0x7B, 0x4A, 0x83, 0xAB, +0x94, 0x0D, 0x94, 0x0C, 0xA4, 0x8E, 0xB5, 0x10, +0xB4, 0xEF, 0xBD, 0x30, 0xA4, 0x6D, 0xA4, 0x6D, +0xAC, 0xAE, 0xB4, 0xEF, 0xB5, 0x10, 0xB4, 0xEF, +0xB4, 0xEF, 0xB4, 0xCE, 0xAC, 0xCE, 0xAC, 0xEF, +0xAC, 0xCE, 0xAC, 0xCE, 0xB4, 0xEF, 0xB4, 0xEF, +0xB4, 0xEF, 0xB4, 0xCE, 0xB4, 0xEF, 0xB4, 0xEF, +0xAC, 0xAE, 0xAC, 0xCE, 0xAC, 0xAE, 0xA4, 0x8D, +0xAC, 0xAE, 0xBD, 0x0F, 0xBD, 0x0F, 0xB4, 0xEE, +0xB4, 0xCE, 0xB4, 0xEF, 0xBD, 0x10, 0x9C, 0x2E, +0x5A, 0x88, 0x39, 0xE6, 0x31, 0xA6, 0x31, 0xA6, +0x31, 0xC6, 0x4A, 0x48, 0x5B, 0x0B, 0x73, 0xAF, +0x73, 0x8E, 0x63, 0x0C, 0x9C, 0xF3, 0xA5, 0x35, +0xC6, 0x39, 0xCE, 0x7A, 0xD6, 0xBB, 0xEF, 0x5D, +0xD6, 0x9A, 0xCE, 0x38, 0xC6, 0x18, 0x94, 0x92, +0xBD, 0xD7, 0x84, 0x10, 0x9C, 0xD4, 0xD6, 0x9A, +0xAD, 0x75, 0xB5, 0x52, 0xD6, 0x14, 0xE6, 0x96, +0xEE, 0xD6, 0xEE, 0xD7, 0xE6, 0x96, 0xE6, 0x96, +0xDE, 0x35, 0xDE, 0x55, 0xDE, 0x75, 0xDE, 0x55, +0xD6, 0x14, 0xD6, 0x14, 0xDE, 0x76, 0xCD, 0xD3, +0x9C, 0x6E, 0xA4, 0xAF, 0x8B, 0xED, 0x6B, 0x2C, +0x6B, 0x6D, 0x6B, 0x4C, 0x6B, 0x4C, 0x73, 0xAE, +0x73, 0xAD, 0x84, 0x0F, 0x8C, 0x30, 0x8C, 0x30, +0x84, 0x0F, 0x83, 0xEF, 0x8C, 0x30, 0x73, 0x8D, +0x4A, 0x48, 0x39, 0xC6, 0x5A, 0xCA, 0x6B, 0x4C, +0x83, 0xCE, 0x41, 0xE7, 0x5A, 0xAA, 0x6B, 0x0B, +0x83, 0xCF, 0xBD, 0xB6, 0xBD, 0xD7, 0x94, 0x72, +0xBD, 0xF7, 0xAD, 0x34, 0x5A, 0xCA, 0x42, 0x07, +0x31, 0xA6, 0x31, 0xA6, 0x39, 0xE7, 0x31, 0xC6, +0x31, 0xA6, 0x42, 0x28, 0x52, 0xAA, 0x63, 0x2C, +0x6B, 0x4D, 0x73, 0xAF, 0x84, 0x31, 0x8C, 0x52, +0xB5, 0xB7, 0xC6, 0x19, 0xCE, 0x7A, 0x9C, 0xD3, +0x42, 0x29, 0x4A, 0x49, 0x5A, 0xAB, 0x5A, 0xCB, +0x5A, 0xCB, 0x73, 0x8D, 0x83, 0xEF, 0x8C, 0x50, +0xD6, 0x58, 0xBD, 0x54, 0xBD, 0x32, 0xAC, 0x8E, +0xC5, 0x10, 0xDD, 0xB2, 0xDD, 0xB2, 0xD5, 0xD3, +0xC5, 0x93, 0xA4, 0xD1, 0xBD, 0x94, 0xC5, 0xD5, +0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x94, +0xBD, 0x94, 0xC5, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, +0xCD, 0xD4, 0xCD, 0xD3, 0xCD, 0xB3, 0xBD, 0x51, +0xBD, 0x31, 0xA4, 0x8E, 0xA4, 0x8E, 0xC5, 0x51, +0xCD, 0xB3, 0xD5, 0xD4, 0xCD, 0xD3, 0xD5, 0xD4, +0xEE, 0x97, 0xB5, 0x32, 0xB5, 0x32, 0xC5, 0x94, +0xB5, 0x53, 0xA4, 0xB1, 0xA4, 0xD1, 0xB5, 0x52, +0xBD, 0x73, 0xBD, 0x73, 0xBD, 0x94, 0xC5, 0xD4, +0xBD, 0x93, 0xC5, 0x94, 0xBD, 0x93, 0xC5, 0x94, +0xC5, 0xB4, 0xC5, 0x94, 0xBD, 0x93, 0xBD, 0x73, +0xB5, 0x53, 0xBD, 0x53, 0xB5, 0x32, 0xA4, 0xB0, +0x9C, 0x90, 0x9C, 0x90, 0x9C, 0x70, 0x94, 0x4F, +0x8C, 0x0F, 0x73, 0x6C, 0x83, 0xED, 0x8C, 0x2E, +0x94, 0x70, 0x9C, 0xB0, 0xA4, 0xF2, 0xA5, 0x12, +0x9C, 0xD1, 0x9C, 0x91, 0x9C, 0xB2, 0xA5, 0x13, +0xB5, 0x54, 0xBD, 0xB5, 0xCE, 0x37, 0xC5, 0xD6, +0xAD, 0x54, 0x94, 0x51, 0x73, 0x8D, 0x6B, 0x4D, +0x6B, 0x4D, 0x83, 0xEF, 0xAD, 0x13, 0xB5, 0x73, +0xA5, 0x11, 0x83, 0xEE, 0x7B, 0x8C, 0x7B, 0xAD, +0x83, 0xCD, 0x83, 0xEE, 0x83, 0xAD, 0x6B, 0x0B, +0x4A, 0x08, 0x41, 0xE7, 0x31, 0x65, 0x42, 0x27, +0x42, 0x07, 0x41, 0xE7, 0x31, 0x86, 0x31, 0xA6, +0x4A, 0x69, 0x52, 0x89, 0x5B, 0x0A, 0x42, 0xA7, +0x42, 0xC7, 0x53, 0x28, 0x42, 0xC6, 0x53, 0x88, +0x6C, 0x4B, 0x4B, 0x07, 0x95, 0x6F, 0x9D, 0xD0, +0x95, 0x90, 0x95, 0xB0, 0x7C, 0xEC, 0x74, 0xCA, +0x74, 0xAA, 0x21, 0xC3, 0x19, 0x43, 0x32, 0x05, +0x11, 0x02, 0x63, 0xAB, 0x95, 0x70, 0x8D, 0x2F, +0x43, 0x06, 0x19, 0xA1, 0x32, 0x83, 0x4B, 0x85, +0x5C, 0x46, 0x54, 0x04, 0x4B, 0xA4, 0x4B, 0x85, +0x7B, 0xEF, 0x73, 0x8D, 0x73, 0x8D, 0x7B, 0xEE, +0x84, 0x0F, 0x8C, 0x4F, 0xC5, 0xF5, 0xD6, 0x35, +0xD6, 0x14, 0xD6, 0x34, 0xDE, 0x55, 0xDE, 0x76, +0xCE, 0x15, 0x9C, 0x4E, 0x93, 0xCC, 0x93, 0xCC, +0xA4, 0x6E, 0xDE, 0x55, 0xE6, 0x76, 0xDE, 0x76, +0xD6, 0x14, 0xDE, 0x55, 0xDE, 0x55, 0xDE, 0x55, +0xDE, 0x75, 0xDE, 0x75, 0xE6, 0xB6, 0xDE, 0x55, +0xDE, 0x55, 0xD6, 0x14, 0xDE, 0x76, 0xDE, 0x76, +0xE6, 0x96, 0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0x76, +0xBD, 0x31, 0xC5, 0x71, 0xD5, 0xB3, 0xD5, 0xD3, +0xD5, 0xD4, 0xC5, 0x72, 0xC5, 0x51, 0xD5, 0x72, +0xDD, 0xB2, 0xD5, 0x92, 0xD5, 0x92, 0xC5, 0x51, +0xB4, 0xF0, 0x9C, 0x8F, 0xB5, 0x52, 0xC5, 0xB3, +0xB5, 0x31, 0xA4, 0xAF, 0x94, 0x6F, 0x94, 0x4E, +0x8B, 0xEC, 0x83, 0xAB, 0x83, 0xAB, 0xA4, 0x8E, +0xB5, 0x10, 0xDE, 0x75, 0xAC, 0xEF, 0xAD, 0x0F, +0xCD, 0xF3, 0xC5, 0xD2, 0xBD, 0x91, 0xB5, 0x0F, +0xCD, 0xD2, 0xBD, 0x51, 0xAD, 0x0F, 0xC5, 0xB2, +0xBD, 0x30, 0xAC, 0xEF, 0xAC, 0xAE, 0xA4, 0x6D, +0xA4, 0x6D, 0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAE, +0xA4, 0x8D, 0xB4, 0xCF, 0xB4, 0xEF, 0xB4, 0xCE, +0xEE, 0x95, 0xE6, 0x54, 0xC5, 0x70, 0xBD, 0x2F, +0xCD, 0x91, 0xCD, 0x91, 0xC5, 0x51, 0xD5, 0xF4, +0xD5, 0xF4, 0xB4, 0xEF, 0x73, 0x29, 0x39, 0xC5, +0x31, 0xA5, 0x31, 0xA6, 0x42, 0x28, 0x63, 0x2C, +0x4A, 0x49, 0x5A, 0xAA, 0x8C, 0x51, 0x84, 0x31, +0xB5, 0xD7, 0xCE, 0x9B, 0xCE, 0x7B, 0xCE, 0x7A, +0xBD, 0xD8, 0xDE, 0xFC, 0xF7, 0x9E, 0xB5, 0x96, +0x7B, 0xD0, 0x5A, 0xCB, 0xA4, 0xF4, 0xBD, 0xB7, +0xA4, 0xF4, 0x9C, 0x91, 0xAD, 0x11, 0xB5, 0x10, +0xAC, 0xAE, 0xAC, 0xCF, 0xB5, 0x10, 0xBD, 0x72, +0xC5, 0xB3, 0xD5, 0xF4, 0xDE, 0x75, 0xE6, 0x96, +0xEE, 0xD6, 0xEE, 0xD7, 0xE6, 0x96, 0xC5, 0xB3, +0x9C, 0x6E, 0xAC, 0xCF, 0x7B, 0x8C, 0x52, 0x89, +0x6B, 0x8D, 0x73, 0x8D, 0x63, 0x4C, 0x7C, 0x0F, +0x7B, 0xEE, 0x84, 0x0F, 0x7B, 0xCE, 0x83, 0xEF, +0x8C, 0x30, 0x84, 0x0F, 0x84, 0x0F, 0x94, 0x91, +0x83, 0xEE, 0x5A, 0xA9, 0x42, 0x27, 0x52, 0x89, +0x83, 0xEF, 0x6B, 0x2C, 0x39, 0xA6, 0x52, 0x48, +0x8C, 0x30, 0xCE, 0x59, 0xCE, 0x59, 0x9C, 0xF4, +0x9C, 0xF3, 0xAD, 0x54, 0x8C, 0x30, 0x52, 0x89, +0x39, 0xC6, 0x31, 0xA6, 0x39, 0xE6, 0x42, 0x07, +0x39, 0xE6, 0x42, 0x27, 0x4A, 0x89, 0x4A, 0x69, +0x52, 0xAB, 0x6B, 0x8E, 0x84, 0x31, 0x94, 0xD4, +0xB5, 0x97, 0xB5, 0xB7, 0xC6, 0x39, 0xC6, 0x39, +0x63, 0x0D, 0x5A, 0xAB, 0x73, 0x8E, 0x63, 0x2C, +0x94, 0x72, 0x94, 0x92, 0x94, 0x92, 0x7B, 0xEF, +0xA4, 0xF3, 0xBD, 0xD6, 0xD6, 0x36, 0xCD, 0x52, +0xDD, 0x92, 0xD5, 0x71, 0xDD, 0xB2, 0xD5, 0xD3, +0xBD, 0x72, 0xAC, 0xF1, 0xBD, 0x74, 0xB5, 0x73, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x73, 0xC5, 0xD4, +0xCE, 0x15, 0xCD, 0xF4, 0xCD, 0xF4, 0xD6, 0x14, +0xD5, 0xF4, 0xD5, 0xF4, 0xD5, 0xD3, 0xD6, 0x14, +0xCD, 0xD3, 0xB4, 0xF0, 0xC5, 0x72, 0xCD, 0xB3, +0xCD, 0xB3, 0xAC, 0xCF, 0xB5, 0x10, 0xC5, 0x31, +0xC5, 0x52, 0x9C, 0x6F, 0xCE, 0x15, 0xCE, 0x56, +0xBD, 0xD4, 0xB5, 0x94, 0xAD, 0x32, 0xAD, 0x32, +0xBD, 0xB4, 0xCE, 0x15, 0xD6, 0x35, 0xCD, 0xF4, +0xBD, 0x72, 0xB5, 0x11, 0xB5, 0x52, 0xAC, 0xF1, +0xB5, 0x32, 0xBD, 0x53, 0xBD, 0x53, 0xBD, 0x73, +0xB5, 0x32, 0xBD, 0x73, 0xC5, 0xB4, 0xC5, 0xD5, +0xAD, 0x32, 0xA4, 0xD1, 0xA4, 0xF1, 0xCD, 0xB4, +0xC5, 0x93, 0xDE, 0x56, 0xD6, 0x57, 0xD6, 0x57, +0xD6, 0x37, 0xCE, 0x16, 0xCE, 0x37, 0xCE, 0x58, +0xCE, 0x58, 0xCE, 0x59, 0xC6, 0x38, 0xBD, 0xD7, +0xAD, 0x55, 0xA5, 0x14, 0x8C, 0x30, 0x7B, 0xAE, +0x8C, 0x10, 0x9C, 0xB2, 0xAD, 0x33, 0xB5, 0x74, +0xB5, 0x53, 0xB5, 0x53, 0xAD, 0x53, 0xAD, 0x32, +0xA5, 0x12, 0xB5, 0x53, 0xAD, 0x53, 0xAD, 0x53, +0xB5, 0x74, 0xB5, 0x53, 0xAD, 0x33, 0xAD, 0x12, +0xA4, 0xD2, 0x94, 0x70, 0x83, 0xEF, 0x4A, 0x08, +0x94, 0x30, 0x9C, 0xB1, 0x83, 0xEF, 0x84, 0x10, +0x94, 0x71, 0x7C, 0x0E, 0x73, 0xEC, 0x5B, 0xEA, +0x6C, 0x6B, 0x53, 0xA8, 0x32, 0x44, 0x43, 0x06, +0x42, 0xC6, 0x42, 0xE6, 0x6C, 0x6A, 0x85, 0x2D, +0x8D, 0x8F, 0x95, 0xAF, 0x85, 0x2D, 0x85, 0x2C, +0x85, 0x4D, 0x3A, 0xA5, 0x42, 0x66, 0x31, 0xE5, +0x10, 0xC2, 0x19, 0x43, 0x5B, 0x8A, 0x9D, 0x70, +0x5B, 0x89, 0x32, 0x44, 0x22, 0x02, 0x32, 0xC3, +0x53, 0xC5, 0x95, 0xCC, 0x74, 0xC9, 0x3B, 0x04, +0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, 0xAD, 0x53, +0xB5, 0x73, 0xBD, 0xB3, 0xCE, 0x15, 0xD6, 0x35, +0xD6, 0x14, 0xD6, 0x14, 0xD6, 0x55, 0xE6, 0xB7, +0xCD, 0xF5, 0x9C, 0x2E, 0xA4, 0x0D, 0xB4, 0xAF, +0xD5, 0xF4, 0xDE, 0x76, 0xDE, 0x34, 0xDE, 0x55, +0xDE, 0x55, 0xDE, 0x55, 0xE6, 0x75, 0xE6, 0x76, +0xD6, 0x14, 0xD6, 0x14, 0xE6, 0x96, 0xDE, 0x75, +0xD6, 0x34, 0xCD, 0xF3, 0xDE, 0x55, 0xE6, 0x75, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x55, +0xBD, 0x10, 0xAC, 0xAE, 0xC5, 0x10, 0xDD, 0xF4, +0xD5, 0xD3, 0xD5, 0xB3, 0xCD, 0x92, 0xD5, 0x71, +0xD5, 0x71, 0xCD, 0x51, 0xCD, 0x51, 0xCD, 0x51, +0xCD, 0x92, 0xC5, 0x92, 0xDE, 0x56, 0xCD, 0xD4, +0xB5, 0x31, 0xA4, 0xAF, 0x8B, 0xED, 0x8C, 0x0D, +0x83, 0xCC, 0x83, 0xCC, 0x8B, 0xEC, 0xA4, 0x8E, +0xB5, 0x10, 0xD6, 0x55, 0xB5, 0x71, 0xBD, 0x91, +0xC6, 0x12, 0xC6, 0x32, 0xCE, 0x74, 0xAD, 0x50, +0xD6, 0x95, 0xD6, 0x94, 0xD6, 0xD5, 0xDE, 0xB5, +0xB5, 0x30, 0xB5, 0x30, 0xB5, 0x31, 0xA4, 0xEF, +0x9C, 0xAE, 0xB5, 0x51, 0xC5, 0xB2, 0xA4, 0xCF, +0xB5, 0x10, 0xBD, 0x50, 0xAC, 0xCE, 0xAC, 0xAD, +0xE6, 0x75, 0xDE, 0x33, 0xCD, 0xD2, 0xB5, 0x0F, +0xA4, 0x8E, 0xAC, 0xCE, 0x9C, 0x6D, 0xA4, 0x6E, +0xD5, 0xF3, 0xDE, 0x13, 0xDE, 0x13, 0xAC, 0xCF, +0x5A, 0x88, 0x31, 0x85, 0x39, 0xE7, 0x52, 0x8A, +0x42, 0x07, 0x42, 0x28, 0x63, 0x0C, 0x7B, 0xEF, +0x8C, 0x92, 0xA5, 0x35, 0xBD, 0xF8, 0xCE, 0x9B, +0xCE, 0x5A, 0xBD, 0xF8, 0xBD, 0xF8, 0x94, 0x93, +0xC5, 0xF8, 0x8C, 0x72, 0xA5, 0x35, 0xEF, 0x3D, +0xD6, 0x9A, 0x9C, 0xB3, 0x8C, 0x0F, 0xB5, 0x32, +0xC5, 0x72, 0xBD, 0x51, 0xAC, 0xAF, 0xA4, 0x8F, +0x94, 0x2D, 0x8B, 0xEC, 0x8B, 0xEB, 0x8B, 0xCB, +0x8B, 0xCC, 0x94, 0x0C, 0x9C, 0x4D, 0x94, 0x2D, +0x9C, 0x4D, 0xAC, 0xAF, 0xAC, 0xAF, 0x7B, 0xAC, +0x7B, 0x8D, 0x6B, 0x0B, 0x63, 0x0B, 0x73, 0xAE, +0x6B, 0x6D, 0x6B, 0x4C, 0x6B, 0x2C, 0x73, 0xAD, +0x7B, 0xEE, 0x7B, 0xCE, 0x84, 0x0F, 0x94, 0xB1, +0xA4, 0xF2, 0x94, 0xB1, 0x6B, 0x4C, 0x4A, 0x28, +0x4A, 0x48, 0x5A, 0xAA, 0x4A, 0x28, 0x62, 0xEB, +0x73, 0x8E, 0xAD, 0x75, 0xC5, 0xF8, 0xBD, 0xB7, +0x9C, 0xD3, 0x7B, 0xCF, 0x73, 0x6D, 0x6B, 0x6C, +0x4A, 0x48, 0x31, 0xC6, 0x39, 0xE7, 0x42, 0x07, +0x42, 0x27, 0x39, 0xE7, 0x4A, 0x69, 0x52, 0xCB, +0x63, 0x2C, 0x6B, 0x6E, 0x7B, 0xD0, 0x9C, 0xD4, +0x9D, 0x15, 0xA5, 0x36, 0xB5, 0xB8, 0xC6, 0x19, +0x9C, 0xD4, 0x73, 0x8F, 0x7B, 0xAE, 0x9C, 0xD2, +0xA4, 0xF3, 0xAD, 0x55, 0x9C, 0xD3, 0x9C, 0xB3, +0xA5, 0x14, 0x7B, 0xAE, 0x73, 0x6D, 0x8B, 0xEE, +0xBD, 0x11, 0xAC, 0x8E, 0xCD, 0x51, 0xCD, 0x92, +0xBD, 0x51, 0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0xB4, +0xC5, 0xD5, 0xC5, 0xB4, 0xC5, 0xB4, 0xB5, 0x72, +0xBD, 0x93, 0xC5, 0xB3, 0xC5, 0xB3, 0xD6, 0x14, +0xBD, 0x72, 0x83, 0x8B, 0xBD, 0x51, 0xCD, 0xB2, +0xDE, 0x35, 0xC5, 0x93, 0xDE, 0x35, 0xD6, 0x14, +0xDE, 0x35, 0xC5, 0x51, 0xBD, 0x30, 0xC5, 0x72, +0xD6, 0x14, 0xA4, 0xB0, 0xD6, 0x56, 0xCE, 0x16, +0xBD, 0xD4, 0xC6, 0x36, 0xCE, 0x57, 0xC5, 0xD4, +0xBD, 0xB4, 0xBD, 0xB4, 0xD6, 0x56, 0xDE, 0xB7, +0xD6, 0x56, 0xCE, 0x15, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x72, 0xB5, 0x73, 0xD6, 0x56, 0xCE, 0x15, +0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x93, 0xC5, 0xF4, +0xD6, 0x56, 0x9C, 0x90, 0xAD, 0x12, 0xDE, 0x15, +0xD5, 0x52, 0xE6, 0x35, 0xD6, 0x16, 0xBD, 0x94, +0xB5, 0x54, 0xB5, 0x95, 0xAD, 0x54, 0x94, 0x71, +0x73, 0xAE, 0x7B, 0x8E, 0x94, 0x51, 0x9C, 0xB2, +0x9C, 0xD2, 0x9C, 0x91, 0xBD, 0x74, 0xD6, 0x36, +0xE6, 0x57, 0xE6, 0x77, 0xE6, 0x97, 0xE6, 0xB7, +0xE6, 0xD8, 0xEE, 0xF8, 0xAD, 0x32, 0xAD, 0x32, +0xBD, 0x94, 0xBD, 0xB3, 0xC5, 0xB4, 0xC5, 0xD4, +0xC5, 0xD4, 0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x73, +0xB5, 0x54, 0xDE, 0x99, 0xC5, 0xD6, 0x7B, 0x6D, +0xC5, 0x95, 0x9C, 0x91, 0x62, 0xEB, 0x84, 0x10, +0x9C, 0xB2, 0x7B, 0xCD, 0x7C, 0x8E, 0x74, 0xAC, +0x6C, 0x6B, 0x32, 0x85, 0x21, 0x82, 0x3A, 0x86, +0x11, 0x21, 0x4B, 0x27, 0x6C, 0x8A, 0x85, 0x4D, +0x95, 0xB0, 0x8D, 0x6F, 0x85, 0x2D, 0x85, 0x2D, +0x7C, 0xEC, 0x21, 0xE3, 0x53, 0x29, 0x29, 0xA3, +0x10, 0xE2, 0x19, 0x23, 0x3A, 0x26, 0x63, 0xAB, +0x4A, 0xE8, 0x32, 0x25, 0x42, 0xC6, 0x43, 0x06, +0x53, 0xC7, 0x74, 0xCA, 0x53, 0xC6, 0x3B, 0x25, +0xB5, 0x73, 0xC5, 0xF5, 0xCE, 0x16, 0xCE, 0x36, +0xD6, 0x56, 0xD6, 0x56, 0xDE, 0x55, 0xDE, 0x55, +0xDE, 0x55, 0xDE, 0x55, 0xDE, 0x76, 0xD6, 0x35, +0xB5, 0x31, 0xAC, 0x8F, 0xCD, 0x11, 0xDD, 0x93, +0xDD, 0xF4, 0xE6, 0x76, 0xDE, 0x34, 0xDE, 0x35, +0xDE, 0x55, 0xDE, 0x35, 0xDE, 0x55, 0xDE, 0x55, +0xDE, 0x35, 0xDE, 0x34, 0xE6, 0x96, 0xE6, 0x75, +0xDE, 0x55, 0xDE, 0x34, 0xDE, 0x55, 0xDE, 0x55, +0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x55, +0xAC, 0x8E, 0xA4, 0x2C, 0xA4, 0x4D, 0xCD, 0x92, +0xDD, 0xF4, 0xD5, 0xD3, 0xCD, 0x51, 0xCD, 0x51, +0xC5, 0x0F, 0xBC, 0xCF, 0xBC, 0xCF, 0xB4, 0xAF, +0xBD, 0x30, 0xC5, 0x92, 0xCD, 0xF4, 0xCD, 0xD3, +0xAC, 0xF0, 0xA4, 0xCF, 0x8C, 0x2E, 0x8C, 0x0D, +0x8C, 0x0D, 0x83, 0xCC, 0x94, 0x4E, 0xAC, 0xF0, +0xB5, 0x30, 0xCE, 0x14, 0xB5, 0x30, 0xBD, 0xB2, +0xBE, 0x32, 0xBE, 0x32, 0xC6, 0x53, 0xBE, 0x33, +0xCE, 0xB4, 0xD6, 0xF5, 0xDF, 0x36, 0xC6, 0x33, +0xC5, 0xD3, 0xBD, 0xB3, 0xC5, 0xD3, 0xBD, 0xB3, +0xBD, 0xB3, 0xC5, 0xF4, 0xCD, 0xF4, 0xAC, 0xEF, +0xBD, 0x51, 0xAC, 0xCF, 0xAC, 0xAE, 0xAC, 0xCE, +0xEE, 0xB5, 0xE6, 0x75, 0xE6, 0x95, 0xEE, 0xD6, +0xD6, 0x14, 0xB5, 0x30, 0xA4, 0xAF, 0xAC, 0xD0, +0xD5, 0xF3, 0xDE, 0x12, 0xD5, 0xF3, 0xD5, 0xF2, +0xCD, 0xD2, 0x9C, 0x8E, 0x52, 0x67, 0x31, 0x85, +0x21, 0x24, 0x31, 0x85, 0x3A, 0x07, 0x4A, 0x69, +0x5A, 0xEB, 0x73, 0xAE, 0x84, 0x31, 0x84, 0x31, +0xAD, 0x76, 0xC6, 0x39, 0xC6, 0x39, 0x94, 0x93, +0xAD, 0x56, 0x83, 0xF0, 0xBD, 0xF8, 0xEF, 0x5D, +0xD6, 0x9A, 0xE7, 0x1C, 0xBD, 0xD7, 0x73, 0x6D, +0x94, 0x4F, 0xAC, 0xF1, 0x9C, 0x4E, 0x94, 0x2D, +0xA4, 0x8F, 0xAC, 0xCF, 0xB5, 0x30, 0xBD, 0x31, +0xB5, 0x10, 0xB4, 0xEF, 0xAC, 0xAF, 0xAC, 0xCF, +0xB4, 0xF0, 0xAC, 0xCF, 0xB4, 0xF0, 0xB5, 0x10, +0xAC, 0xAF, 0xA4, 0x6F, 0x9C, 0x6F, 0x9C, 0x6F, +0x94, 0x2E, 0x94, 0x2E, 0x8B, 0xED, 0x8B, 0xED, +0x83, 0xED, 0x83, 0xEE, 0x83, 0xCD, 0x7B, 0xAD, +0x83, 0xCD, 0x7B, 0xCD, 0x83, 0xEE, 0x63, 0x0A, +0x41, 0xE7, 0x52, 0x69, 0x4A, 0x28, 0x52, 0x89, +0x62, 0xEB, 0x84, 0x30, 0xAD, 0x76, 0xB5, 0x76, +0x8C, 0x31, 0x73, 0x8E, 0x73, 0x6D, 0x6B, 0x4D, +0x63, 0x0B, 0x39, 0xC6, 0x42, 0x07, 0x39, 0xC6, +0x31, 0xA6, 0x3A, 0x07, 0x4A, 0x48, 0x4A, 0x48, +0x5A, 0xCB, 0x52, 0x8A, 0x5A, 0xEC, 0x84, 0x52, +0x94, 0xD4, 0x9C, 0xF5, 0xAD, 0x97, 0xCE, 0x5A, +0xD6, 0x7A, 0x9C, 0xB3, 0x73, 0x8E, 0x73, 0x8E, +0xB5, 0x96, 0xBD, 0xB7, 0xC5, 0xF8, 0xBD, 0xD7, +0xC5, 0xF8, 0xAD, 0x55, 0xA5, 0x14, 0xBD, 0xB6, +0xC5, 0xD6, 0xA4, 0x90, 0xC5, 0x32, 0xC5, 0x51, +0xBD, 0x52, 0xAD, 0x12, 0xB5, 0x53, 0xC5, 0xD4, +0xC5, 0x93, 0xB5, 0x11, 0xC5, 0x93, 0xC5, 0xB3, +0xBD, 0x52, 0xC5, 0x93, 0xC5, 0xB3, 0xD6, 0x35, +0xB5, 0x11, 0xAC, 0xD0, 0xC5, 0x72, 0xC5, 0x92, +0xCD, 0xB2, 0xDE, 0x35, 0xD6, 0x14, 0xD5, 0xF4, +0xD6, 0x14, 0xC5, 0x52, 0xC5, 0x71, 0xC5, 0x51, +0xAC, 0xAF, 0xAC, 0xD0, 0xD6, 0x56, 0xC5, 0xF4, +0xBD, 0xD4, 0xC5, 0xF5, 0xC6, 0x15, 0xBD, 0xD4, +0xC6, 0x15, 0xC5, 0xF4, 0xC5, 0xD4, 0xD6, 0x76, +0xDE, 0x96, 0xDE, 0xB7, 0xDE, 0xB7, 0xCE, 0x56, +0xDE, 0x97, 0xDE, 0x97, 0xCE, 0x36, 0xC5, 0xF5, +0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x35, 0xD6, 0x56, +0xD6, 0x76, 0xA4, 0xD1, 0xB5, 0x32, 0xDD, 0xD4, +0xDD, 0x72, 0xDD, 0xD4, 0x8B, 0xAE, 0x73, 0x4D, +0x62, 0xCA, 0x73, 0x4B, 0x83, 0x8C, 0x9C, 0x2F, +0xD6, 0x57, 0xE6, 0xF9, 0xE6, 0xD9, 0xDE, 0x97, +0xE6, 0xB8, 0xE6, 0x97, 0xDE, 0x36, 0xE6, 0x35, +0xDD, 0xF4, 0xDD, 0xD4, 0xDD, 0xD4, 0xDE, 0x15, +0xDE, 0x56, 0xEF, 0x19, 0x9C, 0x90, 0xAD, 0x33, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xD4, 0xCD, 0xF4, +0xD6, 0x15, 0xD6, 0x15, 0xD6, 0x36, 0xD6, 0x37, +0xBD, 0x95, 0xEF, 0x3B, 0xB5, 0x75, 0x9C, 0x91, +0xCD, 0xD5, 0xA4, 0x91, 0x52, 0x49, 0x73, 0x4D, +0x8C, 0x2F, 0x84, 0x2E, 0x74, 0x4C, 0x64, 0x2A, +0x4B, 0x47, 0x19, 0x42, 0x19, 0x63, 0x32, 0x25, +0x19, 0x42, 0x53, 0x69, 0x85, 0x4E, 0x9D, 0xD0, +0x95, 0xD0, 0x8D, 0x4E, 0x85, 0x2C, 0x74, 0xCB, +0x43, 0x05, 0x2A, 0x04, 0x5B, 0x69, 0x29, 0xE4, +0x31, 0xE5, 0x42, 0x67, 0x4A, 0xE8, 0x6B, 0xEB, +0x5B, 0x69, 0x3A, 0x66, 0x4A, 0xE7, 0x5B, 0xA9, +0x85, 0x0E, 0x7D, 0x0C, 0x6C, 0x69, 0x4B, 0xA6, +0x73, 0x6B, 0x83, 0xED, 0x9C, 0x6F, 0xA4, 0xD1, +0xAC, 0xF1, 0xB5, 0x32, 0xBD, 0x72, 0xC5, 0xB3, +0xC5, 0xB3, 0xBD, 0x72, 0xC5, 0xB3, 0x9C, 0x6E, +0x9C, 0x4E, 0xA4, 0x4E, 0xD5, 0x31, 0xE5, 0xD4, +0xDD, 0xF4, 0xDE, 0x14, 0xDE, 0x34, 0xE6, 0x55, +0xE6, 0x96, 0xE6, 0x75, 0xE6, 0x96, 0xDE, 0x34, +0xDE, 0x14, 0xDE, 0x14, 0xDE, 0x55, 0xDE, 0x55, +0xE6, 0x55, 0xC5, 0x71, 0xDE, 0x14, 0xE6, 0x55, +0xE6, 0x55, 0xE6, 0x75, 0xE6, 0x75, 0xE6, 0x55, +0xAC, 0xAE, 0x9C, 0x2C, 0x8B, 0xAB, 0xAC, 0xAE, +0xA4, 0x6E, 0xB4, 0xAF, 0xB4, 0xCF, 0xBC, 0xCF, +0xC5, 0x0F, 0xC5, 0x0F, 0xBC, 0xCF, 0xB4, 0xCF, +0xB5, 0x10, 0xCD, 0xD3, 0xD6, 0x35, 0xBD, 0x72, +0xAC, 0xF0, 0xA4, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, +0x94, 0x4E, 0x83, 0xCD, 0xA4, 0xD0, 0xBD, 0x72, +0xBD, 0x71, 0xCE, 0x14, 0xAC, 0xEF, 0xBD, 0x92, +0xC6, 0x54, 0xC6, 0x73, 0xC6, 0x93, 0xC6, 0x73, +0xBE, 0x53, 0xDF, 0x36, 0xD6, 0xD5, 0xAD, 0x71, +0xC5, 0xD3, 0xCE, 0x35, 0xCE, 0x35, 0xBD, 0xB3, +0xCE, 0x14, 0xCE, 0x35, 0xD6, 0x76, 0xB5, 0x51, +0xC5, 0xB2, 0xAC, 0xEF, 0xA4, 0xAE, 0xB4, 0xEF, +0xEE, 0xD6, 0xDE, 0x74, 0xDE, 0x74, 0xDE, 0x74, +0xDE, 0x55, 0xBD, 0x51, 0xC5, 0xB2, 0xCE, 0x14, +0xD6, 0x33, 0xDE, 0x74, 0xDE, 0x74, 0xDE, 0x74, +0xD6, 0x54, 0xDE, 0x74, 0xC5, 0xF3, 0x8C, 0x0C, +0x41, 0xE6, 0x29, 0x64, 0x29, 0x44, 0x31, 0x85, +0x39, 0xC6, 0x42, 0x28, 0x4A, 0x69, 0x5A, 0xEB, +0x7B, 0xF0, 0x94, 0xB3, 0xAD, 0x55, 0x94, 0xB3, +0x5A, 0xCB, 0x8C, 0x31, 0xC6, 0x18, 0xC6, 0x39, +0x84, 0x10, 0xDE, 0xDB, 0xE7, 0x1C, 0xD6, 0x7A, +0xB5, 0xB6, 0xCE, 0x79, 0x8C, 0x0F, 0x5A, 0xA9, +0x62, 0xE9, 0x8B, 0xEC, 0xB4, 0xEF, 0xC5, 0x92, +0xC5, 0x72, 0xB5, 0x31, 0xA4, 0xAF, 0xBD, 0x71, +0xCD, 0xD3, 0xBD, 0x51, 0xB5, 0x10, 0xBD, 0x51, +0xBD, 0x51, 0xBD, 0x51, 0xBD, 0x30, 0xBD, 0x30, +0xB5, 0x10, 0xB5, 0x10, 0xB4, 0xF0, 0xB4, 0xF0, +0xAC, 0xD0, 0xB4, 0xF0, 0xB5, 0x10, 0xB5, 0x10, +0xAC, 0xAF, 0xA4, 0x8F, 0xAC, 0xF0, 0xA4, 0xD0, +0x8B, 0xED, 0x42, 0x06, 0x39, 0xC6, 0x42, 0x07, +0x52, 0x68, 0x5A, 0xEB, 0x7B, 0xCF, 0x94, 0x92, +0x6B, 0x6D, 0x7B, 0xCF, 0x8C, 0x71, 0x84, 0x0F, +0x9C, 0x91, 0x52, 0x89, 0x39, 0xE7, 0x39, 0xE6, +0x31, 0xA5, 0x3A, 0x07, 0x42, 0x07, 0x42, 0x28, +0x52, 0xAA, 0x52, 0x8A, 0x63, 0x0C, 0x73, 0xD0, +0x84, 0x32, 0x94, 0xB4, 0x9C, 0xD4, 0xBD, 0xF8, +0xAD, 0x76, 0xB5, 0xB7, 0x94, 0x92, 0xAD, 0x55, +0xC5, 0xF8, 0xC6, 0x18, 0xBD, 0xB7, 0xB5, 0x56, +0xB5, 0x97, 0xBD, 0xB7, 0xA4, 0xF4, 0xCE, 0x39, +0xEE, 0xFB, 0xDE, 0x79, 0xCD, 0xD5, 0xC5, 0x73, +0xB5, 0x31, 0xAC, 0xD1, 0x94, 0x4F, 0xBD, 0x93, +0xC5, 0x93, 0xCD, 0xD3, 0xD5, 0xF4, 0xD6, 0x14, +0xCD, 0xB3, 0xCD, 0xB3, 0xD5, 0xF4, 0xDE, 0x55, +0xC5, 0xB3, 0xBD, 0x51, 0xBD, 0x31, 0xC5, 0x51, +0xCD, 0xB3, 0xDE, 0x55, 0xDE, 0x35, 0xDE, 0x34, +0xDE, 0x55, 0xCD, 0x92, 0xCD, 0x92, 0xBD, 0x30, +0xB4, 0xF0, 0xAC, 0xD0, 0xD6, 0x56, 0xC6, 0x15, +0xC5, 0xF5, 0xC6, 0x36, 0xC6, 0x15, 0xBD, 0xD4, +0xCE, 0x36, 0xCE, 0x35, 0xC5, 0xD4, 0xCE, 0x35, +0xD6, 0x96, 0xDE, 0x96, 0xDE, 0x96, 0xD6, 0x76, +0xCE, 0x35, 0xCE, 0x14, 0xC6, 0x14, 0xCE, 0x56, +0xCE, 0x56, 0xCE, 0x15, 0xCE, 0x35, 0xCE, 0x56, +0xCE, 0x35, 0xA4, 0xB0, 0xAC, 0xD1, 0xE5, 0xF4, +0xED, 0xD3, 0xE5, 0xF4, 0xCD, 0x52, 0xC5, 0x32, +0xDD, 0x93, 0xDD, 0xB2, 0xDD, 0x51, 0xE6, 0x14, +0xF6, 0xF9, 0xE6, 0xD8, 0xE6, 0xF9, 0xE6, 0xB8, +0xE6, 0xB7, 0xE6, 0xB7, 0xE6, 0x76, 0xE6, 0x14, +0xE5, 0xB3, 0xE5, 0xB2, 0xE5, 0xB3, 0xDD, 0xB3, +0xE6, 0x55, 0xEF, 0x19, 0x94, 0x90, 0xBD, 0x94, +0xCE, 0x15, 0xBD, 0x93, 0xB5, 0x73, 0xC5, 0xD4, +0xD6, 0x35, 0xDE, 0x97, 0xE6, 0xD9, 0xBD, 0x75, +0x94, 0x51, 0x9C, 0x91, 0xAD, 0x34, 0xD5, 0xF7, +0xB5, 0x13, 0x7B, 0x4C, 0x52, 0x49, 0x5A, 0xAA, +0x73, 0x8C, 0x84, 0x6E, 0x6C, 0x2B, 0x42, 0xE6, +0x19, 0x62, 0x10, 0xE2, 0x19, 0x23, 0x21, 0x84, +0x19, 0x42, 0x4B, 0x48, 0x7C, 0xED, 0x9D, 0xF1, +0x8D, 0x90, 0x95, 0x8F, 0x85, 0x4D, 0x53, 0xC8, +0x22, 0x03, 0x4B, 0x07, 0x63, 0xEA, 0x19, 0x62, +0x19, 0x42, 0x3A, 0x65, 0x42, 0xC6, 0x63, 0xC9, +0x95, 0x70, 0x53, 0x68, 0x63, 0xEA, 0x84, 0xED, +0x95, 0x90, 0x7C, 0xEC, 0x7D, 0x0C, 0x95, 0xAF, +0x7B, 0x6C, 0x73, 0x4B, 0x73, 0x6B, 0x7B, 0x8C, +0x83, 0xAC, 0x83, 0xCD, 0x83, 0xCD, 0x8B, 0xED, +0x8B, 0xED, 0x94, 0x0D, 0x94, 0x2E, 0x9C, 0x6E, +0xA4, 0x6F, 0xA4, 0x8F, 0xA4, 0x2D, 0xA4, 0x2E, +0xA4, 0x6E, 0xA4, 0x6E, 0xA4, 0x6E, 0xA4, 0x6E, +0xA4, 0x6E, 0xA4, 0x8E, 0xAC, 0xAF, 0xA4, 0x8E, +0xAC, 0xCF, 0xAC, 0xAE, 0xBD, 0x30, 0xCD, 0x92, +0xCD, 0xB2, 0xBD, 0x30, 0xD5, 0xF3, 0xDE, 0x34, +0xDE, 0x54, 0xE6, 0x55, 0xEE, 0x76, 0xEE, 0x75, +0xB4, 0xEF, 0xA4, 0x4D, 0x9C, 0x2C, 0xBD, 0x31, +0xA4, 0x4E, 0xB5, 0x10, 0xCD, 0xB3, 0xC5, 0x30, +0xCD, 0x51, 0xB4, 0xCF, 0xAC, 0x8F, 0xA4, 0x6E, +0x94, 0x0D, 0xAC, 0xF0, 0xB5, 0x31, 0xA4, 0xCF, +0x94, 0x6E, 0x83, 0xED, 0x8C, 0x2E, 0x8C, 0x0D, +0x8B, 0xED, 0x73, 0x6B, 0xA4, 0xD0, 0x9C, 0x8E, +0xB5, 0x51, 0xD6, 0x75, 0xB5, 0x71, 0xBD, 0xB3, +0xCE, 0x75, 0xC6, 0x74, 0xC6, 0x74, 0xC6, 0x54, +0xC6, 0x54, 0xD6, 0xD6, 0xC6, 0x34, 0xBD, 0xD3, +0xBD, 0xB3, 0xC5, 0xF4, 0xC5, 0xD4, 0xC5, 0xF4, +0xC5, 0xF4, 0xC6, 0x14, 0xCE, 0x35, 0xB5, 0x51, +0xBD, 0xB2, 0xAC, 0xEF, 0xB4, 0xEF, 0xAC, 0xCE, +0xE6, 0x95, 0xDE, 0x54, 0xDE, 0x54, 0xDE, 0x54, +0xDE, 0x54, 0xCD, 0xB3, 0xCD, 0xD3, 0xD6, 0x34, +0xDE, 0x34, 0xDE, 0x54, 0xDE, 0x74, 0xE6, 0xB5, +0xDE, 0x94, 0xD6, 0x94, 0xCE, 0x33, 0xCD, 0xF3, +0xC5, 0xD3, 0x94, 0xCF, 0x52, 0xA8, 0x29, 0x64, +0x29, 0x65, 0x31, 0xA6, 0x31, 0xA6, 0x39, 0xE7, +0x52, 0xAA, 0x63, 0x4D, 0x73, 0x8E, 0x73, 0xAE, +0x6B, 0x4D, 0x8C, 0x52, 0x73, 0xAF, 0xAD, 0x76, +0x9C, 0xF4, 0xC6, 0x39, 0xEF, 0x3D, 0xCE, 0x59, +0xC6, 0x18, 0xD6, 0xBA, 0x94, 0x51, 0x94, 0x90, +0x7B, 0xAC, 0x8C, 0x0D, 0xB5, 0x0F, 0xA4, 0xAE, +0x94, 0x2D, 0x94, 0x2E, 0x94, 0x6E, 0xB5, 0x31, +0xBD, 0x92, 0xBD, 0x72, 0xBD, 0x72, 0xC5, 0x93, +0xC5, 0x93, 0xCD, 0xD3, 0xC5, 0xB3, 0xC5, 0xD3, +0xC5, 0xB3, 0xCD, 0xD3, 0xC5, 0xD3, 0xC5, 0xB3, +0xC5, 0x72, 0xB5, 0x11, 0x94, 0x4E, 0x7B, 0x6B, +0x8B, 0xED, 0x83, 0xAC, 0xA4, 0xB0, 0xBD, 0x52, +0xA4, 0xB0, 0x73, 0x6B, 0x7B, 0xAD, 0x6B, 0x4B, +0x41, 0xE6, 0x4A, 0x48, 0x42, 0x28, 0x5A, 0xEB, +0x62, 0xEB, 0x52, 0xAA, 0x63, 0x2C, 0x6B, 0x4D, +0x8C, 0x30, 0x94, 0x91, 0x4A, 0x48, 0x39, 0xC6, +0x31, 0xA6, 0x39, 0xE7, 0x4A, 0x48, 0x4A, 0x68, +0x42, 0x07, 0x5A, 0xCB, 0x5A, 0xCB, 0x6B, 0x6E, +0x7B, 0xF0, 0x84, 0x32, 0x94, 0x93, 0xA4, 0xF5, +0x9C, 0xD4, 0xB5, 0x96, 0xC5, 0xF8, 0xA4, 0xF4, +0xB5, 0x76, 0xC5, 0xF8, 0xBD, 0xD7, 0xE6, 0xFB, +0xD6, 0x7A, 0xE6, 0xFC, 0xB5, 0x97, 0xAD, 0x35, +0xC5, 0xD7, 0xD6, 0x79, 0xDE, 0xBA, 0xD6, 0x38, +0xA4, 0xD2, 0xC5, 0xD5, 0xB5, 0x32, 0xCD, 0xF5, +0xE6, 0xB7, 0xE6, 0x76, 0xDE, 0x55, 0xE6, 0x96, +0xDE, 0x55, 0xDE, 0x55, 0xE6, 0x76, 0xE6, 0x96, +0xDE, 0x55, 0xD5, 0xD3, 0xDE, 0x14, 0xDE, 0x14, +0xDE, 0x55, 0xEE, 0xB6, 0xDE, 0x75, 0xDE, 0x55, +0xEE, 0x96, 0xD5, 0xF3, 0xD5, 0xB2, 0xAC, 0x8E, +0xAC, 0x8E, 0xAC, 0xF0, 0xD6, 0x56, 0xCE, 0x35, +0xC6, 0x15, 0xCE, 0x36, 0xCE, 0x36, 0xCE, 0x36, +0xCE, 0x56, 0xD6, 0x76, 0xBD, 0xD4, 0xCE, 0x15, +0xD6, 0x55, 0xD6, 0x55, 0xD6, 0x56, 0xD6, 0x55, +0xCE, 0x14, 0xCE, 0x15, 0xCE, 0x15, 0xD6, 0x56, +0xD6, 0x76, 0xD6, 0x56, 0xCE, 0x56, 0xCE, 0x35, +0xCE, 0x35, 0xA4, 0xD1, 0xA4, 0xB0, 0xEE, 0x35, +0xED, 0xD3, 0xF6, 0x35, 0xEE, 0x35, 0xEE, 0x15, +0xEE, 0x14, 0xED, 0xF4, 0xED, 0xD3, 0xEE, 0x76, +0xEE, 0xD8, 0xE6, 0xD8, 0xDE, 0xB7, 0xE6, 0xB8, +0xE6, 0xB7, 0xE6, 0x97, 0xE6, 0x56, 0xE5, 0xD3, +0xDD, 0x51, 0xDD, 0x71, 0xE5, 0x92, 0xE5, 0x92, +0xE6, 0x35, 0xEE, 0xF9, 0x9C, 0xB1, 0xC5, 0xD5, +0xC5, 0xF5, 0xC5, 0xB4, 0xCE, 0x36, 0xE6, 0xD8, +0xC5, 0xD5, 0xB5, 0x74, 0xBD, 0x96, 0xB5, 0x55, +0x8B, 0xF0, 0xBD, 0x75, 0xCD, 0xF7, 0xDE, 0x58, +0x9C, 0x0F, 0x83, 0x2C, 0x5A, 0x49, 0x52, 0x48, +0x52, 0x88, 0x6C, 0x0B, 0x4B, 0x27, 0x5B, 0x4A, +0x32, 0x06, 0x10, 0xE2, 0x11, 0x02, 0x19, 0x02, +0x19, 0x43, 0x5B, 0xCA, 0x74, 0x8C, 0x6C, 0x8B, +0x6C, 0xAC, 0x8D, 0x6E, 0x8D, 0x8F, 0x53, 0x87, +0x53, 0x89, 0x8D, 0x2F, 0x53, 0x88, 0x32, 0x65, +0x3A, 0xA5, 0x5B, 0xC8, 0x64, 0x09, 0x7D, 0x0D, +0xB6, 0x93, 0x74, 0x8B, 0x64, 0x09, 0x74, 0x8C, +0x9D, 0xB0, 0x95, 0x4F, 0x64, 0x2A, 0xAE, 0x93, +0x73, 0x2B, 0x7B, 0x8C, 0x7B, 0x6C, 0x83, 0xAC, +0x8C, 0x2E, 0x94, 0x4F, 0x8C, 0x0E, 0x9C, 0x8F, +0x9C, 0x6F, 0x9C, 0x6F, 0x8C, 0x2D, 0x94, 0x2E, +0xA4, 0xD0, 0xB5, 0x11, 0xA4, 0x8F, 0xAC, 0xF0, +0xA4, 0xAF, 0xA4, 0x6E, 0xA4, 0x6E, 0xA4, 0x8E, +0x94, 0x0C, 0x8B, 0xCB, 0x8B, 0xAB, 0x83, 0x8A, +0x8B, 0xAB, 0x8B, 0xCB, 0x9C, 0x0C, 0x9C, 0x2C, +0x94, 0x0C, 0x94, 0x0C, 0x94, 0x0C, 0x9C, 0x2C, +0xA4, 0x6D, 0xA4, 0x8E, 0xAC, 0xAE, 0xB4, 0xCF, +0xAC, 0xCE, 0xAC, 0x8E, 0xA4, 0x6D, 0xB4, 0xCF, +0xAC, 0xD0, 0xB4, 0xF0, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xAE, 0x9C, 0x2D, 0x94, 0x0D, 0x83, 0xAB, +0x83, 0xAB, 0xA4, 0xD0, 0xA4, 0xCF, 0x94, 0x2D, +0x7B, 0x8B, 0x6B, 0x2A, 0x6B, 0x2B, 0x6B, 0x4A, +0x73, 0x4B, 0x73, 0x4A, 0xA4, 0xB0, 0xAC, 0xF0, +0xB5, 0x30, 0xD6, 0x55, 0xBD, 0x92, 0xC6, 0x35, +0xD6, 0x96, 0xCE, 0x75, 0xCE, 0x95, 0xC6, 0x75, +0xC6, 0x54, 0xCE, 0x75, 0xC6, 0x14, 0xB5, 0x72, +0xC5, 0xF4, 0xC6, 0x14, 0xC5, 0xD4, 0xCE, 0x14, +0xCE, 0x14, 0xCE, 0x14, 0xCE, 0x55, 0xB5, 0x72, +0x9C, 0x6E, 0x9C, 0x4D, 0xB4, 0xEF, 0xB5, 0x30, +0xE6, 0x95, 0xDE, 0x53, 0xE6, 0x74, 0xE6, 0xB5, +0xE6, 0x95, 0xCD, 0xF3, 0xCD, 0xF4, 0xD6, 0x34, +0xDE, 0x54, 0xDE, 0x54, 0xC5, 0xF1, 0xBD, 0xD1, +0xC6, 0x12, 0xD6, 0xB4, 0xD6, 0xB4, 0xC6, 0x33, +0xBD, 0xF2, 0xD6, 0xB5, 0xBD, 0xD2, 0x8C, 0x4D, +0x4A, 0x67, 0x31, 0x85, 0x31, 0xA5, 0x42, 0x28, +0x39, 0xE7, 0x42, 0x28, 0x52, 0x89, 0x52, 0xAA, +0x63, 0x2C, 0x6B, 0x4D, 0x6B, 0x4D, 0x8C, 0x52, +0xA5, 0x35, 0xB5, 0xB7, 0xD6, 0x9B, 0xB5, 0x96, +0xB5, 0xB6, 0x83, 0xF0, 0x8C, 0x51, 0xBD, 0xD7, +0x8C, 0x50, 0x94, 0x4F, 0xA4, 0x8F, 0x8C, 0x0D, +0x8C, 0x2E, 0x94, 0x90, 0xAD, 0x32, 0xB5, 0x72, +0xAD, 0x52, 0xBD, 0x93, 0xAD, 0x32, 0xB5, 0x73, +0xBD, 0xB3, 0xC5, 0xD4, 0xCE, 0x15, 0xCE, 0x15, +0xCE, 0x15, 0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xD4, +0xCD, 0xF5, 0xC5, 0xD4, 0xBD, 0xB5, 0x9C, 0xF2, +0xA4, 0xF2, 0xAD, 0x53, 0x94, 0x4F, 0xB5, 0x32, +0xAD, 0x32, 0xB5, 0x73, 0xBD, 0x93, 0xB5, 0x73, +0x8C, 0x2E, 0x52, 0x68, 0x4A, 0x48, 0x8C, 0x51, +0x94, 0x91, 0x5A, 0xEB, 0x5A, 0xAA, 0x8C, 0x51, +0x73, 0x6D, 0x62, 0xEA, 0x52, 0x89, 0x4A, 0x28, +0x42, 0x07, 0x39, 0xE7, 0x3A, 0x07, 0x4A, 0x48, +0x42, 0x07, 0x4A, 0x49, 0x4A, 0x49, 0x52, 0xAB, +0x63, 0x0C, 0x7B, 0xF0, 0x9C, 0xF4, 0x7B, 0xD0, +0x9C, 0xD3, 0xB5, 0x96, 0xB5, 0xB7, 0xA4, 0xF4, +0xAD, 0x56, 0xB5, 0x76, 0xC6, 0x18, 0xA5, 0x15, +0x84, 0x11, 0xB5, 0x76, 0xAD, 0x76, 0x9C, 0xD4, +0x5A, 0xCB, 0x63, 0x0C, 0x94, 0x92, 0x83, 0xEF, +0x42, 0x08, 0x9C, 0xD3, 0x94, 0x50, 0xB5, 0x12, +0xC5, 0x93, 0xC5, 0x72, 0xC5, 0x72, 0xBD, 0x31, +0xA4, 0xAF, 0x9C, 0x8F, 0xA4, 0xB0, 0xAC, 0xB0, +0xAC, 0xD0, 0xA4, 0xB0, 0xAC, 0xD0, 0xC5, 0x72, +0xD5, 0xF3, 0xDE, 0x14, 0xDE, 0x55, 0xDE, 0x34, +0xDE, 0x14, 0xE6, 0x75, 0xC5, 0x71, 0xAC, 0xAE, +0xB5, 0x10, 0xA4, 0xD0, 0xD6, 0x36, 0xD6, 0x76, +0xCE, 0x56, 0xCE, 0x56, 0xCE, 0x56, 0xCE, 0x56, +0xCE, 0x56, 0xCE, 0x56, 0xC5, 0xF5, 0xD6, 0x56, +0xD6, 0x55, 0xD6, 0x55, 0xD6, 0x55, 0xD6, 0x56, +0xCE, 0x14, 0xC5, 0xF4, 0xD6, 0x56, 0xD6, 0x97, +0xD6, 0x97, 0xD6, 0x76, 0xD6, 0x97, 0xD6, 0x76, +0xCE, 0x15, 0xA4, 0xB0, 0xA4, 0x90, 0xE5, 0xF4, +0xED, 0xF4, 0xEE, 0x15, 0xED, 0xF4, 0xED, 0xF4, +0xE5, 0xF4, 0xEE, 0x14, 0xEE, 0x35, 0xEE, 0x97, +0xE6, 0xD8, 0xE6, 0xB8, 0xDE, 0x98, 0xE6, 0xB8, +0xE6, 0xB8, 0xE6, 0x97, 0xE6, 0x35, 0xE5, 0xB3, +0xE5, 0x71, 0xE5, 0x71, 0xE5, 0x92, 0xE5, 0xB2, +0xE6, 0x55, 0xEF, 0x19, 0xA4, 0xD1, 0xC5, 0xF5, +0xD6, 0x77, 0xE6, 0xD9, 0xD6, 0x78, 0xB5, 0x95, +0x94, 0x71, 0xBD, 0xB6, 0xBD, 0x96, 0xCD, 0xF7, +0x9C, 0x71, 0xB5, 0x13, 0xBD, 0x54, 0xAC, 0xB1, +0x82, 0xEB, 0x62, 0x48, 0x49, 0xC6, 0x4A, 0x48, +0x3A, 0x07, 0x6B, 0xEB, 0x52, 0xE8, 0x9C, 0xF2, +0x31, 0xE6, 0x10, 0xE2, 0x19, 0x02, 0x42, 0x25, +0x7C, 0x4A, 0x85, 0x0C, 0x74, 0xAC, 0x74, 0xED, +0x5C, 0x0A, 0x43, 0x47, 0x74, 0xAC, 0x6C, 0x8C, +0x74, 0xAD, 0x85, 0x0F, 0x3A, 0xE6, 0x2A, 0x43, +0x53, 0x88, 0x7D, 0x0D, 0x85, 0x2D, 0x95, 0x90, +0xB6, 0x73, 0x85, 0x2E, 0x7C, 0xCC, 0x7D, 0x0C, +0x95, 0x8F, 0xA5, 0xF2, 0x6C, 0x4B, 0x4B, 0x67, +0x8C, 0x50, 0x73, 0x6C, 0x7B, 0xAD, 0x83, 0xAD, +0x8C, 0x2E, 0x8C, 0x2E, 0x8C, 0x4E, 0x9C, 0xD0, +0xA4, 0xD0, 0x9C, 0xB0, 0x94, 0x6F, 0xA4, 0xD0, +0x94, 0x0D, 0xAC, 0xF0, 0xA4, 0xCF, 0xB5, 0x72, +0xBD, 0x92, 0xBD, 0x92, 0xC5, 0xB2, 0xB5, 0x31, +0xAC, 0xAF, 0xB4, 0xF0, 0xAC, 0xF0, 0xAC, 0xEF, +0xAC, 0xCF, 0xA4, 0xAF, 0xAC, 0xCF, 0xC5, 0xB2, +0xB5, 0x10, 0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x6D, +0xAC, 0xEF, 0xA4, 0x6D, 0x9C, 0x4D, 0x9C, 0x6D, +0xA4, 0x8D, 0xA4, 0x6D, 0xA4, 0x6D, 0xA4, 0x8E, +0xAC, 0x8E, 0xAC, 0x8E, 0xAC, 0xAE, 0xAC, 0xAE, +0xAC, 0xAF, 0xAC, 0xAE, 0xAC, 0xAF, 0xAC, 0xAF, +0xAC, 0xCF, 0xA4, 0xAF, 0xA4, 0xAF, 0x9C, 0x6E, +0x94, 0x2D, 0x8B, 0xEC, 0x83, 0xCC, 0x83, 0xAB, +0x7B, 0x6B, 0x73, 0x4A, 0x94, 0x0D, 0x94, 0x0C, +0x8B, 0xEC, 0x9C, 0xAE, 0xA4, 0xCF, 0xBD, 0xB3, +0xC6, 0x14, 0xC6, 0x14, 0xC6, 0x35, 0xCE, 0x76, +0xC6, 0x35, 0xCE, 0x75, 0xC6, 0x34, 0xA4, 0xF0, +0xC5, 0xF4, 0xDE, 0xB7, 0xD6, 0x96, 0xD6, 0x76, +0xD6, 0x76, 0xD6, 0x76, 0xCE, 0x35, 0xCE, 0x55, +0xCE, 0x15, 0xC5, 0x92, 0xB4, 0xEF, 0xB5, 0x0F, +0xDE, 0x54, 0xEE, 0xB5, 0xE6, 0x95, 0xE6, 0x95, +0xDE, 0x75, 0xD6, 0x14, 0xC5, 0xB3, 0xCD, 0xD3, +0xDE, 0x55, 0xE6, 0xD6, 0xE6, 0xF6, 0xDE, 0xD5, +0xC6, 0x32, 0xAD, 0xAF, 0xB5, 0xD0, 0xCE, 0x94, +0xC6, 0x33, 0xC6, 0x33, 0xA5, 0x2F, 0xB5, 0x70, +0xA4, 0xEF, 0x6B, 0x6A, 0x42, 0x27, 0x31, 0xA6, +0x21, 0x24, 0x31, 0x85, 0x39, 0xE7, 0x42, 0x28, +0x52, 0x8A, 0x52, 0x8A, 0x4A, 0x69, 0x73, 0xAF, +0x9C, 0xF4, 0x7B, 0xD0, 0xBD, 0xB8, 0xA4, 0xF4, +0xB5, 0xB7, 0xAD, 0x56, 0xBD, 0xD8, 0xAD, 0x35, +0xE7, 0x1C, 0xD6, 0x79, 0xAC, 0xF2, 0x83, 0xEE, +0x73, 0x8D, 0x7B, 0xEE, 0x84, 0x0F, 0x8C, 0x50, +0x9C, 0xD1, 0xA4, 0xF1, 0x9C, 0xB0, 0x9C, 0xB1, +0xAD, 0x33, 0xB5, 0x94, 0xC5, 0xD5, 0xC5, 0xF5, +0xB5, 0x73, 0xBD, 0x94, 0xC5, 0xD5, 0xBD, 0xB4, +0xBD, 0xD4, 0xBD, 0xB4, 0xAD, 0x33, 0x94, 0xB1, +0x9C, 0xD1, 0x9C, 0xD1, 0x9C, 0x90, 0xB5, 0x52, +0xBD, 0x94, 0xBD, 0x73, 0xA4, 0xF1, 0x94, 0x8F, +0xBD, 0xD4, 0xCE, 0x16, 0x9C, 0xB1, 0x8C, 0x71, +0x94, 0x92, 0x7B, 0xEF, 0x63, 0x0B, 0x62, 0xEB, +0x5A, 0xAA, 0x31, 0xA5, 0x42, 0x28, 0x52, 0x89, +0x4A, 0x68, 0x39, 0xE7, 0x39, 0xC6, 0x42, 0x27, +0x39, 0xC6, 0x4A, 0x48, 0x52, 0xAA, 0x5A, 0xCB, +0x63, 0x2D, 0x84, 0x10, 0x7B, 0xF0, 0x73, 0x6E, +0xAD, 0x35, 0xC6, 0x39, 0xB5, 0x97, 0xC6, 0x18, +0xBD, 0xB7, 0x8C, 0x51, 0x6B, 0x4D, 0x5A, 0xAB, +0x9C, 0xB4, 0xB5, 0xB6, 0xBD, 0xD7, 0x9C, 0xB3, +0xAD, 0x55, 0x94, 0x92, 0x73, 0x6E, 0x6B, 0x4D, +0x73, 0x6E, 0xBD, 0xB6, 0xC5, 0xF6, 0xC5, 0xB5, +0xD5, 0xF4, 0xCD, 0xB3, 0xD5, 0xF4, 0xD6, 0x15, +0xCD, 0xD4, 0xBD, 0x73, 0xA4, 0xB0, 0x94, 0x4F, +0x9C, 0x6F, 0x9C, 0x90, 0xA4, 0xB0, 0xA4, 0xB0, +0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xD0, 0xAC, 0xD0, +0xAC, 0xD0, 0xA4, 0xAF, 0xA4, 0xAF, 0xBD, 0x11, +0xBD, 0x52, 0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x32, 0xAD, 0x12, 0xA4, 0xF1, 0xA4, 0xF1, +0x9C, 0xD1, 0x9C, 0xB0, 0x9C, 0x90, 0xA4, 0xF1, +0xB5, 0x72, 0xB5, 0x72, 0xAD, 0x32, 0xB5, 0x73, +0xAD, 0x32, 0xAD, 0x32, 0xD6, 0x76, 0xC6, 0x15, +0xC5, 0xF4, 0xD6, 0x56, 0xC5, 0xD4, 0xC5, 0xF5, +0xB5, 0x73, 0xAC, 0xF2, 0xAC, 0xF1, 0xDD, 0xF4, +0xF6, 0x35, 0xEE, 0x14, 0xEE, 0x15, 0xEE, 0x35, +0xEE, 0x35, 0xEE, 0x56, 0xEE, 0x97, 0xEE, 0xF9, +0xEE, 0xF9, 0xEE, 0xF9, 0xEE, 0xF9, 0xEE, 0xF9, +0xEE, 0xF9, 0xEE, 0xD7, 0xEE, 0x97, 0xEE, 0x14, +0xE5, 0xB2, 0xED, 0xB3, 0xED, 0xB2, 0xED, 0xD3, +0xEE, 0x56, 0xEE, 0xF9, 0xC5, 0xF6, 0xE6, 0xB9, +0xB5, 0x74, 0x83, 0xEF, 0x9C, 0xB3, 0xC5, 0xD6, +0xB5, 0x55, 0xB5, 0x75, 0xB5, 0x35, 0xBD, 0x75, +0x9C, 0x71, 0x93, 0xEF, 0x83, 0x4C, 0x72, 0xA9, +0x62, 0x27, 0x49, 0xC6, 0x29, 0x24, 0x31, 0xA6, +0x4A, 0x68, 0x63, 0x6B, 0x9C, 0xF2, 0x94, 0xB1, +0x3A, 0x07, 0x42, 0x27, 0x7B, 0xCE, 0xA5, 0x11, +0xDE, 0xD4, 0xCE, 0x92, 0x74, 0x8C, 0x85, 0x0E, +0x53, 0xC9, 0x4B, 0x89, 0x5C, 0x0B, 0x64, 0x4B, +0x74, 0xCE, 0x74, 0x8D, 0x32, 0xA5, 0x32, 0x84, +0x53, 0xA8, 0x8D, 0x8F, 0x8D, 0x8F, 0x95, 0xB0, +0xAE, 0x33, 0x8D, 0x4E, 0x7D, 0x0D, 0x7D, 0x0C, +0x64, 0x6A, 0x6C, 0x6B, 0x9D, 0xD0, 0x7C, 0xEC, +0xC5, 0xF8, 0x7B, 0x8D, 0x7B, 0x8C, 0x7B, 0xAD, +0x94, 0x6F, 0x94, 0x6F, 0x8C, 0x4E, 0x8C, 0x4E, +0x94, 0x6E, 0x94, 0x6F, 0xA4, 0xF1, 0xAD, 0x32, +0x83, 0xCC, 0x9C, 0x8E, 0xA4, 0xF0, 0xAD, 0x31, +0xAD, 0x31, 0xA4, 0xF0, 0xA4, 0xCF, 0x9C, 0xAF, +0x8B, 0xEC, 0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xEF, +0xAD, 0x10, 0xAC, 0xCF, 0xA4, 0xAE, 0xCE, 0x14, +0xD6, 0x35, 0xCD, 0xF4, 0xCE, 0x14, 0xC5, 0xD3, +0xD6, 0x14, 0xAC, 0xF0, 0x9C, 0x8E, 0x94, 0x2C, +0x8B, 0xEC, 0x83, 0xCB, 0x94, 0x2C, 0x8B, 0xEC, +0x94, 0x2D, 0x9C, 0x6D, 0xA4, 0xAF, 0xB5, 0x10, +0xBD, 0x72, 0xBD, 0x31, 0xB5, 0x10, 0xB5, 0x31, +0xA4, 0xAE, 0xA4, 0xAE, 0xAC, 0xCF, 0xAC, 0xCF, +0xB4, 0xF0, 0xB4, 0xF0, 0xB4, 0xF0, 0xAC, 0xF0, +0xAC, 0xF0, 0xA4, 0xCF, 0xA4, 0x8E, 0xAC, 0xCF, +0xA4, 0x8E, 0x9C, 0x8D, 0x94, 0x2D, 0x94, 0x0C, +0x8C, 0x0C, 0x94, 0x0D, 0x8C, 0x2D, 0xB5, 0x72, +0xAD, 0x51, 0xBD, 0xD3, 0xCE, 0x53, 0xDE, 0xF6, +0xD6, 0x95, 0xAD, 0x71, 0x94, 0x6E, 0x94, 0x4E, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0xA4, 0xAF, +0xB5, 0x31, 0xB5, 0x10, 0xA4, 0xAE, 0xAC, 0xCE, +0xA4, 0x8D, 0x9C, 0x6D, 0x9C, 0x2C, 0x94, 0x2C, +0x94, 0x2C, 0x9C, 0x6D, 0x9C, 0x8E, 0xA4, 0xAE, +0xAC, 0xEF, 0xB5, 0x30, 0xB5, 0x30, 0xC5, 0xB2, +0xD6, 0x33, 0xCE, 0x53, 0xB5, 0x70, 0xBD, 0xD2, +0xCE, 0x75, 0xBD, 0xD2, 0xAD, 0x30, 0xA4, 0xCE, +0xA4, 0xCE, 0x83, 0xEC, 0x7B, 0xCC, 0x5A, 0xA8, +0x42, 0x06, 0x31, 0xA6, 0x31, 0xA5, 0x31, 0xA5, +0x42, 0x27, 0x31, 0xA6, 0x31, 0xA6, 0x52, 0xAA, +0x6B, 0x8D, 0x7B, 0xF0, 0xA4, 0xF4, 0xB5, 0xB7, +0xBD, 0xD7, 0xAD, 0x35, 0xBD, 0xF8, 0xD6, 0x9A, +0xE7, 0x1C, 0xD6, 0xBA, 0xB5, 0x96, 0xA4, 0xF3, +0x8C, 0x30, 0x7B, 0xEF, 0x73, 0x8D, 0x73, 0xAE, +0x8C, 0x50, 0x7B, 0xAE, 0x73, 0x6D, 0x6B, 0x6D, +0x7B, 0xCE, 0x94, 0x71, 0x9C, 0xD2, 0x94, 0xB1, +0x94, 0x91, 0x9C, 0xD2, 0x94, 0xB1, 0x9C, 0xD2, +0x94, 0x91, 0x9C, 0xD2, 0x94, 0x71, 0x84, 0x2F, +0x94, 0x91, 0x8C, 0x4F, 0xA4, 0xD1, 0xBD, 0x93, +0xC5, 0xD4, 0xB5, 0x73, 0xA5, 0x12, 0xBD, 0x94, +0xD6, 0x56, 0xC5, 0xD4, 0xC5, 0xF5, 0x94, 0x91, +0x84, 0x30, 0x83, 0xEF, 0x73, 0x4D, 0x4A, 0x28, +0x39, 0xC6, 0x29, 0x44, 0x29, 0x24, 0x4A, 0x48, +0x52, 0x89, 0x39, 0xE7, 0x31, 0xA6, 0x39, 0xC6, +0x42, 0x07, 0x52, 0x89, 0x52, 0xAA, 0x63, 0x2C, +0x84, 0x10, 0x6B, 0x6D, 0x5A, 0xEB, 0x7B, 0xCF, +0x8C, 0x51, 0x9C, 0xD4, 0xBD, 0xD8, 0xC6, 0x18, +0x84, 0x10, 0x41, 0xE8, 0x41, 0xE8, 0x94, 0x92, +0x8C, 0x51, 0x7B, 0xAF, 0xB5, 0x96, 0xD6, 0x9A, +0xE6, 0xFB, 0xB5, 0x96, 0x9C, 0xB3, 0x8C, 0x31, +0x94, 0x71, 0xCE, 0x37, 0xDE, 0xB8, 0xC5, 0xF6, +0xCE, 0x16, 0xBD, 0x73, 0x9C, 0x6F, 0x8C, 0x0E, +0xA4, 0xD1, 0x9C, 0x90, 0x94, 0x6F, 0x7B, 0x8C, +0x7B, 0xAD, 0x8C, 0x0E, 0x83, 0xCD, 0x83, 0xAD, +0x94, 0x2F, 0x83, 0xCD, 0x83, 0xAD, 0x94, 0x2E, +0xA4, 0xB0, 0xB5, 0x53, 0xBD, 0x93, 0xBD, 0x73, +0xB5, 0x12, 0xB5, 0x52, 0xBD, 0x93, 0xB5, 0x52, +0xB5, 0x52, 0xBD, 0x94, 0xC5, 0xD4, 0xC5, 0xD4, +0xC5, 0xB4, 0xBD, 0x94, 0xBD, 0x94, 0xBD, 0x73, +0xAD, 0x32, 0xB5, 0x53, 0xB5, 0x32, 0xAD, 0x12, +0xAD, 0x12, 0xAC, 0xF1, 0xA4, 0xD1, 0xA4, 0xD1, +0xAD, 0x11, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x11, +0xAC, 0xF1, 0xA4, 0xB0, 0x94, 0x2E, 0xBD, 0x52, +0xD5, 0x93, 0xCD, 0x72, 0xCD, 0x93, 0xDD, 0xF5, +0xDE, 0x15, 0xEE, 0x97, 0xEE, 0xD8, 0xEF, 0x19, +0xEF, 0x1A, 0xE7, 0x19, 0xEF, 0x1A, 0xEF, 0x1A, +0xEE, 0xF9, 0xEE, 0xB8, 0xEE, 0xD8, 0xF6, 0xB7, +0xF6, 0x76, 0xF6, 0x55, 0xEE, 0x55, 0xEE, 0x56, +0xEE, 0x98, 0xD6, 0x37, 0x9C, 0xB2, 0x8C, 0x10, +0xBD, 0x96, 0xB5, 0x55, 0xC5, 0xD7, 0xBD, 0x95, +0xAD, 0x34, 0x8C, 0x30, 0x9C, 0xB2, 0x8C, 0x10, +0x7B, 0xAE, 0x6B, 0x0B, 0x52, 0x07, 0x39, 0x44, +0x62, 0x69, 0x41, 0xE7, 0x21, 0x03, 0x21, 0x03, +0x21, 0x44, 0x31, 0xA6, 0x63, 0x2C, 0x6B, 0x4D, +0x63, 0x0C, 0xBD, 0xD5, 0xAD, 0x32, 0xB5, 0x52, +0xEF, 0x17, 0xEF, 0x16, 0x84, 0xCE, 0x74, 0x8C, +0x4B, 0xA9, 0x6C, 0x8D, 0x74, 0xAE, 0x74, 0xAE, +0x74, 0xCE, 0x5B, 0xEA, 0x3A, 0xE5, 0x3B, 0x06, +0x53, 0xC8, 0x8D, 0x6E, 0x95, 0x90, 0x9D, 0xD1, +0xA6, 0x32, 0x8D, 0x6F, 0x7D, 0x0D, 0x85, 0x2D, +0x74, 0xCC, 0x32, 0x84, 0x53, 0x88, 0x95, 0x6E, +0xBD, 0xF8, 0x94, 0x72, 0x7B, 0x6C, 0x84, 0x0D, +0x9C, 0xD0, 0xA4, 0xF1, 0x9C, 0xD1, 0x9C, 0x90, +0x94, 0x8F, 0x94, 0x90, 0x8C, 0x6F, 0x7B, 0xAC, +0x73, 0x8B, 0x8C, 0x2D, 0xA5, 0x10, 0xAD, 0x11, +0xAD, 0x31, 0xA4, 0xF0, 0xA4, 0xD0, 0xA4, 0xF0, +0x9C, 0xD0, 0xAC, 0xF0, 0xA4, 0xAF, 0xA4, 0x8E, +0xA4, 0x8E, 0xA4, 0x8E, 0xA4, 0xAE, 0xBD, 0xB2, +0xBD, 0xB2, 0xC5, 0xD3, 0xCD, 0xF4, 0xD6, 0x34, +0xD6, 0x75, 0xCD, 0xF4, 0xCE, 0x35, 0xCE, 0x15, +0xCE, 0x15, 0xCD, 0xF4, 0xCD, 0xF4, 0xC5, 0xD4, +0xBD, 0xB3, 0xBD, 0xB3, 0xCD, 0xF4, 0xD6, 0x56, +0xD6, 0x35, 0xCD, 0xF3, 0xCE, 0x14, 0xDE, 0x55, +0xAC, 0xCF, 0xA4, 0xAF, 0xB5, 0x30, 0xAC, 0xCF, +0xA4, 0xCF, 0x9C, 0x6E, 0x94, 0x2D, 0x94, 0x0C, +0x94, 0x0C, 0x94, 0x2D, 0x94, 0x2D, 0x9C, 0x6D, +0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAE, 0xAC, 0xCF, +0xA4, 0xAF, 0xA4, 0x8E, 0xA4, 0xCF, 0xBD, 0x92, +0x9C, 0xAE, 0x9C, 0xAD, 0xA4, 0xEE, 0xB5, 0xB0, +0xD6, 0xF5, 0xE7, 0x77, 0xD6, 0xB5, 0xBD, 0x92, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x52, 0x94, 0x4D, +0x93, 0xEC, 0x94, 0x2C, 0xA4, 0x8D, 0xAC, 0xAE, +0x9C, 0x6D, 0x9C, 0x6E, 0xAC, 0xEF, 0xB5, 0x10, +0xA4, 0xAE, 0xA4, 0xAE, 0xA4, 0xAE, 0xA4, 0xAE, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0x9C, 0x6D, +0xA4, 0x8E, 0xA4, 0x8E, 0x9C, 0x4D, 0x8C, 0x2C, +0xBD, 0xD3, 0xB5, 0xB2, 0x9C, 0xAE, 0x9C, 0x8D, +0xA5, 0x2F, 0xB5, 0xD1, 0xB5, 0xF1, 0xB5, 0xF1, +0xA5, 0x70, 0x7C, 0x0C, 0x42, 0x26, 0x29, 0x64, +0x31, 0x86, 0x29, 0x44, 0x31, 0xA6, 0x39, 0xE7, +0x4A, 0x69, 0x73, 0x8E, 0x94, 0xB3, 0x94, 0x72, +0x8C, 0x51, 0xAD, 0x35, 0xA5, 0x15, 0x84, 0x10, +0x9C, 0xB3, 0x8C, 0x31, 0x6B, 0x4D, 0x8C, 0x51, +0x94, 0x71, 0xAD, 0x55, 0x6B, 0x6D, 0x63, 0x2C, +0x63, 0x4C, 0x63, 0x2C, 0x5A, 0xCA, 0x52, 0xAA, +0x6B, 0x4D, 0x7B, 0xCE, 0x84, 0x30, 0x8C, 0x50, +0x73, 0xAE, 0x84, 0x30, 0x84, 0x30, 0x8C, 0x50, +0x7B, 0xEF, 0x73, 0xAE, 0x84, 0x0F, 0x84, 0x0F, +0x84, 0x0E, 0x7B, 0xAD, 0x9C, 0xB1, 0xB5, 0x52, +0xBD, 0xB4, 0xAD, 0x53, 0xA5, 0x32, 0xD6, 0x77, +0xCE, 0x15, 0xBD, 0x94, 0xB5, 0x74, 0xB5, 0x74, +0x84, 0x0F, 0x94, 0x71, 0x73, 0x8D, 0x39, 0xE7, +0x31, 0x65, 0x29, 0x44, 0x29, 0x44, 0x31, 0xA5, +0x52, 0x88, 0x39, 0xE6, 0x31, 0x85, 0x31, 0xA6, +0x3A, 0x07, 0x52, 0xCA, 0x63, 0x2C, 0x5A, 0xEB, +0x52, 0xAA, 0x4A, 0x69, 0x63, 0x0C, 0x6B, 0x6E, +0x84, 0x11, 0x9C, 0xD4, 0xBD, 0xF8, 0x9C, 0xD3, +0x9C, 0xB3, 0x6B, 0x4D, 0x63, 0x0C, 0xA4, 0xD3, +0x6B, 0x4D, 0x6B, 0x2D, 0x83, 0xF0, 0xAD, 0x35, +0xC5, 0xF8, 0x8C, 0x31, 0x73, 0x6E, 0x7B, 0xAE, +0x73, 0x6D, 0x9C, 0xB2, 0x6B, 0x0C, 0x4A, 0x4A, +0xC5, 0xD6, 0xFF, 0x7B, 0xCD, 0xF6, 0x83, 0xEF, +0x73, 0x6C, 0x9C, 0x70, 0xBD, 0x94, 0xCE, 0x16, +0xC5, 0xD5, 0xC5, 0xD5, 0xAD, 0x12, 0xAC, 0xF2, +0xAD, 0x12, 0x9C, 0xB0, 0x94, 0x4F, 0xA4, 0xD0, +0xAD, 0x31, 0xBD, 0x93, 0xC5, 0xB4, 0xBD, 0x73, +0x9C, 0x90, 0x94, 0x6F, 0x83, 0xCD, 0x94, 0x2E, +0xA4, 0xF1, 0xA4, 0xB0, 0x9C, 0x8F, 0xB5, 0x32, +0xC5, 0xD5, 0x9C, 0x90, 0xAD, 0x12, 0x94, 0x6F, +0xA4, 0xF1, 0xB5, 0x53, 0xC5, 0xD5, 0xBD, 0x73, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x53, 0xAD, 0x32, +0xAD, 0x12, 0xAD, 0x11, 0xA4, 0xD1, 0xA4, 0xD1, +0xA4, 0xF1, 0xA4, 0xD1, 0xA4, 0xB1, 0xA4, 0xD1, +0xAC, 0xF2, 0xAD, 0x12, 0xAD, 0x12, 0xAD, 0x12, +0xAC, 0xF2, 0xA4, 0xD1, 0xA4, 0xD2, 0xA4, 0xF2, +0xA4, 0xD2, 0x9C, 0xD2, 0x9C, 0xD2, 0x9C, 0xD2, +0xA4, 0xD2, 0xA4, 0xD2, 0xA4, 0xD1, 0xB5, 0x33, +0xCD, 0xB5, 0xC5, 0x74, 0xAC, 0xD2, 0xA4, 0xD2, +0xB5, 0x34, 0xBD, 0xB6, 0x94, 0x92, 0xAD, 0x34, +0xCE, 0x18, 0xBD, 0x75, 0xB5, 0x75, 0xA4, 0xF3, +0x94, 0x30, 0x6A, 0xEC, 0x73, 0x4D, 0x52, 0x69, +0x5A, 0xAA, 0x52, 0x48, 0x41, 0xA6, 0x39, 0x85, +0x7B, 0x6D, 0x31, 0x85, 0x21, 0x24, 0x21, 0x24, +0x21, 0x24, 0x31, 0x65, 0x73, 0x6C, 0xA5, 0x13, +0xA4, 0xF2, 0xBD, 0x94, 0xB5, 0x52, 0xB5, 0x32, +0xEF, 0x17, 0xEE, 0xF7, 0x84, 0xAD, 0x64, 0x2B, +0x64, 0x4C, 0x7C, 0xEF, 0x85, 0x10, 0x84, 0xEF, +0x74, 0xCE, 0x53, 0xC9, 0x43, 0x46, 0x43, 0x66, +0x4B, 0xA7, 0x85, 0x2D, 0x95, 0x8F, 0x9D, 0xD1, +0xA5, 0xF2, 0x95, 0xB0, 0x8D, 0x6F, 0x95, 0xB0, +0x85, 0x2E, 0x21, 0xE3, 0x21, 0xE3, 0x3A, 0xC5, +0x5A, 0xCB, 0xA4, 0xF3, 0x7B, 0x8C, 0x8C, 0x2E, +0x9C, 0xD0, 0xA4, 0xD1, 0xA4, 0xF1, 0xA5, 0x12, +0xA5, 0x11, 0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x32, +0x94, 0x6F, 0xA5, 0x12, 0xB5, 0x93, 0xB5, 0x72, +0xB5, 0x73, 0xAD, 0x52, 0xAD, 0x52, 0xC6, 0x16, +0xE7, 0x1B, 0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xDE, +0xEF, 0x3C, 0xC5, 0xF6, 0xAD, 0x11, 0xBD, 0xB2, +0xBD, 0x92, 0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, +0xC5, 0xF3, 0xBD, 0xB3, 0xC5, 0xB3, 0xBD, 0x93, +0xCE, 0x14, 0xD6, 0x35, 0xC5, 0xF4, 0xBD, 0x92, +0xBD, 0xB3, 0xBD, 0xB3, 0xBD, 0xB3, 0xC5, 0xD4, +0xC5, 0xD3, 0xBD, 0x93, 0xC5, 0xD3, 0xCD, 0xF4, +0xA4, 0xAE, 0xB5, 0x10, 0xC5, 0xD3, 0xBD, 0x93, +0xBD, 0x72, 0xB5, 0x51, 0xAD, 0x31, 0xB5, 0x31, +0xB5, 0x31, 0xB5, 0x31, 0xBD, 0x92, 0xD6, 0x78, +0xEF, 0x5C, 0xFF, 0xDF, 0xFF, 0xFF, 0xF7, 0x9E, +0xDE, 0xDA, 0xBD, 0xD4, 0xB5, 0x71, 0xB5, 0x71, +0xBD, 0xB2, 0xB5, 0x71, 0xAD, 0x4F, 0x9C, 0xCD, +0xA5, 0x0F, 0xC6, 0x53, 0xCE, 0x94, 0xAD, 0x51, +0xB5, 0x52, 0xAC, 0xF0, 0x94, 0x6E, 0x7B, 0xAC, +0x7B, 0x8B, 0xA4, 0xAF, 0xAC, 0xAF, 0x7B, 0x8A, +0x52, 0x67, 0x52, 0x68, 0x62, 0xE9, 0x94, 0x4E, +0x73, 0x2A, 0x5A, 0xA8, 0x62, 0xE9, 0x6A, 0xE9, +0x6B, 0x0A, 0x7B, 0x8B, 0x94, 0x4D, 0x9C, 0x6D, +0xA4, 0x8E, 0xA4, 0xAE, 0x8C, 0x0C, 0x73, 0x69, +0x8C, 0x4D, 0xAD, 0x71, 0xAD, 0x30, 0xBD, 0x92, +0xB5, 0xF0, 0xAD, 0xEF, 0xA5, 0xAD, 0xA5, 0xCE, +0xAE, 0x0F, 0xBE, 0x73, 0xB5, 0xD2, 0x4A, 0x67, +0x31, 0x85, 0x31, 0x85, 0x31, 0xA6, 0x31, 0xA6, +0x39, 0xC6, 0x52, 0xAA, 0x6B, 0x6D, 0x6B, 0x6D, +0x84, 0x10, 0xA5, 0x14, 0xA5, 0x14, 0x8C, 0x51, +0x7B, 0xAE, 0x7B, 0xCF, 0x8C, 0x51, 0x8C, 0x71, +0x9C, 0xD3, 0xE7, 0x1C, 0x8C, 0x51, 0x84, 0x10, +0x63, 0x2C, 0x5A, 0xCB, 0x52, 0xAA, 0x52, 0xAA, +0x63, 0x2C, 0x6B, 0x6D, 0x7B, 0xCE, 0x84, 0x0F, +0x73, 0x8D, 0x7B, 0xEF, 0x7B, 0xEF, 0x73, 0xAE, +0x84, 0x30, 0x73, 0x8D, 0x9C, 0xD1, 0x5A, 0xA9, +0x39, 0xE7, 0x4A, 0x28, 0xA4, 0xD1, 0xAD, 0x32, +0xAD, 0x32, 0xA4, 0xF2, 0x9C, 0xF1, 0xAD, 0x53, +0xBD, 0xB4, 0xA5, 0x12, 0xAD, 0x53, 0xB5, 0xB4, +0xB5, 0x94, 0xBD, 0xD5, 0x9C, 0xB2, 0x4A, 0x69, +0x42, 0x07, 0x39, 0xA6, 0x31, 0x65, 0x31, 0x85, +0x4A, 0x48, 0x4A, 0x69, 0x4A, 0x69, 0x4A, 0x68, +0x4A, 0x69, 0x52, 0xAA, 0x4A, 0x89, 0x42, 0x28, +0x39, 0xE7, 0x4A, 0x49, 0x5A, 0xCB, 0x73, 0xAF, +0x84, 0x10, 0xA5, 0x14, 0x94, 0x92, 0x9C, 0xD3, +0xE6, 0xDB, 0xAD, 0x35, 0x8C, 0x10, 0xA4, 0xF4, +0x83, 0xCF, 0x5A, 0xAA, 0x52, 0x8A, 0x6B, 0x2C, +0x7B, 0x8E, 0x52, 0x69, 0x63, 0x0C, 0x7B, 0xCF, +0xB5, 0x75, 0xB5, 0x96, 0x52, 0x8B, 0x7B, 0xCF, +0xBD, 0xB6, 0xCE, 0x17, 0xEE, 0xFB, 0xEE, 0xFB, +0xC5, 0xB6, 0xCD, 0xF7, 0xDE, 0x98, 0xCE, 0x16, +0xDE, 0x98, 0xC5, 0xD5, 0x94, 0x50, 0x9C, 0x91, +0xBD, 0x94, 0xBD, 0x94, 0xA5, 0x11, 0xAC, 0xF1, +0xB5, 0x52, 0xBD, 0x94, 0xAD, 0x53, 0xAD, 0x12, +0xBD, 0xB4, 0xAD, 0x32, 0xAC, 0xF1, 0xB5, 0x53, +0xAD, 0x32, 0xBD, 0x94, 0xA4, 0xF1, 0xB5, 0x73, +0xC5, 0xD5, 0xA4, 0xF1, 0xAD, 0x12, 0x73, 0x4B, +0x9C, 0x8F, 0xAD, 0x11, 0xBD, 0x52, 0xBD, 0x93, +0xC5, 0xB3, 0xBD, 0x73, 0xC5, 0x93, 0xC5, 0xB4, +0xB5, 0x53, 0xB5, 0x11, 0xAC, 0xF1, 0xAC, 0xF1, +0xA4, 0xB0, 0xA4, 0xD0, 0x94, 0x2E, 0x8C, 0x2E, +0x94, 0x2E, 0x9C, 0x6F, 0xA4, 0xD1, 0xAC, 0xF2, +0xAC, 0xF2, 0xAD, 0x12, 0xA4, 0xD2, 0xA4, 0xB1, +0xA4, 0xB0, 0xAD, 0x32, 0xB5, 0x53, 0xAD, 0x12, +0xBD, 0x74, 0xB5, 0x34, 0xBD, 0x95, 0xC5, 0xB6, +0x9C, 0x71, 0xA4, 0xD2, 0xB5, 0x75, 0xC5, 0xB6, +0xCD, 0xD7, 0xBD, 0x75, 0xAD, 0x34, 0xA4, 0xF4, +0xB5, 0x34, 0xAC, 0xF3, 0x94, 0x51, 0x7B, 0x8E, +0x73, 0x6D, 0x5A, 0xAA, 0x4A, 0x48, 0x4A, 0x28, +0x41, 0xE7, 0x31, 0x44, 0x39, 0x65, 0x6A, 0xEB, +0x5A, 0xAA, 0x21, 0x03, 0x18, 0xE3, 0x31, 0xA6, +0x63, 0x2B, 0x8C, 0x2F, 0x94, 0x70, 0x94, 0x6F, +0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xD1, 0xA4, 0xB1, +0xBD, 0x94, 0xBD, 0xB3, 0x5B, 0x69, 0x53, 0xA9, +0x64, 0x0C, 0x53, 0x8A, 0x6C, 0x4C, 0x85, 0x10, +0x85, 0x0F, 0x53, 0xC9, 0x4B, 0x87, 0x4B, 0x66, +0x53, 0xE9, 0x85, 0x2E, 0x8D, 0x6F, 0x8D, 0x8F, +0x9D, 0xF2, 0x9D, 0xD1, 0x8D, 0x8F, 0x85, 0x4E, +0x3A, 0x65, 0x11, 0x02, 0x19, 0x62, 0x3A, 0x85, +0x39, 0xE8, 0x9C, 0xF3, 0x73, 0x6B, 0x94, 0x6F, +0xA4, 0xF1, 0x9C, 0xD0, 0xA5, 0x12, 0xAD, 0x53, +0xAD, 0x53, 0xAD, 0x52, 0xAD, 0x53, 0xA5, 0x12, +0xB5, 0x93, 0xB5, 0x93, 0xB5, 0x93, 0xBD, 0xB3, +0xBD, 0xD4, 0xBD, 0xD4, 0xCE, 0x56, 0xE7, 0x1B, +0xF7, 0xBE, 0xE7, 0x3C, 0xB5, 0x96, 0xCE, 0x59, +0xFF, 0xDE, 0xEF, 0x3C, 0xCE, 0x36, 0xBD, 0xB3, +0xB5, 0x72, 0xB5, 0x72, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0xD3, 0xBD, 0xD3, 0xC5, 0xD4, 0xBD, 0x73, +0xB5, 0x72, 0xB5, 0x72, 0xB5, 0x72, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x93, 0xB5, 0x93, 0xBD, 0x93, +0xBD, 0xB3, 0xBD, 0x93, 0xBD, 0xB3, 0xBD, 0x72, +0xA4, 0x8E, 0xAD, 0x10, 0xBD, 0x92, 0xBD, 0x93, +0xBD, 0xD4, 0xBD, 0xB3, 0xB5, 0x92, 0xB5, 0x72, +0xBD, 0x92, 0xBD, 0x93, 0xD6, 0x78, 0xF7, 0x7D, +0xFF, 0xDE, 0xC6, 0x18, 0xAD, 0x55, 0xE7, 0x1C, +0xF7, 0xBE, 0xEF, 0x5B, 0xD6, 0xB7, 0xC6, 0x53, +0xD6, 0xB5, 0xBD, 0xD1, 0xB5, 0x70, 0xA5, 0x2E, +0xAD, 0x4F, 0xB5, 0x90, 0xB5, 0xD1, 0xC5, 0xF3, +0xCD, 0xD4, 0xC5, 0xB3, 0xB5, 0x52, 0x9C, 0xB0, +0x8C, 0x0D, 0x9C, 0xB0, 0x73, 0x4A, 0x6B, 0x0A, +0x52, 0x68, 0x52, 0x68, 0x4A, 0x47, 0x4A, 0x27, +0x41, 0xE7, 0x42, 0x07, 0x52, 0x68, 0x4A, 0x68, +0x52, 0x88, 0x7B, 0xCC, 0x94, 0xAE, 0xA5, 0x2F, +0xA5, 0x4F, 0xAD, 0x4F, 0xAD, 0x70, 0xAD, 0x51, +0x9C, 0xD0, 0xB5, 0xB2, 0x94, 0xAF, 0x5A, 0xE9, +0x52, 0xE9, 0x7C, 0x0C, 0xA5, 0x0E, 0x84, 0x8A, +0x94, 0xEA, 0x9D, 0x4D, 0xAD, 0xB1, 0x63, 0x4A, +0x42, 0x27, 0x31, 0x85, 0x29, 0x85, 0x29, 0x85, +0x31, 0xA6, 0x42, 0x07, 0x4A, 0x49, 0x63, 0x0B, +0x6B, 0x4D, 0x94, 0x92, 0x7B, 0xF0, 0x84, 0x30, +0x6B, 0x4D, 0x6B, 0x4D, 0x52, 0x8A, 0x62, 0xEC, +0xB5, 0x96, 0xE7, 0x1C, 0xD6, 0xBA, 0xCE, 0x59, +0x84, 0x31, 0x73, 0x6D, 0x83, 0xCD, 0x7B, 0xCD, +0x7B, 0xCD, 0x7B, 0xAD, 0x7B, 0x8C, 0x73, 0x8C, +0x6B, 0x4C, 0x6B, 0x4C, 0x73, 0x6C, 0x63, 0x2B, +0xB5, 0x94, 0x6B, 0x6B, 0x94, 0x4F, 0x8B, 0xED, +0x8B, 0xEE, 0x7B, 0xAD, 0xAD, 0x32, 0xA5, 0x11, +0xAD, 0x32, 0xC6, 0x16, 0xB5, 0x94, 0x9C, 0xD1, +0xAD, 0x53, 0xA5, 0x13, 0xAD, 0x54, 0xBD, 0x94, +0xC5, 0xD5, 0xC6, 0x16, 0xCE, 0x36, 0x9C, 0xB1, +0x9C, 0xB1, 0xBD, 0xB5, 0xAD, 0x33, 0x73, 0x8D, +0x31, 0xA5, 0x4A, 0x68, 0x5A, 0xCA, 0x52, 0x89, +0x39, 0xE7, 0x41, 0xE7, 0x4A, 0x28, 0x42, 0x28, +0x4A, 0x48, 0x52, 0x8A, 0x6B, 0x6D, 0x73, 0x8E, +0x6B, 0x4D, 0x94, 0x93, 0x9C, 0xB3, 0xA4, 0xD3, +0xDE, 0x9A, 0xCD, 0xF7, 0x9C, 0xB3, 0x8C, 0x10, +0x8C, 0x50, 0x7B, 0xAE, 0x8C, 0x0F, 0x94, 0x2F, +0x5A, 0xAA, 0x5A, 0xAA, 0x73, 0x6D, 0xB5, 0x95, +0xBD, 0xD7, 0xAD, 0x55, 0xAD, 0x35, 0xA5, 0x14, +0xC5, 0xF7, 0xBD, 0xB6, 0x6B, 0x4D, 0xDE, 0xBA, +0xE6, 0xDB, 0x9C, 0xB2, 0xB5, 0x54, 0xA4, 0xB2, +0xA4, 0xF2, 0x94, 0x30, 0x6B, 0x0B, 0xC5, 0xD5, +0xCD, 0xF5, 0xD6, 0x56, 0xCD, 0xF5, 0xBD, 0x93, +0xC5, 0xD5, 0xDE, 0x97, 0xDE, 0x98, 0xD6, 0x77, +0x9C, 0xB1, 0xB5, 0x74, 0xC5, 0xF6, 0xAD, 0x32, +0xA4, 0xF1, 0xBD, 0xB4, 0xC5, 0xD5, 0xC5, 0xD5, +0xBD, 0xB4, 0xA4, 0xF1, 0xA4, 0xB1, 0x8C, 0x0E, +0x94, 0x4E, 0x94, 0x2E, 0x9C, 0x6F, 0xA4, 0x8F, +0xAC, 0xF0, 0xA4, 0xD0, 0x9C, 0x6E, 0xA4, 0xD0, +0xB5, 0x31, 0xAC, 0xF1, 0xAD, 0x11, 0xB5, 0x52, +0xBD, 0x73, 0xCD, 0xD4, 0xC5, 0x93, 0xB5, 0x11, +0xA4, 0xB0, 0x94, 0x0E, 0x94, 0x2E, 0xA4, 0x90, +0xB5, 0x12, 0xAD, 0x12, 0xAD, 0x12, 0xC5, 0xB4, +0xC5, 0xB3, 0xDE, 0x76, 0xDE, 0x77, 0xDE, 0x57, +0xB5, 0x54, 0x94, 0x30, 0x9C, 0x92, 0xAD, 0x14, +0x94, 0x71, 0xBD, 0x75, 0xA4, 0xD2, 0xAD, 0x34, +0xAD, 0x13, 0xAD, 0x13, 0xA4, 0xD2, 0x8C, 0x10, +0x8C, 0x30, 0x83, 0xAE, 0x6B, 0x0C, 0x62, 0xAA, +0x62, 0xCA, 0x52, 0x69, 0x39, 0xA6, 0x29, 0x44, +0x29, 0x04, 0x39, 0xA6, 0x73, 0x6D, 0x5A, 0xAA, +0x29, 0x44, 0x29, 0x64, 0x5A, 0xCA, 0x9C, 0xB0, +0xAD, 0x53, 0xB5, 0x53, 0xBD, 0x74, 0xBD, 0x94, +0xBD, 0x94, 0xB5, 0x53, 0xB5, 0x33, 0xB5, 0x53, +0xB5, 0x53, 0x94, 0xAF, 0x4B, 0x08, 0x53, 0x89, +0x32, 0x85, 0x22, 0x24, 0x2A, 0x65, 0x53, 0xAA, +0x8D, 0x70, 0x53, 0xC9, 0x43, 0x26, 0x2A, 0x64, +0x53, 0xC9, 0x74, 0xED, 0x7C, 0xED, 0x8D, 0x6F, +0xA5, 0xF2, 0x9D, 0xD2, 0x85, 0x2E, 0x3A, 0x85, +0x19, 0x22, 0x10, 0xE2, 0x21, 0x63, 0x63, 0xE9, +0x63, 0x6E, 0x8C, 0x71, 0x73, 0x6C, 0x8C, 0x4E, +0x94, 0x6F, 0xA5, 0x11, 0xAD, 0x32, 0x9C, 0xD0, +0xB5, 0x93, 0xB5, 0x93, 0xBD, 0xB4, 0xB5, 0x73, +0xBD, 0xB4, 0xBD, 0xD4, 0xC5, 0xF4, 0xC5, 0xF4, +0xC5, 0xF4, 0xBD, 0xF4, 0xE7, 0x1B, 0xF7, 0xBE, +0xA5, 0x34, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, +0x4A, 0x49, 0xF7, 0x9E, 0xEF, 0x3C, 0xD6, 0x57, +0xB5, 0x93, 0xB5, 0x72, 0xBD, 0x93, 0xB5, 0x72, +0xC5, 0xD4, 0xBD, 0xD4, 0xC5, 0xF4, 0xBD, 0xB4, +0xB5, 0x93, 0xA4, 0xF0, 0xAD, 0x52, 0xB5, 0x72, +0xBD, 0xB4, 0xB5, 0x93, 0xB5, 0x93, 0xB5, 0x93, +0xB5, 0x93, 0xBD, 0x93, 0xB5, 0x72, 0xB5, 0x10, +0xA4, 0x8E, 0xAD, 0x10, 0xCE, 0x14, 0xBD, 0x93, +0xBD, 0xB3, 0xB5, 0x73, 0xB5, 0x72, 0xAD, 0x10, +0xAD, 0x30, 0xC6, 0x15, 0xEF, 0x5C, 0xF7, 0x9D, +0x39, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, +0xA5, 0x14, 0xFF, 0xDE, 0xDF, 0x1A, 0xC6, 0x52, +0xC6, 0x93, 0xBE, 0x10, 0xA5, 0x2B, 0xA5, 0x6B, +0xAD, 0x8C, 0xAD, 0x8D, 0xC6, 0x31, 0xE6, 0xD6, +0xDE, 0x96, 0xD6, 0x55, 0xD6, 0x35, 0xC5, 0xB4, +0xA4, 0xF1, 0xAD, 0x12, 0x73, 0x4B, 0x7B, 0xAD, +0x7B, 0xAD, 0x63, 0x0A, 0x4A, 0x48, 0x42, 0x07, +0x42, 0x07, 0x4A, 0x48, 0x4A, 0x48, 0x4A, 0x48, +0x4A, 0x47, 0xA5, 0x70, 0xAE, 0x10, 0xAE, 0x30, +0xAE, 0x50, 0xAE, 0x10, 0x95, 0x2E, 0x9D, 0x30, +0x9C, 0xCF, 0x9C, 0xF1, 0x6B, 0x6C, 0x4A, 0x68, +0x5A, 0xEA, 0x7B, 0xAD, 0x6B, 0x4A, 0x6B, 0x4A, +0xA4, 0xEE, 0xBD, 0xB1, 0x8C, 0x4D, 0x52, 0x88, +0x6B, 0x4B, 0x52, 0x88, 0x42, 0x27, 0x29, 0x65, +0x31, 0x85, 0x39, 0xE7, 0x42, 0x28, 0x42, 0x07, +0x63, 0x0B, 0x84, 0x0F, 0x73, 0x8E, 0x4A, 0x69, +0x5A, 0xCB, 0x4A, 0x48, 0x39, 0xC7, 0x6B, 0x2D, +0xBD, 0xF8, 0xE7, 0x1C, 0xC6, 0x38, 0xCE, 0x59, +0xDE, 0xBB, 0x83, 0xEF, 0x83, 0xCE, 0x9C, 0xB1, +0x9C, 0x8F, 0x9C, 0x6F, 0x9C, 0x8E, 0xAD, 0x0F, +0x94, 0x6D, 0x94, 0x2D, 0x9C, 0x6E, 0x94, 0x2D, +0xD6, 0x56, 0x83, 0xEC, 0x9C, 0x4E, 0xA4, 0x8F, +0xAC, 0xF0, 0xAC, 0xD0, 0xA4, 0xF0, 0x94, 0x2E, +0x8C, 0x2E, 0x94, 0x90, 0x83, 0xEE, 0x8C, 0x4F, +0x9C, 0xB1, 0x8C, 0x91, 0x94, 0xB1, 0xA4, 0xF2, +0xAD, 0x53, 0xB5, 0x94, 0xC5, 0xF6, 0xBD, 0xD5, +0xC5, 0xF6, 0xBD, 0xD5, 0xC5, 0xF5, 0xC6, 0x15, +0x94, 0x70, 0x39, 0xE6, 0x42, 0x07, 0x39, 0xC6, +0x31, 0x85, 0x39, 0xA6, 0x42, 0x07, 0x4A, 0x28, +0x52, 0x89, 0x52, 0xAA, 0x6B, 0x4D, 0x6B, 0x4D, +0x42, 0x08, 0x83, 0xEF, 0xAD, 0x34, 0xB5, 0x34, +0xBD, 0x75, 0xB5, 0x55, 0x7B, 0xAE, 0x7B, 0x8D, +0x8C, 0x0F, 0x83, 0xCE, 0xA4, 0xB1, 0xBD, 0x53, +0x62, 0xA9, 0x52, 0x69, 0x62, 0xEB, 0x73, 0x4C, +0x5A, 0xCB, 0xB5, 0x76, 0xC6, 0x18, 0xA4, 0xF4, +0xCE, 0x39, 0xB5, 0x55, 0x63, 0x2D, 0xBD, 0xD8, +0xEF, 0x1C, 0xCD, 0xF7, 0xAD, 0x13, 0xA4, 0xD2, +0x83, 0xCE, 0x73, 0x2C, 0x73, 0x6D, 0xAD, 0x32, +0xAC, 0xF1, 0xCD, 0xF5, 0xDE, 0x56, 0xB5, 0x32, +0xC5, 0xB4, 0xDE, 0x56, 0xDE, 0x56, 0xDE, 0xB7, +0xC5, 0xF6, 0xC6, 0x17, 0xD6, 0x99, 0xCE, 0x58, +0xC5, 0xF6, 0xCE, 0x15, 0xCE, 0x15, 0xC5, 0xD4, +0xC5, 0xF5, 0xAD, 0x12, 0x9C, 0x90, 0xA4, 0xB0, +0x9C, 0xB0, 0x94, 0x4F, 0x94, 0x4E, 0x94, 0x2E, +0xA4, 0xB0, 0x9C, 0x8F, 0x8B, 0xED, 0x9C, 0x4E, +0xA4, 0xAF, 0xA4, 0x8F, 0xA4, 0xD0, 0xA4, 0xD0, +0xAC, 0xF0, 0xB5, 0x11, 0xB5, 0x11, 0xB5, 0x11, +0xB5, 0x11, 0xAC, 0xF0, 0xAC, 0xD0, 0xB5, 0x11, +0xC5, 0x73, 0xAD, 0x12, 0xB5, 0x53, 0xBD, 0x94, +0x9C, 0x4F, 0xDE, 0x57, 0xD6, 0x16, 0xCD, 0xD5, +0xBD, 0x74, 0xC5, 0xB5, 0xD6, 0x38, 0xC5, 0xB6, +0xA4, 0xD3, 0x94, 0x50, 0x83, 0xEF, 0xA4, 0xD3, +0x9C, 0x71, 0x8B, 0xEF, 0x83, 0x8E, 0x73, 0x2C, +0x62, 0xEA, 0x62, 0xAA, 0x4A, 0x28, 0x52, 0x28, +0x4A, 0x08, 0x39, 0xA6, 0x29, 0x24, 0x21, 0x04, +0x5A, 0xAB, 0xC5, 0xF8, 0x94, 0x92, 0x31, 0x65, +0x6B, 0x0B, 0x8C, 0x0E, 0x8C, 0x0E, 0x94, 0x2E, +0xA4, 0xB1, 0xB5, 0x32, 0xBD, 0x94, 0xC5, 0xF5, +0xBD, 0x93, 0xB5, 0x73, 0xC5, 0xD4, 0xAD, 0x11, +0x9C, 0xD0, 0x73, 0xCC, 0x4B, 0x49, 0x5B, 0xCA, +0x19, 0xC3, 0x21, 0xE4, 0x3A, 0xA6, 0x32, 0xA5, +0x74, 0xAD, 0x43, 0x27, 0x2A, 0x23, 0x19, 0xC2, +0x2A, 0x24, 0x5B, 0xEA, 0x5C, 0x0A, 0x6C, 0xAC, +0x9D, 0xF2, 0xA6, 0x12, 0x5B, 0xEA, 0x32, 0x65, +0x31, 0xE5, 0x19, 0x23, 0x4B, 0x08, 0x8D, 0x4E, +0x7B, 0xF0, 0x7B, 0xF0, 0x7B, 0x8D, 0x83, 0xED, +0x83, 0xCC, 0x7B, 0xAC, 0x83, 0xCC, 0x83, 0xCC, +0x8C, 0x0D, 0x8C, 0x2E, 0x94, 0x6E, 0x9C, 0x8F, +0x9C, 0x8F, 0x9C, 0xB0, 0x9C, 0xB0, 0x9C, 0xAF, +0xA4, 0xD0, 0xA5, 0x11, 0xEF, 0x7D, 0xEF, 0x5D, +0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x84, 0x10, 0xFF, 0xBE, 0xE6, 0xFA, +0xBD, 0xD4, 0xB5, 0x73, 0xB5, 0x72, 0xB5, 0x73, +0xBD, 0xB4, 0xBD, 0x93, 0xB5, 0x93, 0xAD, 0x52, +0xAD, 0x52, 0xB5, 0x93, 0xBD, 0xD4, 0xBD, 0xD4, +0xCE, 0x36, 0xC5, 0xF5, 0xBD, 0xB3, 0xBD, 0xB3, +0xBD, 0x93, 0xBD, 0xB3, 0xB5, 0x72, 0xAD, 0x10, +0xA4, 0x8E, 0xBD, 0x72, 0xC6, 0x14, 0xBD, 0xB3, +0xB5, 0x73, 0xAD, 0x52, 0xBD, 0x93, 0xAD, 0x31, +0xAD, 0x31, 0xCE, 0x37, 0xF7, 0x9E, 0x7B, 0xCF, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x41, 0xEF, 0x5D, 0xF7, 0x9D, 0xC6, 0x72, +0xC6, 0x72, 0x9D, 0x4B, 0x95, 0x49, 0x8D, 0x07, +0x84, 0xC6, 0x84, 0xE6, 0x8C, 0xE9, 0xAD, 0x8F, +0xCE, 0x34, 0xE6, 0xB7, 0xE6, 0x96, 0xD6, 0x55, +0xD6, 0x15, 0xCD, 0xF5, 0x83, 0xCD, 0xBD, 0xB4, +0xB5, 0x74, 0xA4, 0xD1, 0x73, 0x4C, 0x52, 0x89, +0x52, 0x89, 0x52, 0x89, 0x73, 0x8D, 0x52, 0xA9, +0x42, 0x07, 0x5A, 0xE8, 0x6B, 0xC9, 0x84, 0x8B, +0x95, 0x6D, 0xAE, 0x31, 0xBE, 0xB4, 0xB6, 0x74, +0xB6, 0x13, 0xA5, 0x52, 0x5A, 0xEA, 0x4A, 0x48, +0x4A, 0x68, 0x63, 0x2B, 0x63, 0x0B, 0x63, 0x0A, +0xBD, 0x93, 0xA5, 0x11, 0x62, 0xE9, 0x84, 0x0E, +0xA4, 0xF1, 0x94, 0x4E, 0x8B, 0xED, 0x4A, 0x27, +0x29, 0x65, 0x39, 0xC6, 0x52, 0x89, 0x52, 0x89, +0x4A, 0x69, 0x52, 0xAA, 0x63, 0x0B, 0x42, 0x28, +0x31, 0xA6, 0x42, 0x08, 0x5A, 0xCA, 0x73, 0xAF, +0x7B, 0xAF, 0x9C, 0xF4, 0xA5, 0x35, 0xDF, 0x1B, +0xCE, 0x9A, 0xAD, 0x76, 0xBD, 0xD8, 0xC6, 0x19, +0x84, 0x10, 0x7B, 0x8C, 0x94, 0x6D, 0xAD, 0x8F, +0xA5, 0x2F, 0x9C, 0x6D, 0x94, 0x2D, 0x8C, 0x0C, +0xCE, 0x55, 0x9C, 0x8E, 0xB5, 0x11, 0x9C, 0x8E, +0xA4, 0xCF, 0x9C, 0x8F, 0xA4, 0xF1, 0xB5, 0x52, +0xAD, 0x12, 0xA4, 0xB0, 0x9C, 0xB1, 0x9C, 0x90, +0x94, 0x70, 0x8C, 0x4F, 0x94, 0x4F, 0x94, 0x4F, +0x8C, 0x2F, 0x94, 0x4F, 0x94, 0x4F, 0x94, 0x4F, +0x9C, 0x90, 0x94, 0x90, 0x9C, 0x90, 0x9C, 0xB0, +0x6B, 0x4B, 0x5A, 0xAA, 0x73, 0x6C, 0x4A, 0x48, +0x39, 0xE6, 0x29, 0x65, 0x31, 0x85, 0x52, 0xAA, +0x5A, 0xEB, 0x52, 0xAA, 0x73, 0x6E, 0x8C, 0x51, +0x73, 0x6E, 0xAD, 0x14, 0xD6, 0x38, 0xCD, 0xF7, +0xB5, 0x34, 0x94, 0x71, 0x52, 0x6A, 0x6B, 0x4D, +0x6B, 0x4D, 0x39, 0xA6, 0x41, 0xC7, 0x6A, 0xEA, +0x62, 0xAA, 0x39, 0x86, 0x39, 0x86, 0x41, 0xE7, +0x6B, 0x2D, 0xCE, 0x39, 0xCE, 0x38, 0x9C, 0xB3, +0x8C, 0x51, 0x94, 0x92, 0xAD, 0x35, 0xCE, 0x59, +0xE6, 0xFB, 0xCE, 0x17, 0x8C, 0x30, 0xB5, 0x55, +0xAD, 0x14, 0x83, 0xEF, 0x73, 0x6D, 0x6B, 0x4C, +0x7B, 0xAD, 0xBD, 0x93, 0xD6, 0x35, 0xC5, 0x93, +0xDE, 0x56, 0xE6, 0x97, 0xDE, 0x76, 0xDE, 0x97, +0xA4, 0xD2, 0xA5, 0x14, 0xBD, 0xF7, 0xDE, 0xDB, +0xE6, 0xDA, 0xE6, 0xB8, 0xE6, 0xB8, 0xDE, 0x77, +0xD6, 0x56, 0xAD, 0x12, 0x9C, 0x6F, 0x9C, 0x90, +0xA4, 0xB0, 0x94, 0x4E, 0x9C, 0x8F, 0x9C, 0x6F, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x6F, 0xA4, 0xB0, +0xA4, 0xB0, 0xA4, 0xD0, 0xA4, 0xD0, 0xA4, 0xAF, +0x9C, 0x8F, 0xA4, 0x8F, 0xA4, 0xB0, 0xA4, 0xAF, +0xB5, 0x11, 0xB5, 0x11, 0xB5, 0x11, 0xBD, 0x52, +0xC5, 0x93, 0x9C, 0x70, 0x9C, 0x91, 0xAD, 0x13, +0xCD, 0xF7, 0xCD, 0xF6, 0xA4, 0x91, 0xBD, 0x54, +0xB5, 0x13, 0xAC, 0xF3, 0xB5, 0x54, 0xA4, 0xB2, +0xA4, 0xD2, 0x7B, 0x6E, 0x62, 0xAB, 0x62, 0xEB, +0x7B, 0x6D, 0x73, 0x4C, 0x6A, 0xEB, 0x5A, 0x89, +0x4A, 0x07, 0x39, 0xA6, 0x31, 0x85, 0x29, 0x24, +0x29, 0x24, 0x21, 0x04, 0x39, 0xC7, 0xA4, 0xF3, +0xC6, 0x18, 0x9C, 0xF3, 0x7B, 0x8D, 0xB5, 0x33, +0xCD, 0xD5, 0xCD, 0xD4, 0xC5, 0xB3, 0xCD, 0xD4, +0xD6, 0x36, 0xC5, 0xB4, 0xBD, 0x93, 0xB5, 0x72, +0xBD, 0x73, 0xBD, 0x73, 0xB5, 0x73, 0xBD, 0x73, +0xA5, 0x11, 0x53, 0x28, 0x5B, 0xAA, 0x53, 0x89, +0x21, 0xE4, 0x19, 0xA3, 0x21, 0xC3, 0x32, 0x44, +0x4B, 0x27, 0x32, 0x64, 0x32, 0x64, 0x21, 0xE3, +0x11, 0x41, 0x2A, 0x44, 0x22, 0x24, 0x2A, 0x65, +0x53, 0x69, 0x7C, 0xCD, 0x2A, 0x23, 0x22, 0x03, +0x3A, 0x66, 0x19, 0x43, 0x4A, 0xC8, 0xA5, 0xF1, +0x9D, 0x14, 0x73, 0xAE, 0x73, 0x6C, 0x7B, 0xAC, +0x83, 0xCC, 0x8C, 0x0D, 0x94, 0x2E, 0x94, 0x4E, +0x9C, 0x6F, 0x94, 0x6F, 0x9C, 0x8F, 0xA4, 0xD0, +0xA4, 0xF0, 0x9C, 0xAF, 0x94, 0x6F, 0x9C, 0x6E, +0x9C, 0x8F, 0x94, 0x4E, 0xF7, 0x7D, 0xA5, 0x34, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x31, 0xA6, 0xFF, 0xDF, 0xE7, 0x1B, +0xB5, 0x52, 0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x4E, +0x94, 0x4E, 0x8C, 0x0C, 0x8C, 0x2D, 0x8B, 0xEC, +0x94, 0x4E, 0xA4, 0xF1, 0xAD, 0x11, 0xAD, 0x32, +0xBD, 0x93, 0xBD, 0xB3, 0xB5, 0x72, 0xBD, 0x92, +0xC5, 0xB3, 0xC5, 0xD3, 0xBD, 0xB2, 0xB5, 0x10, +0xA4, 0xAE, 0xBD, 0x72, 0xC5, 0xD2, 0xC5, 0xF3, +0xC5, 0xD3, 0xB5, 0x72, 0xB5, 0x51, 0xAD, 0x31, +0xBD, 0xB3, 0xCE, 0x78, 0xF7, 0xBE, 0x42, 0x08, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xBD, 0xD7, 0xFF, 0xDF, 0xBE, 0x72, +0xB6, 0x10, 0x95, 0x0A, 0xA5, 0xAB, 0x95, 0x29, +0x95, 0x4A, 0x9D, 0x4C, 0xAD, 0xCF, 0xC6, 0x11, +0xDE, 0x95, 0xE6, 0xB6, 0xE6, 0x96, 0xE6, 0x96, +0xDE, 0x56, 0xCD, 0xD4, 0x83, 0xAC, 0xD6, 0x77, +0xC5, 0xD4, 0xB5, 0x73, 0x94, 0x4F, 0x83, 0xEE, +0x73, 0x6C, 0x73, 0x8D, 0xA4, 0xF2, 0x7B, 0xCE, +0x73, 0x6C, 0x6B, 0x2B, 0x42, 0x46, 0x84, 0x6C, +0xAE, 0x31, 0xCF, 0x36, 0xC7, 0x16, 0xC7, 0x16, +0xD7, 0x57, 0xAD, 0xB2, 0x52, 0xA9, 0x4A, 0x69, +0x42, 0x28, 0x63, 0x0B, 0x5A, 0xAA, 0x84, 0x0F, +0xA4, 0xD2, 0x62, 0xEA, 0x6B, 0x6B, 0x94, 0x6F, +0xAD, 0x11, 0xA4, 0xD0, 0xA4, 0xF0, 0x83, 0xCC, +0x52, 0x68, 0x5A, 0xA9, 0x52, 0x89, 0x42, 0x07, +0x31, 0x85, 0x39, 0xC6, 0x39, 0xC6, 0x39, 0xC6, +0x29, 0x65, 0x21, 0x03, 0x39, 0xC7, 0x63, 0x2C, +0x63, 0x0C, 0x6B, 0x4D, 0xBD, 0xD7, 0xE7, 0x1C, +0xDE, 0xFC, 0xC6, 0x39, 0xEF, 0x7E, 0xEF, 0x7E, +0xE7, 0x3D, 0xC5, 0xF7, 0xA5, 0x11, 0xA5, 0x8F, +0xAD, 0xD0, 0xAD, 0x2F, 0x9C, 0xAE, 0xA4, 0xF0, +0xBD, 0xB3, 0x83, 0xCC, 0xA4, 0xAF, 0xAC, 0xF0, +0xAC, 0xD0, 0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xD0, +0x9C, 0x4F, 0x94, 0x0E, 0x8B, 0xCD, 0x7B, 0x8C, +0x9C, 0x70, 0xA4, 0xD1, 0xA4, 0xF1, 0xBD, 0x94, +0xB5, 0x53, 0xAD, 0x12, 0xAD, 0x12, 0xB5, 0x33, +0xB5, 0x53, 0xB5, 0x53, 0xB5, 0x33, 0xB5, 0x53, +0x83, 0xEE, 0x62, 0xEB, 0x6B, 0x2B, 0x52, 0x48, +0x4A, 0x48, 0x39, 0xE7, 0x39, 0xC6, 0x42, 0x07, +0x42, 0x07, 0x52, 0x69, 0x5A, 0xAB, 0x7B, 0x8E, +0x8C, 0x31, 0xB5, 0x75, 0xCD, 0xF7, 0xCD, 0xF8, +0xBD, 0x55, 0x73, 0x6E, 0x84, 0x31, 0x6B, 0x4D, +0x39, 0xC7, 0x4A, 0x49, 0x5A, 0xAA, 0x39, 0xC6, +0x39, 0xC6, 0x29, 0x24, 0x18, 0xE3, 0x21, 0x03, +0x8C, 0x51, 0xD6, 0x9A, 0xAD, 0x55, 0xA4, 0xF4, +0xBD, 0xD7, 0xBD, 0x96, 0xBD, 0xB6, 0xE6, 0xDB, +0xC5, 0xD7, 0x7B, 0xAF, 0x94, 0x92, 0x94, 0x71, +0xBD, 0x75, 0xD6, 0x58, 0xD6, 0x38, 0xC5, 0xD7, +0xAC, 0xF2, 0xBD, 0x73, 0xD6, 0x36, 0xDE, 0x96, +0xE6, 0xB7, 0xCD, 0xF4, 0xE6, 0x97, 0xAC, 0xF1, +0x52, 0xAB, 0x73, 0x8F, 0x94, 0x93, 0xB5, 0xB7, +0xD6, 0xBA, 0xD6, 0x99, 0xC5, 0xF5, 0xE6, 0xD9, +0xD6, 0x56, 0xA4, 0xD1, 0x94, 0x4F, 0x9C, 0x6F, +0x9C, 0x8F, 0x94, 0x2E, 0x94, 0x4F, 0x94, 0x4E, +0xA4, 0xB0, 0x9C, 0xB0, 0xA4, 0xB0, 0xA4, 0xD0, +0xA4, 0xB0, 0xAC, 0xD1, 0xAD, 0x11, 0xAC, 0xD0, +0xA4, 0xB0, 0xA4, 0x6F, 0xA4, 0xB0, 0xAC, 0xD0, +0xB5, 0x11, 0xB5, 0x12, 0xBD, 0x33, 0xCD, 0xB4, +0xC5, 0xB5, 0xB5, 0x54, 0xD6, 0x59, 0xE6, 0xDB, +0xE6, 0xBA, 0xC5, 0xD6, 0x83, 0xAE, 0x83, 0xAE, +0x8C, 0x0F, 0x94, 0x51, 0x94, 0x30, 0x8C, 0x10, +0x8B, 0xEF, 0x41, 0xE7, 0x39, 0xA6, 0x41, 0xC7, +0x52, 0x69, 0x5A, 0x69, 0x4A, 0x07, 0x31, 0x65, +0x29, 0x24, 0x29, 0x04, 0x29, 0x24, 0x20, 0xE3, +0x21, 0x24, 0x4A, 0x29, 0x7B, 0xAF, 0x8C, 0x51, +0x63, 0x0B, 0xAD, 0x33, 0xCE, 0x15, 0xCD, 0xF4, +0xCD, 0xF4, 0xCD, 0xF4, 0xCD, 0xF4, 0xD6, 0x14, +0xCD, 0xF4, 0xD6, 0x35, 0xD6, 0x15, 0xC5, 0xD4, +0xC5, 0xB3, 0xCD, 0xF4, 0xD6, 0x35, 0xCE, 0x15, +0x8C, 0x6E, 0x5B, 0xAA, 0x5B, 0xCA, 0x3A, 0xE7, +0x3A, 0xA7, 0x32, 0x65, 0x2A, 0x25, 0x2A, 0x04, +0x21, 0xA3, 0x21, 0xC3, 0x2A, 0x44, 0x2A, 0x24, +0x3A, 0x86, 0x42, 0xE7, 0x2A, 0x44, 0x32, 0x45, +0x32, 0x65, 0x2A, 0x44, 0x2A, 0x44, 0x32, 0x65, +0x3A, 0xA6, 0x29, 0xC4, 0x11, 0x02, 0x74, 0x4C, +0x9C, 0xD3, 0x62, 0xEB, 0x6B, 0x4B, 0x73, 0x4B, +0x73, 0x4A, 0x83, 0xCC, 0x7B, 0x8B, 0x73, 0x4A, +0x83, 0xCC, 0x94, 0x2D, 0x83, 0xCC, 0x8C, 0x0D, +0x9C, 0xB0, 0xA4, 0xB0, 0x9C, 0xAF, 0xA4, 0xF0, +0xAD, 0x11, 0xB5, 0x51, 0xF7, 0xBE, 0x84, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x41, 0xFF, 0xDF, 0xE6, 0xFA, +0xB5, 0x52, 0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAE, +0xA4, 0xAF, 0xA4, 0xAF, 0xA4, 0xAE, 0xA4, 0x8E, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0x9C, 0x4D, +0x9C, 0x6E, 0xA4, 0x8E, 0xA4, 0xAE, 0xA4, 0xCE, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xEF, 0xAC, 0xEF, +0xA4, 0xAE, 0x94, 0x0C, 0x94, 0x2C, 0x94, 0x4D, +0x9C, 0x6D, 0x9C, 0x6E, 0x9C, 0xAE, 0x9C, 0xAE, +0xAD, 0x11, 0xC6, 0x37, 0xF7, 0x9E, 0x63, 0x0C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xDE, 0xDB, 0xF7, 0x9E, 0xB6, 0x11, +0x95, 0x0D, 0x84, 0x8B, 0xAD, 0xEF, 0xA5, 0x8D, +0xE7, 0x14, 0xEF, 0x15, 0xEE, 0xF5, 0xE6, 0xB5, +0xEF, 0x3A, 0xEF, 0x1A, 0xF7, 0x3A, 0xF7, 0x3A, +0xEF, 0x19, 0xD6, 0x15, 0xBD, 0xB5, 0xDE, 0xFA, +0xD6, 0x78, 0xC6, 0x37, 0xC5, 0xF6, 0xB5, 0x95, +0xC5, 0xF7, 0xCE, 0x58, 0xCE, 0x58, 0xC6, 0x17, +0xBD, 0xD6, 0x9C, 0xB1, 0x52, 0xA8, 0x9D, 0x30, +0xB6, 0x73, 0xA6, 0x11, 0xA6, 0x11, 0xAE, 0x53, +0xAD, 0xB2, 0x7C, 0x0D, 0x5A, 0xCA, 0x4A, 0x89, +0x42, 0x28, 0x4A, 0x69, 0x7B, 0xCE, 0xA5, 0x34, +0x5A, 0xCA, 0x73, 0x8C, 0x84, 0x0D, 0x8C, 0x0D, +0x9C, 0xB0, 0x9C, 0x8F, 0x9C, 0x6F, 0x8C, 0x0E, +0x8C, 0x0E, 0x9C, 0xB0, 0x6B, 0x2B, 0x41, 0xE7, +0x31, 0x85, 0x31, 0xA6, 0x39, 0xC6, 0x31, 0x85, +0x18, 0xE2, 0x29, 0x24, 0x39, 0xC6, 0x5A, 0xCB, +0x6B, 0x6D, 0x6B, 0x6E, 0xA5, 0x14, 0xA5, 0x15, +0xBD, 0xF8, 0xAD, 0x55, 0xD6, 0xBB, 0xDE, 0xDB, +0xEF, 0x5D, 0xC6, 0x38, 0xD6, 0xB9, 0xD6, 0xF8, +0xD6, 0xF8, 0xDF, 0x18, 0xC6, 0x14, 0xC5, 0xF4, +0xAD, 0x51, 0x94, 0x4E, 0xA4, 0xF0, 0xA4, 0xD0, +0xAC, 0xD0, 0xA4, 0xB0, 0xB5, 0x11, 0xBD, 0x52, +0xC5, 0x72, 0xB5, 0x11, 0xA4, 0x6F, 0x7B, 0x8C, +0xAD, 0x12, 0xB5, 0x53, 0xC5, 0xF5, 0xBD, 0xB4, +0xAD, 0x32, 0x7B, 0x8C, 0x62, 0xEA, 0x63, 0x2A, +0x6B, 0x4B, 0x6B, 0x4B, 0x73, 0x6B, 0x7B, 0x8D, +0x94, 0x50, 0xA4, 0xD1, 0x7B, 0x8C, 0x62, 0xEA, +0x4A, 0x48, 0x4A, 0x48, 0x42, 0x28, 0x4A, 0x28, +0x52, 0x89, 0x5A, 0xAA, 0x5A, 0xAB, 0x5A, 0xAA, +0x62, 0xEC, 0x7B, 0xCF, 0x94, 0x30, 0x94, 0x72, +0x83, 0xCF, 0x52, 0x49, 0x4A, 0x69, 0x31, 0x65, +0x31, 0xA6, 0x5A, 0xEB, 0x5A, 0xCA, 0x42, 0x28, +0x39, 0xA6, 0x21, 0x24, 0x29, 0x65, 0x31, 0xA6, +0x73, 0xAE, 0xCE, 0x38, 0xC6, 0x38, 0xDE, 0xDB, +0xCE, 0x59, 0xBD, 0xB6, 0x84, 0x10, 0xB5, 0x96, +0xD6, 0x39, 0xC5, 0xB7, 0x83, 0xCF, 0x52, 0x6A, +0x52, 0x8A, 0x73, 0x6E, 0xAD, 0x14, 0xD6, 0x59, +0xB5, 0x54, 0x83, 0xEF, 0x8B, 0xEE, 0x94, 0x4F, +0x9C, 0x6F, 0x94, 0x0E, 0x9C, 0x6F, 0x5A, 0x68, +0x39, 0xC7, 0x52, 0x8B, 0x6B, 0x6E, 0x8C, 0x93, +0xAD, 0x55, 0x83, 0xF0, 0xA5, 0x34, 0xE6, 0xFA, +0xCE, 0x16, 0x9C, 0xB1, 0x8C, 0x0E, 0x94, 0x2E, +0x9C, 0x6F, 0x83, 0xCD, 0x83, 0xCD, 0x83, 0xED, +0xA4, 0xB0, 0x9C, 0xB0, 0xAC, 0xF1, 0xAC, 0xF1, +0xAC, 0xF1, 0xB5, 0x11, 0xA4, 0xD0, 0xA4, 0xD1, +0xAC, 0xF1, 0xAC, 0xF1, 0xAC, 0xF1, 0x9C, 0x6F, +0x9C, 0x91, 0xCD, 0xD6, 0xD6, 0x17, 0xDE, 0x99, +0xDE, 0x78, 0xBD, 0x95, 0xCE, 0x18, 0xD6, 0x38, +0xBD, 0x96, 0x9C, 0x71, 0x73, 0x6D, 0x62, 0xEB, +0x83, 0xAE, 0x8B, 0xEF, 0x73, 0x6D, 0x73, 0x2C, +0x73, 0x4C, 0x52, 0x48, 0x5A, 0xAA, 0x52, 0x69, +0x31, 0x65, 0x41, 0xE7, 0x62, 0xEB, 0x41, 0xE7, +0x52, 0x69, 0x31, 0x45, 0x5A, 0xCB, 0x7B, 0xCF, +0xAD, 0x55, 0xC5, 0xF7, 0x9C, 0xF3, 0x84, 0x0F, +0xA4, 0xD1, 0xD6, 0x76, 0xD6, 0x15, 0xD6, 0x35, +0xCD, 0xF4, 0xCD, 0xF4, 0xC5, 0x93, 0xCD, 0xF4, +0xCD, 0xF4, 0xD6, 0x55, 0xDE, 0x96, 0xD6, 0x14, +0xCD, 0xF4, 0xCD, 0xF4, 0xD6, 0x14, 0xBD, 0xD3, +0x63, 0x8A, 0x6C, 0x2B, 0x64, 0x0A, 0x53, 0x89, +0x63, 0xEB, 0x53, 0x49, 0x2A, 0x24, 0x19, 0x82, +0x21, 0x83, 0x2A, 0x05, 0x21, 0xE3, 0x22, 0x03, +0x5B, 0xC9, 0x53, 0xA8, 0x43, 0x07, 0x4B, 0x48, +0x53, 0x68, 0x43, 0x27, 0x43, 0x07, 0x4B, 0x48, +0x53, 0x88, 0x3A, 0x86, 0x10, 0xE1, 0x21, 0xA3, +0x52, 0x89, 0x62, 0xEA, 0x73, 0x6B, 0x83, 0xCC, +0x83, 0xAB, 0x83, 0xCC, 0x94, 0x4D, 0x9C, 0x6E, +0xA4, 0xAF, 0x9C, 0x8E, 0x83, 0xEC, 0x83, 0xCC, +0x83, 0xED, 0xA4, 0xD0, 0xAC, 0xF1, 0xB5, 0x51, +0xBD, 0x72, 0xC5, 0xB3, 0xF7, 0xBE, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xC3, 0xFF, 0xDF, 0xE6, 0xFA, +0xBD, 0x72, 0x8B, 0xEB, 0xA4, 0xAE, 0xA4, 0xAF, +0xA4, 0x8E, 0x94, 0x2C, 0xA4, 0x8E, 0xBD, 0x31, +0xB5, 0x10, 0xA4, 0xAE, 0x9C, 0x6D, 0xA4, 0xAF, +0xA4, 0xAE, 0xA4, 0xAE, 0xB5, 0x0F, 0xB5, 0x0F, +0xB5, 0x0F, 0xBD, 0x51, 0xB5, 0x10, 0xAC, 0xCF, +0xAC, 0xEF, 0xB5, 0x30, 0xAC, 0xEF, 0xAC, 0xEF, +0xAC, 0xEF, 0xA4, 0xAE, 0xA4, 0x8E, 0x9C, 0x4D, +0xA4, 0x8E, 0xBD, 0xB4, 0xEF, 0x5C, 0xDE, 0xBA, +0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x63, 0x0C, 0xFF, 0xDE, 0xDE, 0xDA, 0xA5, 0x90, +0x6B, 0xE9, 0x95, 0x2E, 0xBE, 0x51, 0xBE, 0x6F, +0xBE, 0x4E, 0xC6, 0x4E, 0xCE, 0x50, 0xC5, 0xD1, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xEF, 0x3B, 0xCE, 0x37, 0xE7, 0x1C, 0xF7, 0x9E, +0xF7, 0x9E, 0xF7, 0x9D, 0xE7, 0x3C, 0xCE, 0x79, +0xE7, 0x3C, 0xF7, 0x9E, 0xF7, 0x9E, 0xEF, 0x7D, +0xDE, 0xDB, 0xA4, 0xF2, 0x6B, 0x6B, 0x94, 0xCF, +0xB6, 0x53, 0xA6, 0x11, 0xAE, 0x11, 0xA5, 0xB1, +0x94, 0x8E, 0x62, 0xEA, 0x5A, 0xCA, 0x52, 0x89, +0x39, 0xC7, 0x7B, 0xEF, 0xA5, 0x34, 0x5A, 0xEA, +0x73, 0x6B, 0x9C, 0xB0, 0x83, 0xCC, 0x83, 0xED, +0x9C, 0x8F, 0x9C, 0x6F, 0x9C, 0x8F, 0x9C, 0xAF, +0x94, 0x6F, 0xA4, 0xF1, 0x6B, 0x0A, 0x62, 0xEA, +0x52, 0xA9, 0x4A, 0x48, 0x39, 0xC6, 0x31, 0xC6, +0x31, 0xA6, 0x31, 0x86, 0x39, 0xE7, 0x4A, 0x69, +0x63, 0x2D, 0x6B, 0x4D, 0x94, 0x72, 0x6B, 0x6E, +0xAD, 0x76, 0xDE, 0xDC, 0xA5, 0x35, 0xAD, 0x35, +0xEF, 0x5D, 0xE7, 0x3C, 0xF7, 0x9D, 0xF7, 0xDE, +0xF7, 0xBE, 0xF7, 0xBD, 0xD6, 0xB7, 0xD6, 0x95, +0xAD, 0x10, 0xAC, 0xF0, 0xAD, 0x10, 0xB5, 0x31, +0xB5, 0x31, 0xBD, 0x31, 0xC5, 0x92, 0xC5, 0x72, +0xC5, 0x72, 0xCD, 0x72, 0xAC, 0xCF, 0x8C, 0x0E, +0xB5, 0x53, 0xBD, 0xB4, 0xCE, 0x36, 0xBD, 0x93, +0xCE, 0x15, 0xBD, 0xB4, 0xB5, 0x53, 0xA5, 0x12, +0xA4, 0xF1, 0x9C, 0x90, 0xA4, 0xD1, 0x94, 0x50, +0x7B, 0x6D, 0x94, 0x2F, 0xBD, 0x93, 0xBD, 0xB4, +0x83, 0xEE, 0x63, 0x0B, 0x62, 0xEB, 0x63, 0x0B, +0x73, 0x6D, 0x83, 0xF0, 0x9C, 0xB2, 0x7B, 0xAE, +0x52, 0x6A, 0x4A, 0x29, 0x5A, 0xCB, 0x6B, 0x4D, +0x52, 0x8A, 0x39, 0xE7, 0x29, 0x45, 0x29, 0x24, +0x31, 0xA6, 0x42, 0x28, 0x31, 0xC6, 0x39, 0xC6, +0x29, 0x65, 0x21, 0x24, 0x31, 0x85, 0x39, 0xC6, +0x6B, 0x6D, 0xCE, 0x39, 0xEF, 0x7D, 0xF7, 0x9E, +0xF7, 0xBE, 0xEF, 0x5D, 0xB5, 0x96, 0xC5, 0xB7, +0xD6, 0x39, 0xCE, 0x18, 0xCE, 0x38, 0x94, 0x92, +0x63, 0x0D, 0xA5, 0x14, 0xBD, 0xD7, 0xD6, 0x58, +0xB5, 0x55, 0xC5, 0xB6, 0xC5, 0xD6, 0xB5, 0x33, +0xB5, 0x33, 0xB5, 0x33, 0xB5, 0x33, 0x94, 0x50, +0x42, 0x08, 0x42, 0x08, 0x4A, 0x8A, 0x63, 0x4D, +0x7B, 0xF0, 0x7C, 0x11, 0xA5, 0x55, 0xC6, 0x18, +0xDE, 0xDB, 0xC6, 0x17, 0xB5, 0x75, 0xAD, 0x13, +0x9C, 0xB1, 0x8B, 0xEE, 0x83, 0xCD, 0x83, 0xCD, +0x8B, 0xEE, 0x8C, 0x0E, 0xA4, 0xD0, 0xAC, 0xF1, +0x9C, 0x6F, 0xAC, 0xF1, 0x8C, 0x0E, 0x8C, 0x0E, +0x9C, 0x90, 0x9C, 0x91, 0xCD, 0xF6, 0x7B, 0xAE, +0xA4, 0xD3, 0xBD, 0x96, 0xC5, 0xB6, 0xDE, 0x58, +0xC5, 0xB6, 0xA4, 0xF3, 0xBD, 0x96, 0xBD, 0x96, +0xBD, 0x75, 0x8C, 0x10, 0x7B, 0x6D, 0x5A, 0x89, +0x6B, 0x2C, 0x6B, 0x0C, 0x6B, 0x0C, 0x62, 0xCB, +0x5A, 0x8A, 0x52, 0x49, 0x4A, 0x28, 0x31, 0x65, +0x52, 0x69, 0x8C, 0x10, 0xA4, 0xF3, 0xB5, 0x96, +0xBD, 0xD7, 0x83, 0xEF, 0xBD, 0xB7, 0x9C, 0xF3, +0x8C, 0x71, 0x73, 0x6E, 0x52, 0x6A, 0x83, 0xCE, +0xBD, 0xB4, 0xD6, 0x15, 0xBD, 0x72, 0xC5, 0xB3, +0xC5, 0x92, 0xBD, 0x72, 0xBD, 0x93, 0xCD, 0xF4, +0xD6, 0x35, 0xE6, 0x96, 0xEE, 0xD7, 0xE6, 0x96, +0xD6, 0x55, 0xDE, 0x55, 0xDE, 0x76, 0xAD, 0x51, +0x74, 0x6D, 0x64, 0x0B, 0x64, 0x0A, 0x3A, 0xE7, +0x3A, 0xC6, 0x4B, 0x28, 0x3A, 0x86, 0x2A, 0x05, +0x42, 0xE8, 0x32, 0x25, 0x3A, 0x87, 0x2A, 0x24, +0x53, 0xA8, 0x64, 0x4A, 0x4B, 0x88, 0x53, 0xA9, +0x64, 0x2A, 0x5B, 0xE9, 0x53, 0xC9, 0x5C, 0x0A, +0x53, 0x88, 0x22, 0x04, 0x11, 0x22, 0x10, 0xE2, +0x4A, 0x48, 0x62, 0xEA, 0x8C, 0x0D, 0x8C, 0x2D, +0x9C, 0x8E, 0xAD, 0x31, 0xB5, 0x71, 0xB5, 0x51, +0xB5, 0x30, 0xB5, 0x71, 0xB5, 0x51, 0xB5, 0x51, +0xBD, 0x93, 0xA4, 0xD0, 0xA4, 0xB0, 0xBD, 0x72, +0xAD, 0x10, 0xB5, 0x31, 0xF7, 0x9D, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDF, 0xEF, 0x3B, +0xD6, 0x55, 0xAD, 0x30, 0xD6, 0x76, 0xD6, 0x56, +0xCE, 0x15, 0xC5, 0xD4, 0xC5, 0xB4, 0xD6, 0x15, +0xC5, 0x92, 0x9C, 0x6D, 0xAC, 0xF0, 0xBD, 0x93, +0xC5, 0xD4, 0xBD, 0x73, 0xC5, 0xD4, 0xD6, 0x34, +0xA4, 0xAE, 0xBD, 0x51, 0xB5, 0x31, 0xC5, 0xD4, +0xDE, 0x77, 0xDE, 0x97, 0xCE, 0x15, 0xDE, 0x55, +0xD6, 0x34, 0xB5, 0x30, 0xC5, 0xB2, 0xBD, 0x31, +0xC5, 0x92, 0xCE, 0x16, 0xEF, 0x1B, 0xFF, 0xDF, +0xE7, 0x1C, 0x73, 0xAE, 0x5A, 0xEB, 0x9C, 0xF3, +0xFF, 0xDE, 0xF7, 0x7C, 0xCE, 0x56, 0x63, 0x88, +0x5B, 0xC7, 0x95, 0x4E, 0xBE, 0x71, 0xAE, 0x4D, +0xB6, 0x4C, 0xB6, 0x4C, 0xBE, 0x6D, 0xBD, 0xEF, +0xFF, 0xFF, 0xD6, 0x9A, 0x73, 0xAE, 0xE7, 0x1C, +0xEF, 0x5D, 0xD6, 0x78, 0xF7, 0x9D, 0xC6, 0x18, +0x73, 0xAE, 0xAD, 0x75, 0xF7, 0x9E, 0xDE, 0xBA, +0xF7, 0x9E, 0xCE, 0x59, 0x73, 0xAE, 0xEF, 0x3C, +0xDE, 0xFB, 0x94, 0x70, 0x83, 0xCC, 0x94, 0x8E, +0x9D, 0x2F, 0xA5, 0xF1, 0x9D, 0x6F, 0x94, 0xAD, +0x9C, 0xCF, 0x9C, 0xB0, 0x94, 0x6F, 0x8C, 0x2E, +0x94, 0x91, 0x9C, 0xD3, 0x52, 0x89, 0x6B, 0x4B, +0x9C, 0xAF, 0x9C, 0x8F, 0x7B, 0xAC, 0xAD, 0x72, +0xC6, 0x56, 0xBE, 0x14, 0xC6, 0x74, 0xC6, 0x74, +0xAD, 0x92, 0x9C, 0x8F, 0x83, 0xED, 0x52, 0x68, +0x5A, 0xCA, 0x62, 0xEA, 0x62, 0xEA, 0x4A, 0x48, +0x39, 0xC6, 0x31, 0x85, 0x39, 0xE6, 0x42, 0x07, +0x5A, 0xCB, 0x5A, 0xEB, 0x7B, 0xF0, 0x9C, 0xD3, +0xBD, 0xF8, 0xC6, 0x39, 0xCE, 0x7A, 0x7B, 0xCF, +0xAD, 0x56, 0xF7, 0x9E, 0xFF, 0xFF, 0x7B, 0xEF, +0xB5, 0x96, 0xF7, 0xBE, 0xD6, 0xB8, 0xD6, 0x75, +0xC5, 0x92, 0xBD, 0x51, 0xC5, 0x31, 0xCD, 0xB2, +0xCD, 0x92, 0xC5, 0x72, 0xCD, 0x92, 0xC5, 0x72, +0xCD, 0x92, 0xD5, 0xD3, 0xC5, 0x72, 0xA4, 0xD0, +0xB5, 0x53, 0xBD, 0x93, 0xBD, 0xB3, 0xB5, 0x52, +0xCE, 0x35, 0xC5, 0xF5, 0xC5, 0xD5, 0xBD, 0xB5, +0xBD, 0x94, 0xBD, 0x94, 0xC5, 0xD5, 0x83, 0xEE, +0x20, 0xE3, 0x94, 0x51, 0xBD, 0x94, 0xBD, 0xB4, +0xB5, 0x74, 0xAD, 0x54, 0xBD, 0xF7, 0xC6, 0x18, +0xC5, 0xF8, 0xC5, 0xF7, 0xBD, 0xB6, 0xAD, 0x55, +0x5A, 0xAB, 0x42, 0x08, 0x41, 0xE7, 0x42, 0x28, +0x42, 0x28, 0x41, 0xE7, 0x29, 0x65, 0x29, 0x45, +0x31, 0x85, 0x29, 0x65, 0x18, 0xE3, 0x29, 0x65, +0x29, 0x44, 0x21, 0x24, 0x29, 0x65, 0x39, 0xC6, +0x7B, 0xCE, 0xD6, 0xBA, 0xF7, 0x9E, 0x73, 0xAE, +0xC6, 0x18, 0xF7, 0x9E, 0xDE, 0xBA, 0xDE, 0x9A, +0xCE, 0x18, 0xC5, 0xD7, 0xBD, 0x76, 0xC5, 0xF7, +0x94, 0x92, 0x7B, 0x8E, 0x8C, 0x31, 0xAD, 0x34, +0xBD, 0xB6, 0xE7, 0x1B, 0xDE, 0xBA, 0xDE, 0x99, +0xC5, 0xB5, 0xAC, 0xF2, 0xC5, 0xD5, 0xBD, 0x94, +0x94, 0x70, 0x52, 0xA9, 0x42, 0x08, 0x4A, 0x6A, +0x52, 0xAB, 0x6B, 0x6F, 0x8C, 0x52, 0xC6, 0x18, +0xEF, 0x5D, 0xF7, 0xBE, 0xF7, 0xBE, 0xEF, 0x5C, +0xD6, 0x99, 0xB5, 0x53, 0xAC, 0xF2, 0xA4, 0xF1, +0x9C, 0x70, 0xA4, 0xF2, 0xBD, 0x94, 0xA4, 0xB1, +0xAD, 0x33, 0xB5, 0x33, 0xB5, 0x54, 0xB5, 0x54, +0xD6, 0x18, 0xE6, 0xBA, 0xF7, 0x5C, 0x94, 0x71, +0xBD, 0xB7, 0xBD, 0x96, 0xCE, 0x18, 0xC5, 0xB7, +0xB5, 0x55, 0x9C, 0x72, 0xB5, 0x34, 0xA4, 0xD3, +0x83, 0xAE, 0x62, 0xCA, 0x62, 0xCA, 0x5A, 0x69, +0x5A, 0x8A, 0x5A, 0xAA, 0x5A, 0x89, 0x52, 0x28, +0x52, 0x49, 0x5A, 0x8A, 0x39, 0xC7, 0x20, 0xE4, +0x73, 0x8E, 0xA4, 0xF3, 0xA4, 0xD3, 0x9C, 0xD3, +0x84, 0x10, 0xA4, 0xF2, 0xB5, 0x33, 0xBD, 0x94, +0xBD, 0xB4, 0x94, 0x91, 0x9C, 0xB2, 0x94, 0x70, +0xCE, 0x15, 0xD6, 0x15, 0xC5, 0x93, 0xD6, 0x35, +0xBD, 0x72, 0xC5, 0xB3, 0xDE, 0x75, 0xDE, 0x96, +0xE6, 0x96, 0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x75, +0xD6, 0x55, 0xE6, 0x96, 0xE6, 0xD7, 0xAD, 0x92, +0x63, 0xCA, 0x63, 0xEA, 0x8D, 0x50, 0x5B, 0xAA, +0x43, 0x07, 0x5B, 0x8A, 0x42, 0xC6, 0x43, 0x07, +0x22, 0x04, 0x21, 0xC3, 0x53, 0x69, 0x43, 0x07, +0x4B, 0x47, 0x53, 0xC9, 0x5C, 0x09, 0x6C, 0x8B, +0x74, 0xCC, 0x6C, 0xAB, 0x53, 0xE9, 0x3A, 0xC5, +0x19, 0xE2, 0x19, 0xA2, 0x21, 0xC4, 0x21, 0x64, +0x4A, 0x48, 0x5A, 0xCA, 0x8C, 0x0D, 0x8C, 0x2D, +0x9C, 0x8E, 0xB5, 0x31, 0xB5, 0x51, 0xAD, 0x30, +0xBD, 0x71, 0xB5, 0x30, 0xB5, 0x30, 0xBD, 0x71, +0xCE, 0x14, 0xA4, 0xB0, 0x9C, 0x6F, 0xCE, 0x15, +0xAD, 0x10, 0xAD, 0x10, 0xF7, 0x9E, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDF, 0xEF, 0x3B, +0xDE, 0x97, 0x9C, 0xB0, 0xDE, 0xD9, 0xEF, 0x5B, +0xEF, 0x5C, 0xEF, 0x5C, 0xE7, 0x1B, 0xDE, 0x98, +0xD6, 0x35, 0xAD, 0x11, 0xD6, 0x78, 0xE7, 0x1B, +0xEF, 0x7C, 0xEF, 0x5C, 0xEF, 0x3B, 0xEE, 0xF9, +0xB5, 0x52, 0xE6, 0xB7, 0xEF, 0x1A, 0xF7, 0x7D, +0xFF, 0xBE, 0xF7, 0x9D, 0xEF, 0x3B, 0xEF, 0x19, +0xD6, 0x55, 0xAC, 0xCF, 0xCD, 0xD3, 0xA4, 0xD0, +0xC5, 0xF6, 0xE7, 0x1B, 0xFF, 0xBE, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xF7, 0x9D, +0xEF, 0x3B, 0xD6, 0x97, 0xCE, 0x35, 0x63, 0x88, +0x6C, 0x29, 0x95, 0x2E, 0xAD, 0xAF, 0xBE, 0x4F, +0xB6, 0x2F, 0xBE, 0x6E, 0xB6, 0x2D, 0xBE, 0x50, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x7D, 0xD6, 0x98, 0xF7, 0x9D, 0x8C, 0x71, +0x00, 0x00, 0x6B, 0x4D, 0xF7, 0xBE, 0xE6, 0xFB, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0xEF, 0x3C, 0xBD, 0x73, 0xB5, 0x10, 0xB5, 0x10, +0xA5, 0x0F, 0x9D, 0x2F, 0xA5, 0x2E, 0xA5, 0x0F, +0x94, 0x6E, 0xAD, 0x52, 0xA5, 0x10, 0xC5, 0xD4, +0xAD, 0x33, 0x4A, 0x68, 0x7B, 0xCD, 0x94, 0xAF, +0x8C, 0x0C, 0x73, 0x6A, 0xA5, 0x72, 0xC6, 0x76, +0xDF, 0x3A, 0xCE, 0xF6, 0xC6, 0xB4, 0xB6, 0x52, +0xBE, 0x33, 0xA4, 0xF0, 0x8C, 0x2E, 0x52, 0x48, +0x5A, 0xA9, 0x63, 0x0A, 0x6B, 0x2B, 0x7B, 0xCD, +0x73, 0x8D, 0x42, 0x07, 0x31, 0xC6, 0x39, 0xE6, +0x42, 0x07, 0x4A, 0x69, 0x63, 0x0C, 0x8C, 0x72, +0xB5, 0xB7, 0xAD, 0x76, 0x9C, 0xD3, 0x6B, 0x6E, +0xCE, 0x7A, 0xEF, 0x7E, 0xFF, 0xFF, 0x08, 0x41, +0x6B, 0x6D, 0xF7, 0x9E, 0xBD, 0xD6, 0xA4, 0xF2, +0xAD, 0x11, 0xCD, 0xB3, 0xD5, 0xB2, 0xDE, 0x14, +0xD5, 0xF3, 0xC5, 0x51, 0xC5, 0x71, 0xC5, 0x51, +0xCD, 0x92, 0xDD, 0xF3, 0xDD, 0xF4, 0x9C, 0x6F, +0xB5, 0x53, 0xB5, 0x73, 0xBD, 0xB4, 0xC5, 0xD4, +0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xB4, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0xB5, 0xC5, 0xD5, 0x83, 0xAE, +0x52, 0x69, 0xB5, 0x34, 0xBD, 0x95, 0xCE, 0x37, +0xD6, 0x79, 0xD6, 0x79, 0xC6, 0x18, 0xCE, 0x59, +0xBD, 0xB6, 0xA5, 0x14, 0x9C, 0x92, 0x94, 0x71, +0x5A, 0xAA, 0x41, 0xE7, 0x42, 0x08, 0x42, 0x08, +0x39, 0xC7, 0x31, 0x86, 0x31, 0x86, 0x21, 0x24, +0x31, 0x85, 0x31, 0xA6, 0x31, 0x86, 0x39, 0xA6, +0x29, 0x44, 0x21, 0x03, 0x29, 0x44, 0x4A, 0x48, +0x84, 0x0F, 0xDE, 0xDB, 0xEF, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x9E, 0xE6, 0xDB, 0xD6, 0x59, +0xC5, 0xF7, 0xD6, 0x59, 0xAD, 0x34, 0xB5, 0x76, +0xCE, 0x59, 0xBD, 0xD7, 0x73, 0x4E, 0x7B, 0xAF, +0x94, 0x92, 0xD6, 0x79, 0xEF, 0x1C, 0xBD, 0xB6, +0xA5, 0x13, 0x94, 0x51, 0xC5, 0xB6, 0xDE, 0xB9, +0xC5, 0xB5, 0xB5, 0x74, 0x5A, 0xAA, 0x39, 0xC7, +0x42, 0x28, 0x5A, 0xCC, 0x84, 0x31, 0xC6, 0x18, +0xF7, 0x9E, 0xEF, 0x5D, 0xDE, 0xFB, 0xF7, 0xBE, +0xD6, 0x79, 0xA4, 0xD3, 0xAC, 0xF3, 0xAD, 0x34, +0x9C, 0xB2, 0x9C, 0x91, 0xB5, 0x55, 0xB5, 0x55, +0xCE, 0x38, 0xD6, 0x58, 0xEE, 0xFA, 0xEF, 0x3C, +0xEE, 0xFB, 0xF7, 0x1C, 0xD6, 0x79, 0x7B, 0xAF, +0x7B, 0xCF, 0xAD, 0x14, 0xCE, 0x18, 0xBD, 0x96, +0x8C, 0x10, 0x7B, 0x4D, 0x6B, 0x0C, 0x5A, 0x69, +0x49, 0xE7, 0x41, 0xC7, 0x49, 0xE7, 0x41, 0xC7, +0x52, 0x49, 0x5A, 0xAA, 0x63, 0x0B, 0x83, 0xEF, +0x9C, 0xD2, 0x7B, 0xAE, 0x5A, 0xAA, 0x31, 0x86, +0x62, 0xCA, 0x7B, 0x8E, 0x73, 0x4D, 0x73, 0x6D, +0x9C, 0x91, 0xC5, 0xF5, 0xD6, 0x35, 0xD6, 0x56, +0xD6, 0x56, 0xAD, 0x32, 0xB5, 0x54, 0xA4, 0xF2, +0xB5, 0x32, 0xB5, 0x11, 0xB5, 0x12, 0xBD, 0x94, +0xBD, 0x94, 0xBD, 0x93, 0xBD, 0x72, 0xC5, 0xD4, +0xCE, 0x14, 0xD6, 0x35, 0xD6, 0x35, 0xD6, 0x35, +0xDE, 0x55, 0xD6, 0x35, 0xD6, 0x35, 0x8C, 0xAF, +0x42, 0xC7, 0x64, 0x0B, 0xA6, 0x13, 0x5B, 0xCA, +0x6C, 0x2C, 0x74, 0x8D, 0x4B, 0x68, 0x32, 0xA4, +0x2A, 0x23, 0x2A, 0x65, 0x53, 0x89, 0x53, 0xA9, +0x64, 0x0A, 0x4B, 0x48, 0x32, 0xA5, 0x5B, 0xE9, +0x6C, 0x8B, 0x85, 0x2D, 0x64, 0x0A, 0x21, 0xE3, +0x19, 0xC3, 0x21, 0xE3, 0x32, 0x66, 0x21, 0x84, +0x52, 0x89, 0x63, 0x0A, 0x83, 0xCC, 0x8C, 0x0C, +0x94, 0x6D, 0xAC, 0xF0, 0xA4, 0xEF, 0xAD, 0x30, +0xB5, 0x30, 0xAD, 0x0F, 0xAC, 0xF0, 0xBD, 0x71, +0xCE, 0x34, 0xA4, 0xAF, 0xA4, 0x8F, 0xB5, 0x72, +0xB5, 0x31, 0xB5, 0x31, 0xF7, 0x9E, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDF, 0xE7, 0x1B, +0xDE, 0xB7, 0xD6, 0x78, 0xF7, 0x7D, 0xFF, 0xDE, +0xEF, 0x7D, 0xE7, 0x3C, 0xFF, 0xDE, 0xF7, 0x9D, +0xE7, 0x1A, 0xDE, 0xDA, 0xFF, 0xBE, 0xF7, 0x9E, +0xC6, 0x18, 0xCE, 0x59, 0xFF, 0xBE, 0xF7, 0x9D, +0xDE, 0xBA, 0xF7, 0x9D, 0xFF, 0xDE, 0xE7, 0x1C, +0xAD, 0x55, 0xC6, 0x38, 0xFF, 0xDF, 0xF7, 0x9D, +0xE6, 0xD8, 0xB5, 0x52, 0xD6, 0x55, 0xCE, 0x37, +0xF7, 0x7D, 0xF7, 0x9E, 0xB5, 0x96, 0xA5, 0x34, +0xE7, 0x1C, 0xFF, 0xFF, 0xEF, 0x7D, 0xDF, 0x19, +0xEF, 0x59, 0xD6, 0x95, 0xD6, 0x97, 0x63, 0x69, +0x7C, 0x6B, 0xB6, 0x12, 0xC6, 0x33, 0xD6, 0xB4, +0xCE, 0x74, 0xC6, 0x52, 0xBE, 0x11, 0xB5, 0xB0, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x7D, 0xE6, 0xFA, 0xF7, 0xBE, 0xBD, 0xD7, +0x63, 0x0C, 0xA5, 0x14, 0xF7, 0xBE, 0xE6, 0xFB, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0xEF, 0x5C, 0xCE, 0x36, 0xCD, 0xF4, 0xD6, 0x55, +0xCE, 0x14, 0xDE, 0x95, 0xBD, 0x71, 0xAC, 0xEF, +0x8C, 0x0D, 0xB5, 0x53, 0xCE, 0x16, 0xAD, 0x53, +0x73, 0xAD, 0x94, 0xB0, 0xA5, 0x50, 0xA5, 0x4F, +0xA5, 0x0F, 0x9C, 0xCF, 0xC6, 0x55, 0xDF, 0x19, +0xEF, 0x7C, 0xCE, 0xB7, 0xAD, 0xF2, 0x94, 0xEF, +0x94, 0x8E, 0xBD, 0xB4, 0xB5, 0x53, 0x84, 0x0F, +0xA4, 0xD2, 0x9C, 0x91, 0x9C, 0x91, 0xC6, 0x16, +0x8C, 0x6F, 0x8C, 0x70, 0x7B, 0xCD, 0x63, 0x2C, +0x6B, 0x6D, 0x73, 0xAE, 0x84, 0x0F, 0x84, 0x30, +0x94, 0x72, 0x73, 0x8E, 0x63, 0x2D, 0x84, 0x10, +0xC6, 0x18, 0xE7, 0x3D, 0xFF, 0xFF, 0x08, 0x41, +0x6B, 0x6D, 0xF7, 0x9E, 0xC6, 0x18, 0xAD, 0x74, +0xAD, 0x13, 0xD6, 0x36, 0xDE, 0x35, 0xDE, 0x34, +0xDE, 0x34, 0xBD, 0x10, 0xC5, 0x51, 0xCD, 0x92, +0xD5, 0xD2, 0xD5, 0xF3, 0xCD, 0xB3, 0xA4, 0xB0, +0xBD, 0xB4, 0xB5, 0x74, 0xC6, 0x16, 0xCE, 0x36, +0xCE, 0x16, 0xC5, 0xF5, 0xBD, 0xB4, 0xBD, 0xB4, +0xB5, 0x93, 0xB5, 0x53, 0xAD, 0x32, 0x73, 0x4C, +0xA4, 0xD3, 0xCE, 0x17, 0x9C, 0x91, 0x94, 0x71, +0xC6, 0x18, 0xBD, 0xD7, 0x9C, 0xD3, 0x94, 0x71, +0x8C, 0x51, 0x73, 0x8E, 0x63, 0x0C, 0x7B, 0x8E, +0x41, 0xE7, 0x39, 0xA6, 0x31, 0x85, 0x39, 0xC6, +0x31, 0xA6, 0x42, 0x07, 0x5A, 0xCB, 0x6B, 0x2C, +0x6B, 0x4D, 0x6B, 0x6D, 0x73, 0x8E, 0x6B, 0x4D, +0x5A, 0xCA, 0x39, 0xE7, 0x42, 0x07, 0x63, 0x0B, +0x8C, 0x30, 0xDE, 0xDB, 0xF7, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x9E, 0xCE, 0x59, 0xC5, 0xD7, +0xCE, 0x18, 0xCE, 0x18, 0xAD, 0x35, 0xCE, 0x59, +0xD6, 0x9A, 0xD6, 0x79, 0xA4, 0xF4, 0xC6, 0x18, +0xB5, 0x96, 0x9C, 0xB3, 0xE6, 0xDB, 0xE7, 0x1C, +0xC5, 0xF8, 0xDE, 0xBB, 0xCE, 0x18, 0xBD, 0x96, +0xC5, 0xD6, 0xC5, 0xD6, 0x94, 0x71, 0x6B, 0x4C, +0x5A, 0xCB, 0x7B, 0xF0, 0x9C, 0xF4, 0xCE, 0x59, +0xF7, 0xBE, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xDF, +0xE7, 0x3C, 0xCE, 0x58, 0xE6, 0xDA, 0xCE, 0x38, +0xC5, 0xF7, 0xC5, 0xD7, 0xD6, 0x59, 0xDE, 0x79, +0xC5, 0xD6, 0xAD, 0x55, 0xCE, 0x38, 0xCE, 0x59, +0xCE, 0x38, 0xBD, 0xB6, 0x9C, 0x93, 0x6B, 0x0D, +0x5A, 0xAB, 0x41, 0xE8, 0x4A, 0x49, 0x4A, 0x6A, +0x4A, 0x08, 0x41, 0xC7, 0x41, 0xC6, 0x39, 0xA6, +0x31, 0x45, 0x31, 0x45, 0x39, 0xA6, 0x62, 0xEC, +0xAD, 0x55, 0xAD, 0x54, 0xAD, 0x34, 0xA4, 0xF3, +0x94, 0x92, 0x8C, 0x51, 0x84, 0x10, 0x63, 0x0C, +0x62, 0xEB, 0x73, 0x6C, 0xAD, 0x32, 0xBD, 0xB5, +0xBD, 0xD6, 0xBD, 0xD5, 0xBD, 0xB5, 0xBD, 0xB5, +0xC5, 0xD6, 0xCE, 0x17, 0xCE, 0x17, 0xCE, 0x17, +0xCE, 0x37, 0xC5, 0xF6, 0xBD, 0x95, 0xB5, 0x53, +0xB5, 0x53, 0xBD, 0x74, 0xBD, 0x95, 0xBD, 0x94, +0xB5, 0x74, 0xB5, 0x54, 0xAD, 0x33, 0xA4, 0xF2, +0xA4, 0xD1, 0xA4, 0xF2, 0xA5, 0x12, 0x8C, 0x90, +0x8C, 0x90, 0x8C, 0x90, 0x42, 0xE6, 0x2A, 0x43, +0x53, 0x68, 0x32, 0x44, 0x3A, 0xC5, 0x3A, 0xE5, +0x3A, 0xC5, 0x43, 0x07, 0x5B, 0xEA, 0x53, 0xA9, +0x64, 0x4B, 0x3A, 0xC6, 0x22, 0x03, 0x19, 0xC2, +0x43, 0x27, 0x85, 0x2E, 0x74, 0xAC, 0x22, 0x03, +0x19, 0xA3, 0x2A, 0x24, 0x2A, 0x25, 0x21, 0x84, +0x52, 0xA9, 0x63, 0x0A, 0x7B, 0xAC, 0x83, 0xCB, +0x94, 0x2D, 0x9C, 0x8E, 0x9C, 0x8E, 0xA4, 0xCF, +0x94, 0x4D, 0xAD, 0x30, 0xA4, 0xEF, 0xB5, 0x71, +0xCE, 0x34, 0xA4, 0xAF, 0xA4, 0xAF, 0xB5, 0x71, +0xB5, 0x51, 0xB5, 0x72, 0xF7, 0x9E, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDF, 0xE7, 0x1B, +0xDE, 0xB8, 0xEF, 0x7C, 0xEF, 0x7D, 0x52, 0xAA, +0x00, 0x00, 0x00, 0x00, 0x39, 0xE7, 0xE7, 0x1B, +0xFF, 0xDE, 0xFF, 0xBE, 0xD6, 0x9A, 0x21, 0x04, +0x00, 0x00, 0x00, 0x00, 0x31, 0x86, 0xE7, 0x1C, +0xFF, 0xBE, 0xFF, 0xFF, 0x9C, 0xF3, 0x00, 0x20, +0x00, 0x00, 0x00, 0x00, 0x42, 0x28, 0xF7, 0xBE, +0xF7, 0x7C, 0xC5, 0xD5, 0xDE, 0xB8, 0xEF, 0x5C, +0xEF, 0x3C, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, +0x08, 0x41, 0xAD, 0x55, 0xF7, 0xBE, 0xD6, 0xD8, +0xC6, 0x95, 0xE7, 0x58, 0xD6, 0xB6, 0x6B, 0x8A, +0x9D, 0x50, 0xDF, 0x17, 0xE6, 0xD7, 0xE6, 0xD6, +0xDE, 0xB6, 0xDE, 0xB6, 0xDE, 0xB5, 0xDE, 0x75, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xE7, 0x1A, 0xFF, 0xBE, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBE, 0xE6, 0xFA, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0xF7, 0x9E, 0xE7, 0x1B, 0xEF, 0x3B, 0xEF, 0x5B, +0xE6, 0xFA, 0xDE, 0xB9, 0xC5, 0xF6, 0xAD, 0x32, +0xA5, 0x12, 0xDE, 0xDA, 0xD6, 0x99, 0xC6, 0x38, +0xCE, 0x58, 0xCE, 0x77, 0xAD, 0xB2, 0xA5, 0x6E, +0xB6, 0x31, 0xAD, 0xB2, 0xCE, 0xB8, 0xEF, 0x7C, +0xF7, 0xBE, 0xDF, 0x1B, 0xBE, 0x16, 0x9C, 0xD1, +0x73, 0x6C, 0x7B, 0xAD, 0xAD, 0x74, 0xCE, 0x38, +0xEF, 0x3C, 0xEF, 0x3C, 0xEF, 0x5D, 0xCE, 0x79, +0x7B, 0xEF, 0x94, 0xB1, 0xD6, 0x98, 0xCE, 0x79, +0xCE, 0x59, 0xCE, 0x79, 0xCE, 0x79, 0xC6, 0x38, +0xB5, 0x96, 0x94, 0xB2, 0x8C, 0x51, 0xAD, 0x56, +0xBD, 0xF8, 0xE7, 0x1C, 0xFF, 0xDF, 0x08, 0x41, +0x6B, 0x6D, 0xFF, 0xDF, 0xDE, 0xFB, 0xDE, 0xDB, +0xEF, 0x3C, 0xEF, 0x7D, 0xE7, 0x1A, 0xE7, 0x18, +0xDE, 0xB6, 0xC5, 0xF3, 0x9C, 0x6D, 0x94, 0x0D, +0xA4, 0x6E, 0xAC, 0xAF, 0xAC, 0xD0, 0xBD, 0xB5, +0xCE, 0x58, 0xD6, 0xBA, 0xE7, 0x1B, 0xE7, 0x3B, +0xE7, 0x3B, 0xDE, 0xFA, 0xD6, 0x98, 0xCE, 0x57, +0xAD, 0xB2, 0xA5, 0x4F, 0x9C, 0xCF, 0xAD, 0x13, +0xAC, 0xF3, 0xB5, 0x54, 0x9C, 0xD3, 0xAD, 0x75, +0xCE, 0x59, 0xD6, 0x9A, 0xD6, 0x9A, 0xCE, 0x79, +0xC6, 0x38, 0xAD, 0x75, 0x94, 0x91, 0x6B, 0x4D, +0x39, 0xE7, 0x31, 0x85, 0x31, 0x85, 0x4A, 0x69, +0x52, 0xAA, 0x84, 0x10, 0xAD, 0x55, 0xC6, 0x18, +0xCE, 0x59, 0xCE, 0x79, 0xCE, 0x79, 0xC6, 0x38, +0xB5, 0x96, 0x94, 0x92, 0x7B, 0xCE, 0x52, 0x89, +0x84, 0x0F, 0xDE, 0xDB, 0xF7, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x7D, 0xBD, 0xB6, 0xA4, 0xD3, +0xC5, 0xB7, 0xB5, 0x76, 0xCE, 0x59, 0xE7, 0x3C, +0xD6, 0xBA, 0xEF, 0x3D, 0xDE, 0xFB, 0xD6, 0x9A, +0xBD, 0xF7, 0xC5, 0xF8, 0xDE, 0xDB, 0xDE, 0xDB, +0xE7, 0x1C, 0xE7, 0x1C, 0xEF, 0x5D, 0xE7, 0x1C, +0xC6, 0x18, 0xBD, 0xD7, 0x9C, 0x91, 0xD6, 0x78, +0xA5, 0x14, 0xBD, 0xD7, 0xCE, 0x79, 0xDE, 0xFB, +0xF7, 0xBE, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xFF, +0xEF, 0x7D, 0xDE, 0xDB, 0xE7, 0x1C, 0xD6, 0x9A, +0xBD, 0xB7, 0xCE, 0x38, 0xC5, 0xD7, 0xEF, 0x1C, +0xD6, 0x9A, 0xCE, 0x59, 0xD6, 0xBA, 0xD6, 0xBA, +0xDE, 0xBA, 0xCE, 0x79, 0xC5, 0xF7, 0x9C, 0xD3, +0x7B, 0xAE, 0x52, 0x6A, 0x41, 0xE8, 0x39, 0xC7, +0x29, 0x65, 0x31, 0x65, 0x42, 0x08, 0x73, 0x6D, +0x9C, 0xD3, 0xBD, 0xB6, 0xBD, 0xF7, 0xAD, 0x55, +0x94, 0xB2, 0xAD, 0x55, 0xBD, 0xF7, 0xCE, 0x59, +0xD6, 0xBA, 0xDE, 0xDA, 0xD6, 0x99, 0xC6, 0x37, +0xC5, 0xF5, 0xCE, 0x15, 0xBD, 0xB3, 0xB5, 0x74, +0xCE, 0x37, 0xDE, 0xDA, 0xEF, 0x1B, 0xE7, 0x1B, +0xDE, 0xDA, 0xDE, 0xDA, 0xE6, 0xFB, 0xE7, 0x1B, +0xE7, 0x1B, 0xDE, 0xDB, 0xC6, 0x17, 0xB5, 0x74, +0xC5, 0xD6, 0xCE, 0x58, 0xDE, 0xDA, 0xE6, 0xFB, +0xE7, 0x1B, 0xE7, 0x1B, 0xE6, 0xFB, 0xDE, 0xDA, +0xDE, 0xBA, 0xDE, 0xDA, 0xE7, 0x3C, 0xE7, 0x3C, +0xEF, 0x5C, 0xD6, 0xDA, 0x22, 0x03, 0x22, 0x23, +0x22, 0x03, 0x2A, 0x24, 0x43, 0x27, 0x53, 0xC8, +0x53, 0xA8, 0x53, 0xA8, 0x64, 0x4B, 0x5B, 0xEA, +0x43, 0x28, 0x19, 0xC3, 0x21, 0xE4, 0x19, 0xC3, +0x19, 0xC3, 0x32, 0x84, 0x3A, 0xA5, 0x32, 0x85, +0x11, 0x82, 0x22, 0x04, 0x11, 0x42, 0x10, 0xC1, +0x52, 0x89, 0x52, 0x88, 0x62, 0xE9, 0x6B, 0x09, +0x73, 0x4A, 0x7B, 0xCC, 0x8C, 0x0C, 0x9C, 0x6E, +0xA4, 0xF0, 0xAD, 0x31, 0xAD, 0x30, 0xB5, 0x30, +0xB5, 0x51, 0x9C, 0x4E, 0x9C, 0x4E, 0xA4, 0xCF, +0xA4, 0xAF, 0x9C, 0xAF, 0xF7, 0x9D, 0x9C, 0xD3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0xA2, 0xFF, 0xDF, 0xF7, 0x7D, +0xEF, 0x5C, 0xFF, 0xDE, 0x6B, 0x4D, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x08, +0xFF, 0xFF, 0xFF, 0xFF, 0x31, 0x86, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xAA, +0xFF, 0xFF, 0xE7, 0x3C, 0x08, 0x41, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x50, +0xFF, 0xDE, 0xE6, 0xFB, 0xFF, 0x9D, 0xFF, 0xDF, +0x63, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x61, 0xF7, 0x9E, 0xE7, 0x3C, +0xAD, 0xD4, 0xDF, 0x38, 0xAD, 0x71, 0x8C, 0x8D, +0xBE, 0x34, 0xCE, 0x34, 0xCE, 0x34, 0xCE, 0x14, +0xC6, 0x13, 0xC5, 0xF3, 0xCE, 0x34, 0xCE, 0x34, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xE7, 0x1A, 0xF7, 0x9D, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBE, 0xDE, 0xDA, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xFB, +0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xDF, 0xFF, 0xDE, 0xF7, 0x9D, 0xEF, 0x3B, +0xDE, 0xDA, 0xDE, 0xFB, 0xF7, 0x9D, 0xFF, 0xDE, +0xF7, 0xBE, 0xEF, 0x5D, 0xC6, 0x36, 0x9D, 0x6F, +0xBE, 0x73, 0xC6, 0x96, 0xEF, 0x9D, 0xFF, 0xDF, +0xFF, 0xFF, 0xF7, 0xBE, 0xE7, 0x1B, 0x9C, 0xD2, +0x52, 0x89, 0x6B, 0x6D, 0xC6, 0x38, 0xEF, 0x7D, +0xF7, 0xBE, 0xFF, 0xDF, 0xF7, 0xBE, 0xD6, 0xBA, +0xB5, 0x96, 0xD6, 0xBA, 0xF7, 0xBE, 0xFF, 0xDE, +0xFF, 0xBE, 0xFF, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xEF, 0x7D, 0xDE, 0xFB, 0xBD, 0xF7, 0xA5, 0x14, +0xB5, 0x96, 0xE7, 0x1C, 0xFF, 0xDF, 0x08, 0x41, +0x6B, 0x6D, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xF7, 0xBE, +0xEF, 0x7C, 0xD6, 0xF8, 0xCE, 0x55, 0xBD, 0x92, +0xB5, 0x72, 0xBD, 0xB4, 0xD6, 0x99, 0xEF, 0x5C, +0xF7, 0x9E, 0xFF, 0xDE, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDE, 0xEF, 0x7C, +0xCE, 0xB8, 0xA5, 0x91, 0x9D, 0x6F, 0xBD, 0xF4, +0xAD, 0x33, 0xBD, 0xF7, 0xDE, 0xFB, 0xEF, 0x7D, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xF7, 0xBE, 0xEF, 0x7D, 0xE7, 0x1C, 0xBD, 0xF7, +0x84, 0x10, 0x42, 0x28, 0x39, 0xC6, 0x63, 0x2C, +0xA5, 0x34, 0xD6, 0xBA, 0xEF, 0x7D, 0xF7, 0x9E, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xF7, 0x9E, 0xE7, 0x1C, 0xC6, 0x18, 0x8C, 0x71, +0x84, 0x30, 0xDE, 0xDB, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xEF, 0x7D, 0xB5, 0x55, 0xB5, 0x55, +0xC5, 0xD7, 0xDE, 0xDB, 0xF7, 0xBE, 0xFF, 0xDF, +0xF7, 0xBE, 0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0x9E, +0xDE, 0xDB, 0xE7, 0x3C, 0xF7, 0x9E, 0xFF, 0xDF, +0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, +0xF7, 0xBE, 0xEF, 0x5D, 0xCE, 0x59, 0xB5, 0x96, +0xBD, 0xF7, 0xEF, 0x5D, 0xF7, 0xBE, 0xFF, 0xDF, +0xFF, 0xFF, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xFF, +0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0xBE, 0xEF, 0x5D, +0xD6, 0x59, 0xC5, 0xF8, 0xE7, 0x1C, 0xEF, 0x5D, +0xF7, 0x9E, 0xF7, 0xBE, 0xFF, 0xBF, 0xFF, 0xDF, +0xF7, 0xBE, 0xF7, 0xBE, 0xEF, 0x7D, 0xE6, 0xFB, +0xBD, 0xF7, 0x73, 0xAE, 0x4A, 0x29, 0x29, 0x65, +0x21, 0x24, 0x31, 0x86, 0xB5, 0x75, 0xC6, 0x17, +0xBD, 0xD7, 0xB5, 0x95, 0x8C, 0x71, 0xB5, 0x96, +0xDE, 0xFB, 0xEF, 0x7D, 0xF7, 0xBE, 0xFF, 0xDF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, +0xFF, 0xDD, 0xEF, 0x5B, 0xCE, 0x56, 0xAD, 0x33, +0xE7, 0x1B, 0xFF, 0xBE, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xEF, 0x7D, +0xEF, 0x7D, 0xF7, 0xBE, 0xE6, 0xDA, 0xDE, 0x99, +0xEF, 0x3C, 0xF7, 0x9E, 0xFF, 0xDE, 0xFF, 0xDE, +0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xBE, +0xFF, 0xBE, 0xFF, 0xBE, 0xEF, 0x7D, 0xB5, 0x96, +0xD6, 0xBA, 0xEF, 0x5D, 0x32, 0xA4, 0x32, 0x84, +0x32, 0xA5, 0x63, 0xEB, 0x3A, 0xE6, 0x4B, 0x67, +0x5B, 0xE9, 0x53, 0xA8, 0x6C, 0x8C, 0x53, 0xA9, +0x19, 0xA2, 0x11, 0x82, 0x19, 0xC3, 0x19, 0xC3, +0x19, 0xA2, 0x2A, 0x24, 0x32, 0x85, 0x3A, 0xA5, +0x11, 0x41, 0x11, 0x42, 0x11, 0x22, 0x29, 0xC5, +0x5A, 0xCA, 0x5A, 0xCA, 0x5A, 0x89, 0x5A, 0xA9, +0x6B, 0x0A, 0x6B, 0x0A, 0x6B, 0x2A, 0x73, 0x2A, +0x7B, 0x6B, 0x83, 0xAB, 0x73, 0x6A, 0x73, 0x2A, +0x83, 0xCC, 0x94, 0x4E, 0x9C, 0x8F, 0x8C, 0x0D, +0x94, 0x2D, 0x94, 0x2E, 0xF7, 0x7D, 0x84, 0x30, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x08, 0x41, 0xFF, 0xFF, 0xFF, 0xBE, +0xF7, 0xBE, 0xFF, 0xFF, 0x18, 0xC3, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xEF, 0x7D, 0xEF, 0x5D, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, +0xFF, 0xFF, 0xA5, 0x14, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xE7, +0xFF, 0xFF, 0xF7, 0x7D, 0xFF, 0xBE, 0xFF, 0xFF, +0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xBD, 0xD7, 0xEF, 0x7D, +0xAD, 0xD3, 0xD7, 0x17, 0x9D, 0x0F, 0xB5, 0xD3, +0xC6, 0x54, 0xC6, 0x34, 0xC6, 0x14, 0xC5, 0xF4, +0xCE, 0x14, 0xCE, 0x55, 0xCE, 0x34, 0xCE, 0x34, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xDE, 0xD9, 0xF7, 0x9D, 0xDE, 0xDB, +0x29, 0x65, 0xB5, 0xB6, 0xF7, 0xBE, 0xDE, 0xB9, +0xF7, 0x9E, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xFB, +0xAD, 0x55, 0x42, 0x28, 0x18, 0xC3, 0x00, 0x00, +0x10, 0xA2, 0x39, 0xE7, 0x9C, 0xD3, 0xFF, 0xDF, +0xEF, 0x7D, 0xE7, 0x1C, 0xFF, 0xDF, 0x6B, 0x6D, +0x4A, 0x49, 0xFF, 0xDE, 0xDF, 0x1A, 0xB6, 0x32, +0xA5, 0x90, 0xCE, 0xB8, 0xF7, 0xBE, 0x63, 0x0C, +0x31, 0x86, 0x94, 0xB2, 0xF7, 0xBE, 0xCE, 0xB8, +0xA5, 0x92, 0xAD, 0x73, 0xE7, 0x1C, 0xE7, 0x1C, +0x31, 0x86, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x1C, +0xE7, 0x3C, 0xF7, 0xBE, 0x9C, 0xD3, 0x42, 0x08, +0x18, 0xC3, 0x00, 0x00, 0x10, 0x82, 0x29, 0x65, +0x73, 0xAE, 0xE7, 0x3C, 0xF7, 0x9E, 0xD6, 0xBA, +0xCE, 0x59, 0xE7, 0x3D, 0xFF, 0xDF, 0x08, 0x41, +0x6B, 0x6D, 0xDE, 0xFB, 0x6B, 0x4D, 0x29, 0x45, +0x08, 0x41, 0x08, 0x41, 0x21, 0x24, 0x6B, 0x6D, +0xE7, 0x1C, 0xF7, 0xBE, 0xE7, 0x1A, 0xBD, 0xB3, +0xC5, 0xF4, 0xE7, 0x1A, 0xF7, 0xBE, 0xE7, 0x1C, +0x73, 0x8E, 0x29, 0x65, 0x10, 0xA2, 0x00, 0x00, +0x08, 0x61, 0x21, 0x24, 0x63, 0x2C, 0xD6, 0x9A, +0xF7, 0x9D, 0xD6, 0xD8, 0xA5, 0xD1, 0xAD, 0xF1, +0xD6, 0xB8, 0xF7, 0xBD, 0xE7, 0x3C, 0x73, 0xAE, +0x31, 0x86, 0x10, 0x82, 0x00, 0x00, 0x08, 0x61, +0x21, 0x24, 0x63, 0x0C, 0xCE, 0x79, 0xF7, 0x9D, +0xCE, 0x59, 0x84, 0x10, 0x6B, 0x4C, 0xAD, 0x55, +0xE7, 0x1C, 0xEF, 0x5D, 0x84, 0x30, 0x39, 0xC7, +0x10, 0x82, 0x00, 0x00, 0x08, 0x41, 0x21, 0x04, +0x63, 0x0C, 0xD6, 0x9A, 0xEF, 0x7D, 0xCE, 0x79, +0xA5, 0x14, 0xDE, 0xFB, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x9E, 0xBD, 0x96, 0xBD, 0x96, +0xDE, 0xDB, 0xF7, 0xBE, 0xB5, 0xB6, 0x31, 0x86, +0x63, 0x0C, 0xF7, 0xBE, 0xEF, 0x7D, 0xE7, 0x3C, +0xEF, 0x7D, 0xFF, 0xDF, 0xBD, 0xF7, 0x5A, 0xCB, +0x18, 0xE3, 0x08, 0x41, 0x08, 0x41, 0x21, 0x04, +0x63, 0x0C, 0xCE, 0x59, 0xFF, 0xDF, 0xE7, 0x3C, +0xD6, 0xBA, 0xF7, 0x9E, 0x73, 0x8E, 0x31, 0x86, +0x31, 0x86, 0x10, 0xA2, 0x00, 0x00, 0x21, 0x04, +0x21, 0x04, 0x21, 0x04, 0x73, 0xAE, 0xF7, 0xBE, +0xDE, 0xBA, 0xEF, 0x3C, 0xF7, 0xBE, 0xD6, 0x9A, +0x63, 0x0C, 0x29, 0x45, 0x10, 0x82, 0x00, 0x00, +0x08, 0x61, 0x29, 0x65, 0x73, 0xAE, 0xDE, 0xFB, +0xEF, 0x5D, 0xBD, 0xD7, 0x6B, 0x4D, 0x31, 0x86, +0x29, 0x45, 0x29, 0x24, 0x5A, 0xCA, 0x62, 0xEB, +0x52, 0xAB, 0x73, 0xAE, 0xBD, 0xF7, 0xEF, 0x7D, +0xE7, 0x3C, 0x7B, 0xCF, 0x31, 0x86, 0x10, 0xA2, +0x00, 0x00, 0x08, 0x61, 0x21, 0x24, 0x63, 0x0C, +0xCE, 0x79, 0xFF, 0xDE, 0xE7, 0x3B, 0xCE, 0x37, +0xEF, 0x5C, 0xEF, 0x5C, 0x21, 0x24, 0xB5, 0x96, +0xB5, 0x96, 0x39, 0xC7, 0x08, 0x41, 0x00, 0x00, +0x52, 0x8A, 0xFF, 0xDF, 0xF7, 0x7C, 0xF7, 0x9D, +0xF7, 0xBE, 0x94, 0xB2, 0x42, 0x08, 0x18, 0xE3, +0x08, 0x41, 0x00, 0x20, 0x18, 0xC3, 0x31, 0xA6, +0x84, 0x10, 0xC6, 0x18, 0x10, 0x82, 0x00, 0x00, +0x9C, 0xF3, 0xEF, 0x5D, 0x3A, 0xE5, 0x3B, 0x06, +0x64, 0x0B, 0x85, 0x0F, 0x5B, 0xCA, 0x43, 0x07, +0xA5, 0xD2, 0x53, 0x88, 0x74, 0xAD, 0x43, 0x07, +0x19, 0xA3, 0x19, 0xA3, 0x21, 0xC3, 0x19, 0xA3, +0x19, 0xA3, 0x19, 0xA2, 0x32, 0x64, 0x32, 0x85, +0x19, 0xA3, 0x21, 0xC3, 0x2A, 0x25, 0x32, 0x66, +0x73, 0x4C, 0x83, 0xCD, 0x6B, 0x0A, 0x83, 0xED, +0xAC, 0xF1, 0xAC, 0xD0, 0xAC, 0xD0, 0x9C, 0x8F, +0x9C, 0x6F, 0x94, 0x4E, 0x8B, 0xED, 0x8C, 0x0D, +0xA4, 0xD0, 0xBD, 0x73, 0xB5, 0x32, 0xA4, 0xB0, +0xA4, 0xD0, 0xAC, 0xD0, 0xF7, 0x9D, 0x5A, 0xEB, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xDE, +0xF7, 0xBE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC6, 0x38, 0xDE, 0xDB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, +0xFF, 0xDF, 0xEF, 0x7C, 0xFF, 0xBE, 0xFF, 0xFF, +0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xA5, 0x14, 0xEF, 0x7D, +0xB6, 0x14, 0xB6, 0x94, 0xBE, 0x74, 0x9D, 0x0F, +0x94, 0xAD, 0xAD, 0x70, 0xA5, 0x2E, 0x9D, 0x4D, +0xA5, 0x6E, 0xC6, 0x53, 0xD6, 0x96, 0xB5, 0x72, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xCE, 0x58, 0xF7, 0x9D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xDE, 0xB9, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0x52, 0xAA, +0x00, 0x00, 0x52, 0x8A, 0x8C, 0x71, 0x9C, 0xD3, +0x84, 0x30, 0x39, 0xE7, 0x00, 0x00, 0x52, 0xAA, +0xFF, 0xDF, 0xF7, 0x9E, 0xFF, 0xFF, 0x84, 0x30, +0x00, 0x00, 0xE7, 0x1C, 0xE7, 0x5C, 0xAD, 0xF2, +0xAD, 0xF2, 0xDF, 0x3B, 0xF7, 0xBE, 0x08, 0x41, +0x08, 0x61, 0x39, 0xE7, 0xF7, 0xDE, 0xDF, 0x1A, +0xB6, 0x54, 0xCE, 0x97, 0xEF, 0x7D, 0xA5, 0x34, +0x00, 0x00, 0xCE, 0x59, 0xFF, 0xDF, 0xF7, 0xBE, +0xF7, 0x9E, 0x42, 0x08, 0x00, 0x00, 0x4A, 0x69, +0x8C, 0x71, 0xA5, 0x34, 0x9C, 0xD3, 0x6B, 0x6D, +0x10, 0xA2, 0x10, 0x82, 0xCE, 0x79, 0xF7, 0xBE, +0xE7, 0x3C, 0xEF, 0x7D, 0xFF, 0xFF, 0x08, 0x41, +0x42, 0x28, 0x10, 0x82, 0x21, 0x24, 0x7B, 0xCF, +0x9C, 0xD3, 0x94, 0x92, 0x63, 0x2C, 0x08, 0x61, +0x10, 0x82, 0xD6, 0xBA, 0xEF, 0x7D, 0xBD, 0xD6, +0xC6, 0x16, 0xEF, 0x7D, 0xD6, 0xBA, 0x10, 0x82, +0x08, 0x41, 0x5A, 0xCB, 0x84, 0x30, 0x9C, 0xD3, +0x8C, 0x71, 0x6B, 0x4D, 0x18, 0xC3, 0x08, 0x41, +0xBD, 0xF7, 0xEF, 0x9D, 0xC6, 0x76, 0xBE, 0x56, +0xEF, 0x7D, 0xCE, 0x59, 0x10, 0x82, 0x10, 0x82, +0x63, 0x0C, 0x94, 0x92, 0x9C, 0xD3, 0x94, 0xB2, +0x73, 0x8E, 0x18, 0xE3, 0x00, 0x00, 0xA5, 0x14, +0xEF, 0x7D, 0xBD, 0xF7, 0xA5, 0x13, 0xDE, 0xDB, +0xEF, 0x5D, 0x29, 0x65, 0x00, 0x20, 0x52, 0xAA, +0x84, 0x10, 0x9C, 0xD3, 0x94, 0x92, 0x6B, 0x4D, +0x10, 0x82, 0x00, 0x20, 0xAD, 0x75, 0xEF, 0x7D, +0xCE, 0x59, 0xEF, 0x5D, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xDF, 0xDE, 0xBA, 0xD6, 0xBA, +0xF7, 0x9E, 0xB5, 0x96, 0x00, 0x20, 0x39, 0xE7, +0xEF, 0x5D, 0xEF, 0x5D, 0xCE, 0x59, 0xE7, 0x1C, +0xFF, 0xDF, 0x7B, 0xEF, 0x00, 0x00, 0x31, 0x86, +0x84, 0x10, 0x9C, 0xF3, 0x9C, 0xF3, 0x7B, 0xEF, +0x29, 0x65, 0x00, 0x00, 0x94, 0xB2, 0xF7, 0xBE, +0xEF, 0x7D, 0xFF, 0xDF, 0x94, 0xB2, 0x63, 0x2C, +0x63, 0x2C, 0x29, 0x45, 0x08, 0x41, 0x73, 0xAE, +0x73, 0xAE, 0x73, 0xAE, 0xAD, 0x55, 0xF7, 0xBE, +0xE7, 0x1C, 0xF7, 0x9E, 0xBD, 0xF7, 0x08, 0x41, +0x10, 0xA2, 0x63, 0x2C, 0x8C, 0x71, 0x9C, 0xD3, +0x8C, 0x51, 0x5A, 0xEB, 0x08, 0x61, 0x10, 0xA2, +0xD6, 0xBA, 0xE7, 0x1C, 0x94, 0x92, 0x42, 0x07, +0x21, 0x04, 0x21, 0x04, 0x21, 0x24, 0x29, 0x65, +0x62, 0xEB, 0xBD, 0xD6, 0xF7, 0x9D, 0xCE, 0x79, +0x10, 0x82, 0x08, 0x61, 0x63, 0x0C, 0x8C, 0x71, +0x9C, 0xD3, 0x94, 0xB2, 0x73, 0x8E, 0x21, 0x04, +0x00, 0x00, 0x9C, 0xF3, 0xF7, 0xBE, 0xEF, 0x5B, +0xFF, 0xDD, 0xE7, 0x3C, 0x00, 0x00, 0x42, 0x08, +0x00, 0x20, 0x52, 0x8A, 0x94, 0x92, 0x9C, 0xD3, +0xBD, 0xD7, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, 0xDF, +0x4A, 0x49, 0x00, 0x00, 0x4A, 0x49, 0x8C, 0x71, +0x9C, 0xF3, 0x9C, 0xF3, 0x84, 0x30, 0x5A, 0xEB, +0x08, 0x41, 0x00, 0x00, 0x5A, 0xCB, 0xDE, 0xFB, +0xFF, 0xDF, 0xE7, 0x3C, 0x43, 0x26, 0x64, 0x6C, +0x85, 0x30, 0x9D, 0xB3, 0x85, 0x10, 0x7C, 0x8D, +0xA5, 0xB2, 0x2A, 0x04, 0x53, 0x69, 0x2A, 0x24, +0x11, 0x62, 0x19, 0xC4, 0x2A, 0x05, 0x21, 0xC3, +0x21, 0xC3, 0x43, 0x07, 0x19, 0xA2, 0x3A, 0x85, +0x22, 0x03, 0x3A, 0xC6, 0x42, 0xE6, 0x32, 0x24, +0x9C, 0x4F, 0x94, 0x2E, 0x6A, 0xEA, 0xA4, 0xF1, +0xC5, 0xB3, 0xC5, 0xB4, 0xBD, 0x93, 0xBD, 0x52, +0xB5, 0x32, 0x94, 0x4F, 0x8C, 0x2E, 0x8C, 0x0D, +0x83, 0xED, 0x83, 0xCD, 0x7B, 0xAC, 0x73, 0x4B, +0x73, 0x4B, 0x73, 0x6B, 0xEF, 0x7D, 0x63, 0x2C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9E, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xDE, 0xFB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0xA5, 0x14, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, +0xFF, 0xDE, 0xE7, 0x1B, 0xEF, 0x5C, 0xFF, 0xDE, +0x18, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xAD, 0x75, 0xEF, 0x7D, +0xB6, 0x55, 0xBE, 0xB5, 0xBE, 0x94, 0xA5, 0x91, +0x8C, 0x8D, 0xAD, 0x90, 0x7C, 0x88, 0x8D, 0x09, +0x8D, 0x08, 0x8C, 0xEA, 0x94, 0xEC, 0xAD, 0x4F, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xDE, 0xD9, 0xF7, 0x9D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xDE, 0xB9, +0xFF, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0x00, 0x00, +0xB5, 0x96, 0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0x9D, +0xF7, 0xBE, 0xFF, 0xDF, 0x84, 0x10, 0x00, 0x00, +0xAD, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0x79, +0x00, 0x00, 0xA5, 0x14, 0xEF, 0x9D, 0xC6, 0x55, +0xCE, 0x76, 0xEF, 0x9D, 0xBD, 0xF7, 0x00, 0x00, +0x7B, 0xEF, 0x00, 0x20, 0xF7, 0x9E, 0xDF, 0x3B, +0xAE, 0x13, 0xCE, 0xD8, 0xFF, 0xDE, 0x63, 0x2C, +0x10, 0x82, 0xFF, 0xDF, 0xF7, 0xBE, 0xFF, 0xFF, +0x73, 0xAE, 0x00, 0x20, 0xBD, 0xD7, 0xF7, 0xBE, +0xEF, 0x7D, 0xEF, 0x5D, 0xEF, 0x7D, 0xF7, 0xBE, +0xE7, 0x3C, 0x21, 0x24, 0x29, 0x45, 0xF7, 0xBE, +0xE7, 0x1C, 0xE7, 0x1C, 0xFF, 0xDF, 0x08, 0x41, +0x00, 0x00, 0x4A, 0x69, 0xF7, 0xBE, 0xF7, 0x9E, +0xF7, 0x9E, 0xF7, 0xBE, 0xFF, 0xDF, 0xDE, 0xDB, +0x10, 0xA2, 0x39, 0xE7, 0xFF, 0xDF, 0xEF, 0x5D, +0xE7, 0x3C, 0xFF, 0xDE, 0x52, 0xAA, 0x08, 0x61, +0xDE, 0xDB, 0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0xBE, +0xFF, 0xDE, 0xFF, 0xDF, 0xEF, 0x7D, 0x29, 0x45, +0x31, 0x86, 0xF7, 0xDE, 0xDF, 0x1A, 0xE7, 0x3B, +0xF7, 0xDE, 0x29, 0x45, 0x29, 0x45, 0xE7, 0x3C, +0xF7, 0xBE, 0xEF, 0x9D, 0xEF, 0x7D, 0xEF, 0x7D, +0xF7, 0x9E, 0xF7, 0xBE, 0x4A, 0x49, 0x08, 0x41, +0xE7, 0x1C, 0xE7, 0x3C, 0xD6, 0x9A, 0xF7, 0x9E, +0x6B, 0x4D, 0x00, 0x00, 0xB5, 0xB6, 0xF7, 0xBE, +0xEF, 0x7D, 0xEF, 0x5D, 0xEF, 0x7D, 0xF7, 0x9E, +0xEF, 0x7D, 0x31, 0x86, 0x10, 0x82, 0xEF, 0x7D, +0xEF, 0x5D, 0xEF, 0x7D, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0xF7, 0x9E, 0xF7, 0xBE, +0xA5, 0x14, 0x00, 0x20, 0x4A, 0x69, 0xF7, 0x9E, +0xEF, 0x3C, 0xBD, 0xF7, 0xC6, 0x18, 0xEF, 0x7D, +0xBD, 0xF7, 0x00, 0x00, 0x73, 0xAE, 0xFF, 0xDF, +0xF7, 0xBE, 0xF7, 0x9E, 0xF7, 0x9E, 0xF7, 0xBE, +0xFF, 0xDF, 0x5A, 0xCB, 0x00, 0x20, 0xD6, 0xBA, +0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xFF, 0xFF, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xFF, +0xFF, 0xDF, 0xF7, 0x9E, 0xF7, 0xBE, 0xF7, 0x9E, +0xEF, 0x5D, 0xF7, 0xBE, 0x29, 0x65, 0x18, 0xE3, +0xEF, 0x5D, 0xF7, 0xBE, 0xEF, 0x7D, 0xEF, 0x7D, +0xEF, 0x7D, 0xF7, 0xBE, 0xE7, 0x1C, 0x10, 0x82, +0x52, 0xAA, 0xEF, 0x7D, 0xAD, 0x75, 0x52, 0xCA, +0x41, 0xE7, 0x7B, 0xAD, 0xAD, 0x32, 0xCE, 0x15, +0xD6, 0x77, 0xEF, 0x5C, 0xFF, 0xDF, 0x29, 0x65, +0x21, 0x24, 0xE7, 0x3C, 0xFF, 0xDE, 0xF7, 0xDE, +0xF7, 0xBD, 0xF7, 0xBD, 0xFF, 0xDE, 0xF7, 0xBE, +0x4A, 0x69, 0x08, 0x41, 0xE7, 0x1C, 0xFF, 0xDE, +0xFF, 0xDE, 0xE7, 0x3C, 0x00, 0x00, 0x00, 0x20, +0xC6, 0x18, 0xFF, 0xDF, 0xFF, 0xBE, 0xFF, 0xBE, +0xFF, 0xBE, 0xFF, 0xBE, 0xFF, 0xFF, 0xB5, 0xB6, +0x00, 0x00, 0x9C, 0xD3, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9D, 0xF7, 0xBE, 0xF7, 0xBE, 0xFF, 0xDF, +0xDE, 0xDB, 0x08, 0x61, 0x73, 0x8E, 0xFF, 0xDF, +0xEF, 0x5C, 0xC6, 0x78, 0x6C, 0x6B, 0x8D, 0x50, +0x95, 0x72, 0xA6, 0x15, 0x95, 0x72, 0x53, 0x29, +0x53, 0x49, 0x29, 0xE4, 0x21, 0xC3, 0x19, 0xA2, +0x11, 0x42, 0x21, 0xC4, 0x32, 0x66, 0x21, 0xC4, +0x09, 0x01, 0x19, 0xA3, 0x11, 0x42, 0x21, 0xE4, +0x32, 0x85, 0x5B, 0xE9, 0x43, 0x46, 0x3A, 0xA5, +0x9C, 0x70, 0x8B, 0xED, 0x6B, 0x0A, 0xAD, 0x11, +0xBD, 0xB3, 0xCD, 0xF4, 0xCD, 0xF5, 0xCE, 0x15, +0xDE, 0x77, 0xD6, 0x36, 0xCD, 0xF5, 0xD6, 0x56, +0xD6, 0x77, 0xBD, 0xB4, 0xAD, 0x32, 0xAD, 0x11, +0xA4, 0xD0, 0x9C, 0x90, 0xF7, 0x9D, 0x6B, 0x4D, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF7, 0x9E, +0xEF, 0x7D, 0xFF, 0xDF, 0x00, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xDE, 0xFB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0xA5, 0x14, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, +0xFF, 0xDE, 0xEF, 0x3B, 0xEF, 0x3B, 0xFF, 0xDE, +0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xAD, 0x75, 0xEF, 0x7D, +0x9D, 0x72, 0xA5, 0xD1, 0xBE, 0x95, 0x6B, 0xCB, +0xA5, 0x30, 0xAD, 0x90, 0x63, 0xC6, 0xA5, 0xCC, +0x84, 0xE8, 0x7C, 0xA8, 0x84, 0x89, 0x84, 0x2A, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x3C, 0xC5, 0xF6, 0xEF, 0x5C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9D, 0xDE, 0xB9, +0xF7, 0x9D, 0x9C, 0xF3, 0x00, 0x00, 0x52, 0xAA, +0xFF, 0xDF, 0xE7, 0x3B, 0xC6, 0x76, 0xBE, 0x14, +0xDE, 0xF9, 0xF7, 0x9D, 0xFF, 0xDF, 0x21, 0x04, +0x4A, 0x49, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, +0x10, 0xA2, 0x63, 0x0C, 0xFF, 0xDE, 0xEF, 0x5B, +0xE7, 0x19, 0xF7, 0xBE, 0x7B, 0xCF, 0x21, 0x24, +0xE7, 0x1C, 0x00, 0x00, 0xBD, 0xD7, 0xEF, 0x9D, +0xD6, 0xB7, 0xDF, 0x1A, 0xFF, 0xDF, 0x21, 0x04, +0x52, 0xAA, 0xFF, 0xFF, 0xFF, 0xDE, 0xF7, 0xBE, +0x08, 0x61, 0x6B, 0x4D, 0xFF, 0xDF, 0xE7, 0x3C, +0xBE, 0x17, 0xBE, 0x16, 0xBE, 0x36, 0xD6, 0x99, +0xF7, 0x9E, 0xAD, 0x55, 0x00, 0x00, 0xBD, 0xF7, +0xF7, 0x9E, 0xE7, 0x3C, 0xFF, 0xDF, 0x08, 0x41, +0x00, 0x20, 0xE7, 0x1C, 0xEF, 0x5D, 0xC6, 0x18, +0xA5, 0x14, 0xAD, 0x35, 0xCE, 0x79, 0xF7, 0xBE, +0x8C, 0x71, 0x00, 0x00, 0xDE, 0xDB, 0xF7, 0xBE, +0xF7, 0x9E, 0xFF, 0xDF, 0x18, 0xE3, 0x63, 0x0C, +0xFF, 0xFF, 0xF7, 0x7D, 0xDE, 0xDB, 0xB5, 0xB6, +0xC6, 0x18, 0xD6, 0xBA, 0xF7, 0xBE, 0x7B, 0xEF, +0x00, 0x20, 0xF7, 0xDE, 0xEF, 0x7C, 0xF7, 0xBE, +0xC6, 0x18, 0x00, 0x00, 0xAD, 0x55, 0xF7, 0xDE, +0xE7, 0x7B, 0xD6, 0xF8, 0xBE, 0x55, 0xBD, 0xF5, +0xC6, 0x17, 0xEF, 0x5D, 0xD6, 0xBA, 0x00, 0x00, +0x94, 0x92, 0xFF, 0xDF, 0xEF, 0x7D, 0xF7, 0x9E, +0x08, 0x61, 0x5A, 0xCB, 0xF7, 0xBE, 0xD6, 0x9A, +0xA5, 0x34, 0x94, 0xB2, 0x9C, 0xF3, 0xC6, 0x17, +0xEF, 0x7D, 0xBD, 0xD7, 0x00, 0x00, 0xB5, 0x96, +0xF7, 0xBE, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0xD3, +0x00, 0x00, 0x5A, 0xEB, 0xF7, 0xBE, 0xE7, 0x3C, +0xAD, 0x75, 0xA4, 0xF3, 0xCE, 0x79, 0xF7, 0x9E, +0x52, 0x8A, 0x21, 0x04, 0xFF, 0xDF, 0xF7, 0x9E, +0xDE, 0xDB, 0xDE, 0xFB, 0xD6, 0x9A, 0xEF, 0x5D, +0xF7, 0xBE, 0xEF, 0x5D, 0x00, 0x20, 0x7B, 0xCF, +0xFF, 0xBF, 0xDE, 0xDB, 0xCE, 0x79, 0xCE, 0x79, +0xF7, 0xBE, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xDF, +0xE7, 0x1C, 0xB5, 0xB6, 0xAD, 0x75, 0xBD, 0xD7, +0xDE, 0xFB, 0xEF, 0x7D, 0x00, 0x00, 0x84, 0x30, +0xF7, 0xBE, 0xD6, 0x9A, 0xB5, 0x96, 0xA5, 0x34, +0xAD, 0x75, 0xD6, 0x9A, 0xF7, 0xBE, 0x52, 0xAA, +0x29, 0x45, 0xF7, 0x9E, 0xC6, 0x17, 0x9C, 0xD1, +0xCE, 0x35, 0xEF, 0x18, 0xEF, 0x18, 0xEF, 0x18, +0xDE, 0xB8, 0xF7, 0x9D, 0xCE, 0x58, 0x00, 0x00, +0xA5, 0x34, 0xFF, 0xDE, 0xDE, 0xF9, 0xDF, 0x17, +0xDF, 0x16, 0xDF, 0x36, 0xEF, 0x99, 0xF7, 0xDD, +0xDE, 0xFB, 0x00, 0x00, 0x8C, 0x71, 0xFF, 0xFF, +0xFF, 0xFE, 0xE7, 0x3C, 0x00, 0x00, 0x5A, 0xCB, +0xFF, 0xFF, 0xF7, 0x9C, 0xE6, 0xF9, 0xE6, 0xB8, +0xDE, 0x98, 0xE6, 0xFA, 0xFF, 0xDE, 0x7B, 0xEF, +0x00, 0x00, 0xEF, 0x5D, 0xF7, 0x9D, 0xD6, 0x78, +0xD6, 0x37, 0xE6, 0xB8, 0xDE, 0x98, 0xEF, 0x5C, +0xFF, 0xDF, 0x4A, 0x49, 0x39, 0xC7, 0xF7, 0xBE, +0xCE, 0xB8, 0x8D, 0x10, 0x85, 0x4F, 0x95, 0x92, +0xA5, 0xD4, 0x9D, 0xB3, 0x4B, 0x29, 0x19, 0xA3, +0x2A, 0x04, 0x21, 0xE3, 0x21, 0xE3, 0x11, 0x82, +0x11, 0x62, 0x19, 0x83, 0x32, 0x66, 0x19, 0x83, +0x19, 0x62, 0x11, 0x21, 0x19, 0xC3, 0x2A, 0x65, +0x43, 0x27, 0x4B, 0x87, 0x4B, 0xA7, 0x5B, 0xE9, +0x9C, 0x6F, 0x83, 0xAC, 0x73, 0x4B, 0xB5, 0x32, +0xB5, 0x52, 0xAD, 0x10, 0xAD, 0x31, 0xBD, 0x93, +0xCD, 0xF4, 0xD6, 0x36, 0xCD, 0xF4, 0xDE, 0x76, +0xD6, 0x56, 0xBD, 0x93, 0xB5, 0x31, 0xB5, 0x32, +0xE6, 0xD8, 0xDE, 0x77, 0xF7, 0xBE, 0x6B, 0x4D, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF7, 0x9E, +0xEF, 0x7D, 0xFF, 0xDF, 0x00, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xDE, 0xFB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0xA5, 0x14, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, +0xFF, 0xDF, 0xF7, 0x9C, 0xF7, 0x9C, 0xFF, 0xDF, +0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xAD, 0x75, 0xEF, 0x7D, +0xA5, 0xB3, 0x8C, 0xEE, 0x9D, 0x51, 0x84, 0x6E, +0x94, 0xAE, 0x9D, 0x0E, 0x74, 0x27, 0x74, 0x67, +0x6C, 0x26, 0x8C, 0xCA, 0xAD, 0x4E, 0xAD, 0x0F, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x5C, 0xCE, 0x16, 0xEF, 0x3C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9D, 0xDE, 0xB9, +0xF7, 0x9D, 0x9C, 0xF3, 0x00, 0x00, 0xA5, 0x14, +0xF7, 0x9D, 0xC6, 0x36, 0xA5, 0x0F, 0x9C, 0x8E, +0xBD, 0xB4, 0xD6, 0x79, 0xF7, 0x9E, 0x63, 0x2C, +0x10, 0xA2, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, 0xDF, +0x52, 0xAA, 0x18, 0xE3, 0xFF, 0xDE, 0xE7, 0x1B, +0xDE, 0xFB, 0xF7, 0xBE, 0x39, 0xC7, 0x63, 0x2C, +0xFF, 0xFF, 0x21, 0x04, 0x7B, 0xCF, 0xF7, 0xBE, +0xDE, 0xFA, 0xEF, 0x7D, 0xDE, 0xFB, 0x00, 0x00, +0x9C, 0xD3, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0x59, +0x00, 0x00, 0xB5, 0xB6, 0xFF, 0xDF, 0xE7, 0x3B, +0xD6, 0xF9, 0xD6, 0xF9, 0xD6, 0xD9, 0xDF, 0x1A, +0xF7, 0xBE, 0xE7, 0x3C, 0x00, 0x00, 0x8C, 0x71, +0xFF, 0xDF, 0xEF, 0x5D, 0xFF, 0xDF, 0x08, 0x41, +0x31, 0xA6, 0xF7, 0xBE, 0xD6, 0xBA, 0xB5, 0x96, +0xAD, 0x55, 0x9C, 0xF3, 0xB5, 0x96, 0xEF, 0x5D, +0xD6, 0x9A, 0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, +0xE7, 0x3C, 0xF7, 0xBE, 0x10, 0xA2, 0x6B, 0x4D, +0xFF, 0xDF, 0xE7, 0x1C, 0xCE, 0x59, 0xBD, 0xD6, +0xB5, 0xB6, 0xCE, 0x79, 0xF7, 0xBE, 0xEF, 0x7D, +0xE7, 0x1C, 0xF7, 0xDE, 0xEF, 0x9D, 0xFF, 0xDF, +0x94, 0x92, 0x00, 0x00, 0xEF, 0x5C, 0xEF, 0x9C, +0xCE, 0xF6, 0x95, 0x6F, 0xAD, 0xF1, 0xBE, 0x74, +0xBD, 0xD5, 0xDE, 0xFB, 0xFF, 0xDF, 0x18, 0xC3, +0x63, 0x0C, 0xFF, 0xFF, 0xFF, 0xDF, 0xCE, 0x79, +0x00, 0x00, 0xA5, 0x14, 0xEF, 0x5D, 0xA5, 0x14, +0x63, 0x0B, 0x52, 0x89, 0x52, 0x89, 0x8C, 0x51, +0xDE, 0xFB, 0xEF, 0x5D, 0x00, 0x00, 0x94, 0x92, +0xFF, 0xDF, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0x94, 0x92, 0x00, 0x00, +0x6B, 0x6D, 0xF7, 0xBE, 0xDE, 0xFB, 0xAD, 0x55, +0x73, 0x6D, 0x83, 0xEF, 0xCE, 0x79, 0xF7, 0xBE, +0x10, 0xA2, 0x6B, 0x4D, 0xFF, 0xDF, 0xEF, 0x7D, +0xE7, 0x3C, 0xEF, 0x5D, 0xE7, 0x1C, 0xEF, 0x5D, +0xEF, 0x7E, 0xFF, 0xFF, 0x29, 0x65, 0x42, 0x28, +0xF7, 0xBE, 0xBD, 0xF8, 0x8C, 0x51, 0xBD, 0xD7, +0xF7, 0x9E, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x79, 0x7B, 0xCF, 0x52, 0x8A, 0x7B, 0xEF, +0xD6, 0xBA, 0xEF, 0x5D, 0x00, 0x00, 0x8C, 0x71, +0xF7, 0xBE, 0xDE, 0xDB, 0xC6, 0x18, 0xB5, 0x96, +0xAD, 0x75, 0xCE, 0x79, 0xF7, 0xBE, 0xEF, 0x5D, +0xE7, 0x3C, 0xF7, 0x9E, 0xD6, 0xBA, 0xBD, 0xF4, +0xAD, 0x72, 0xAD, 0x51, 0xB5, 0x91, 0xBD, 0xB2, +0xCE, 0x36, 0xF7, 0x9D, 0x9C, 0xD3, 0x00, 0x00, +0xE7, 0x1C, 0xEF, 0x5C, 0xC6, 0x54, 0xA5, 0x6E, +0xB6, 0x0F, 0xBE, 0x4E, 0xC6, 0x91, 0xE7, 0x3A, +0xFF, 0xDF, 0x21, 0x04, 0x5A, 0xEB, 0xFF, 0xFF, +0xFF, 0xDF, 0xE7, 0x3C, 0x00, 0x00, 0x8C, 0x51, +0xFF, 0xDE, 0xEF, 0x5A, 0xCE, 0x34, 0xE6, 0xB6, +0xD6, 0x35, 0xE6, 0xB9, 0xFF, 0xBE, 0x84, 0x10, +0x00, 0x20, 0xFF, 0xFF, 0xF7, 0x7D, 0xD6, 0x58, +0xDE, 0x77, 0xE6, 0xB8, 0xE6, 0xB8, 0xF7, 0x5C, +0xFF, 0xDF, 0x42, 0x28, 0x31, 0xA6, 0xF7, 0xBE, +0xC6, 0x77, 0x74, 0x8C, 0x53, 0xE8, 0x85, 0x4F, +0x95, 0x71, 0x53, 0x8A, 0x21, 0xE3, 0x19, 0xA3, +0x22, 0x04, 0x21, 0xE3, 0x21, 0xE3, 0x19, 0xA2, +0x11, 0x62, 0x11, 0x62, 0x21, 0xC3, 0x19, 0xA3, +0x21, 0xC3, 0x11, 0x41, 0x4B, 0x28, 0x5C, 0x0A, +0x5C, 0x0A, 0x4B, 0xA8, 0x5C, 0x09, 0x6C, 0x8C, +0xA4, 0xB0, 0x83, 0xAC, 0x73, 0x6B, 0xBD, 0x93, +0xAC, 0xF0, 0xA4, 0xF0, 0xA5, 0x10, 0xAD, 0x31, +0xB5, 0x52, 0xBD, 0xB3, 0xB5, 0x72, 0xCE, 0x15, +0xC5, 0xD4, 0xC5, 0xD4, 0xB5, 0x52, 0xB5, 0x52, +0xD6, 0x76, 0xDE, 0x96, 0xFF, 0xBE, 0x6B, 0x4D, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9D, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xDE, 0xFB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0x9C, 0xF3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, +0xFF, 0xFF, 0xF7, 0x9D, 0xF7, 0x9D, 0xFF, 0xFF, +0x10, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xAD, 0x75, 0xEF, 0x9D, +0xBE, 0x15, 0xA5, 0x51, 0x9D, 0x10, 0x94, 0xCF, +0x73, 0xEB, 0x73, 0xE9, 0x8C, 0x8B, 0x94, 0xCC, +0x94, 0xAC, 0xA5, 0x0E, 0xC5, 0xD2, 0xCD, 0xF3, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xDE, 0x98, 0xEF, 0x7C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xFF, 0xBE, 0xE6, 0xFA, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xBD, 0xF7, +0xF7, 0x9D, 0xCE, 0x15, 0xC5, 0xB3, 0xD6, 0x36, +0xAD, 0x13, 0xAD, 0x54, 0xF7, 0x9D, 0x84, 0x10, +0x00, 0x00, 0xFF, 0xDF, 0xF7, 0xBE, 0xFF, 0xDF, +0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xFB, 0xF7, 0xBE, +0xF7, 0x9E, 0xEF, 0x7D, 0x00, 0x20, 0xAD, 0x55, +0xFF, 0xFF, 0x63, 0x2C, 0x39, 0xC7, 0xFF, 0xDF, +0xF7, 0x7D, 0xFF, 0xDF, 0x9C, 0xF3, 0x00, 0x00, +0xDE, 0xFB, 0xFF, 0xDF, 0xFF, 0xFF, 0xB5, 0x96, +0x00, 0x00, 0xD6, 0xBA, 0xFF, 0xFF, 0xFF, 0xDF, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xFF, 0xDE, +0xFF, 0xFF, 0xFF, 0xDF, 0x00, 0x00, 0x7B, 0xCF, +0xFF, 0xDF, 0xF7, 0x9D, 0xFF, 0xDF, 0x08, 0x41, +0x52, 0x8A, 0xF7, 0x9E, 0xBD, 0xD7, 0x84, 0x30, +0x8C, 0x51, 0x6B, 0x6D, 0x94, 0xB2, 0xE7, 0x3C, +0xEF, 0x5D, 0x00, 0x00, 0x94, 0xB2, 0xF7, 0xBE, +0xDE, 0xFB, 0xF7, 0xBE, 0x4A, 0x69, 0x18, 0xC3, +0xD6, 0x9A, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xBE, +0xF7, 0xBE, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xEF, 0x9D, 0xE7, 0x7C, 0xFF, 0xDE, +0x84, 0x10, 0x00, 0x00, 0xFF, 0xDF, 0xE7, 0x7B, +0xA5, 0xD1, 0x74, 0x4A, 0x7C, 0x2B, 0x84, 0x6E, +0x94, 0xB1, 0xCE, 0x79, 0xFF, 0xDE, 0x29, 0x65, +0x52, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0x55, +0x00, 0x00, 0xCE, 0x59, 0xE7, 0x1C, 0x84, 0x10, +0x42, 0x27, 0x3A, 0x06, 0x42, 0x27, 0x7B, 0xCE, +0xD6, 0x99, 0xF7, 0x9E, 0xFF, 0xDF, 0xFF, 0xDF, +0xF7, 0xBE, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0x8C, 0x51, 0x00, 0x00, 0x8C, 0x51, +0xFF, 0xFF, 0xE7, 0x5D, 0xC6, 0x18, 0x6B, 0x4D, +0x5A, 0x8A, 0x7B, 0xCF, 0xD6, 0xBA, 0xF7, 0x9E, +0x00, 0x00, 0x8C, 0x51, 0xFF, 0xFF, 0xFF, 0xDF, +0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xBF, 0xF7, 0xBF, +0xFF, 0xDF, 0xFF, 0xFF, 0x42, 0x28, 0x31, 0x86, +0xF7, 0xBE, 0xCE, 0x59, 0xA5, 0x14, 0xB5, 0x96, +0xEF, 0x7D, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x6D, 0x31, 0x86, 0x6B, 0x4D, +0xC6, 0x38, 0xF7, 0xBE, 0x21, 0x24, 0x29, 0x65, +0xDE, 0xFB, 0xF7, 0xBE, 0xF7, 0x9E, 0xEF, 0x7D, +0xEF, 0x7D, 0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xDF, 0xF7, 0x9D, 0xDE, 0xD9, 0xAD, 0x73, +0xA5, 0x31, 0xAD, 0x92, 0xB5, 0x91, 0xB5, 0x92, +0xC6, 0x36, 0xF7, 0x9E, 0x84, 0x30, 0x00, 0x00, +0xF7, 0xBE, 0xEF, 0x5B, 0xBE, 0x32, 0x9D, 0x6A, +0xA5, 0xAA, 0xAE, 0x0A, 0xB6, 0x2D, 0xD6, 0xF8, +0xFF, 0xDE, 0x31, 0xA6, 0x4A, 0x49, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0xBE, 0xDE, 0xF8, 0xA4, 0xF0, 0xD6, 0x76, +0xDE, 0xB7, 0xD6, 0x78, 0xF7, 0x9E, 0xAD, 0x55, +0x00, 0x00, 0xC6, 0x38, 0xFF, 0xDF, 0xF7, 0x9D, +0xF7, 0x9D, 0xF7, 0x7D, 0xF7, 0x9D, 0xFF, 0xDF, +0xF7, 0x9E, 0x10, 0xA2, 0x63, 0x0C, 0xF7, 0x9D, +0xB5, 0xF5, 0x6C, 0x6B, 0x3B, 0x44, 0x64, 0x2A, +0x5B, 0xEA, 0x32, 0x85, 0x21, 0xE3, 0x11, 0x82, +0x22, 0x03, 0x21, 0xE3, 0x21, 0xE3, 0x19, 0xA3, +0x19, 0x83, 0x19, 0xC3, 0x2A, 0x04, 0x2A, 0x04, +0x19, 0xA3, 0x21, 0xC3, 0x64, 0x0A, 0x6C, 0x8B, +0x53, 0xC8, 0x53, 0xC8, 0x74, 0xCD, 0x7D, 0x0E, +0xAC, 0xF1, 0x83, 0xAC, 0x73, 0x4B, 0xC5, 0xD4, +0xB5, 0x52, 0xAD, 0x10, 0xA4, 0xD0, 0xAD, 0x11, +0xB5, 0x72, 0xAD, 0x31, 0xAD, 0x31, 0xC5, 0xF4, +0xBD, 0xD4, 0xBD, 0x93, 0xC6, 0x15, 0xC5, 0xF4, +0xD6, 0x76, 0xD6, 0x75, 0xFF, 0xBE, 0x63, 0x2C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xDE, +0xFF, 0xBE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xC6, 0x38, 0xDE, 0xDB, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF7, 0x9E, 0x7B, 0xEF, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, +0xFF, 0xFF, 0xFF, 0xBD, 0xFF, 0xBD, 0xFF, 0xFF, +0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x94, 0xB2, 0xFF, 0xDE, +0xCE, 0x76, 0xC6, 0x14, 0xC5, 0xF4, 0xAD, 0x72, +0x8C, 0x8E, 0xBD, 0xF3, 0xE7, 0x17, 0xD6, 0x75, +0xA4, 0xCE, 0xAC, 0xEF, 0xBD, 0xB2, 0xCD, 0xF3, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xDE, 0x98, 0xEF, 0x7D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9E, 0xDE, 0xB9, +0xF7, 0x9D, 0x9C, 0xF3, 0x00, 0x00, 0xD6, 0x9A, +0xEF, 0x5C, 0xCE, 0x35, 0xDE, 0x77, 0xAD, 0x12, +0x5A, 0xCA, 0xC5, 0xF6, 0xF7, 0x9D, 0x8C, 0x71, +0x00, 0x00, 0xEF, 0x7D, 0xF7, 0x9D, 0xF7, 0x9E, +0xE7, 0x1C, 0x00, 0x00, 0x9C, 0xF3, 0xFF, 0xFF, +0xFF, 0xFF, 0xB5, 0x96, 0x00, 0x00, 0xEF, 0x5D, +0xFF, 0xFF, 0xAD, 0x55, 0x00, 0x20, 0xF7, 0x9E, +0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0xEB, 0x21, 0x24, +0xFF, 0xDF, 0xF7, 0x7D, 0xFF, 0xDF, 0xA5, 0x14, +0x00, 0x00, 0x39, 0xE7, 0x42, 0x28, 0x42, 0x28, +0x42, 0x28, 0x42, 0x28, 0x42, 0x28, 0x42, 0x28, +0x42, 0x28, 0x42, 0x28, 0x00, 0x20, 0x6B, 0x4D, +0xFF, 0xFF, 0xF7, 0xBE, 0xFF, 0xDF, 0x08, 0x41, +0x63, 0x2C, 0xEF, 0x7D, 0xAD, 0x75, 0x63, 0x0C, +0x52, 0xAA, 0x63, 0x0C, 0x94, 0xB2, 0xE7, 0x1C, +0xF7, 0xBE, 0x00, 0x00, 0x84, 0x10, 0xF7, 0x9E, +0xD6, 0xDA, 0xF7, 0xBE, 0xD6, 0xBA, 0x21, 0x04, +0x00, 0x00, 0x18, 0xC3, 0x42, 0x08, 0x63, 0x2C, +0x84, 0x30, 0xA5, 0x34, 0xD6, 0x9A, 0xFF, 0xDF, +0xFF, 0xDF, 0xE7, 0x5C, 0xDF, 0x19, 0xF7, 0xBE, +0x73, 0xAE, 0x08, 0x41, 0xFF, 0xFF, 0xDF, 0x3A, +0x95, 0x0F, 0x95, 0x2E, 0xA5, 0x6F, 0x9D, 0x0F, +0x9D, 0x31, 0xCE, 0x99, 0xFF, 0xDE, 0x42, 0x08, +0x39, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0xF3, +0x00, 0x00, 0xDE, 0xDB, 0xDE, 0xDB, 0x7B, 0xEF, +0x39, 0xE6, 0x31, 0x85, 0x31, 0xA5, 0x6B, 0x4C, +0xBD, 0xD6, 0xDE, 0xDB, 0xE7, 0x1B, 0xE7, 0x1C, +0xE7, 0x1C, 0xEF, 0x7D, 0xF7, 0x9E, 0x00, 0x00, +0x21, 0x04, 0x00, 0x00, 0x8C, 0x51, 0xFF, 0xFF, +0xF7, 0xBE, 0xCE, 0x59, 0xCE, 0x7A, 0x7B, 0xAF, +0x73, 0xAF, 0xB5, 0xB6, 0xEF, 0x5D, 0xEF, 0x5D, +0x00, 0x00, 0x29, 0x45, 0x42, 0x28, 0x42, 0x28, +0x42, 0x28, 0x42, 0x28, 0x42, 0x28, 0x42, 0x28, +0x42, 0x28, 0x42, 0x28, 0x10, 0xA2, 0x21, 0x04, +0xF7, 0xBE, 0xC6, 0x38, 0x7B, 0xEF, 0xA5, 0x35, +0xEF, 0x7D, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x6D, 0x29, 0x65, 0x52, 0x8A, +0xA5, 0x34, 0xEF, 0x5D, 0xBD, 0xF7, 0x10, 0xA2, +0x00, 0x00, 0x21, 0x04, 0x42, 0x28, 0x6B, 0x4D, +0x8C, 0x51, 0xAD, 0x75, 0xD6, 0xBA, 0xFF, 0xFF, +0xFF, 0xDF, 0xE7, 0x1B, 0xB5, 0x94, 0x9C, 0xD0, +0xB5, 0x92, 0xBD, 0xB2, 0xAD, 0x2F, 0xC6, 0x33, +0xC6, 0x36, 0xF7, 0x9D, 0x7B, 0xCF, 0x00, 0x20, +0xFF, 0xDF, 0xEF, 0x7B, 0xC6, 0x93, 0xA5, 0xAC, +0xA5, 0xAB, 0xB6, 0x4B, 0xAE, 0x2B, 0xD6, 0xF7, +0xFF, 0xFE, 0x42, 0x28, 0x39, 0xC7, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0xBE, 0xD6, 0x98, 0xB5, 0x73, 0xA5, 0x11, +0xEF, 0x79, 0xE7, 0x3A, 0xF7, 0xBE, 0xF7, 0x9E, +0x10, 0xA2, 0x18, 0xC3, 0x84, 0x30, 0xC6, 0x18, +0xD6, 0x9A, 0xD6, 0xBA, 0xC6, 0x38, 0x9C, 0xD3, +0x29, 0x65, 0x08, 0x41, 0xCE, 0x79, 0xE7, 0x3C, +0x95, 0x11, 0x53, 0xA7, 0x3B, 0x44, 0x3B, 0x05, +0x3A, 0xC6, 0x22, 0x24, 0x19, 0xC2, 0x11, 0x61, +0x19, 0xC3, 0x22, 0x03, 0x21, 0xE3, 0x21, 0xE3, +0x21, 0xE3, 0x22, 0x04, 0x2A, 0x25, 0x21, 0xE4, +0x11, 0x42, 0x21, 0xA3, 0x53, 0x68, 0x3A, 0xC5, +0x3B, 0x06, 0x74, 0xCD, 0x85, 0x4F, 0x85, 0x0F, +0x8B, 0xEE, 0x73, 0x2A, 0x73, 0x4B, 0xA4, 0xF0, +0xAD, 0x10, 0xB5, 0x31, 0xB5, 0x31, 0xAC, 0xF0, +0xB5, 0x32, 0xAD, 0x11, 0xB5, 0x73, 0xB5, 0x72, +0xA4, 0xF0, 0x83, 0xCC, 0xBD, 0xB4, 0xE6, 0xD8, +0xDE, 0xB7, 0xDE, 0x96, 0xF7, 0xBE, 0x94, 0xB2, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xDF, 0xFF, 0xFF, 0x10, 0x82, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xD6, 0xBA, 0xEF, 0x7D, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, +0xFF, 0xFF, 0xB5, 0xB6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x28, +0xFF, 0xFF, 0xF7, 0x9D, 0xFF, 0xBE, 0xFF, 0xFF, +0x39, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xCE, 0x79, 0xF7, 0xBD, +0xD6, 0xD7, 0xD6, 0xB6, 0xBD, 0xF3, 0xA5, 0x31, +0x84, 0x4E, 0xCE, 0x55, 0xE6, 0xD7, 0xDE, 0xB6, +0xA4, 0xEF, 0xAD, 0x0F, 0xCE, 0x34, 0xD6, 0x55, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x9D, 0xE6, 0xF9, 0xF7, 0x9D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE6, 0xDA, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0xEF, 0x5C, 0xC6, 0x14, 0xA5, 0x11, 0x5A, 0xC9, +0x94, 0x6F, 0xD6, 0x77, 0xEF, 0x7D, 0x94, 0xB2, +0x00, 0x00, 0xEF, 0x5D, 0xEF, 0x5D, 0xE7, 0x3C, +0xFF, 0xDE, 0x21, 0x24, 0x5A, 0xEB, 0xFF, 0xFF, +0xFF, 0xFF, 0x73, 0x8E, 0x29, 0x65, 0xFF, 0xFF, +0xFF, 0xFF, 0xEF, 0x5D, 0x00, 0x00, 0xB5, 0xB6, +0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0xC3, 0x6B, 0x4D, +0xFF, 0xDE, 0xEF, 0x3C, 0xF7, 0xBE, 0x9C, 0xD3, +0x00, 0x00, 0x5A, 0xEB, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, 0xA5, 0x34, +0xFF, 0xFF, 0xF7, 0xBE, 0xFF, 0xFF, 0x08, 0x41, +0x73, 0x8E, 0xF7, 0x9D, 0xAD, 0x55, 0x5A, 0xCA, +0x39, 0xE7, 0x52, 0xAA, 0x8C, 0x71, 0xDE, 0xDB, +0xFF, 0xDF, 0x00, 0x00, 0x84, 0x10, 0xF7, 0x9E, +0xD6, 0xBA, 0xEF, 0x7C, 0xFF, 0xDF, 0xFF, 0xDF, +0xB5, 0x96, 0x7B, 0xEF, 0x5A, 0xCB, 0x31, 0xA6, +0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, +0xB5, 0xB6, 0xF7, 0x9E, 0xE7, 0x3C, 0xF7, 0xDE, +0x73, 0x8E, 0x10, 0x82, 0xFF, 0xDF, 0xD6, 0xD9, +0xA5, 0xB1, 0x95, 0x6B, 0xAD, 0xED, 0xA5, 0xAE, +0x95, 0x2E, 0xCE, 0x98, 0xFF, 0xDE, 0x42, 0x08, +0x39, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0xD3, +0x00, 0x00, 0xDE, 0xFB, 0xDE, 0xDB, 0x7B, 0xEF, +0x31, 0xA5, 0x29, 0x64, 0x29, 0x64, 0x63, 0x0B, +0xAD, 0x75, 0xD6, 0x9A, 0xDE, 0xDB, 0xDE, 0xFB, +0xE7, 0x1C, 0xEF, 0x7D, 0xF7, 0x9E, 0x00, 0x00, +0x73, 0xAE, 0x29, 0x65, 0x18, 0xE3, 0xDE, 0xDB, +0xFF, 0xDF, 0xDE, 0xDB, 0xC5, 0xF8, 0xCE, 0x59, +0xD6, 0x9A, 0xCE, 0x59, 0xEF, 0x5D, 0xDE, 0xFB, +0x00, 0x00, 0x39, 0xE7, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, +0x63, 0x2C, 0x63, 0x2C, 0x63, 0x2C, 0x7B, 0xCF, +0xF7, 0xBE, 0xC6, 0x38, 0x84, 0x30, 0xB5, 0x76, +0xEF, 0x7D, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x4D, 0x29, 0x45, 0x4A, 0x69, +0x9C, 0xD3, 0xDE, 0xDB, 0xFF, 0xDF, 0xF7, 0x9E, +0xAD, 0x55, 0x7B, 0xCF, 0x52, 0xAA, 0x31, 0x86, +0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0x31, 0x86, +0xCE, 0x79, 0xF7, 0xBE, 0xD6, 0x98, 0xB5, 0x94, +0xAD, 0x12, 0x8C, 0x2E, 0x9C, 0xAF, 0xC6, 0x13, +0xC6, 0x16, 0xF7, 0x7D, 0x73, 0xAE, 0x08, 0x41, +0xFF, 0xDF, 0xDE, 0xFA, 0xC6, 0x95, 0x95, 0x0E, +0x8C, 0xEC, 0xAE, 0x2B, 0xAE, 0x0B, 0xD7, 0x17, +0xFF, 0xFE, 0x42, 0x28, 0x39, 0xC7, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0x9E, 0xC6, 0x36, 0xBD, 0xB3, 0xDE, 0xD7, +0xEF, 0x59, 0xEF, 0x5C, 0xE7, 0x3C, 0x21, 0x04, +0x4A, 0x49, 0x5A, 0xCB, 0x08, 0x41, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x39, 0xC7, 0xC6, 0x18, 0xEF, 0x9D, 0xBE, 0x37, +0x6C, 0x0C, 0x64, 0x0A, 0x64, 0x09, 0x74, 0x8C, +0x74, 0x6D, 0x19, 0xE3, 0x11, 0x82, 0x09, 0x01, +0x19, 0xA2, 0x22, 0x03, 0x21, 0xE3, 0x19, 0xC2, +0x11, 0x82, 0x21, 0xC3, 0x19, 0xC3, 0x19, 0x83, +0x09, 0x02, 0x11, 0x42, 0x42, 0xE7, 0x21, 0xE3, +0x3A, 0xC6, 0x74, 0xAC, 0x85, 0x2F, 0x8D, 0x70, +0x5A, 0x89, 0x6B, 0x0A, 0x73, 0x4B, 0x7B, 0x8B, +0x7B, 0x8A, 0x83, 0xAB, 0x83, 0xAB, 0x83, 0xAB, +0x83, 0xCC, 0x94, 0x4E, 0x83, 0xCC, 0x83, 0xCC, +0x8B, 0xEC, 0x9C, 0x8F, 0xBD, 0x93, 0xCE, 0x15, +0xCD, 0xF4, 0xC5, 0xD3, 0xF7, 0x9D, 0xDE, 0xFB, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x52, 0x8A, 0xFF, 0xFF, 0xFF, 0xBE, +0xFF, 0xBE, 0xFF, 0xFF, 0x52, 0xAA, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, +0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0xE7, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xCB, +0xFF, 0xFF, 0xF7, 0x9E, 0x18, 0xC3, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xF3, +0xFF, 0xDE, 0xF7, 0x7C, 0xEF, 0x5B, 0xF7, 0xBE, +0x94, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x29, 0x45, 0xFF, 0xDE, 0xEF, 0x7C, +0xD6, 0xF7, 0xC6, 0x34, 0x5B, 0x08, 0x84, 0x2D, +0x63, 0x49, 0xD6, 0xB6, 0xDE, 0xB6, 0xD6, 0x75, +0x94, 0x8C, 0x7C, 0x4A, 0x84, 0xAC, 0x9D, 0x2F, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x7D, 0xDE, 0xD9, 0xF7, 0x9D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x3B, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xD6, 0x9A, +0xE7, 0x3C, 0xBE, 0x15, 0x5A, 0xE9, 0x7C, 0x0C, +0xB5, 0x91, 0xD6, 0x57, 0xF7, 0x9D, 0x84, 0x30, +0x00, 0x00, 0xF7, 0x9E, 0xE7, 0x3C, 0xDE, 0xFA, +0xF7, 0xBE, 0x6B, 0x6D, 0x18, 0xC3, 0xFF, 0xFF, +0xFF, 0xFF, 0x29, 0x65, 0x73, 0x8E, 0xFF, 0xFF, +0xF7, 0xBE, 0xFF, 0xFF, 0x29, 0x65, 0x73, 0x8E, +0xFF, 0xFF, 0xD6, 0xBA, 0x00, 0x00, 0xAD, 0x75, +0xF7, 0x9D, 0xDE, 0xD9, 0xF7, 0x9D, 0xA5, 0x14, +0x00, 0x00, 0xDE, 0xFB, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9E, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xF7, 0xDE, 0xFF, 0xFF, 0x08, 0x41, +0x63, 0x2C, 0xF7, 0xBE, 0xC6, 0x17, 0x63, 0x2C, +0x39, 0xE6, 0x42, 0x07, 0x84, 0x0F, 0xDE, 0xDB, +0xEF, 0x7D, 0x00, 0x00, 0x8C, 0x51, 0xFF, 0xDF, +0xEF, 0x7D, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xDE, +0xFF, 0xDF, 0xEF, 0x5D, 0xB5, 0x96, 0x31, 0x86, +0x08, 0x61, 0xE7, 0x3C, 0xF7, 0xBE, 0xFF, 0xFF, +0x7B, 0xEF, 0x00, 0x00, 0xF7, 0xDE, 0xDF, 0x1A, +0xAD, 0xF0, 0x7C, 0xE7, 0x8D, 0x48, 0x85, 0x08, +0x8D, 0x4D, 0xCE, 0xB8, 0xF7, 0xDE, 0x31, 0xA6, +0x4A, 0x49, 0xFF, 0xFF, 0xFF, 0xFF, 0xA5, 0x34, +0x00, 0x00, 0xCE, 0x59, 0xE7, 0x1B, 0x7C, 0x0F, +0x39, 0xE6, 0x31, 0xA5, 0x31, 0xC5, 0x6B, 0x6D, +0xC6, 0x18, 0xEF, 0x7D, 0xF7, 0xBE, 0xF7, 0xBE, +0xF7, 0xBE, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xEF, 0x5D, 0x29, 0x65, 0x18, 0xC3, +0xD6, 0x9A, 0xF7, 0xBE, 0xDE, 0xFB, 0xCE, 0x59, +0xC6, 0x38, 0xB5, 0x96, 0xE7, 0x1C, 0xE7, 0x3C, +0x00, 0x00, 0x94, 0x92, 0xFF, 0xFF, 0xF7, 0xBE, +0xF7, 0x9E, 0xF7, 0x9E, 0xF7, 0x9E, 0xF7, 0x9E, +0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xF7, 0xBE, 0xCE, 0x59, 0xA5, 0x14, 0xCE, 0x59, +0xF7, 0x9E, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x4D, 0x31, 0xA6, 0x7B, 0xEF, +0xD6, 0xBA, 0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xF7, 0xBE, 0xF7, 0xBE, 0xFF, 0xDE, +0xFF, 0xFF, 0xE7, 0x1C, 0xA5, 0x34, 0x18, 0xE3, +0x21, 0x04, 0xFF, 0xDE, 0xE7, 0x1B, 0xB5, 0x94, +0xAD, 0x12, 0x6B, 0x4B, 0xA4, 0xF1, 0xCE, 0x14, +0xBD, 0xB5, 0xEF, 0x7D, 0x84, 0x10, 0x00, 0x00, +0xF7, 0xBE, 0xDE, 0xDA, 0xAD, 0x93, 0x9D, 0x90, +0xA5, 0xAF, 0xAE, 0x2C, 0xA5, 0xEC, 0xD7, 0x17, +0xF7, 0xDE, 0x39, 0xC7, 0x42, 0x28, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0x9D, 0xC6, 0x36, 0xC6, 0x53, 0xCE, 0x53, +0xE7, 0x39, 0xF7, 0xBE, 0x94, 0x92, 0x08, 0x41, +0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xE7, 0x3C, +0xD6, 0xBA, 0xCE, 0x79, 0xDE, 0xDB, 0xF7, 0x9E, +0xFF, 0xFF, 0xFF, 0xDF, 0xD6, 0xDA, 0x8C, 0xB1, +0x6B, 0xCB, 0xAD, 0xB2, 0x74, 0x2B, 0x8D, 0x30, +0x95, 0x51, 0x19, 0xA3, 0x19, 0x82, 0x21, 0xC4, +0x2A, 0x44, 0x22, 0x23, 0x21, 0xE3, 0x19, 0xC2, +0x11, 0x62, 0x11, 0x42, 0x11, 0x42, 0x19, 0xA4, +0x09, 0x02, 0x11, 0x43, 0x19, 0xA3, 0x2A, 0x24, +0x4B, 0x68, 0x64, 0x4B, 0x43, 0x47, 0x7C, 0xEE, +0x62, 0xCA, 0x7B, 0xAC, 0x8C, 0x2E, 0x73, 0x6B, +0x7B, 0x6A, 0x83, 0x8B, 0x9C, 0x4E, 0xA4, 0xAF, +0xA4, 0xB0, 0xA4, 0xCF, 0x9C, 0x6E, 0x94, 0x2D, +0x94, 0x2D, 0x8C, 0x0C, 0x94, 0x0C, 0x8B, 0xEC, +0x8B, 0xEC, 0x8B, 0xEC, 0xDE, 0xDA, 0xFF, 0xDE, +0x52, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x20, 0xC6, 0x38, 0xF7, 0x9E, 0xD6, 0x99, +0xD6, 0x58, 0xEF, 0x7D, 0xE7, 0x1B, 0x29, 0x45, +0x00, 0x00, 0x00, 0x00, 0x10, 0xA2, 0xC6, 0x38, +0xFF, 0xFF, 0xFF, 0xDF, 0xDE, 0xFB, 0x31, 0x86, +0x00, 0x00, 0x00, 0x00, 0x42, 0x08, 0xEF, 0x5D, +0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x38, 0x21, 0x04, +0x00, 0x00, 0x00, 0x20, 0x7B, 0xCF, 0xFF, 0xDE, +0xF7, 0x9C, 0xDE, 0xD7, 0xCE, 0x96, 0xF7, 0xBD, +0xFF, 0xFF, 0x73, 0xAE, 0x08, 0x41, 0x00, 0x00, +0x39, 0xC7, 0xD6, 0xBA, 0xEF, 0x5C, 0xAD, 0x95, +0xB6, 0x13, 0x95, 0x0E, 0x63, 0x68, 0x9D, 0x0F, +0x73, 0xAB, 0xBE, 0x13, 0x9C, 0xEE, 0x7C, 0x6B, +0x74, 0x49, 0x7C, 0xCB, 0x95, 0x4D, 0x95, 0x0C, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x7D, 0xD6, 0x98, 0xEF, 0x7D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x1B, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0xB5, 0x96, +0xF7, 0xBE, 0xAD, 0x74, 0x5B, 0x2A, 0x7C, 0x4A, +0x8C, 0xCD, 0xCE, 0x77, 0xF7, 0xBE, 0x73, 0xAE, +0x10, 0xA2, 0xFF, 0xDF, 0xE7, 0x1B, 0xCE, 0x77, +0xF7, 0x9D, 0xB5, 0x95, 0x00, 0x00, 0xDE, 0xDB, +0xEF, 0x7D, 0x00, 0x00, 0xB5, 0x96, 0xFF, 0xBE, +0xEF, 0x5C, 0xFF, 0xDE, 0x73, 0x8E, 0x31, 0x86, +0xFF, 0xFF, 0x94, 0xB2, 0x00, 0x00, 0xEF, 0x5D, +0xE7, 0x1B, 0xC6, 0x36, 0xEF, 0x7D, 0xBD, 0xD7, +0x00, 0x00, 0xCE, 0x79, 0xF7, 0xBE, 0xD6, 0x9A, +0xE7, 0x3B, 0xE7, 0x3B, 0xC6, 0x38, 0xCE, 0x79, +0xEF, 0x7D, 0xFF, 0xFF, 0xDE, 0xFB, 0xEF, 0x7D, +0xFF, 0xFF, 0xF7, 0xBE, 0xFF, 0xFF, 0x08, 0x41, +0x42, 0x28, 0xFF, 0xFF, 0xDF, 0x1B, 0xB5, 0xF5, +0x5A, 0xEA, 0x4A, 0x48, 0x94, 0x91, 0xE7, 0x1C, +0xDE, 0xFB, 0x00, 0x00, 0xA5, 0x34, 0xFF, 0xDF, +0xF7, 0xBE, 0xEF, 0x7D, 0xBD, 0xD7, 0xEF, 0x5D, +0xFF, 0xDE, 0xD6, 0xF9, 0xBE, 0x36, 0xCE, 0x98, +0xDF, 0x5A, 0xE7, 0x3B, 0xF7, 0xBE, 0xC6, 0x38, +0x00, 0x00, 0xAD, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, +0x8C, 0x71, 0x00, 0x00, 0xEF, 0x7D, 0xDF, 0x3B, +0xA5, 0xB0, 0xB6, 0x6E, 0xB6, 0x4D, 0xA5, 0xEC, +0x95, 0x8F, 0xD6, 0xF9, 0xFF, 0xDE, 0x21, 0x24, +0x52, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0xF7, +0x00, 0x00, 0xB5, 0xB6, 0xEF, 0x5D, 0x8C, 0x71, +0x3A, 0x07, 0x31, 0xA5, 0x39, 0xE6, 0x73, 0x8D, +0xCE, 0x79, 0xF7, 0xBE, 0x31, 0xA6, 0x7B, 0xCF, +0xFF, 0xDF, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0xEF, 0x7D, 0x31, 0x86, +0x10, 0x82, 0xCE, 0x59, 0xF7, 0xBE, 0xE7, 0x1C, +0xD6, 0x7A, 0xCE, 0x39, 0xDE, 0xDB, 0xF7, 0xBE, +0x00, 0x20, 0x84, 0x10, 0xF7, 0xBE, 0xD6, 0xBA, +0xB5, 0xB6, 0xAD, 0x75, 0xAD, 0x75, 0xB5, 0xB6, +0xDE, 0xDB, 0xF7, 0xBE, 0xEF, 0x5D, 0xE7, 0x1C, +0xF7, 0xBE, 0xC6, 0x38, 0xB5, 0xB6, 0xC6, 0x38, +0xF7, 0x9E, 0x6B, 0x6D, 0x10, 0x82, 0xF7, 0xBE, +0xCE, 0x59, 0x6B, 0x4D, 0x31, 0x86, 0x84, 0x30, +0xE7, 0x3C, 0xE7, 0x3C, 0xBD, 0xD7, 0xF7, 0x9E, +0xF7, 0x9E, 0xDF, 0x1B, 0xCE, 0xB8, 0xD6, 0xD9, +0xE7, 0x5B, 0xF7, 0x9D, 0xFF, 0xDF, 0xA5, 0x14, +0x00, 0x00, 0xCE, 0x79, 0xEF, 0x7D, 0xC6, 0x17, +0xBD, 0xB5, 0x94, 0x91, 0x94, 0x70, 0xB5, 0x73, +0xC5, 0xF7, 0xF7, 0x9E, 0x94, 0x92, 0x00, 0x00, +0xE7, 0x3C, 0xE7, 0x1B, 0xA5, 0x53, 0x9D, 0x50, +0x63, 0xE9, 0x95, 0x8B, 0xA5, 0xCD, 0xDF, 0x18, +0xFF, 0xDE, 0x29, 0x65, 0x52, 0x8A, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0x9D, 0xD6, 0x96, 0xBE, 0x4F, 0xAD, 0x8E, +0xE6, 0xF8, 0xF7, 0xBE, 0x94, 0xB2, 0x00, 0x00, +0xA5, 0x14, 0xEF, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x1C, 0xAD, 0x55, +0x8C, 0x70, 0xA5, 0x31, 0x8C, 0x8E, 0x95, 0x10, +0x74, 0x4E, 0x53, 0x4B, 0x32, 0x26, 0x32, 0x46, +0x21, 0xE3, 0x22, 0x03, 0x21, 0xE3, 0x19, 0xC3, +0x19, 0xC3, 0x21, 0xC3, 0x11, 0x62, 0x19, 0xA3, +0x21, 0xE4, 0x2A, 0x25, 0x32, 0x86, 0x3A, 0xA6, +0x4B, 0x69, 0x6C, 0x6C, 0x3A, 0xC5, 0x64, 0x4B, +0x5A, 0x89, 0x39, 0xC6, 0x5A, 0xA9, 0x52, 0x68, +0x42, 0x06, 0x5A, 0xA8, 0x9C, 0x8F, 0xBD, 0xB4, +0xC5, 0x94, 0xA4, 0xD0, 0x7B, 0x8B, 0x8C, 0x0C, +0x9C, 0x4D, 0x83, 0xAB, 0x83, 0x8B, 0x94, 0x0D, +0xAC, 0xD0, 0xA4, 0x8F, 0xC5, 0xD5, 0xEF, 0x3C, +0xF7, 0xBE, 0x8C, 0x51, 0x42, 0x08, 0x5A, 0xCB, +0xCE, 0x59, 0xFF, 0xFF, 0xEF, 0x7D, 0xD6, 0x98, +0xCE, 0x16, 0xDE, 0xB9, 0xEF, 0x7D, 0xF7, 0x9E, +0xBD, 0xD7, 0xB5, 0x96, 0xEF, 0x7D, 0xFF, 0xFF, +0xF7, 0x9E, 0xF7, 0x9D, 0xFF, 0xDF, 0xFF, 0xDF, +0xD6, 0xBA, 0xDE, 0xFB, 0xFF, 0xFF, 0xFF, 0xDF, +0xF7, 0x9D, 0xFF, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, +0xE7, 0x1B, 0xF7, 0x9D, 0xFF, 0xDE, 0xEF, 0x7C, +0xE6, 0xF8, 0xD6, 0x96, 0xE7, 0x39, 0xF7, 0xBD, +0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xDF, 0xEF, 0x5D, +0xF7, 0xBE, 0xE7, 0x5C, 0xCE, 0x78, 0xA5, 0x52, +0x84, 0x6C, 0x6B, 0xC8, 0x95, 0x0D, 0xAD, 0xB1, +0x7C, 0x0C, 0xAD, 0xD1, 0x84, 0x6A, 0x8C, 0xED, +0x8D, 0x2D, 0x7C, 0xAB, 0x84, 0xAB, 0x8C, 0xEC, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0x7D, 0xD6, 0x99, 0xF7, 0x7D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x1B, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0x73, 0xAE, +0xF7, 0xBE, 0xC6, 0x38, 0xA5, 0x73, 0x95, 0x30, +0xA5, 0x92, 0xD6, 0xD9, 0xFF, 0xDE, 0x39, 0xE7, +0x42, 0x08, 0xFF, 0xDE, 0xDE, 0xD9, 0xC6, 0x15, +0xE7, 0x5C, 0xEF, 0x7D, 0x00, 0x20, 0x9C, 0xD3, +0xAD, 0x55, 0x00, 0x00, 0xEF, 0x5D, 0xEF, 0x5C, +0xD6, 0x98, 0xF7, 0x9D, 0xB5, 0x96, 0x00, 0x00, +0xEF, 0x5D, 0x52, 0xAA, 0x31, 0xA6, 0xF7, 0xBE, +0xCE, 0x98, 0xA5, 0x73, 0xDF, 0x1B, 0xE7, 0x3C, +0x00, 0x00, 0x9C, 0xD3, 0xFF, 0xDE, 0xDE, 0xFA, +0xF7, 0xDC, 0xD6, 0xB9, 0x9C, 0xF3, 0xB5, 0xB7, +0xE7, 0x3D, 0xF7, 0x9E, 0x00, 0x00, 0x8C, 0x51, +0xFF, 0xDF, 0xEF, 0x7D, 0xFF, 0xDF, 0x08, 0x41, +0x08, 0x61, 0xF7, 0xBE, 0xEF, 0x5D, 0xCE, 0x98, +0xC6, 0x77, 0xA5, 0x53, 0xDF, 0x1A, 0xEF, 0x7D, +0xAD, 0x55, 0x00, 0x00, 0xCE, 0x79, 0xF7, 0xBE, +0xF7, 0xBE, 0xD6, 0x9A, 0x00, 0x00, 0xAD, 0x55, +0xF7, 0xDE, 0xBE, 0x56, 0x9D, 0x71, 0x9D, 0x92, +0xBE, 0x75, 0xBE, 0x36, 0xEF, 0x5D, 0xDF, 0x1B, +0x00, 0x00, 0x9C, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, +0xB5, 0x96, 0x00, 0x00, 0xC6, 0x18, 0xF7, 0xBD, +0xDF, 0x37, 0xC6, 0x73, 0xC6, 0xD3, 0xC6, 0xD3, +0xC6, 0xB5, 0xE7, 0x5C, 0xEF, 0x7D, 0x00, 0x00, +0x7B, 0xEF, 0xFF, 0xFF, 0xF7, 0xBE, 0xEF, 0x5C, +0x00, 0x00, 0x8C, 0x51, 0xF7, 0xBE, 0xC6, 0x38, +0x84, 0x30, 0x73, 0xCE, 0x7B, 0xEF, 0xA5, 0x13, +0xE7, 0x1C, 0xF7, 0x9E, 0x00, 0x20, 0x84, 0x30, +0xFF, 0xDF, 0xF7, 0x9E, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xFF, 0xFF, 0xFF, 0xDF, 0xEF, 0x7D, +0x31, 0xA6, 0x10, 0x82, 0xC6, 0x38, 0xF7, 0xBF, +0xE7, 0x1C, 0xD6, 0x7A, 0xDE, 0xFC, 0xF7, 0xBE, +0x31, 0x86, 0x52, 0x8A, 0xF7, 0xBE, 0xD6, 0x9A, +0x9C, 0xF3, 0x84, 0x30, 0x8C, 0x51, 0x9C, 0xF3, +0xD6, 0x9A, 0xF7, 0xBE, 0x39, 0xE7, 0x42, 0x08, +0xF7, 0x9E, 0xCE, 0x59, 0xAD, 0x75, 0xAD, 0x75, +0xEF, 0x7D, 0x6B, 0x6D, 0x10, 0x82, 0xFF, 0xDF, +0xD6, 0xBA, 0x94, 0x92, 0x73, 0xAE, 0x9C, 0xF3, +0xEF, 0x5D, 0xAD, 0x75, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x7D, 0xB5, 0xB6, 0x9C, 0xD3, 0xA5, 0x33, +0xB5, 0xD6, 0xCE, 0x58, 0xFF, 0xDE, 0xBD, 0xF7, +0x00, 0x00, 0xC6, 0x18, 0xF7, 0x9E, 0xDE, 0xFB, +0xE7, 0x1B, 0xDE, 0xFB, 0xDE, 0xDB, 0xDE, 0xFB, +0xE6, 0xFB, 0xF7, 0xBE, 0xB5, 0xB6, 0x00, 0x00, +0xBD, 0xF7, 0xF7, 0x9D, 0xD6, 0x98, 0xBD, 0xF4, +0xA5, 0x92, 0xB6, 0x52, 0xC6, 0x94, 0xE7, 0x7B, +0xF7, 0x9E, 0x00, 0x20, 0x7B, 0xCF, 0xFF, 0xFF, +0xFF, 0xDE, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0xBD, 0xD6, 0xD5, 0xAD, 0xEB, 0xAD, 0x8D, +0xD6, 0x97, 0xF7, 0xBE, 0xEF, 0x7D, 0x31, 0x86, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, +0x21, 0x04, 0x31, 0x86, 0x42, 0x08, 0x52, 0xAA, +0x73, 0xAE, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x3C, +0xCE, 0x78, 0xBD, 0xF4, 0x8C, 0xAE, 0x7C, 0x2C, +0x8D, 0x11, 0x95, 0x32, 0x32, 0x67, 0x2A, 0x26, +0x22, 0x04, 0x22, 0x23, 0x19, 0xC2, 0x19, 0xA2, +0x11, 0x62, 0x21, 0xE4, 0x19, 0xA3, 0x19, 0xA3, +0x32, 0x45, 0x42, 0xE8, 0x4B, 0x29, 0x4B, 0x49, +0x4B, 0x69, 0x53, 0x88, 0x2A, 0x44, 0x64, 0x2B, +0x73, 0x6C, 0x62, 0xEB, 0x83, 0xEE, 0x73, 0x6C, +0x6B, 0x0A, 0x7B, 0xCD, 0x9C, 0xD1, 0xAD, 0x32, +0x9C, 0x90, 0x6B, 0x4B, 0x6B, 0x0A, 0x83, 0xEC, +0x9C, 0x4D, 0x94, 0x4F, 0xAD, 0x33, 0x94, 0x2F, +0x83, 0xCD, 0x83, 0xED, 0x94, 0x4F, 0xBD, 0xB5, +0xDE, 0xFB, 0xF7, 0x7D, 0xFF, 0xDE, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xF7, 0x9D, +0xE7, 0x3C, 0xD6, 0x99, 0xD6, 0x78, 0xE6, 0xFB, +0xF7, 0x7D, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, +0xFF, 0xBE, 0xFF, 0xBE, 0xFF, 0xDE, 0xFF, 0xFF, +0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xBE, 0xEF, 0x5C, 0xDE, 0xD9, 0xD6, 0x77, +0xD6, 0x98, 0xE7, 0x3B, 0xF7, 0x9E, 0xFF, 0xDE, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xEF, 0x5D, +0xD6, 0xB9, 0xBE, 0x15, 0xAD, 0x32, 0x7B, 0xAB, +0x8C, 0x6C, 0xA5, 0x6F, 0x9D, 0x4F, 0x84, 0x6C, +0x84, 0x6E, 0x8C, 0xCD, 0x53, 0x05, 0x95, 0x2F, +0xAE, 0x32, 0x95, 0x2E, 0xAD, 0x90, 0xCE, 0x74, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0xBD, 0xEF, 0x1A, 0xF7, 0x7D, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0xBE, 0xE7, 0x1B, +0xF7, 0xBE, 0x9C, 0xF3, 0x00, 0x00, 0x10, 0x82, +0xE7, 0x3C, 0xF7, 0xBE, 0xEF, 0x7C, 0xE7, 0x3B, +0xE7, 0x5C, 0xF7, 0xBE, 0xC6, 0x38, 0x00, 0x00, +0x8C, 0x71, 0xF7, 0x9E, 0xCE, 0x57, 0xBD, 0xF4, +0xDE, 0xD9, 0xFF, 0xDE, 0x39, 0xE7, 0x52, 0xAA, +0x6B, 0x4D, 0x31, 0xA6, 0xFF, 0xDE, 0xE6, 0xFA, +0xD6, 0x56, 0xE7, 0x3B, 0xEF, 0x7D, 0x00, 0x20, +0xAD, 0x55, 0x10, 0xA2, 0x7B, 0xEF, 0xF7, 0xBE, +0xBE, 0x76, 0xA5, 0xB2, 0xCE, 0xB9, 0xF7, 0xDE, +0x42, 0x08, 0x29, 0x45, 0xF7, 0x9E, 0xFF, 0xDE, +0xF7, 0xDE, 0xEF, 0x5C, 0xDE, 0xFB, 0xEF, 0x5D, +0xFF, 0xDF, 0x9C, 0xD3, 0x00, 0x00, 0xCE, 0x59, +0xF7, 0x9E, 0xEF, 0x5D, 0xFF, 0xDF, 0x08, 0x41, +0x00, 0x00, 0x8C, 0x71, 0xFF, 0xDF, 0xF7, 0xBD, +0xEF, 0x9D, 0xEF, 0x9D, 0xF7, 0xBE, 0xF7, 0xBE, +0x39, 0xC7, 0x21, 0x04, 0xF7, 0xBE, 0xDF, 0x1B, +0xEF, 0x7C, 0xEF, 0x7D, 0x00, 0x20, 0x73, 0x8E, +0xFF, 0xFF, 0xEF, 0x7D, 0xDF, 0x3B, 0xDF, 0x3B, +0xE7, 0x5B, 0xEF, 0x5C, 0xF7, 0xDE, 0xAD, 0x55, +0x00, 0x00, 0xC6, 0x18, 0xF7, 0xDE, 0xF7, 0xBD, +0xEF, 0x7D, 0x08, 0x61, 0x52, 0x8A, 0xFF, 0xDF, +0xF7, 0xBD, 0xE7, 0x1B, 0xDF, 0x1A, 0xE7, 0x3B, +0xEF, 0x9D, 0xFF, 0xDF, 0x84, 0x30, 0x00, 0x00, +0xCE, 0x59, 0xF7, 0xBE, 0xE7, 0x5B, 0xFF, 0xDE, +0x42, 0x08, 0x18, 0xE3, 0xF7, 0x9E, 0xFF, 0xBE, +0xE7, 0x5C, 0xDE, 0xDA, 0xDE, 0xDB, 0xE7, 0x3C, +0xF7, 0xBE, 0x9C, 0xD3, 0x00, 0x00, 0xCE, 0x59, +0xF7, 0x9E, 0xEF, 0x7D, 0xF7, 0x9E, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0xBE, 0xE7, 0x1C, 0xF7, 0x9E, +0xEF, 0x7D, 0x31, 0xA6, 0x08, 0x41, 0xBD, 0xD7, +0xF7, 0xBE, 0xE7, 0x1C, 0xE7, 0x1C, 0xFF, 0xDF, +0x8C, 0x51, 0x00, 0x20, 0xCE, 0x79, 0xF7, 0x9E, +0xE7, 0x1C, 0xD6, 0xBA, 0xD6, 0xBA, 0xE7, 0x1C, +0xF7, 0x9E, 0xDE, 0xFB, 0x00, 0x20, 0x84, 0x30, +0xEF, 0x7D, 0xCE, 0x59, 0xB5, 0xB7, 0xB5, 0x96, +0xEF, 0x7D, 0x7B, 0xEF, 0x00, 0x20, 0xF7, 0xBE, +0xF7, 0x9E, 0xDE, 0xFB, 0xDE, 0xDB, 0xE7, 0x1B, +0xF7, 0xBE, 0xD6, 0xBA, 0x00, 0x00, 0x94, 0xB2, +0xFF, 0xDF, 0xE7, 0x3C, 0xDE, 0xDB, 0xDE, 0xFB, +0xE7, 0x3C, 0xEF, 0x5D, 0xFF, 0xDF, 0x84, 0x30, +0x00, 0x00, 0xE7, 0x3C, 0xF7, 0x9D, 0xEF, 0x5D, +0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, +0xEF, 0x5D, 0xEF, 0x7D, 0xEF, 0x7D, 0x10, 0x82, +0x4A, 0x69, 0xFF, 0xDF, 0xF7, 0x9D, 0xE7, 0x3B, +0xE7, 0x3B, 0xE7, 0x3B, 0xEF, 0x9D, 0xFF, 0xDF, +0x8C, 0x51, 0x00, 0x00, 0xC6, 0x18, 0xFF, 0xDE, +0xF7, 0xBE, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0xBD, 0xBE, 0x32, 0xAD, 0xCB, 0xAD, 0x6D, +0xCE, 0x35, 0xF7, 0x9D, 0xFF, 0xDF, 0x6B, 0x4D, +0x18, 0xC3, 0x8C, 0x71, 0xA5, 0x14, 0x94, 0x92, +0x84, 0x10, 0x73, 0x8E, 0x63, 0x0C, 0x4A, 0x69, +0x21, 0x24, 0x00, 0x00, 0x21, 0x24, 0xDE, 0xDB, +0xF7, 0x9D, 0xB5, 0xD4, 0x42, 0xC6, 0x3A, 0xC6, +0x2A, 0x25, 0x32, 0x66, 0x3A, 0xA7, 0x32, 0x45, +0x22, 0x03, 0x19, 0xE2, 0x21, 0xE3, 0x19, 0x82, +0x11, 0x42, 0x2A, 0x24, 0x2A, 0x24, 0x21, 0xE4, +0x3A, 0x86, 0x53, 0x6A, 0x53, 0xAA, 0x64, 0x2C, +0x5B, 0xEA, 0x43, 0x27, 0x3A, 0xC5, 0x3A, 0xE6, +0xB5, 0xB6, 0xAD, 0x34, 0xB5, 0x53, 0xAD, 0x12, +0xA4, 0xF1, 0xA4, 0xD1, 0xAD, 0x52, 0xC5, 0xD5, +0xB5, 0x73, 0x94, 0x6F, 0x9C, 0x90, 0xA4, 0xD0, +0x94, 0x2D, 0xBD, 0xB4, 0xD6, 0x77, 0xD6, 0x57, +0xCE, 0x16, 0xC5, 0xD5, 0xC5, 0xB5, 0xBD, 0x94, +0xC5, 0xD6, 0xD6, 0x78, 0xEF, 0x3C, 0xFF, 0xDF, +0xF7, 0x9E, 0x84, 0x30, 0x5A, 0xEB, 0x8C, 0x51, +0xF7, 0x9E, 0xEF, 0x5D, 0xCE, 0x37, 0xC5, 0xB5, +0xDE, 0x99, 0xF7, 0xBE, 0xFF, 0xFF, 0x9C, 0xD3, +0x52, 0x8A, 0x63, 0x0C, 0xCE, 0x59, 0xFF, 0xDF, +0xF7, 0x9D, 0xF7, 0x9D, 0xFF, 0xDF, 0xBD, 0xF7, +0x4A, 0x69, 0x39, 0xC7, 0x84, 0x10, 0xF7, 0xBE, +0xFF, 0xBE, 0xEF, 0x1A, 0xD6, 0x56, 0xD6, 0x97, +0xEF, 0x7C, 0xF7, 0xBE, 0x7B, 0xEF, 0x29, 0x65, +0x31, 0xA6, 0x9C, 0xD3, 0xFF, 0xDF, 0xEF, 0x5C, +0xBD, 0xF5, 0x7C, 0x0C, 0x4A, 0x46, 0x39, 0xC4, +0x52, 0xC6, 0x95, 0x0E, 0xAD, 0xB0, 0x63, 0x48, +0x84, 0x4D, 0x8C, 0xCD, 0x3A, 0x83, 0x53, 0x47, +0x8C, 0xCD, 0xB5, 0xD2, 0xB5, 0x91, 0xB5, 0x50, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x5C, 0xC6, 0x17, 0xEF, 0x3C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9E, 0xDE, 0xB9, +0xF7, 0x9E, 0x9C, 0xF3, 0x00, 0x00, 0x21, 0x04, +0x21, 0x24, 0xAD, 0x55, 0xE7, 0x3C, 0xEF, 0x7D, +0xDE, 0xDB, 0x94, 0x92, 0x10, 0x82, 0x21, 0x04, +0xEF, 0x7D, 0xE7, 0x3C, 0xC6, 0x15, 0xBD, 0xD3, +0xD6, 0xB8, 0xF7, 0xBE, 0x84, 0x10, 0x10, 0xA2, +0x21, 0x24, 0x7B, 0xCF, 0xF7, 0x9E, 0xC6, 0x36, +0xB5, 0xB3, 0xE7, 0x1A, 0xFF, 0xDE, 0x39, 0xC7, +0x39, 0xE7, 0x00, 0x00, 0xBD, 0xF7, 0xEF, 0x7C, +0xA5, 0x92, 0x84, 0xAD, 0xAD, 0xD4, 0xEF, 0x5C, +0xCE, 0x79, 0x08, 0x61, 0x29, 0x65, 0xAD, 0x55, +0xE7, 0x3C, 0xFF, 0xDE, 0xEF, 0x7D, 0xCE, 0x79, +0x7B, 0xCF, 0x08, 0x41, 0x52, 0xAA, 0xFF, 0xDF, +0xE7, 0x3C, 0xE7, 0x5C, 0xFF, 0xDF, 0x08, 0x41, +0x21, 0x04, 0x00, 0x00, 0x7B, 0xCF, 0xD6, 0x9A, +0xEF, 0x7D, 0xE7, 0x3C, 0xBD, 0xD7, 0x42, 0x08, +0x00, 0x00, 0xA5, 0x34, 0xEF, 0x7D, 0xBD, 0xD7, +0xD6, 0xFA, 0xF7, 0xBE, 0x73, 0x8E, 0x00, 0x00, +0x73, 0x8E, 0xC6, 0x38, 0xEF, 0x5C, 0xFF, 0xDE, +0xEF, 0x7D, 0xD6, 0xBA, 0x8C, 0x71, 0x10, 0x82, +0x31, 0xA6, 0xF7, 0xDE, 0xE7, 0x5B, 0xD6, 0xF9, +0xF7, 0x9D, 0x8C, 0x71, 0x00, 0x00, 0x4A, 0x69, +0xB5, 0xB6, 0xE7, 0x3C, 0xEF, 0x7D, 0xE7, 0x3C, +0xC6, 0x18, 0x6B, 0x6D, 0x00, 0x00, 0x5A, 0xEB, +0xFF, 0xDE, 0xE7, 0x5B, 0xD6, 0xF8, 0xF7, 0xBD, +0xCE, 0x59, 0x00, 0x20, 0x29, 0x65, 0xAD, 0x55, +0xE7, 0x3C, 0xEF, 0x7D, 0xE7, 0x3C, 0xCE, 0x79, +0x84, 0x10, 0x08, 0x41, 0x52, 0x8A, 0xF7, 0xBE, +0xDE, 0xFB, 0xE7, 0x3C, 0xEF, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xF7, 0x9E, 0xBD, 0xF8, 0xC6, 0x59, +0xEF, 0x7D, 0xEF, 0x7D, 0x31, 0xA6, 0x00, 0x20, +0xAD, 0x75, 0xF7, 0xBE, 0xEF, 0x7D, 0xFF, 0xDF, +0xF7, 0xBE, 0x29, 0x65, 0x10, 0x82, 0x8C, 0x71, +0xD6, 0xBA, 0xF7, 0x9E, 0xF7, 0x9E, 0xDE, 0xDB, +0x9C, 0xD3, 0x21, 0x04, 0x18, 0xE3, 0xEF, 0x5D, +0xE6, 0xFC, 0xCE, 0x59, 0xB5, 0x96, 0xAD, 0x76, +0xE7, 0x3D, 0xA5, 0x34, 0x00, 0x00, 0x73, 0x8E, +0xD6, 0x9A, 0xE7, 0x3C, 0xDE, 0xFB, 0xF7, 0x9E, +0xFF, 0xDF, 0xFF, 0xFF, 0x4A, 0x69, 0x08, 0x41, +0x84, 0x10, 0xCE, 0x79, 0xEF, 0x5D, 0xFF, 0xDF, +0xEF, 0x5D, 0xCE, 0x59, 0x7B, 0xEF, 0x00, 0x20, +0x5A, 0xEB, 0xFF, 0xDE, 0xEF, 0x3C, 0xEF, 0x5D, +0xFF, 0xDF, 0x08, 0x61, 0x00, 0x00, 0xEF, 0x7D, +0xEF, 0x7D, 0xE6, 0xFB, 0xF7, 0xBE, 0x94, 0xB2, +0x00, 0x00, 0x4A, 0x49, 0xB5, 0xB6, 0xE7, 0x3C, +0xEF, 0x7D, 0xEF, 0x5D, 0xC6, 0x38, 0x73, 0x8E, +0x00, 0x00, 0x52, 0xAA, 0xFF, 0xDE, 0xEF, 0x5C, +0xF7, 0x7D, 0xE7, 0x1C, 0x00, 0x00, 0x9C, 0xD3, +0xF7, 0x9D, 0xAD, 0xB2, 0xBE, 0x0E, 0xA5, 0x2E, +0xCE, 0x76, 0xF7, 0xBD, 0xA5, 0x14, 0x08, 0x61, +0xE7, 0x1C, 0xFF, 0xDF, 0xF7, 0xBE, 0xF7, 0xBE, +0xFF, 0xDE, 0xF7, 0xBE, 0xF7, 0xBE, 0xFF, 0xDF, +0xFF, 0xFF, 0xC6, 0x18, 0x08, 0x41, 0x63, 0x2C, +0xFF, 0xDE, 0xBE, 0x16, 0x21, 0xC2, 0x32, 0x64, +0x32, 0x44, 0x42, 0xC6, 0x42, 0xC7, 0x2A, 0x24, +0x21, 0xE3, 0x21, 0xE2, 0x19, 0xC2, 0x11, 0x41, +0x21, 0xE4, 0x2A, 0x24, 0x22, 0x03, 0x21, 0xE3, +0x4B, 0x49, 0x64, 0x0B, 0x5B, 0xEB, 0x74, 0x8E, +0x53, 0x89, 0x32, 0xA5, 0x2A, 0x23, 0x21, 0xE3, +0x9C, 0xF3, 0xB5, 0x95, 0xB5, 0x53, 0xB5, 0x32, +0xB5, 0x32, 0xB5, 0x52, 0xB5, 0x53, 0xBD, 0xD4, +0xC5, 0xD5, 0xAD, 0x52, 0xB5, 0x93, 0xBD, 0xB3, +0x94, 0x0D, 0xC5, 0xD4, 0xD6, 0x36, 0xD6, 0x56, +0xD6, 0x36, 0xCE, 0x16, 0xD6, 0x36, 0xD6, 0x36, +0xD6, 0x56, 0xDE, 0x98, 0xF7, 0x9D, 0xF7, 0x9E, +0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x31, 0xA6, 0xFF, 0xBE, 0xF7, 0x7C, 0xE6, 0xD9, +0xF7, 0x5B, 0xFF, 0xDF, 0x6B, 0x6D, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xBD, 0xF7, +0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0xF7, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x8A, +0xFF, 0xDF, 0xE7, 0x1A, 0xD6, 0x76, 0xE6, 0xFA, +0xF7, 0xBE, 0x63, 0x2C, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x94, 0xB2, 0xF7, 0x9D, +0xCE, 0x57, 0x7C, 0x0C, 0x6B, 0xAA, 0x63, 0x69, +0x5B, 0x68, 0x5B, 0x88, 0x8C, 0xEC, 0x8C, 0xCD, +0x63, 0x49, 0x9D, 0x2F, 0x6B, 0xA8, 0x84, 0xAD, +0x9D, 0x2F, 0xA4, 0xF0, 0x94, 0x6E, 0x94, 0x4D, +0xFF, 0xFF, 0xA5, 0x34, 0x00, 0x00, 0xCE, 0x79, +0xEF, 0x5C, 0xCE, 0x57, 0xEF, 0x7C, 0xD6, 0x9A, +0x00, 0x00, 0xA5, 0x34, 0xF7, 0x9D, 0xDE, 0xB9, +0xF7, 0x9E, 0x9C, 0xF3, 0x00, 0x00, 0xDE, 0xDB, +0x4A, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x42, 0x08, 0xDE, 0xDB, +0xEF, 0x7D, 0xC6, 0x16, 0x9C, 0xAF, 0x8C, 0x2C, +0xB5, 0x73, 0xEF, 0x7D, 0xC6, 0x38, 0x00, 0x00, +0x00, 0x00, 0xBD, 0xD7, 0xEF, 0x7D, 0xBE, 0x75, +0xA5, 0xD1, 0xC6, 0x56, 0xF7, 0xBE, 0x7B, 0xCF, +0x00, 0x00, 0x08, 0x41, 0xF7, 0xBE, 0xDF, 0x1B, +0xA5, 0x71, 0x6B, 0xC9, 0x84, 0x8E, 0xC6, 0x78, +0xF7, 0x9D, 0xCE, 0x79, 0x42, 0x08, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x41, 0x73, 0x8E, 0xF7, 0xBE, 0xEF, 0x5C, +0xC6, 0x57, 0xEF, 0x9D, 0xFF, 0xFF, 0x08, 0x41, +0x84, 0x30, 0x94, 0x92, 0x08, 0x61, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA2, +0x9C, 0xF3, 0xF7, 0xBE, 0xD6, 0xBA, 0x94, 0xD1, +0xBE, 0x55, 0xDF, 0x1B, 0xF7, 0xDE, 0x84, 0x30, +0x10, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x52, 0xAA, +0xE7, 0x3C, 0xEF, 0xBD, 0xCE, 0xD7, 0xA5, 0xB2, +0xD6, 0xFA, 0xF7, 0xDE, 0x9D, 0x13, 0x21, 0x04, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0xA2, 0x84, 0x10, 0xF7, 0xBE, +0xEF, 0x9C, 0xCF, 0x17, 0xC6, 0xF5, 0xDF, 0x5A, +0xF7, 0xDE, 0xC6, 0x18, 0x31, 0xA6, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x41, 0x6B, 0x4D, 0xEF, 0x9D, 0xDE, 0xFB, +0xB5, 0xB6, 0xDE, 0xDB, 0xEF, 0x7D, 0x00, 0x00, +0x8C, 0x51, 0xEF, 0x7D, 0xAD, 0x55, 0x94, 0xB3, +0xC6, 0x38, 0xEF, 0x7D, 0xEF, 0x5D, 0x31, 0xA6, +0x00, 0x20, 0xAD, 0x55, 0xFF, 0xDF, 0xFF, 0xDF, +0xFF, 0xFF, 0xEF, 0x7D, 0x63, 0x0C, 0x00, 0x20, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x4A, 0x49, 0xDE, 0xDB, 0xE7, 0x3D, +0xD6, 0x9A, 0xC6, 0x18, 0xA5, 0x35, 0x94, 0x92, +0xD6, 0x9A, 0xF7, 0x9E, 0x63, 0x0C, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x79, +0xF7, 0xBE, 0xF7, 0x9E, 0xEF, 0x7D, 0x73, 0x8E, +0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x6B, 0x6D, +0xF7, 0x9E, 0xEF, 0x5C, 0xD6, 0x79, 0xEF, 0x3C, +0xFF, 0xDF, 0x08, 0x61, 0x00, 0x00, 0xEF, 0x7D, +0xEF, 0x3C, 0xCE, 0x58, 0xE7, 0x1B, 0xFF, 0xBE, +0xA5, 0x34, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA2, +0x7B, 0xEF, 0xF7, 0xBE, 0xF7, 0x9D, 0xDE, 0xB9, +0xEF, 0x5C, 0xE7, 0x3C, 0x00, 0x00, 0x9C, 0xD3, +0xEF, 0x7D, 0xBE, 0x33, 0xCE, 0xB2, 0x9C, 0xEE, +0xD6, 0xB7, 0xFF, 0xBE, 0x63, 0x2C, 0x39, 0xC7, +0xFF, 0xFF, 0xF7, 0x9D, 0xEF, 0x3B, 0xE7, 0x1A, +0xDF, 0x19, 0xDF, 0x1A, 0xE7, 0x3C, 0xEF, 0x5D, +0xF7, 0x9E, 0xFF, 0xFF, 0x42, 0x28, 0x39, 0xC7, +0xFF, 0xDE, 0xC6, 0x37, 0x32, 0x64, 0x42, 0xE6, +0x32, 0x64, 0x32, 0x85, 0x3A, 0xA5, 0x2A, 0x24, +0x21, 0xE3, 0x21, 0xE3, 0x19, 0xA2, 0x22, 0x03, +0x32, 0xA5, 0x32, 0x64, 0x2A, 0x24, 0x21, 0xE3, +0x53, 0x69, 0x6C, 0x6C, 0x64, 0x2B, 0x84, 0xEF, +0x32, 0xA6, 0x19, 0xE2, 0x19, 0xE2, 0x19, 0xC2, +0x94, 0x91, 0xAD, 0x12, 0xB5, 0x52, 0xB5, 0x52, +0xBD, 0x93, 0xBD, 0x93, 0xBD, 0x94, 0xCE, 0x36, +0xCD, 0xF5, 0xC5, 0xD4, 0xC5, 0xD4, 0xD6, 0x35, +0x94, 0x2D, 0xCE, 0x15, 0xD6, 0x56, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x56, 0xD6, 0x36, 0xD6, 0x36, +0xD6, 0x56, 0xDE, 0xB9, 0xF7, 0xBE, 0x94, 0xB2, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xA5, 0x34, 0xFF, 0xBE, 0xEF, 0x1A, +0xF7, 0x7D, 0xEF, 0x5D, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x28, +0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x49, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xDE, 0xDB, 0xEF, 0x7C, 0xD6, 0xB8, 0xEF, 0x3B, +0xF7, 0x9E, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0xFF, 0xBE, +0xDE, 0xD9, 0x8C, 0x6E, 0x84, 0xED, 0x95, 0x6E, +0x7C, 0xAC, 0x53, 0x88, 0x6C, 0x09, 0x9D, 0x6E, +0x5B, 0x28, 0x94, 0xCE, 0xA5, 0x2F, 0x94, 0xAE, +0x7B, 0xEC, 0x73, 0x6B, 0x73, 0x6B, 0x7B, 0xAC, +0xFF, 0xFF, 0xEF, 0x7D, 0xD6, 0x9A, 0xF7, 0x9E, +0xE7, 0x1C, 0xCE, 0x37, 0xE7, 0x3C, 0xF7, 0xBE, +0xD6, 0xBA, 0xEF, 0x7D, 0xF7, 0x9D, 0xE6, 0xFA, +0xF7, 0xBE, 0xEF, 0x7D, 0xDE, 0xDB, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0x1C, 0xBD, 0xF7, 0xAD, 0x55, +0xB5, 0xB6, 0xDE, 0xFB, 0xF7, 0xBE, 0xE7, 0x3C, +0xBD, 0xF6, 0xC5, 0xF4, 0xB5, 0x30, 0xAD, 0x10, +0xB5, 0x92, 0xDE, 0xFA, 0xF7, 0xBE, 0xDE, 0xDB, +0xDE, 0xDB, 0xF7, 0xBE, 0xDF, 0x1A, 0xA5, 0x91, +0x8D, 0x0C, 0xB5, 0xF3, 0xEF, 0x7C, 0xEF, 0x7D, +0xDE, 0xDB, 0xE7, 0x1B, 0xF7, 0xBE, 0xD6, 0x98, +0xBD, 0xD3, 0xA4, 0xEF, 0x83, 0xED, 0xA5, 0x32, +0xD6, 0xB9, 0xF7, 0xBE, 0xFF, 0xDF, 0xE7, 0x3C, +0xBD, 0xF7, 0xAD, 0x75, 0xB5, 0xB6, 0xD6, 0x9A, +0xF7, 0x9E, 0xF7, 0xBE, 0xE7, 0x3B, 0xBE, 0x36, +0xCE, 0xB8, 0xEF, 0x9C, 0xFF, 0xDF, 0xDE, 0xFB, +0xEF, 0x7D, 0xFF, 0xFF, 0xF7, 0xBE, 0xC6, 0x38, +0xAD, 0x75, 0xAD, 0x75, 0xCE, 0x59, 0xF7, 0xBE, +0xF7, 0xBE, 0xD6, 0xDA, 0xA5, 0x92, 0x7C, 0xAC, +0x7C, 0xAB, 0xAE, 0x14, 0xEF, 0x9C, 0xF7, 0xBE, +0xF7, 0xBE, 0xCE, 0x79, 0xB5, 0x96, 0xAD, 0x55, +0xAD, 0x75, 0xBE, 0x17, 0xEF, 0x5D, 0xF7, 0xBE, +0xE7, 0x3B, 0xCE, 0xD7, 0xAE, 0x31, 0x74, 0x8B, +0xA5, 0x92, 0xD6, 0xD9, 0xEF, 0x5D, 0xF7, 0xBE, +0xDE, 0xDB, 0xBD, 0xD7, 0xAD, 0x55, 0xB5, 0xB6, +0xCE, 0x79, 0xF7, 0xBE, 0xEF, 0x9D, 0xDE, 0xFA, +0xA5, 0x73, 0x7C, 0x6D, 0x9D, 0xD0, 0xCF, 0x36, +0xE7, 0x7A, 0xEF, 0x9D, 0xFF, 0xFF, 0xE7, 0x1C, +0xBD, 0xD7, 0xAD, 0x55, 0xB5, 0xB6, 0xCE, 0x59, +0xF7, 0x9E, 0xFF, 0xFE, 0xEF, 0x7C, 0xCE, 0xB6, +0xAD, 0x92, 0xD6, 0xBA, 0xF7, 0xBE, 0xDE, 0xDB, +0xEF, 0x5D, 0xEF, 0x5D, 0x9C, 0xF3, 0x6B, 0x8E, +0x8C, 0x72, 0xBD, 0xF7, 0xEF, 0x5D, 0xF7, 0x9E, +0xDE, 0xDB, 0xDE, 0xFB, 0xFF, 0xFF, 0xFF, 0xDF, +0xF7, 0xBE, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xBE, +0xC6, 0x38, 0xB5, 0x96, 0xAD, 0x75, 0xC6, 0x38, +0xE7, 0x3C, 0xF7, 0x9E, 0xE7, 0x1C, 0xC6, 0x18, +0xD6, 0x9A, 0xB5, 0xB6, 0x8C, 0x72, 0x6B, 0x4D, +0x9C, 0xD3, 0xDE, 0xDB, 0xF7, 0x9E, 0xE7, 0x3C, +0xBD, 0xF7, 0xAD, 0x55, 0xAD, 0x55, 0xEF, 0x5D, +0xE7, 0x1C, 0xBD, 0xF7, 0xDE, 0xDB, 0xF7, 0x9E, +0xF7, 0x9E, 0xC6, 0x38, 0xB5, 0x96, 0xAD, 0x55, +0xB5, 0x96, 0xC6, 0x38, 0xEF, 0x7D, 0xFF, 0xDF, +0xEF, 0x5D, 0xCE, 0x58, 0xD6, 0x79, 0xE7, 0x3C, +0xFF, 0xDF, 0xD6, 0xBA, 0xD6, 0xBA, 0xFF, 0xBE, +0xE7, 0x3C, 0xC5, 0xF6, 0xCE, 0x38, 0xE7, 0x3C, +0xF7, 0x9E, 0xFF, 0xDF, 0xDE, 0xDB, 0xBD, 0xD7, +0xAD, 0x55, 0xB5, 0xB6, 0xCE, 0x79, 0xF7, 0xDE, +0xF7, 0xDE, 0xE7, 0x5B, 0xDE, 0xB7, 0xDE, 0xD7, +0xEF, 0x5C, 0xFF, 0xDE, 0xDE, 0xFB, 0xEF, 0x7D, +0xEF, 0x9C, 0xD6, 0xD5, 0xD6, 0xD4, 0xAD, 0x90, +0xD6, 0x97, 0xF7, 0xBE, 0x6B, 0x4D, 0x10, 0xA2, +0xFF, 0xDF, 0xFF, 0xDE, 0xF7, 0x9D, 0xEF, 0x7D, +0xEF, 0x5C, 0xEF, 0x7D, 0xF7, 0x9E, 0xF7, 0xBE, +0xFF, 0xDF, 0xFF, 0xDF, 0x21, 0x04, 0x4A, 0x49, +0xF7, 0xBE, 0xB5, 0xD6, 0x32, 0x44, 0x2A, 0x44, +0x2A, 0x24, 0x2A, 0x24, 0x11, 0x81, 0x19, 0xA2, +0x21, 0xE3, 0x19, 0xA2, 0x19, 0x82, 0x32, 0x85, +0x43, 0x06, 0x3A, 0xC5, 0x2A, 0x64, 0x21, 0xE3, +0x3A, 0xE6, 0x53, 0xC9, 0x74, 0x8D, 0x8D, 0x30, +0x3A, 0xA6, 0x22, 0x03, 0x22, 0x02, 0x19, 0xE2, +0x94, 0x90, 0xB5, 0x52, 0xBD, 0xB3, 0xC5, 0xB2, +0xC5, 0xB3, 0xCE, 0x14, 0xD6, 0x35, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x55, 0xCE, 0x15, 0xCE, 0x15, +0x94, 0x2D, 0xD6, 0x15, 0xDE, 0x56, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x56, 0xD6, 0x36, 0xD6, 0x56, +0xD6, 0x56, 0xDE, 0xB9, 0xFF, 0xBE, 0x73, 0xAE, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x8C, 0x51, 0xFF, 0xDE, 0xEF, 0x1A, +0xF7, 0x9D, 0xD6, 0xBA, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, +0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0xC7, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCE, 0x59, 0xF7, 0xBD, 0xE7, 0x3A, 0xEF, 0x7C, +0xEF, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0xE3, 0xFF, 0xDE, +0xDE, 0xB9, 0xA5, 0x30, 0x95, 0x4F, 0x8D, 0x2F, +0x4B, 0x27, 0x53, 0x68, 0x8C, 0xED, 0xA5, 0xAF, +0x7C, 0x2B, 0x94, 0xCE, 0xC6, 0x74, 0xB5, 0x92, +0x9C, 0xD0, 0xA4, 0xD1, 0xA4, 0xD0, 0x9C, 0xAF, +0xEF, 0x3C, 0xEF, 0x5C, 0xEF, 0x5C, 0xEF, 0x3C, +0xDE, 0xB9, 0xC5, 0xD5, 0xD6, 0x99, 0xEF, 0x3C, +0xEF, 0x5C, 0xEF, 0x3C, 0xE7, 0x1B, 0xDE, 0xD9, +0xDE, 0xFA, 0xE7, 0x1C, 0xF7, 0x7D, 0xEF, 0x5C, +0xF7, 0x7C, 0xF7, 0x9D, 0xF7, 0x9D, 0xF7, 0x9D, +0xF7, 0x9D, 0xDE, 0xFB, 0xC6, 0x58, 0x9D, 0x32, +0x74, 0x0D, 0xCE, 0x75, 0xCE, 0x14, 0xBD, 0xD3, +0x9C, 0xEF, 0xBD, 0xD5, 0xDF, 0x1A, 0xEF, 0x5C, +0xEF, 0x5C, 0xE7, 0x3B, 0xCE, 0x98, 0xAD, 0x71, +0x8C, 0xAD, 0x8C, 0x6F, 0xCE, 0x58, 0xE7, 0x3C, +0xEF, 0x3C, 0xE7, 0x1C, 0xDE, 0xDA, 0xBD, 0xB4, +0x9C, 0x8F, 0xAD, 0x11, 0xD6, 0x77, 0xA5, 0x32, +0xC6, 0x57, 0xF7, 0xBD, 0xE7, 0x3C, 0xE7, 0x1C, +0xE7, 0x3C, 0xEF, 0x5C, 0xE7, 0x5C, 0xEF, 0x9C, +0xE7, 0x3B, 0xC6, 0x98, 0xBE, 0x56, 0xD7, 0x38, +0xD6, 0xF9, 0xE7, 0x5B, 0xEF, 0x9D, 0xEF, 0x9D, +0xEF, 0x7C, 0xEF, 0x5C, 0xEF, 0x9D, 0xEF, 0x5C, +0xEF, 0x9D, 0xEF, 0x7D, 0xF7, 0xBD, 0xE7, 0x3A, +0xBE, 0x56, 0x8D, 0x0F, 0x5B, 0xC8, 0x4B, 0x85, +0x5B, 0xE7, 0x7C, 0xCB, 0x8C, 0xD0, 0xB5, 0xB5, +0xD6, 0xFA, 0xE7, 0x5C, 0xE7, 0x5C, 0xEF, 0x7D, +0xEF, 0x9D, 0xE7, 0x5C, 0xDE, 0xFA, 0xC6, 0x77, +0xA5, 0xB3, 0x6C, 0x0B, 0x5B, 0xA7, 0x53, 0xA6, +0x74, 0x4A, 0x84, 0xAF, 0xA5, 0x54, 0xCE, 0x79, +0xE7, 0x7C, 0xE7, 0x5C, 0xE7, 0x5C, 0xE7, 0x5C, +0xDF, 0x1B, 0xD6, 0xB9, 0xBE, 0x35, 0x84, 0x8F, +0x52, 0xE9, 0x3A, 0x86, 0x42, 0xE5, 0x95, 0xCE, +0xA6, 0x11, 0xAD, 0xF4, 0xCE, 0xD8, 0xE7, 0x3B, +0xEF, 0x7C, 0xEF, 0x7D, 0xEF, 0x7C, 0xEF, 0x7C, +0xEF, 0x9C, 0xD6, 0xF8, 0xBE, 0x93, 0xAE, 0x0E, +0xAD, 0xEF, 0xCE, 0x97, 0xDE, 0xDB, 0xEF, 0x5C, +0xEF, 0x7C, 0xDE, 0xFA, 0x8C, 0x71, 0x63, 0x0C, +0x5B, 0x0C, 0x84, 0x10, 0xBD, 0xD7, 0xE7, 0x1C, +0xEF, 0x5D, 0xEF, 0x5D, 0xE7, 0x1C, 0xE7, 0x3C, +0xE7, 0x3C, 0xE7, 0x1C, 0xE7, 0x1C, 0xF7, 0xBE, +0xFF, 0xDF, 0xF7, 0x9E, 0xEF, 0x7D, 0xE7, 0x3C, +0xDE, 0xDB, 0xBD, 0xF7, 0x9C, 0xD3, 0xC6, 0x39, +0xBD, 0xF8, 0xAD, 0x55, 0x6B, 0x6E, 0x4A, 0x6A, +0x5A, 0xCB, 0x8C, 0x71, 0xBD, 0xF7, 0xDE, 0xDB, +0xE7, 0x3C, 0xE7, 0x3C, 0xE7, 0x3C, 0xDE, 0xDB, +0xBD, 0xD7, 0x7B, 0xEF, 0x8C, 0x51, 0xB5, 0xB6, +0xD6, 0x9A, 0xE7, 0x1C, 0xEF, 0x5D, 0xEF, 0x7D, +0xEF, 0x5D, 0xE7, 0x3C, 0xDE, 0xFB, 0xD6, 0x9A, +0xC6, 0x18, 0xAD, 0x55, 0xCE, 0x59, 0xE7, 0x3D, +0xF7, 0x9E, 0xF7, 0x9E, 0xF7, 0xBE, 0xF7, 0x9E, +0xE7, 0x5D, 0xD6, 0xBB, 0xD6, 0xDB, 0xDE, 0xFC, +0xE7, 0x1C, 0xEF, 0x5D, 0xEF, 0x7D, 0xF7, 0x9E, +0xF7, 0x9D, 0xEF, 0x7C, 0xE7, 0x5C, 0xDF, 0x3A, +0xD6, 0xD8, 0xC6, 0x35, 0xA5, 0x10, 0xBD, 0xD2, +0xF7, 0x9A, 0xEF, 0x7B, 0xE7, 0x5B, 0xEF, 0x7B, +0xDF, 0x19, 0xE7, 0x55, 0xA5, 0x6E, 0xAD, 0xB1, +0xCE, 0x37, 0xF7, 0x7D, 0xC6, 0x38, 0x00, 0x20, +0x39, 0xE7, 0x9C, 0xD3, 0xCE, 0x79, 0xDE, 0xDB, +0xEF, 0x5D, 0xEF, 0x5D, 0xDE, 0xFB, 0xCE, 0x79, +0x9C, 0xD3, 0x39, 0xE7, 0x00, 0x00, 0xAD, 0x75, +0xEF, 0x5C, 0x9D, 0x13, 0x32, 0x85, 0x32, 0x65, +0x32, 0x85, 0x19, 0xA3, 0x11, 0x41, 0x19, 0xC3, +0x2A, 0x24, 0x21, 0xC3, 0x19, 0xA2, 0x32, 0x85, +0x4B, 0x07, 0x3A, 0xC5, 0x2A, 0x64, 0x21, 0xE2, +0x32, 0x84, 0x4B, 0xA8, 0x7C, 0xEE, 0x8D, 0x50, +0x32, 0x85, 0x2A, 0x23, 0x22, 0x23, 0x21, 0xE2, +0x6B, 0x2A, 0x83, 0xAC, 0x94, 0x4D, 0x9C, 0x8E, +0xAD, 0x10, 0xBD, 0x72, 0xC5, 0xD4, 0xCD, 0xF4, +0xD6, 0x55, 0xDE, 0x76, 0xDE, 0x97, 0xCD, 0xF4, +0x9C, 0x4D, 0xCD, 0xD3, 0xDE, 0x76, 0xE6, 0x97, +0xE6, 0xB7, 0xE6, 0xB7, 0xDE, 0x76, 0xDE, 0x76, +0xDE, 0x56, 0xEE, 0xF9, 0xF7, 0xBE, 0xAD, 0x75, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xC6, 0x18, 0xFF, 0xBE, 0xDE, 0xB9, +0xF7, 0x7C, 0xFF, 0xDE, 0x18, 0xC3, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x6D, +0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x10, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xE3, +0xF7, 0xBE, 0xF7, 0x9D, 0xEF, 0x3A, 0xF7, 0x7C, +0xFF, 0xDE, 0x39, 0xE7, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6B, 0x6D, 0xF7, 0xBE, +0xDE, 0xD8, 0xAD, 0xB1, 0x8C, 0xED, 0x53, 0x68, +0x53, 0x69, 0x6C, 0x2B, 0x84, 0xAC, 0xA5, 0xB0, +0xB5, 0xF2, 0x84, 0x6D, 0xC6, 0x54, 0xAD, 0x51, +0xA4, 0xF0, 0x9C, 0x90, 0xAD, 0x11, 0xAD, 0x11, +0xBD, 0xD5, 0xC5, 0xD5, 0xBD, 0xB4, 0xC5, 0xB4, +0xC5, 0xB4, 0xB5, 0x73, 0xAD, 0x12, 0xBD, 0x73, +0xB5, 0x53, 0x9C, 0x90, 0xBD, 0xB4, 0xA4, 0xF2, +0x84, 0x0F, 0xC6, 0x16, 0xD6, 0x77, 0xD6, 0x36, +0xD6, 0x36, 0xD6, 0x56, 0xCE, 0x15, 0xD6, 0x56, +0xCE, 0x56, 0x7C, 0x2E, 0x74, 0x0C, 0x5B, 0x88, +0x53, 0x26, 0xB5, 0xB2, 0xC6, 0x14, 0xC5, 0xD3, +0xBD, 0xB3, 0xB5, 0x52, 0xBD, 0xB3, 0xBD, 0xB3, +0xB5, 0x72, 0x9C, 0xB1, 0x73, 0x8D, 0x5A, 0xEA, +0x52, 0xA9, 0x73, 0x8C, 0xB5, 0x74, 0xBD, 0xD5, +0xB5, 0x74, 0xAD, 0x54, 0xA4, 0xF2, 0x9C, 0xD1, +0x7B, 0xCD, 0xC6, 0x57, 0xD6, 0xB7, 0xDE, 0xF9, +0xA5, 0x33, 0xE7, 0x3A, 0xDE, 0xF9, 0xA5, 0x32, +0x9D, 0x32, 0x94, 0xF1, 0x8C, 0xD0, 0xAE, 0x13, +0x9D, 0x91, 0x8C, 0xEE, 0xC6, 0xF4, 0xBE, 0x91, +0xAD, 0xF2, 0xC6, 0x97, 0xC6, 0x77, 0xAD, 0xB4, +0xA5, 0x73, 0xBE, 0x16, 0xD6, 0xF8, 0xB6, 0x34, +0xB6, 0x33, 0xBE, 0x75, 0xAD, 0xD2, 0x8C, 0xEE, +0x6C, 0x4A, 0x53, 0x86, 0x6C, 0x49, 0x85, 0x0B, +0x74, 0xA8, 0x5C, 0x06, 0x3A, 0xA6, 0x63, 0x8B, +0x9D, 0x90, 0x95, 0x50, 0x84, 0x2F, 0x95, 0x31, +0xA5, 0xD1, 0x95, 0x50, 0x84, 0xEE, 0x84, 0xED, +0x95, 0xAE, 0x85, 0x0C, 0x7C, 0xAA, 0x7C, 0xC9, +0x95, 0x8C, 0x6C, 0x28, 0x63, 0x8A, 0xA5, 0xB0, +0xA5, 0x90, 0x8C, 0xB0, 0x84, 0x2F, 0x7C, 0x2F, +0x84, 0x8F, 0x8D, 0x0E, 0x6C, 0x2B, 0x32, 0x45, +0x19, 0x42, 0x2A, 0x03, 0x4B, 0x66, 0x4B, 0xA5, +0x53, 0xC6, 0x5B, 0xE9, 0x7C, 0xCD, 0x9D, 0xB0, +0xBE, 0x93, 0xB6, 0x12, 0xA5, 0xB0, 0x9D, 0x90, +0x9D, 0x8F, 0x8D, 0x0C, 0x8D, 0x4A, 0x8D, 0x49, +0x85, 0x29, 0x95, 0x4D, 0xBE, 0x52, 0xCE, 0xD4, +0xB5, 0xF3, 0xA5, 0x52, 0x84, 0x6D, 0x63, 0x69, +0x63, 0x8A, 0x73, 0xEC, 0x8C, 0xB0, 0xB5, 0xB5, +0xBD, 0xD7, 0xAD, 0x55, 0x94, 0x92, 0xA5, 0x14, +0xBD, 0xF7, 0xCE, 0x59, 0xCE, 0x59, 0xCE, 0x59, +0xCE, 0x7A, 0xDE, 0xDA, 0xCE, 0x99, 0xAD, 0xD5, +0xB6, 0x15, 0xA5, 0x73, 0xA5, 0x34, 0xC6, 0x38, +0x9C, 0xD3, 0x8C, 0x52, 0x52, 0xAB, 0x42, 0x08, +0x31, 0x86, 0x42, 0x28, 0x63, 0x2C, 0x7B, 0xEF, +0x84, 0x30, 0x84, 0x10, 0x84, 0x30, 0x84, 0x0F, +0x63, 0x0C, 0x4A, 0x49, 0x4A, 0x29, 0x63, 0x0C, +0x73, 0x8E, 0x83, 0xEF, 0x8C, 0x50, 0x9C, 0xD2, +0x9C, 0xD3, 0xBD, 0xB6, 0xA5, 0x14, 0x8C, 0x31, +0x9C, 0xF4, 0xA5, 0x14, 0x8C, 0x72, 0xA5, 0x56, +0xB5, 0xD8, 0xAD, 0xB8, 0xB5, 0xD8, 0xB5, 0xF9, +0xB5, 0xF9, 0xA5, 0x98, 0xA5, 0xB8, 0xAD, 0xB8, +0xAD, 0x98, 0xBE, 0x19, 0xC6, 0x9B, 0xCE, 0x9B, +0xCE, 0xBA, 0xB6, 0x35, 0xA5, 0xD1, 0xAD, 0xD1, +0x9D, 0x6F, 0xB5, 0xD0, 0xCE, 0x72, 0xD6, 0xD2, +0xEF, 0x94, 0xCE, 0xB1, 0xA5, 0xAF, 0xA5, 0xCF, +0xAD, 0xEF, 0xEF, 0x93, 0xBE, 0x11, 0xDF, 0x39, +0xD6, 0xDA, 0xEF, 0x7D, 0xFF, 0xDF, 0xBD, 0xF7, +0x39, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x29, 0x45, 0xAD, 0x55, 0xF7, 0xDE, +0xCE, 0x79, 0x7C, 0x2E, 0x2A, 0x44, 0x32, 0x85, +0x32, 0x65, 0x11, 0x62, 0x19, 0xA3, 0x19, 0xA3, +0x21, 0xC3, 0x19, 0xA3, 0x11, 0x42, 0x09, 0x21, +0x32, 0x44, 0x3A, 0xE5, 0x2A, 0x64, 0x21, 0xE2, +0x2A, 0x43, 0x53, 0xA8, 0x85, 0x2F, 0x74, 0xAD, +0x42, 0xE6, 0x22, 0x23, 0x2A, 0x64, 0x21, 0xE2, +0x7B, 0xAC, 0x7B, 0x6B, 0x73, 0x49, 0x8B, 0xEC, +0x9C, 0x4D, 0x9C, 0x4D, 0x94, 0x2C, 0x9C, 0x6D, +0x9C, 0x6E, 0xA4, 0xAE, 0xA4, 0xCF, 0xA4, 0xAE, +0xA4, 0x8E, 0xAC, 0xCF, 0xA4, 0xAF, 0x9C, 0x6E, +0xA4, 0x8E, 0xAC, 0xD0, 0xBD, 0x31, 0xC5, 0x92, +0xBD, 0x71, 0xBD, 0x72, 0xDE, 0xDA, 0xFF, 0xBE, +0x63, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x73, 0xAE, 0xFF, 0xDE, 0xF7, 0x5C, 0xE6, 0xD8, +0xF7, 0x3B, 0xFF, 0xDE, 0xBD, 0xF7, 0x10, 0xA2, +0x00, 0x00, 0x00, 0x00, 0x39, 0xE7, 0xEF, 0x7D, +0xFF, 0xBE, 0xFF, 0xDE, 0xF7, 0xBE, 0x5A, 0xCB, +0x00, 0x00, 0x00, 0x00, 0x18, 0xE3, 0xC6, 0x38, +0xFF, 0xBE, 0xEF, 0x3A, 0xE7, 0x19, 0xEF, 0x3A, +0xFF, 0xBE, 0xDE, 0xFB, 0x39, 0xC7, 0x00, 0x00, +0x00, 0x00, 0x52, 0xAA, 0xEF, 0x7D, 0xE7, 0x3B, +0xB5, 0x93, 0x5B, 0x08, 0x63, 0x89, 0x63, 0xCA, +0x5B, 0xAA, 0x95, 0x2F, 0x9D, 0x4F, 0xBE, 0x53, +0xC6, 0x74, 0x7C, 0x2B, 0xBE, 0x33, 0xB5, 0xB2, +0x9C, 0xB0, 0x94, 0x6F, 0xA4, 0xF1, 0xAD, 0x11, +0xAD, 0x31, 0xB5, 0x50, 0xB5, 0x90, 0xB5, 0x90, +0xB5, 0x50, 0xAD, 0x31, 0x73, 0x6B, 0xA4, 0xCF, +0xA4, 0xD0, 0xAD, 0x12, 0x7B, 0x8C, 0x6B, 0x4B, +0xB5, 0x52, 0xAD, 0x31, 0xBD, 0x92, 0xBD, 0x72, +0xC5, 0xB3, 0xC5, 0xB3, 0xA4, 0xD0, 0xBD, 0xB3, +0xBD, 0xD3, 0x42, 0xC4, 0x3A, 0xE4, 0x43, 0x03, +0x3A, 0xE4, 0x73, 0xEB, 0xC6, 0x14, 0xC5, 0xD3, +0xB5, 0x71, 0x94, 0x4D, 0xB5, 0x71, 0xA4, 0xCF, +0xA4, 0xAF, 0xA4, 0xF1, 0x84, 0x0E, 0x84, 0x0E, +0x94, 0x90, 0xA4, 0xF2, 0xB5, 0x74, 0xA5, 0x12, +0x94, 0x90, 0x9C, 0xD1, 0x94, 0xB0, 0x94, 0xB0, +0xBD, 0xF5, 0xDE, 0xD9, 0xBE, 0x15, 0xAD, 0xB3, +0x9D, 0x51, 0xA5, 0xB2, 0xA5, 0xB2, 0x94, 0xEF, +0x63, 0x8A, 0x74, 0x4C, 0x9D, 0x8F, 0x9D, 0xAE, +0x7C, 0x8A, 0x85, 0x0B, 0xB6, 0x8F, 0xBE, 0x8E, +0x63, 0xC9, 0xC6, 0x97, 0xD7, 0x1A, 0x84, 0x6F, +0x9D, 0x32, 0xAD, 0xD3, 0xA5, 0x90, 0xA5, 0xF0, +0x8D, 0x4D, 0x74, 0x69, 0x5B, 0xC5, 0x53, 0xC3, +0x53, 0x85, 0x95, 0x2E, 0xA5, 0x8F, 0x84, 0xCB, +0x5B, 0xE5, 0x53, 0xE5, 0x64, 0x47, 0x7C, 0xC9, +0x74, 0xA9, 0x5B, 0xC7, 0x4B, 0x26, 0x74, 0xAA, +0x9E, 0x0D, 0x8D, 0x6A, 0x7D, 0x09, 0x64, 0x47, +0x7C, 0xEA, 0x9D, 0xAE, 0xA6, 0x0F, 0x6C, 0x88, +0x4B, 0x45, 0x42, 0xE4, 0x3A, 0x84, 0x53, 0x46, +0x53, 0x66, 0x53, 0x47, 0x29, 0xC4, 0x19, 0x23, +0x29, 0xC4, 0x4B, 0x47, 0x4B, 0x26, 0x42, 0xE5, +0x2A, 0x24, 0x2A, 0x03, 0x43, 0x05, 0x4B, 0x65, +0x5B, 0xE7, 0x7C, 0xCB, 0x8D, 0x6D, 0x5B, 0xE7, +0x7C, 0xC9, 0x95, 0x8B, 0x74, 0xA7, 0x6C, 0x86, +0x6C, 0x66, 0xA5, 0xEE, 0xBE, 0xD2, 0x8D, 0x6A, +0x6C, 0x86, 0x7C, 0xA7, 0xC6, 0xD1, 0xC6, 0xF2, +0xBE, 0xD3, 0xBE, 0x93, 0xAE, 0x30, 0x6C, 0x26, +0x7C, 0xC8, 0x7C, 0xE8, 0x7C, 0xA9, 0x8C, 0xEE, +0x8C, 0x70, 0x73, 0xAE, 0x8C, 0x71, 0x9C, 0xD3, +0xCE, 0x7A, 0xAD, 0x76, 0x9C, 0xB3, 0xA4, 0xD3, +0x9C, 0xD4, 0x94, 0xB3, 0xAD, 0x75, 0x9D, 0x12, +0xAD, 0xF4, 0xB6, 0x35, 0xC6, 0x58, 0xBD, 0xF7, +0x9C, 0xD3, 0x6B, 0x4D, 0x42, 0x29, 0x31, 0x86, +0x29, 0x65, 0x29, 0x45, 0x31, 0x86, 0x39, 0xC7, +0x42, 0x28, 0x42, 0x08, 0x21, 0x04, 0x31, 0x86, +0x29, 0x45, 0x4A, 0x28, 0x5A, 0xCB, 0x39, 0xA6, +0x39, 0xC7, 0x5A, 0xCB, 0x41, 0xE7, 0x4A, 0x29, +0x42, 0x08, 0x62, 0xEB, 0x6B, 0x4D, 0x7B, 0xD0, +0x8C, 0x72, 0x9C, 0xD4, 0xA5, 0x14, 0xAD, 0x76, +0xA5, 0x35, 0x73, 0xF1, 0x8C, 0xD4, 0xB5, 0xD8, +0x7C, 0x32, 0x74, 0x32, 0x7C, 0x73, 0x84, 0xB5, +0x8C, 0xD5, 0x84, 0xB5, 0x84, 0xB5, 0x84, 0xB5, +0x84, 0x93, 0x8D, 0x11, 0x8D, 0x4C, 0x8D, 0x4B, +0x8C, 0xEB, 0xC6, 0xB1, 0xCE, 0xAF, 0xD7, 0x0F, +0xB5, 0xE9, 0xB6, 0x29, 0x95, 0x65, 0x85, 0x04, +0x95, 0x66, 0xA5, 0x8B, 0x95, 0x2F, 0x8C, 0xF2, +0x9D, 0x35, 0xB5, 0xF9, 0xDE, 0xFC, 0xF7, 0xBF, +0xFF, 0xDF, 0xEF, 0x7D, 0xCE, 0x79, 0xBD, 0xF7, +0xB5, 0x96, 0xAD, 0x55, 0xBD, 0xD7, 0xC6, 0x38, +0xE7, 0x3C, 0xF7, 0xBE, 0xF7, 0xBD, 0xDF, 0x3A, +0x94, 0xF1, 0x4B, 0x08, 0x32, 0x85, 0x4B, 0x07, +0x32, 0x45, 0x21, 0xE4, 0x2A, 0x25, 0x11, 0x42, +0x19, 0x62, 0x19, 0xA3, 0x21, 0xA4, 0x11, 0x01, +0x32, 0x45, 0x4B, 0x47, 0x2A, 0x43, 0x22, 0x03, +0x22, 0x43, 0x53, 0xA9, 0x74, 0xCD, 0x7C, 0xED, +0x3A, 0xC6, 0x09, 0x20, 0x2A, 0x44, 0x21, 0xE3, +0x83, 0xED, 0x8B, 0xED, 0x7B, 0x4A, 0x8B, 0xEB, +0xA4, 0xAE, 0xA4, 0xAE, 0xA4, 0xAE, 0xA4, 0xAF, +0xA4, 0x8E, 0xB5, 0x10, 0xB5, 0x10, 0xAD, 0x10, +0xB5, 0x10, 0xB5, 0x10, 0xBD, 0x51, 0xBD, 0x51, +0xBD, 0x72, 0xC5, 0xB2, 0xBD, 0x51, 0xB5, 0x10, +0xB5, 0x10, 0xBD, 0x72, 0xCE, 0x36, 0xEF, 0x5C, +0xFF, 0xBE, 0xCE, 0x79, 0xA5, 0x34, 0xD6, 0x9A, +0xF7, 0xBE, 0xE7, 0x1B, 0xC5, 0xB4, 0xA4, 0xAF, +0xB5, 0x32, 0xD6, 0x99, 0xF7, 0x7D, 0xEF, 0x7D, +0xBD, 0xD7, 0xCE, 0x59, 0xFF, 0xBE, 0xF7, 0x7D, +0xE6, 0xD9, 0xE6, 0xD9, 0xF7, 0x7C, 0xFF, 0xDE, +0xE7, 0x1C, 0xD6, 0x99, 0xFF, 0xBE, 0xFF, 0xBE, +0xF7, 0x5B, 0xEF, 0x19, 0xEF, 0x19, 0xEE, 0xF9, +0xF7, 0x7C, 0xF7, 0x9D, 0xFF, 0xDF, 0xE7, 0x3C, +0xEF, 0x7D, 0xFF, 0xDE, 0xEF, 0x7C, 0xD6, 0x57, +0xA4, 0xCF, 0x73, 0x89, 0x74, 0x0B, 0x63, 0xCA, +0x63, 0xCA, 0x9D, 0x91, 0x74, 0x0B, 0x8C, 0xED, +0xAE, 0x11, 0x73, 0xEB, 0x8C, 0x8E, 0xC6, 0x35, +0x7B, 0xCC, 0x8C, 0x2E, 0x9C, 0xD0, 0xB5, 0x92, +0xBE, 0x11, 0xBE, 0x50, 0xBE, 0x6F, 0xBE, 0x6F, +0xC6, 0x70, 0xC6, 0x53, 0x7B, 0x8A, 0xAD, 0x10, +0xAD, 0x11, 0x6B, 0x4B, 0x63, 0x2A, 0x9C, 0xB0, +0xB5, 0x72, 0xB5, 0x52, 0xAD, 0x31, 0xBD, 0x72, +0xBD, 0x72, 0xBD, 0x72, 0x83, 0xEC, 0xC5, 0xF4, +0xAD, 0x50, 0x4B, 0x05, 0x32, 0x82, 0x3A, 0xA2, +0x3A, 0xA3, 0x53, 0x68, 0x7C, 0x6C, 0x84, 0x6D, +0xA5, 0x51, 0x8C, 0x4D, 0xAD, 0x10, 0x9C, 0x8E, +0x9C, 0x6D, 0xB5, 0x52, 0x94, 0x8F, 0x9C, 0xF1, +0xAD, 0x73, 0xAD, 0x73, 0xA5, 0x12, 0x94, 0x90, +0x6B, 0x4B, 0x6B, 0x6C, 0x83, 0xEE, 0xC5, 0xF6, +0xCE, 0x77, 0xA5, 0x32, 0x5B, 0x4A, 0x42, 0xE8, +0x42, 0xC7, 0x6B, 0xEB, 0x9D, 0x71, 0xA5, 0x91, +0xA5, 0x92, 0x7C, 0x6C, 0xBE, 0x72, 0xBE, 0xB2, +0x7C, 0xAA, 0x74, 0x88, 0x9D, 0xCC, 0xA5, 0xED, +0x5B, 0x89, 0xD6, 0xF9, 0x94, 0xF1, 0x9D, 0x51, +0xA5, 0xB1, 0xAE, 0x32, 0x84, 0xEB, 0x8D, 0x2C, +0x95, 0x6D, 0x53, 0xC5, 0x4B, 0xA3, 0x43, 0x43, +0x63, 0x87, 0x8C, 0x8D, 0x7C, 0x2A, 0x7C, 0xA9, +0x53, 0xC4, 0x64, 0x46, 0x64, 0x26, 0x85, 0x29, +0x6C, 0x88, 0x32, 0x63, 0x21, 0xE2, 0x4B, 0x66, +0x74, 0xCA, 0x74, 0xC9, 0x74, 0xC9, 0x95, 0xAD, +0x95, 0x8C, 0x95, 0xAC, 0x7D, 0x09, 0x4B, 0x84, +0x32, 0x63, 0x43, 0x05, 0x3A, 0x84, 0x3A, 0xC5, +0x43, 0x05, 0x4B, 0x27, 0x11, 0x21, 0x11, 0x02, +0x11, 0x01, 0x2A, 0x24, 0x42, 0xC6, 0xAE, 0x11, +0x84, 0xCC, 0x4A, 0xE7, 0x74, 0x4C, 0x8D, 0x2E, +0x8D, 0x4D, 0x7C, 0xCB, 0x5B, 0xE7, 0x64, 0x49, +0x64, 0x48, 0x4B, 0xC4, 0x74, 0xE9, 0x9E, 0x0E, +0xAE, 0x71, 0xAE, 0x50, 0x9D, 0xCE, 0x7D, 0x0A, +0x6C, 0x88, 0x95, 0x4A, 0xBE, 0x8F, 0xA5, 0xEF, +0xC7, 0x14, 0xBE, 0xF4, 0xB6, 0x71, 0x53, 0xC5, +0x54, 0x03, 0x64, 0x63, 0x7C, 0xC7, 0xB6, 0x30, +0x84, 0x6D, 0x63, 0x0C, 0x9C, 0xD3, 0x9C, 0xF4, +0xBD, 0xF8, 0x8C, 0x31, 0x7B, 0x8E, 0x8B, 0xCF, +0xA4, 0xB3, 0xB5, 0x55, 0x8C, 0x51, 0x8C, 0x30, +0xAD, 0x94, 0xA5, 0x54, 0xA5, 0x34, 0x9C, 0xF4, +0x8C, 0x92, 0x52, 0xCB, 0x39, 0xC7, 0x31, 0x65, +0x21, 0x44, 0x29, 0x44, 0x31, 0x85, 0x31, 0x86, +0x52, 0x89, 0x5A, 0xCA, 0x29, 0x45, 0x21, 0x04, +0x31, 0x65, 0x52, 0x8A, 0x62, 0xEB, 0x5A, 0xAB, +0x39, 0xA6, 0x52, 0x8A, 0x6B, 0x2D, 0x41, 0xE8, +0x42, 0x08, 0x4A, 0x49, 0x5A, 0xCC, 0x7B, 0xAF, +0x94, 0x72, 0x94, 0x92, 0x94, 0x92, 0x8C, 0x71, +0x8C, 0x51, 0x94, 0xB3, 0xA5, 0x35, 0x94, 0xD4, +0x74, 0x12, 0x6B, 0xD1, 0x63, 0xB1, 0x63, 0xB1, +0x63, 0xB1, 0x63, 0xB0, 0x6B, 0xD1, 0x63, 0xB0, +0x63, 0x8F, 0x6B, 0xEE, 0x8D, 0x2D, 0x8D, 0x2B, +0x8D, 0x2A, 0xC6, 0xAF, 0xD6, 0xEE, 0xD7, 0x0E, +0xAD, 0xA7, 0xC6, 0xAA, 0xA5, 0xE7, 0x8D, 0x23, +0x8D, 0x25, 0x9D, 0x8B, 0x8C, 0xEF, 0x84, 0xB2, +0x8C, 0xD4, 0x8C, 0xF5, 0xAD, 0x97, 0xEF, 0x5C, +0xEF, 0x7C, 0xEF, 0x7D, 0xF7, 0xBE, 0xFF, 0xDF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, +0xEF, 0x7D, 0xDF, 0x1B, 0xD6, 0xF7, 0xB6, 0x31, +0x6C, 0x4A, 0x3A, 0xA6, 0x5B, 0xAA, 0x5B, 0xAA, +0x2A, 0x04, 0x2A, 0x04, 0x32, 0x66, 0x19, 0xA3, +0x21, 0xA3, 0x21, 0xE4, 0x19, 0x63, 0x2A, 0x05, +0x6C, 0x4C, 0x5C, 0x09, 0x22, 0x23, 0x22, 0x23, +0x22, 0x23, 0x3A, 0xE6, 0x4B, 0x27, 0x7C, 0xEE, +0x21, 0xC3, 0x19, 0xA3, 0x32, 0x85, 0x21, 0xE3, +0xB5, 0x73, 0x8C, 0x0D, 0x7B, 0x6A, 0x9C, 0x6E, +0xBD, 0x51, 0xB5, 0x30, 0xB5, 0x10, 0xA4, 0xAF, +0xAD, 0x10, 0xBD, 0x92, 0xC5, 0x93, 0xC5, 0x92, +0xCD, 0xF4, 0xBD, 0x72, 0xBD, 0x72, 0xBD, 0x92, +0xBD, 0x51, 0xC5, 0x92, 0xA4, 0x8E, 0x8C, 0x0C, +0x94, 0x2D, 0x9C, 0x4D, 0x9C, 0x8F, 0xC5, 0xD5, +0xE7, 0x1B, 0xF7, 0xBE, 0xFF, 0xFF, 0xFF, 0xDE, +0xF7, 0x7C, 0xE6, 0xB8, 0xD6, 0x14, 0xCD, 0xF3, +0xC5, 0x92, 0xD6, 0x56, 0xE6, 0xF9, 0xF7, 0x9D, +0xFF, 0xDF, 0xFF, 0xBE, 0xEF, 0x3C, 0xDE, 0x78, +0xB5, 0x31, 0xB5, 0x31, 0xC5, 0xF5, 0xE6, 0xFA, +0xF7, 0x9D, 0xF7, 0x9E, 0xE7, 0x3C, 0xCE, 0x37, +0xAD, 0x11, 0xA4, 0x8E, 0x9C, 0x8E, 0xA4, 0xAF, +0xBD, 0x72, 0xCE, 0x37, 0xE7, 0x1B, 0xF7, 0x9D, +0xF7, 0x7D, 0xE7, 0x1A, 0xCE, 0x36, 0xBD, 0x72, +0xA4, 0xAE, 0x8C, 0x2B, 0x63, 0x48, 0x4B, 0x07, +0x74, 0x6C, 0x84, 0xEE, 0x5B, 0x69, 0x84, 0xCC, +0x85, 0x0C, 0xB6, 0x32, 0x84, 0x4C, 0x7C, 0x0D, +0x6B, 0x2A, 0x8C, 0x2E, 0xA5, 0x10, 0xC6, 0x52, +0xBE, 0x0F, 0xB6, 0x0D, 0xB5, 0xCC, 0xB5, 0xCD, +0xB5, 0xEE, 0xAD, 0x6F, 0x7B, 0xCC, 0xB5, 0x52, +0x63, 0x0A, 0x52, 0x88, 0x63, 0x2A, 0x94, 0x8F, +0xB5, 0x92, 0xB5, 0x72, 0xAD, 0x10, 0xB5, 0x52, +0xBD, 0x72, 0xB5, 0x72, 0x7B, 0xCC, 0xCE, 0x15, +0x9C, 0xEF, 0x6C, 0x0A, 0x53, 0xA8, 0x43, 0x05, +0x32, 0x63, 0x3A, 0xC5, 0x74, 0x6C, 0x8D, 0x0F, +0xA5, 0x51, 0x94, 0xCF, 0xAD, 0x31, 0xA4, 0xAE, +0x94, 0x2D, 0xA4, 0xF1, 0xAD, 0x52, 0xB5, 0x53, +0xBD, 0x94, 0xB5, 0x74, 0xAD, 0x33, 0x7B, 0xED, +0x8C, 0x8F, 0x63, 0x6B, 0xA5, 0x53, 0xBD, 0xF5, +0xA5, 0x72, 0x7C, 0x8E, 0x63, 0xEC, 0x53, 0x48, +0x6B, 0xEA, 0x8C, 0xCE, 0xA5, 0x71, 0xAD, 0xD2, +0xA5, 0x90, 0x95, 0x0D, 0x84, 0xAB, 0xAD, 0xEF, +0x9D, 0x8D, 0x64, 0x07, 0x8D, 0x2B, 0x95, 0x2B, +0x7C, 0x8F, 0xCE, 0xD9, 0x84, 0x2F, 0x9D, 0x31, +0xB6, 0x53, 0xA5, 0xF1, 0x5B, 0xE7, 0x5B, 0xC6, +0x85, 0x0B, 0x4B, 0x63, 0x43, 0x03, 0x4A, 0xE6, +0x84, 0x2D, 0x94, 0x6D, 0x9D, 0x0E, 0x74, 0x48, +0x5B, 0xE5, 0x4B, 0x83, 0x7D, 0x09, 0x8D, 0x6A, +0x6C, 0x88, 0x11, 0x60, 0x21, 0xA3, 0x2A, 0x44, +0x3A, 0xC5, 0x2A, 0x23, 0x19, 0xA1, 0x6C, 0x49, +0xAE, 0x4F, 0x85, 0x29, 0x5C, 0x03, 0x74, 0x88, +0x95, 0x4C, 0x63, 0xC8, 0x74, 0x4A, 0x53, 0x67, +0x74, 0x6B, 0x53, 0x47, 0x21, 0x62, 0x19, 0x22, +0x11, 0x01, 0x53, 0x08, 0xA5, 0xAF, 0xBE, 0x91, +0x84, 0x8C, 0x7C, 0x2D, 0x95, 0x10, 0x74, 0x6C, +0x3A, 0x84, 0x22, 0x02, 0x74, 0x8B, 0x85, 0x4D, +0x6C, 0x89, 0x64, 0x66, 0x85, 0x4B, 0xA6, 0x30, +0xAE, 0x51, 0x7D, 0x0B, 0x6C, 0xA9, 0x85, 0x4B, +0x9D, 0xAD, 0x9D, 0xAC, 0x95, 0x6A, 0x7C, 0x68, +0x9D, 0xAF, 0xC7, 0x15, 0xAE, 0x51, 0x7C, 0xCA, +0x6C, 0xC8, 0x75, 0x08, 0x8D, 0x8A, 0xB6, 0x4E, +0x9D, 0x4D, 0x63, 0x4B, 0x8C, 0x71, 0xA5, 0x35, +0xA5, 0x14, 0x62, 0xCB, 0x62, 0xAB, 0x8B, 0xEF, +0xBD, 0x54, 0xAD, 0x33, 0x5A, 0xA9, 0x9C, 0xD2, +0x9C, 0xB2, 0xCE, 0x79, 0xDE, 0xDB, 0xB5, 0x96, +0x73, 0xD0, 0x52, 0xAA, 0x5A, 0xA9, 0x84, 0x0C, +0x4A, 0x46, 0x29, 0x64, 0x39, 0xA6, 0x39, 0xC6, +0x63, 0x0B, 0x7B, 0xAE, 0x5A, 0x8A, 0x18, 0xC3, +0x31, 0x65, 0x42, 0x08, 0x5A, 0xAA, 0x73, 0x6D, +0x52, 0x49, 0x39, 0xA7, 0x5A, 0xCB, 0x5A, 0xCB, +0x41, 0xC7, 0x52, 0x6A, 0x62, 0xCC, 0x7B, 0xD0, +0x84, 0x10, 0x83, 0xEF, 0x83, 0xEF, 0x7B, 0xCF, +0x73, 0x6E, 0x9C, 0xD3, 0xBD, 0xD7, 0xBE, 0x19, +0xB6, 0x3A, 0xB6, 0x1A, 0xAD, 0xFA, 0xAD, 0xB9, +0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, 0xA5, 0x98, +0xA5, 0x97, 0xBE, 0x36, 0xC6, 0x73, 0x8C, 0xEB, +0xAD, 0xCC, 0xEF, 0xD2, 0xD6, 0xCE, 0xAD, 0xA8, +0xC6, 0x49, 0xD7, 0x0B, 0xC6, 0xA9, 0x95, 0x44, +0x95, 0x86, 0xBE, 0x8E, 0xA5, 0xB1, 0x95, 0x13, +0x95, 0x35, 0x95, 0x16, 0xB5, 0xB6, 0xEF, 0x79, +0xDE, 0xD6, 0x5A, 0xA9, 0x4A, 0x29, 0x4A, 0x09, +0x5A, 0xCB, 0x8C, 0x51, 0x7B, 0xEF, 0x52, 0xAA, +0x3A, 0x05, 0x9D, 0x6D, 0xB6, 0x4E, 0x8D, 0x6A, +0x64, 0x07, 0x42, 0xE7, 0x7C, 0xAE, 0x5B, 0xAB, +0x11, 0x62, 0x19, 0xA3, 0x32, 0x45, 0x19, 0xA3, +0x11, 0x62, 0x11, 0x22, 0x09, 0x01, 0x42, 0xE7, +0x64, 0x4A, 0x53, 0xC8, 0x2A, 0x43, 0x2A, 0x23, +0x19, 0xA2, 0x09, 0x21, 0x21, 0xA3, 0x42, 0xC8, +0x09, 0x21, 0x21, 0xC3, 0x2A, 0x24, 0x3A, 0x86, +0xBD, 0xB4, 0x8B, 0xCC, 0x83, 0x8A, 0x9C, 0x6E, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x4E, 0x9C, 0x8E, +0xBD, 0xB3, 0xC5, 0xB3, 0xBD, 0x72, 0xAD, 0x31, +0xB5, 0x52, 0xAD, 0x11, 0xA4, 0xD0, 0xAD, 0x11, +0xAD, 0x11, 0xD6, 0x14, 0xCD, 0xB3, 0xC5, 0x72, +0xCD, 0xD3, 0xCD, 0xF4, 0xC5, 0xB3, 0xD5, 0xF4, +0xD5, 0xF4, 0xA4, 0x6D, 0xB4, 0xEF, 0xDE, 0x54, +0xDE, 0x54, 0xC5, 0x92, 0xC5, 0xB2, 0xD6, 0x34, +0xD6, 0x34, 0xD6, 0x34, 0xD6, 0x14, 0xE6, 0x96, +0xCD, 0xF3, 0xC5, 0x91, 0xC5, 0xB2, 0xD6, 0x34, +0x9C, 0x6E, 0xB5, 0x0F, 0xC5, 0xB2, 0xDE, 0x35, +0xE6, 0x75, 0xDE, 0x34, 0xCD, 0xF3, 0xCD, 0xD3, +0xAC, 0xEF, 0xA4, 0xAD, 0xAD, 0x2F, 0xB5, 0x50, +0xB5, 0x2F, 0xC5, 0xF3, 0xE7, 0x38, 0xD6, 0xD7, +0xB6, 0x33, 0xB5, 0xB1, 0xAD, 0x2F, 0xB5, 0x30, +0xB5, 0x2F, 0x94, 0xAC, 0x6B, 0xE8, 0x42, 0xA6, +0x7C, 0x8D, 0x95, 0x2F, 0x9D, 0x2F, 0x95, 0x4E, +0x74, 0x89, 0x95, 0x4C, 0xB6, 0x31, 0xB5, 0xD2, +0xB5, 0xB3, 0xD6, 0xB6, 0xCE, 0x92, 0xCE, 0x92, +0x94, 0xCB, 0x94, 0xAB, 0x94, 0x6B, 0x94, 0x2A, +0x94, 0x4B, 0x83, 0xEC, 0xA4, 0xD1, 0x6B, 0x4B, +0x6B, 0x0A, 0x83, 0xCC, 0x83, 0xED, 0x9C, 0xAF, +0xAD, 0x10, 0xA4, 0xD0, 0x8C, 0x2D, 0xA4, 0xD0, +0x9C, 0xD0, 0x94, 0x8F, 0x8C, 0x2E, 0xC6, 0x15, +0xBD, 0xD3, 0x8C, 0xED, 0x74, 0x6B, 0x74, 0x6B, +0x6C, 0x2A, 0x74, 0x4B, 0xA5, 0xD1, 0xAD, 0xF2, +0xA5, 0xB2, 0x95, 0x0F, 0xAD, 0x31, 0xAC, 0xF0, +0x8C, 0x2D, 0x9C, 0xAF, 0xAD, 0x32, 0xA4, 0xF1, +0xBD, 0xB4, 0xB5, 0x94, 0xAD, 0x73, 0x84, 0x4E, +0xCE, 0xB6, 0xB6, 0x13, 0x73, 0xCC, 0x42, 0x87, +0x42, 0xC6, 0x43, 0x07, 0x53, 0x48, 0x74, 0x2C, +0xDF, 0x16, 0xE7, 0x36, 0xC6, 0x74, 0x9D, 0x0F, +0x95, 0x0E, 0xA5, 0x6F, 0x63, 0x48, 0x7B, 0xEA, +0x7C, 0x6B, 0x95, 0x30, 0x95, 0x2E, 0x95, 0x4E, +0x84, 0x8F, 0xB5, 0xD6, 0x84, 0x50, 0x94, 0xD0, +0xC6, 0xB6, 0x7C, 0x8D, 0x6C, 0x08, 0x95, 0x6D, +0x53, 0xA6, 0x5B, 0xA7, 0x4A, 0xE6, 0xAD, 0x92, +0xB5, 0xB3, 0x84, 0x2D, 0x84, 0xAB, 0x53, 0x85, +0x3A, 0xE2, 0x5B, 0xE6, 0xA6, 0x0E, 0x95, 0xAB, +0x64, 0x27, 0x11, 0x41, 0x2A, 0x25, 0x19, 0x82, +0x42, 0xE6, 0x3A, 0xA5, 0x4B, 0x06, 0x19, 0x81, +0x64, 0x48, 0x6C, 0x86, 0x6C, 0x86, 0x9D, 0xCD, +0xA5, 0xEF, 0x4A, 0xE5, 0x5B, 0x68, 0x63, 0x88, +0x53, 0x27, 0x42, 0x44, 0x4A, 0x46, 0x5B, 0x08, +0x84, 0x8C, 0xAE, 0x10, 0xB6, 0x2F, 0xA5, 0xAE, +0x3A, 0x65, 0x73, 0xED, 0xA5, 0x73, 0x7C, 0x4E, +0x11, 0x62, 0x2A, 0x23, 0x74, 0xCC, 0x85, 0x4D, +0x85, 0x4C, 0x6C, 0xA9, 0x8D, 0x8D, 0x95, 0xEE, +0x6C, 0x69, 0x43, 0x43, 0x85, 0x6B, 0x95, 0xAD, +0x8D, 0x6C, 0x95, 0x8C, 0x8D, 0x2A, 0x95, 0x4B, +0x8D, 0x2C, 0xAE, 0x71, 0xAE, 0x71, 0x8D, 0x6D, +0x7D, 0x0A, 0x74, 0xE8, 0x8D, 0xAA, 0x8D, 0x69, +0x7C, 0xA7, 0x7C, 0xAC, 0x94, 0xF0, 0x94, 0xB1, +0x73, 0x6D, 0x52, 0x68, 0x94, 0x2E, 0x9C, 0x6E, +0xBD, 0x92, 0xC6, 0x12, 0xAD, 0x8F, 0xB5, 0xB1, +0xAD, 0x72, 0xBD, 0xD6, 0xB5, 0x96, 0xD6, 0xBB, +0xB5, 0x96, 0x63, 0x2C, 0x9C, 0xCF, 0xCE, 0x50, +0xAD, 0x2C, 0x42, 0x05, 0x42, 0x07, 0x42, 0x07, +0x73, 0x6C, 0x83, 0xAE, 0x73, 0x4C, 0x18, 0xA2, +0x29, 0x24, 0x4A, 0x28, 0x5A, 0xAB, 0x73, 0x4D, +0x73, 0x6E, 0x4A, 0x29, 0x52, 0x49, 0x6B, 0x0C, +0x5A, 0x8A, 0x7B, 0x8D, 0x73, 0x4D, 0x7B, 0xAE, +0x73, 0x6D, 0x94, 0x51, 0x83, 0xCF, 0x83, 0xEF, +0x9C, 0xD3, 0xB5, 0x76, 0xC6, 0x18, 0xC6, 0x5A, +0xCE, 0xDC, 0xCE, 0xFD, 0xCE, 0xFE, 0xCE, 0xDE, +0xCE, 0xDD, 0xCE, 0xFD, 0xCE, 0xDD, 0xC6, 0x9C, +0xCE, 0xB9, 0xDF, 0x36, 0xE7, 0x56, 0xBE, 0x10, +0xCE, 0x90, 0xCE, 0xAF, 0x8C, 0xC6, 0xA5, 0x89, +0xD6, 0xED, 0xE7, 0x6D, 0xD7, 0x2B, 0xAE, 0x28, +0xAE, 0x07, 0xB6, 0x6C, 0xC6, 0xD5, 0x9D, 0x74, +0xB6, 0x38, 0xBE, 0x5A, 0xC6, 0x59, 0xC5, 0xF6, +0x83, 0xED, 0x42, 0x07, 0x41, 0xE8, 0x41, 0xE7, +0x83, 0xEF, 0xAD, 0x34, 0x7B, 0xAE, 0x39, 0xE7, +0x63, 0xA9, 0x9D, 0x8C, 0xBE, 0x90, 0x8D, 0x6B, +0x4B, 0x65, 0x4B, 0x48, 0x6C, 0x2C, 0x3A, 0xA7, +0x19, 0xA3, 0x19, 0xA3, 0x2A, 0x04, 0x19, 0x63, +0x08, 0xE1, 0x08, 0xC1, 0x21, 0xC4, 0x32, 0x85, +0x3A, 0xC5, 0x53, 0xA8, 0x2A, 0x63, 0x22, 0x03, +0x11, 0x82, 0x11, 0x42, 0x11, 0x02, 0x11, 0x42, +0x21, 0xC4, 0x21, 0xC4, 0x19, 0xA3, 0x4B, 0x09, +0xBD, 0x93, 0x83, 0xCC, 0x83, 0xCB, 0xA4, 0xAF, +0x9C, 0x4E, 0x8B, 0xED, 0x8C, 0x0D, 0x94, 0x4E, +0x9C, 0xAF, 0x8C, 0x0D, 0xA4, 0xD0, 0xA4, 0xD0, +0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0xB0, 0x94, 0x6F, +0xAD, 0x11, 0xCD, 0xD4, 0xD5, 0xF4, 0xD5, 0xF4, +0xDE, 0x76, 0xE6, 0x96, 0xDE, 0x75, 0xDE, 0x55, +0xEE, 0x96, 0xBD, 0x10, 0xAC, 0xEF, 0xDE, 0x54, +0xD6, 0x34, 0xCE, 0x13, 0xD6, 0x14, 0xD6, 0x75, +0xD6, 0x55, 0xD6, 0x35, 0xD6, 0x34, 0xDE, 0x75, +0xD6, 0x34, 0xC5, 0xD3, 0xDE, 0x76, 0xE6, 0xB7, +0xB5, 0x31, 0xC5, 0xD3, 0xCE, 0x14, 0xCD, 0xF3, +0xD6, 0x14, 0xD6, 0x34, 0xD6, 0x14, 0xDE, 0x34, +0x9C, 0xAD, 0x84, 0x07, 0x7C, 0x47, 0x84, 0x68, +0x8C, 0x89, 0xA5, 0x6F, 0xCE, 0xF7, 0xAE, 0x14, +0x9D, 0xB1, 0xA5, 0x90, 0x9C, 0x8E, 0x9C, 0x8E, +0x9C, 0x8D, 0x7C, 0x29, 0x74, 0x49, 0x63, 0xC8, +0x74, 0x4B, 0x8C, 0xCD, 0xAD, 0xD0, 0x8C, 0xEB, +0x6C, 0x68, 0x7C, 0xA9, 0xBE, 0x71, 0xC6, 0x53, +0xC6, 0x34, 0xA5, 0x0F, 0x9C, 0xED, 0xB5, 0xCE, +0xC6, 0x70, 0xCE, 0x72, 0xB5, 0x90, 0xA4, 0xCE, +0xAD, 0x11, 0xA4, 0xF1, 0x63, 0x0A, 0x7B, 0xCD, +0x9C, 0xAF, 0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x4E, +0x9C, 0x4E, 0x9C, 0x6E, 0xA4, 0xAF, 0x94, 0x4E, +0x83, 0xEC, 0x83, 0xCC, 0x83, 0xCC, 0x83, 0xAC, +0x7B, 0x8A, 0x73, 0xAA, 0x63, 0xC9, 0x84, 0xED, +0x8D, 0x2E, 0x8D, 0x0E, 0x9D, 0x70, 0x8D, 0x0F, +0x7C, 0xAD, 0x8C, 0xCE, 0x9C, 0xCF, 0xA4, 0xEF, +0x9C, 0x8E, 0x83, 0xEC, 0x94, 0x6F, 0xA4, 0xF1, +0xAD, 0x73, 0x9C, 0xB0, 0x8C, 0x4F, 0x7C, 0x0D, +0xC6, 0x95, 0xCE, 0xF6, 0x95, 0x70, 0x4B, 0x28, +0x5B, 0xA9, 0x6C, 0x4C, 0x74, 0x6C, 0x7C, 0x6C, +0x84, 0x8D, 0x5B, 0x88, 0x42, 0xE5, 0x84, 0x6E, +0x94, 0xF0, 0xA5, 0x31, 0x7B, 0xEC, 0x6B, 0x6A, +0xA5, 0x53, 0xCE, 0xDB, 0xAD, 0xD6, 0xAD, 0xD4, +0x63, 0xAC, 0x6B, 0xCD, 0x6B, 0xAC, 0x6B, 0xAB, +0x6B, 0x8A, 0x6B, 0x8A, 0x6B, 0xEA, 0x84, 0xEB, +0x84, 0xCB, 0x32, 0x24, 0x5B, 0x09, 0xA5, 0x72, +0x84, 0x6D, 0x6B, 0xEA, 0x63, 0xE8, 0x53, 0xA5, +0x6C, 0x88, 0x6C, 0x87, 0x9D, 0xCD, 0x9D, 0xCD, +0x4B, 0x05, 0x11, 0x21, 0x19, 0xA2, 0x3A, 0x85, +0x4B, 0x66, 0x5B, 0xE8, 0x63, 0xE8, 0x19, 0x41, +0x74, 0xAA, 0x7D, 0x29, 0x95, 0xCD, 0xA6, 0x0F, +0x9D, 0xAE, 0x74, 0x29, 0x29, 0xA2, 0x52, 0xC7, +0x31, 0xE3, 0x4A, 0x45, 0x62, 0xE7, 0x63, 0x48, +0x63, 0xA8, 0xA5, 0xAE, 0xBE, 0x91, 0x6B, 0xC9, +0x21, 0x83, 0x63, 0x6C, 0xA5, 0x53, 0x84, 0x6F, +0x19, 0x82, 0x32, 0x84, 0x53, 0xA7, 0x6C, 0xAA, +0x7D, 0x0C, 0x9D, 0xF0, 0xA6, 0x30, 0x53, 0xC6, +0x32, 0xE3, 0x33, 0x02, 0x4B, 0xA6, 0x64, 0x28, +0x74, 0xAA, 0x85, 0x2B, 0x85, 0x0A, 0x7C, 0xC9, +0x64, 0x27, 0x85, 0x2C, 0xBE, 0xD3, 0xA6, 0x30, +0x95, 0xAE, 0x8D, 0x8C, 0x8D, 0x6A, 0x74, 0xA6, +0x64, 0x45, 0x64, 0x06, 0x7C, 0x4A, 0x9C, 0xCE, +0x6B, 0x09, 0x94, 0x8D, 0x94, 0x8B, 0x94, 0x8B, +0x8C, 0x6A, 0x7C, 0x28, 0xA5, 0x6E, 0x84, 0x4B, +0x8C, 0x8E, 0x9D, 0x11, 0xBD, 0xD6, 0xCE, 0x79, +0xC6, 0x18, 0xC5, 0xF7, 0xC6, 0x14, 0xCE, 0x31, +0xBD, 0xAD, 0x7B, 0xC9, 0x8C, 0x2D, 0x52, 0x48, +0x62, 0xEB, 0x94, 0x70, 0x6B, 0x0B, 0x18, 0xA2, +0x29, 0x24, 0x5A, 0x8A, 0x7B, 0x8E, 0x73, 0x6E, +0x73, 0x6E, 0x6B, 0x2D, 0x52, 0x49, 0x5A, 0xCB, +0x73, 0x4D, 0xAC, 0xF3, 0x94, 0x50, 0x62, 0xEB, +0x5A, 0x8A, 0x73, 0x6D, 0x83, 0xF0, 0x84, 0x10, +0x94, 0x92, 0xAD, 0x55, 0xBD, 0xD6, 0xAD, 0x55, +0xAD, 0x96, 0xB5, 0xF7, 0xBE, 0x7A, 0xBE, 0x5B, +0xBE, 0x5C, 0xBE, 0x5C, 0xBE, 0x7B, 0xCE, 0xDA, +0xBE, 0x55, 0xE7, 0x56, 0xE7, 0x54, 0xD6, 0xF2, +0xCE, 0xB0, 0xB5, 0xEC, 0x8C, 0xE7, 0xB6, 0x2E, +0xCF, 0x10, 0xD6, 0xED, 0xDF, 0x2C, 0xBE, 0x68, +0xB6, 0x47, 0xB6, 0x6C, 0xBE, 0xD5, 0xC6, 0xB9, +0xB6, 0x18, 0xCE, 0xDB, 0xCE, 0xDB, 0xCE, 0x99, +0xA5, 0x34, 0x63, 0x4C, 0x31, 0xA6, 0x5A, 0xCB, +0x9C, 0x91, 0xB5, 0x54, 0x7B, 0xCF, 0x31, 0xA5, +0x74, 0x6A, 0x8D, 0x6B, 0xBE, 0xB2, 0xA6, 0x10, +0x4B, 0x45, 0x32, 0x64, 0x2A, 0x04, 0x42, 0xC7, +0x3A, 0x86, 0x21, 0xE3, 0x2A, 0x05, 0x11, 0x62, +0x11, 0x42, 0x11, 0x22, 0x32, 0x45, 0x2A, 0x44, +0x2A, 0x84, 0x53, 0xE8, 0x2A, 0xA4, 0x11, 0x81, +0x11, 0x42, 0x11, 0x43, 0x19, 0x83, 0x19, 0x83, +0x21, 0xE4, 0x19, 0x83, 0x19, 0xA4, 0x4B, 0x09, +0xC5, 0xB4, 0x8B, 0xEC, 0x83, 0xCB, 0x9C, 0x4D, +0x9C, 0x6E, 0xA4, 0xD0, 0x9C, 0x8F, 0x9C, 0x8F, +0x9C, 0x8F, 0x5A, 0x88, 0x94, 0x6F, 0x9C, 0xB0, +0xA4, 0xB0, 0xA4, 0xB0, 0x9C, 0x8F, 0xA4, 0xD0, +0xAD, 0x11, 0xBD, 0x72, 0xB5, 0x31, 0xA4, 0xAF, +0xC5, 0x92, 0xCD, 0xD3, 0xCD, 0xB3, 0xCD, 0x92, +0xE6, 0x55, 0xC5, 0x72, 0xB5, 0x10, 0xDE, 0x55, +0xD6, 0x34, 0xD6, 0x55, 0xD6, 0x35, 0xD6, 0x75, +0xCE, 0x35, 0xB5, 0x52, 0xC5, 0xF4, 0xDE, 0x76, +0xD6, 0x55, 0xD6, 0x75, 0xDE, 0xB7, 0xE6, 0xD7, +0xC5, 0xD4, 0xB5, 0x52, 0xC5, 0xD3, 0xDE, 0x55, +0xDE, 0x54, 0xDE, 0x74, 0xD6, 0x54, 0xDE, 0x55, +0x9C, 0x8C, 0x94, 0xAA, 0x8C, 0xCA, 0x7C, 0xA8, +0x7C, 0x87, 0x74, 0x88, 0x7C, 0xCC, 0x95, 0x90, +0xA5, 0xD1, 0x8C, 0x8D, 0x83, 0xEB, 0x83, 0xEB, +0x73, 0xC9, 0x9D, 0x2E, 0x7C, 0x8B, 0x74, 0x2A, +0x95, 0x2E, 0x7C, 0x6A, 0x74, 0x68, 0x74, 0xA8, +0x7C, 0xC8, 0x7C, 0xA8, 0xA5, 0xEE, 0xC6, 0x73, +0x8C, 0x4D, 0x94, 0x4C, 0x94, 0x6C, 0xA4, 0xEC, +0xAD, 0x4C, 0xA5, 0x2D, 0x94, 0x6D, 0x94, 0x4E, +0xBD, 0x94, 0x6B, 0x2B, 0x73, 0x8C, 0x84, 0x0E, +0x62, 0xEA, 0x6B, 0x2A, 0x8B, 0xED, 0x62, 0xC9, +0x5A, 0x88, 0x7B, 0x6B, 0x9C, 0x8F, 0x8B, 0xEC, +0xA4, 0xCF, 0x9C, 0x6E, 0x9C, 0x8E, 0xB5, 0x71, +0xA4, 0xCF, 0xAD, 0x30, 0x63, 0xA9, 0x7C, 0xAC, +0x84, 0xCD, 0x95, 0x6F, 0x84, 0xED, 0x84, 0xCD, +0x8D, 0x2E, 0x94, 0xEE, 0x9C, 0xED, 0x9D, 0x0C, +0xA5, 0x2D, 0xA5, 0x2E, 0x9C, 0xEE, 0x94, 0x8E, +0x8C, 0x4D, 0x83, 0xEC, 0x83, 0xEC, 0x94, 0xAF, +0xA5, 0xB2, 0x9D, 0x90, 0xA5, 0xD0, 0x9D, 0xB0, +0x84, 0xEE, 0x8D, 0x2F, 0x7C, 0xAD, 0x4B, 0x47, +0x43, 0x06, 0x3B, 0x06, 0x43, 0x06, 0x84, 0xAE, +0x95, 0x10, 0x8C, 0x6E, 0x73, 0xCC, 0x6B, 0x6A, +0xAD, 0xD5, 0xC6, 0x79, 0xB6, 0x18, 0xAD, 0xF5, +0x7C, 0xAD, 0x84, 0xEC, 0x7C, 0xAB, 0x84, 0xCC, +0x9D, 0x2D, 0xB6, 0x31, 0xAD, 0xF0, 0x6C, 0x48, +0x64, 0x07, 0x4B, 0x26, 0x74, 0x6B, 0x8C, 0xED, +0x85, 0x0D, 0x6C, 0x4A, 0x5B, 0xE7, 0x8D, 0x8C, +0x7D, 0x09, 0x5C, 0x45, 0x4B, 0xA3, 0x53, 0xE5, +0x5B, 0xE8, 0x3A, 0xA4, 0x32, 0x23, 0x4B, 0x26, +0x32, 0xA3, 0x6C, 0x69, 0x2A, 0x23, 0x21, 0xA2, +0x85, 0x0C, 0xAE, 0x70, 0xAE, 0x70, 0xAE, 0x50, +0xA6, 0x0F, 0x7C, 0xCA, 0x4A, 0xC5, 0x63, 0x28, +0x5B, 0x27, 0x52, 0x86, 0x39, 0xA3, 0x42, 0x25, +0x42, 0x45, 0x32, 0x44, 0x4A, 0xE6, 0x32, 0x44, +0x29, 0xE4, 0x32, 0x06, 0x4A, 0xA8, 0x42, 0xA8, +0x32, 0x85, 0x3A, 0xE5, 0x4B, 0xA7, 0x7D, 0x0C, +0x9E, 0x30, 0x9E, 0x10, 0x6C, 0x6A, 0x2A, 0x82, +0x22, 0x41, 0x22, 0x41, 0x22, 0x42, 0x32, 0xC3, +0x43, 0x66, 0x53, 0xC7, 0x64, 0x47, 0x43, 0x64, +0x53, 0xE6, 0x85, 0x4C, 0x9D, 0xEF, 0x7C, 0xEC, +0xA6, 0x51, 0x8D, 0x6E, 0x74, 0xEB, 0x5C, 0x06, +0x5C, 0x27, 0x63, 0xE8, 0x4A, 0xA4, 0x83, 0xEA, +0x9C, 0xCC, 0xA5, 0x4D, 0x8C, 0x49, 0x5B, 0x06, +0x52, 0xA6, 0x5A, 0xC7, 0xA4, 0xAF, 0x94, 0x6F, +0x62, 0xEA, 0x83, 0xEE, 0x83, 0xEF, 0x8C, 0x51, +0xA5, 0x14, 0xDE, 0xFB, 0xC5, 0xF6, 0xA4, 0xF0, +0xB5, 0x6F, 0x94, 0xAD, 0xAD, 0x30, 0x6B, 0x0A, +0x4A, 0x27, 0x73, 0x6C, 0x29, 0x44, 0x18, 0xA2, +0x29, 0x24, 0x5A, 0xAA, 0x8C, 0x30, 0x73, 0x6E, +0x84, 0x10, 0x84, 0x10, 0x6B, 0x0C, 0x52, 0x6A, +0x62, 0xCB, 0x7B, 0xAE, 0xB5, 0x75, 0x7B, 0x8E, +0x73, 0x6D, 0x9C, 0xB3, 0x9C, 0xD3, 0x94, 0x72, +0x8C, 0x31, 0x7B, 0xEF, 0xA5, 0x34, 0x8C, 0x72, +0x84, 0x10, 0x8C, 0x71, 0xB5, 0xD7, 0xBE, 0x19, +0xB5, 0xFA, 0xAD, 0xD8, 0xD6, 0xD9, 0xE7, 0x37, +0xE7, 0x54, 0xCE, 0x8F, 0xD6, 0xCF, 0xD6, 0xF0, +0xCE, 0x8F, 0xC6, 0x4D, 0xB6, 0x2D, 0xC6, 0xD1, +0xB6, 0x6E, 0xAE, 0x09, 0xCE, 0xEA, 0xB6, 0x25, +0xAE, 0x26, 0xAE, 0x4C, 0xAE, 0x32, 0xBE, 0x56, +0xBE, 0x57, 0xD7, 0x19, 0xE7, 0x79, 0xD6, 0xD7, +0xC6, 0x76, 0xB6, 0x34, 0x8C, 0xB0, 0x9C, 0xD3, +0xC5, 0xD6, 0xB5, 0x75, 0x7B, 0xAE, 0x31, 0xE5, +0x7C, 0xCA, 0x7D, 0x07, 0x95, 0x8B, 0x9D, 0xEE, +0x6C, 0x69, 0x19, 0xC2, 0x11, 0x62, 0x21, 0xC4, +0x3A, 0xA7, 0x3A, 0x86, 0x2A, 0x25, 0x19, 0xA3, +0x21, 0xE4, 0x21, 0xC3, 0x32, 0x45, 0x2A, 0x23, +0x32, 0xA4, 0x43, 0x66, 0x32, 0xC4, 0x11, 0x41, +0x11, 0x42, 0x11, 0x62, 0x19, 0xA3, 0x19, 0x83, +0x11, 0x42, 0x11, 0x42, 0x2A, 0x46, 0x4B, 0x29, +0xC5, 0xB3, 0x8B, 0xEC, 0x83, 0xCC, 0x9C, 0x6E, +0x8C, 0x0D, 0x8C, 0x0D, 0x84, 0x0D, 0x94, 0x2E, +0x94, 0x4E, 0x62, 0xE9, 0x83, 0xAC, 0x94, 0x6F, +0x94, 0x6F, 0x94, 0x4E, 0x94, 0x2E, 0x9C, 0x8F, +0xAC, 0xF1, 0xAD, 0x11, 0xBD, 0x52, 0xBD, 0x72, +0xBD, 0x72, 0xC5, 0xB3, 0xC5, 0xB3, 0xCD, 0xB3, +0xDE, 0x55, 0xC5, 0x92, 0xA4, 0xCF, 0xD6, 0x34, +0xCD, 0xF3, 0xC5, 0xF3, 0xCE, 0x34, 0xD6, 0x55, +0xBD, 0xD4, 0x94, 0x90, 0xAD, 0x52, 0xD6, 0x76, +0xDE, 0x96, 0xDE, 0xB7, 0xBD, 0xB3, 0xD6, 0x76, +0xD6, 0x55, 0xC5, 0xD3, 0xCE, 0x14, 0xDE, 0x55, +0xD6, 0x34, 0xD6, 0x54, 0xD6, 0x34, 0xD6, 0x34, +0x9C, 0x8D, 0xA5, 0x0D, 0xA5, 0x4E, 0x84, 0x8A, +0x84, 0xAA, 0x7C, 0x69, 0x53, 0x66, 0x6C, 0x2A, +0xA5, 0xB0, 0x9C, 0xEF, 0x94, 0x6E, 0x94, 0x6D, +0x7C, 0x2A, 0xA5, 0x4F, 0x9D, 0x2F, 0xA5, 0x90, +0x84, 0xAC, 0x4B, 0x44, 0x5C, 0x04, 0x53, 0xE3, +0x6C, 0x87, 0x85, 0x09, 0x8D, 0x2C, 0xCE, 0xB5, +0x7B, 0xCA, 0x9C, 0x6D, 0xA4, 0xEF, 0x9C, 0xAE, +0x94, 0x4D, 0x94, 0x6E, 0x8C, 0x0E, 0xB5, 0x94, +0x7B, 0xAD, 0x73, 0x6C, 0x9C, 0xB1, 0x7B, 0xCD, +0x52, 0x88, 0x7B, 0xAD, 0xA4, 0xD0, 0x9C, 0xB0, +0x83, 0xCC, 0x73, 0x8B, 0x73, 0x4A, 0x6A, 0xE9, +0x5A, 0x88, 0x73, 0xAA, 0x8C, 0xAD, 0xB5, 0xD2, +0xAD, 0x92, 0xA5, 0x30, 0x63, 0x89, 0x74, 0x2B, +0x8D, 0x0E, 0x8D, 0x2E, 0x85, 0x0D, 0x85, 0x0D, +0x6B, 0xEA, 0x63, 0x68, 0x84, 0x8A, 0x84, 0xA9, +0x84, 0xA9, 0x95, 0x2C, 0x9D, 0x6E, 0xAD, 0x90, +0xAD, 0x91, 0x8C, 0x2D, 0x83, 0xEC, 0xC6, 0x35, +0xAD, 0xF3, 0x7C, 0xCC, 0x85, 0x0C, 0x8D, 0x2E, +0x95, 0x6F, 0x7C, 0xAC, 0x5B, 0xE9, 0x42, 0xE6, +0x4B, 0x26, 0x4B, 0x67, 0x53, 0xA8, 0x4B, 0x69, +0x84, 0xCF, 0xA5, 0xB2, 0x9D, 0x30, 0x9D, 0x10, +0x7C, 0x0E, 0x94, 0xF3, 0x9D, 0x54, 0x95, 0x70, +0x84, 0xEA, 0x64, 0x26, 0x5C, 0x06, 0x7D, 0x0A, +0x6C, 0x88, 0x64, 0x47, 0x4B, 0x84, 0x32, 0xE2, +0x3A, 0xE2, 0x6C, 0x48, 0x7C, 0xAB, 0x9D, 0xD0, +0xA6, 0x31, 0x9D, 0xD0, 0x9D, 0xCF, 0x9D, 0xEE, +0x85, 0x6B, 0x74, 0xE8, 0x64, 0x87, 0x74, 0xC9, +0xA6, 0x2F, 0x5C, 0x07, 0x43, 0x24, 0x43, 0x04, +0x5B, 0xE7, 0x6C, 0x49, 0x19, 0x61, 0x19, 0xA2, +0x95, 0x8F, 0xAE, 0x50, 0xAE, 0x51, 0xAE, 0x50, +0xAE, 0x71, 0x8D, 0x4C, 0x53, 0x05, 0x42, 0x85, +0x6B, 0xA9, 0x29, 0x62, 0x4A, 0x46, 0x6B, 0x69, +0x5B, 0x27, 0x3A, 0x85, 0x2A, 0x04, 0x2A, 0x04, +0x32, 0x45, 0x21, 0xC4, 0x19, 0x83, 0x3A, 0x86, +0x4B, 0x87, 0x53, 0xC7, 0x6C, 0xAA, 0x9D, 0xF0, +0x74, 0xAC, 0x3A, 0xC5, 0x2A, 0x83, 0x2A, 0x63, +0x22, 0x42, 0x22, 0x42, 0x32, 0xA3, 0x3A, 0xE4, +0x43, 0x46, 0x53, 0xE7, 0x7C, 0xEA, 0x53, 0xC5, +0x3B, 0x03, 0x3B, 0x24, 0x4B, 0x86, 0x3A, 0xC5, +0x9D, 0xF1, 0x9D, 0xF0, 0x8D, 0x6E, 0x8D, 0x4D, +0x6C, 0x49, 0x9D, 0x6E, 0x6B, 0xA8, 0x9D, 0x2D, +0x95, 0x0C, 0xB6, 0x10, 0xC6, 0x72, 0xAD, 0xB1, +0x5A, 0xC9, 0x62, 0x89, 0x6A, 0xC9, 0xA4, 0x91, +0x9C, 0x50, 0x5A, 0xCA, 0x83, 0xEF, 0x63, 0x2C, +0x94, 0x72, 0xC6, 0x38, 0xD6, 0x79, 0xB5, 0x75, +0xBD, 0xB6, 0xBD, 0xD6, 0xAD, 0x73, 0x6B, 0x2B, +0x6B, 0x2B, 0x62, 0xEB, 0x20, 0xE3, 0x39, 0xC7, +0x18, 0xC2, 0x4A, 0x48, 0x7B, 0xAE, 0x7B, 0xAE, +0x8C, 0x30, 0x94, 0x51, 0x83, 0xF0, 0x73, 0x4D, +0x6B, 0x4D, 0x42, 0x08, 0xA4, 0xF3, 0x8C, 0x30, +0x8C, 0x30, 0xAD, 0x55, 0xA4, 0xD4, 0x9C, 0xD3, +0x9C, 0x93, 0x6B, 0x4D, 0x7B, 0xF0, 0x9C, 0xB3, +0x94, 0x72, 0x94, 0x92, 0xA5, 0x14, 0xC6, 0x38, +0xB5, 0xD6, 0xDF, 0x18, 0xF7, 0x96, 0xEF, 0x32, +0xEF, 0x72, 0xDF, 0x0E, 0xD6, 0xAD, 0xEF, 0x71, +0xAD, 0x6B, 0xD6, 0xEE, 0xB6, 0x4D, 0xBE, 0xB1, +0xC6, 0xD0, 0xA5, 0xE8, 0xAE, 0x05, 0xA6, 0x04, +0x8D, 0x23, 0x95, 0x88, 0x95, 0x6D, 0xB6, 0x54, +0xBE, 0x96, 0xC6, 0x75, 0xD6, 0xD5, 0xE7, 0x97, +0xE7, 0x77, 0xB6, 0x32, 0xAD, 0xD4, 0xB5, 0xB6, +0xBD, 0xB6, 0xA5, 0x13, 0x63, 0x0C, 0x5B, 0x29, +0x95, 0x6D, 0x8D, 0x8A, 0x85, 0x27, 0x85, 0x49, +0x6C, 0x68, 0x19, 0xE2, 0x11, 0x82, 0x11, 0x62, +0x3A, 0xA7, 0x4B, 0x08, 0x32, 0x45, 0x19, 0xC3, +0x22, 0x04, 0x2A, 0x24, 0x21, 0xE3, 0x32, 0x64, +0x32, 0x84, 0x3B, 0x25, 0x22, 0x23, 0x11, 0x41, +0x11, 0x42, 0x11, 0x42, 0x21, 0xC4, 0x19, 0xA3, +0x11, 0x62, 0x21, 0xC4, 0x32, 0x66, 0x42, 0xE8, +0x9C, 0x6E, 0x83, 0x8A, 0x83, 0xAB, 0x7B, 0x8A, +0x6B, 0x29, 0x73, 0x4A, 0x8C, 0x2D, 0xAC, 0xF0, +0xBD, 0x52, 0xAC, 0xF0, 0xAC, 0xD0, 0xAC, 0xF1, +0xB5, 0x11, 0xAC, 0xF1, 0xA4, 0xAF, 0x94, 0x2E, +0xA4, 0xAF, 0xAC, 0xF0, 0xA4, 0xAF, 0x9C, 0x6E, +0xA4, 0xB0, 0xAC, 0xD0, 0xBD, 0x51, 0xC5, 0xB2, +0xE6, 0x76, 0xC5, 0x92, 0xAD, 0x10, 0xCD, 0xF3, +0xCD, 0xF3, 0xC5, 0xD3, 0xC5, 0xF3, 0xC5, 0xF4, +0xAD, 0x52, 0xA5, 0x12, 0xAD, 0x52, 0xC6, 0x15, +0xD6, 0x55, 0xDE, 0xB7, 0xDE, 0x96, 0xD6, 0x55, +0xDE, 0x96, 0xDE, 0x76, 0xCE, 0x34, 0xD6, 0x34, +0xCD, 0xF4, 0xC5, 0xD3, 0xBD, 0xB2, 0xC5, 0xD3, +0xA4, 0xAE, 0xA4, 0xEE, 0xA4, 0xEE, 0x9C, 0xEE, +0xA5, 0x0E, 0x9C, 0xEE, 0x6B, 0xA9, 0x4B, 0x06, +0x74, 0x2B, 0xB5, 0xB2, 0xB5, 0x31, 0xBD, 0x92, +0x9C, 0xEF, 0xBD, 0xF2, 0x9D, 0x0F, 0x6C, 0x2A, +0x43, 0x04, 0x43, 0x23, 0x4B, 0xA3, 0x53, 0xA4, +0x5B, 0xE6, 0x95, 0x4D, 0x84, 0x4C, 0xC6, 0x35, +0x6B, 0x29, 0xAD, 0x10, 0xAD, 0x10, 0x7B, 0xAB, +0x8C, 0x0D, 0x9C, 0xB0, 0xAD, 0x33, 0x84, 0x0E, +0x63, 0x0A, 0x94, 0x90, 0x94, 0x90, 0x62, 0xEA, +0x4A, 0x68, 0x5A, 0xC9, 0x94, 0x6F, 0xA5, 0x11, +0xAD, 0x51, 0x94, 0xAE, 0x94, 0x6E, 0x6B, 0x2A, +0x31, 0xA5, 0x5B, 0x49, 0x9D, 0x70, 0x84, 0xEF, +0x9D, 0x92, 0x94, 0xF0, 0x63, 0x69, 0x6B, 0x8A, +0x74, 0x2C, 0x63, 0xC9, 0x84, 0xED, 0x7C, 0xCC, +0x7C, 0x4B, 0x84, 0x8B, 0x7C, 0xA9, 0x84, 0xC8, +0x7C, 0xC8, 0x84, 0xEA, 0x95, 0x6D, 0xA5, 0xAF, +0xBE, 0x12, 0x5A, 0xE8, 0x84, 0x0E, 0xCE, 0xB7, +0xC6, 0xB5, 0x74, 0x49, 0x7C, 0xAA, 0x95, 0x2D, +0xBE, 0x73, 0x9D, 0x8E, 0x6C, 0x4A, 0x64, 0x2B, +0x64, 0x2B, 0x64, 0x2B, 0x85, 0x0D, 0x7C, 0xCE, +0x84, 0xEE, 0x8D, 0x2F, 0xA5, 0xB2, 0xAD, 0xD3, +0x84, 0x6F, 0x95, 0x12, 0xB6, 0x34, 0x85, 0x0B, +0x5B, 0xE4, 0x5B, 0xE5, 0x74, 0xE8, 0x64, 0x46, +0x4B, 0xA3, 0x43, 0x63, 0x32, 0xE2, 0x5C, 0x27, +0x53, 0xE5, 0x85, 0x2B, 0x8D, 0x4D, 0x9D, 0xF0, +0xA6, 0x11, 0xA6, 0x11, 0xA6, 0x31, 0x7C, 0xEA, +0x7D, 0x2A, 0x74, 0xE9, 0x74, 0xC9, 0x9D, 0xCE, +0x95, 0xAE, 0x74, 0xAA, 0x7D, 0x0B, 0x64, 0x28, +0x85, 0x4C, 0x64, 0x09, 0x19, 0x61, 0x21, 0xA3, +0x42, 0xE6, 0x3A, 0xA4, 0x42, 0xE5, 0x6C, 0x2A, +0xA6, 0x0F, 0x9D, 0xCE, 0x63, 0xE7, 0x4B, 0x25, +0x84, 0xCB, 0x42, 0xC5, 0x31, 0xE3, 0x4A, 0xC6, +0x29, 0xC2, 0x42, 0xA6, 0x32, 0x44, 0x2A, 0x04, +0x3A, 0xA7, 0x32, 0x66, 0x32, 0x45, 0x43, 0x07, +0x53, 0xA8, 0x2A, 0x63, 0x43, 0x05, 0x32, 0x85, +0x2A, 0x24, 0x3A, 0xA5, 0x22, 0x42, 0x22, 0x22, +0x22, 0x22, 0x2A, 0x83, 0x43, 0x25, 0x4B, 0xA6, +0x64, 0x69, 0x74, 0xCA, 0xAE, 0x50, 0x64, 0x47, +0x43, 0x44, 0x2A, 0xA2, 0x2A, 0x62, 0x2A, 0x43, +0x7C, 0xED, 0xAE, 0x93, 0x9D, 0xF1, 0xAE, 0x52, +0x84, 0xED, 0x7C, 0xAB, 0x95, 0x4D, 0x95, 0x6D, +0x95, 0x8E, 0xC7, 0x15, 0xA5, 0xD0, 0x8C, 0xCD, +0x73, 0x6B, 0x5A, 0x48, 0x49, 0xE7, 0x8B, 0xAE, +0xAC, 0xB1, 0x83, 0xAE, 0x5A, 0x8A, 0x52, 0x8A, +0x7B, 0xCE, 0x73, 0x8E, 0x9C, 0xD3, 0xD6, 0x99, +0xD6, 0xBA, 0xBD, 0xD7, 0x84, 0x0F, 0x4A, 0x68, +0x73, 0x6D, 0x6B, 0x0B, 0x29, 0x24, 0x29, 0x45, +0x10, 0x82, 0x31, 0x65, 0x62, 0xCA, 0x7B, 0xAE, +0x94, 0x72, 0xA4, 0xD3, 0xA4, 0xD3, 0x7B, 0xAE, +0x73, 0x4D, 0x73, 0x6D, 0x52, 0x6A, 0x9C, 0x92, +0x7B, 0xAE, 0x8C, 0x51, 0xA5, 0x14, 0x94, 0x72, +0x8C, 0x31, 0x84, 0x10, 0x94, 0x72, 0xAD, 0x55, +0xBD, 0x97, 0xC5, 0xF8, 0xAD, 0x55, 0xAD, 0x55, +0xAD, 0x74, 0xDE, 0xF5, 0xE7, 0x33, 0xEF, 0x72, +0xDF, 0x0F, 0xCE, 0x8C, 0xDF, 0x0E, 0xEF, 0x71, +0x8C, 0xA7, 0xC6, 0xAD, 0xAE, 0x2B, 0xBE, 0xB0, +0xAE, 0x4D, 0x9D, 0xC6, 0x9D, 0xA3, 0xAE, 0x46, +0xA5, 0xE8, 0xA6, 0x0B, 0xB6, 0x8F, 0xB6, 0x93, +0xAD, 0xF2, 0xCE, 0xF7, 0xC6, 0xB5, 0xB6, 0x51, +0xD6, 0xF2, 0xBE, 0x71, 0xA5, 0x92, 0xC6, 0x38, +0xBD, 0xB6, 0x8C, 0x71, 0x4A, 0x49, 0x74, 0x2D, +0xAE, 0x51, 0x9D, 0xED, 0x85, 0x27, 0x8D, 0xAA, +0x7D, 0x2A, 0x43, 0x24, 0x19, 0xC1, 0x11, 0x62, +0x42, 0xC7, 0x5B, 0xCA, 0x32, 0x66, 0x11, 0x21, +0x19, 0xC3, 0x19, 0xA3, 0x11, 0x41, 0x32, 0xA5, +0x22, 0x43, 0x32, 0xC4, 0x11, 0x61, 0x11, 0x22, +0x09, 0x22, 0x11, 0x22, 0x22, 0x04, 0x21, 0xE3, +0x19, 0xA3, 0x2A, 0x25, 0x3A, 0xA7, 0x53, 0x6A, +0x8B, 0xAB, 0x8B, 0xEC, 0x8B, 0xEC, 0x8B, 0xEC, +0x8C, 0x0C, 0x8B, 0xEC, 0x8B, 0xCC, 0x8B, 0xCB, +0x8B, 0xCC, 0x8B, 0xCC, 0x83, 0x8A, 0x7B, 0x6A, +0x7B, 0x6A, 0x7B, 0x6A, 0x83, 0xAB, 0x7B, 0x6A, +0x83, 0x8B, 0x8B, 0xCB, 0x8B, 0xEC, 0x8B, 0xCC, +0x83, 0xAB, 0x9C, 0x4D, 0xB5, 0x10, 0xCD, 0xD3, +0xD5, 0xF3, 0xBD, 0x30, 0xAC, 0xAE, 0xB5, 0x50, +0xC5, 0xB2, 0xC5, 0xD3, 0xC5, 0xF4, 0xBD, 0xB3, +0xAD, 0x32, 0xAD, 0x53, 0xAD, 0x52, 0xB5, 0x93, +0xBD, 0xD3, 0xD6, 0x55, 0xDE, 0xD7, 0xDE, 0xB7, +0xDE, 0x96, 0xD6, 0x55, 0xC5, 0xF3, 0xBD, 0xB3, +0xBD, 0x93, 0xB5, 0x72, 0xAD, 0x31, 0xAD, 0x31, +0xA4, 0xCF, 0xA4, 0xCE, 0xA4, 0xEF, 0xAD, 0x10, +0xA4, 0xCF, 0xAD, 0x30, 0x84, 0x0B, 0x3A, 0xA4, +0x3A, 0x84, 0x94, 0xCF, 0xBD, 0xB3, 0xBD, 0x72, +0xBD, 0xB3, 0xC5, 0xF3, 0xAD, 0x71, 0x42, 0xA4, +0x3A, 0xC3, 0x43, 0x23, 0x4B, 0x85, 0x5B, 0xA7, +0x9D, 0x2F, 0xBD, 0xF3, 0x83, 0xEC, 0xAD, 0x52, +0x5A, 0xA8, 0xAD, 0x10, 0xA4, 0xAE, 0x8C, 0x0D, +0x9C, 0xB0, 0x9C, 0xB0, 0xA4, 0xD1, 0x5A, 0xA9, +0x8C, 0x4F, 0x9C, 0xD1, 0x8C, 0x2F, 0x5A, 0xEA, +0xA5, 0x32, 0xA5, 0x71, 0x94, 0xAE, 0x94, 0xAE, +0xAD, 0xB1, 0xAD, 0x90, 0x94, 0x8E, 0x6B, 0x0A, +0x31, 0xA6, 0x3A, 0x26, 0x9D, 0x91, 0x7C, 0x8D, +0x6C, 0x6C, 0x5B, 0x89, 0x74, 0x0C, 0x5B, 0x29, +0x7C, 0x4D, 0x6B, 0xEB, 0x7C, 0x8B, 0x74, 0x69, +0x7C, 0x89, 0x7C, 0xA9, 0x7C, 0x69, 0x7C, 0x88, +0x7C, 0xA8, 0x84, 0xEA, 0x9D, 0x8E, 0xCE, 0xF5, +0xD7, 0x16, 0xBD, 0xF4, 0xAD, 0x73, 0x8C, 0xCF, +0x63, 0xA9, 0x74, 0x49, 0x95, 0x0C, 0xA5, 0x4E, +0xB5, 0xB1, 0x8D, 0x0D, 0x7C, 0xCC, 0x74, 0x8D, +0x7C, 0xCE, 0x74, 0x6C, 0x64, 0x2A, 0x6C, 0x6B, +0x74, 0x8C, 0x7C, 0xAD, 0x8D, 0x2F, 0x7C, 0xAD, +0x74, 0x0C, 0x95, 0x4F, 0x8D, 0x4C, 0x5C, 0x05, +0x5C, 0x25, 0x7D, 0x09, 0x53, 0xE4, 0x53, 0xC4, +0x64, 0x27, 0x74, 0x8B, 0x63, 0xC8, 0x6C, 0xA8, +0x4B, 0xA4, 0x64, 0x27, 0x74, 0xCA, 0x85, 0x2C, +0x95, 0x8F, 0x9D, 0xF0, 0x95, 0x8E, 0x7D, 0x0A, +0x7D, 0x2A, 0x7D, 0x0A, 0x8D, 0x8D, 0xAE, 0x31, +0x95, 0xAF, 0x8D, 0x6D, 0xAE, 0x71, 0x7C, 0xCA, +0x8D, 0x8D, 0x5B, 0xA8, 0x19, 0x62, 0x19, 0xA3, +0x21, 0xC3, 0x32, 0x44, 0x32, 0x24, 0x2A, 0x03, +0x53, 0x67, 0x7C, 0xCA, 0x5B, 0xE6, 0x4B, 0x64, +0x5C, 0x07, 0x42, 0xE4, 0x53, 0x66, 0x64, 0x08, +0x4B, 0x25, 0x4B, 0x26, 0x32, 0x64, 0x2A, 0x24, +0x3A, 0xC7, 0x42, 0xC7, 0x42, 0xE7, 0x43, 0x06, +0x32, 0x64, 0x2A, 0x23, 0x3A, 0xC5, 0x43, 0x06, +0x5B, 0xCA, 0x5B, 0xCA, 0x2A, 0x43, 0x22, 0x22, +0x2A, 0x42, 0x22, 0x22, 0x32, 0xA3, 0x53, 0xE7, +0x5C, 0x27, 0x85, 0x4D, 0xB6, 0x72, 0x6C, 0x89, +0x64, 0x68, 0x53, 0xC6, 0x4B, 0x85, 0x4B, 0x66, +0x4B, 0x87, 0x8D, 0xB0, 0xA6, 0x52, 0x9D, 0xF1, +0x8D, 0x4E, 0x85, 0x0D, 0xB6, 0x71, 0x85, 0x2D, +0xA6, 0x32, 0xB6, 0x93, 0x7C, 0xAB, 0x3A, 0x04, +0x5A, 0x68, 0x41, 0xA6, 0x52, 0x48, 0x7B, 0x4B, +0xAC, 0x70, 0xAC, 0xB1, 0x7B, 0x8D, 0x52, 0xAA, +0x73, 0x8E, 0x5A, 0xAA, 0x6B, 0x4D, 0xBD, 0xB6, +0x8C, 0x71, 0x5A, 0xCB, 0x4A, 0x49, 0x42, 0x28, +0x5A, 0xCA, 0x5A, 0xAA, 0x84, 0x0E, 0x73, 0x8C, +0x18, 0xA3, 0x18, 0xC3, 0x39, 0x86, 0x62, 0xCB, +0x84, 0x10, 0x9C, 0xD2, 0x9C, 0xD2, 0x7B, 0xCE, +0x6A, 0xEB, 0x6A, 0xEB, 0x5A, 0x8A, 0x83, 0xEF, +0xAD, 0x34, 0x6B, 0x4D, 0xA4, 0xF4, 0x9C, 0xB3, +0xA4, 0xF4, 0xB5, 0x56, 0xB5, 0x56, 0x83, 0xF0, +0x83, 0xF0, 0x94, 0x92, 0x94, 0x72, 0x84, 0x10, +0x6B, 0x4D, 0x6B, 0x6B, 0x84, 0x2B, 0xAD, 0xAE, +0xBE, 0x4D, 0xAD, 0xEA, 0xCE, 0xED, 0xC6, 0xAC, +0x7C, 0xA4, 0x85, 0x26, 0x8D, 0x47, 0x9D, 0xCA, +0xA6, 0x0A, 0x85, 0x03, 0x8D, 0x81, 0xAE, 0x25, +0xB6, 0x69, 0xB6, 0x6A, 0xAE, 0x4B, 0x9D, 0xED, +0x9D, 0xF0, 0xCE, 0xF6, 0xC6, 0xB4, 0xB6, 0x70, +0xBE, 0x8F, 0xDF, 0x54, 0xB5, 0xF4, 0xCE, 0x58, +0xAD, 0x55, 0x73, 0x8E, 0x31, 0xC6, 0x7C, 0x8C, +0x95, 0xCE, 0x95, 0xAB, 0x85, 0x48, 0x6C, 0x66, +0x5C, 0x06, 0x74, 0xC9, 0x43, 0x25, 0x19, 0x82, +0x3A, 0x87, 0x95, 0x51, 0x42, 0xC8, 0x19, 0x83, +0x2A, 0x44, 0x42, 0xE6, 0x19, 0x82, 0x3A, 0xC6, +0x19, 0xA2, 0x21, 0xE3, 0x11, 0x61, 0x11, 0x22, +0x09, 0x02, 0x09, 0x22, 0x21, 0xE4, 0x22, 0x04, +0x2A, 0x25, 0x4B, 0x28, 0x4B, 0x49, 0x5B, 0xEB, +0x7B, 0x8B, 0x7B, 0x8B, 0x7B, 0x8B, 0x7B, 0x6A, +0x83, 0xAB, 0x8B, 0xEC, 0x94, 0x0D, 0x9C, 0x4E, +0x9C, 0x4E, 0x9C, 0x4E, 0x9C, 0x8F, 0xA4, 0x8F, +0xA4, 0x8F, 0x94, 0x0C, 0x94, 0x0C, 0xA4, 0x8E, +0xAC, 0xD0, 0xAC, 0xD0, 0xA4, 0x8E, 0xA4, 0x6E, +0xA4, 0x8F, 0x9C, 0x6E, 0x9C, 0x2D, 0x9C, 0x4D, +0xA4, 0x8D, 0xA4, 0x6D, 0x9C, 0x4D, 0x94, 0x2C, +0x94, 0x0C, 0x8C, 0x0C, 0x94, 0x2C, 0x94, 0x4D, +0x9C, 0x8E, 0x9C, 0x6E, 0x9C, 0x6E, 0x94, 0x8F, +0xA4, 0xD0, 0xAD, 0x31, 0xBD, 0xB3, 0xCE, 0x14, +0xCD, 0xF4, 0xCE, 0x13, 0xCD, 0xF3, 0xC5, 0xB3, +0xC5, 0xD3, 0xBD, 0xB2, 0xAD, 0x10, 0xBD, 0x72, +0xAC, 0xF0, 0xB5, 0x30, 0xB5, 0x51, 0xB5, 0x51, +0xA4, 0xEF, 0xA5, 0x0F, 0x9C, 0xCE, 0x3A, 0x84, +0x42, 0xE5, 0x5B, 0x28, 0xAD, 0x51, 0xD6, 0x76, +0xBD, 0xD3, 0xBD, 0xF3, 0x9D, 0x0F, 0x42, 0xC3, +0x3B, 0x03, 0x53, 0x85, 0x63, 0xC9, 0xAD, 0x71, +0xCE, 0x55, 0xCE, 0x35, 0x8C, 0x0E, 0xAD, 0x32, +0x62, 0xEA, 0x9C, 0x8F, 0x8C, 0x0D, 0x8C, 0x2E, +0x94, 0x6F, 0x94, 0x4E, 0x7B, 0xAC, 0x83, 0xED, +0x9C, 0xB0, 0x9C, 0x90, 0x73, 0x4B, 0x4A, 0x68, +0x7C, 0x2D, 0xA5, 0xD0, 0x8D, 0x0C, 0xA5, 0xAF, +0xC6, 0x92, 0xC6, 0x72, 0x73, 0xAA, 0x52, 0x68, +0x39, 0xA6, 0x3A, 0x27, 0xBE, 0x75, 0x9D, 0x70, +0x4B, 0x27, 0x5B, 0xA9, 0x63, 0xAA, 0x4A, 0xA7, +0x84, 0x8E, 0x84, 0x8D, 0x95, 0x0E, 0x9D, 0x6E, +0x64, 0x06, 0x6C, 0x27, 0x6B, 0xE9, 0x6B, 0xCA, +0x74, 0x0A, 0x84, 0xAC, 0xB6, 0x13, 0xD7, 0x17, +0xCE, 0xB6, 0xB5, 0xF2, 0x6B, 0xEA, 0x63, 0xE9, +0x53, 0x47, 0x53, 0x27, 0x6B, 0x89, 0x9C, 0xEF, +0x73, 0xAA, 0xAD, 0xD2, 0x84, 0xCE, 0x85, 0x0F, +0x7C, 0xCD, 0x6C, 0x4B, 0x6C, 0x2A, 0x74, 0x6B, +0x8D, 0x2E, 0x8D, 0x4F, 0x85, 0x2F, 0x85, 0x0E, +0x5B, 0xC9, 0x74, 0xCA, 0x5C, 0x25, 0x53, 0xC5, +0x85, 0x4B, 0x6C, 0x47, 0x95, 0x8E, 0x7C, 0xAC, +0xA5, 0xF0, 0xB6, 0x32, 0x8D, 0x0D, 0x6C, 0x47, +0x64, 0x46, 0x5C, 0x05, 0x64, 0x48, 0x8D, 0x8D, +0x9E, 0x10, 0x8D, 0x8E, 0x6C, 0x89, 0x74, 0xE9, +0x85, 0x4B, 0x85, 0x4C, 0x9D, 0xEF, 0xA6, 0x31, +0x95, 0xAE, 0x9D, 0xCF, 0x9D, 0xCF, 0x5B, 0xC7, +0x3A, 0xE5, 0x19, 0xA2, 0x21, 0xA3, 0x21, 0xC3, +0x19, 0xA3, 0x32, 0x65, 0x3A, 0xC6, 0x2A, 0x24, +0x21, 0xE2, 0x53, 0xA6, 0x43, 0x44, 0x43, 0x24, +0x5B, 0xE7, 0x43, 0x04, 0x3A, 0xC3, 0x5C, 0x07, +0x6C, 0x68, 0x4B, 0x46, 0x2A, 0x03, 0x32, 0x65, +0x43, 0x08, 0x53, 0x49, 0x4B, 0x48, 0x4B, 0x47, +0x4B, 0x67, 0x43, 0x46, 0x3B, 0x25, 0x3B, 0x05, +0x4B, 0x67, 0x4B, 0x67, 0x3A, 0xC5, 0x2A, 0x43, +0x3A, 0xC5, 0x22, 0x02, 0x22, 0x22, 0x6C, 0xAA, +0x6C, 0xA9, 0x85, 0x4D, 0x9D, 0xF0, 0x74, 0xCA, +0x7D, 0x0A, 0x5C, 0x07, 0x4B, 0x85, 0x43, 0x65, +0x32, 0xE4, 0x3A, 0xE5, 0x64, 0x2A, 0x85, 0x4E, +0x64, 0x49, 0x53, 0x67, 0x8D, 0x6E, 0x8D, 0x8F, +0xBE, 0xD4, 0x95, 0x6F, 0x8D, 0x0D, 0x7C, 0x0A, +0x73, 0x6A, 0x52, 0x46, 0x49, 0xE7, 0x72, 0xEA, +0xA4, 0x0D, 0x72, 0xEA, 0x83, 0xAD, 0x4A, 0x48, +0x62, 0xEB, 0x52, 0x6A, 0x62, 0xEC, 0x83, 0xEF, +0x73, 0x8E, 0x6B, 0x4D, 0x6B, 0x2C, 0x94, 0x71, +0xA5, 0x13, 0x94, 0x71, 0x94, 0xB0, 0x7B, 0xCD, +0x20, 0xE4, 0x18, 0xC3, 0x18, 0xC3, 0x39, 0x86, +0x5A, 0xAA, 0x7B, 0xCE, 0x83, 0xEF, 0x63, 0x0C, +0x7B, 0x8E, 0x62, 0xEB, 0x5A, 0x8A, 0x39, 0xC7, +0x9C, 0xB3, 0xBD, 0x75, 0xBD, 0x96, 0xA4, 0xF4, +0x9C, 0xB3, 0x9C, 0xD3, 0x94, 0x72, 0x94, 0x72, +0xAD, 0x55, 0xAD, 0x55, 0xBD, 0xF7, 0xCE, 0x59, +0x7B, 0xCF, 0x62, 0xEB, 0x6B, 0x2B, 0x7C, 0x0C, +0x8D, 0x0C, 0x9D, 0xAB, 0xB6, 0x6C, 0xA5, 0xE8, +0x64, 0x41, 0x64, 0x41, 0x6C, 0x82, 0x85, 0x26, +0xBE, 0xCF, 0x8D, 0x68, 0x8D, 0x63, 0x9D, 0xC3, +0xA5, 0xE5, 0xA6, 0x06, 0x9D, 0xE6, 0x95, 0xC9, +0xA6, 0x0F, 0xBE, 0x93, 0xC6, 0xD2, 0xA6, 0x0D, +0xAE, 0x4E, 0xBE, 0x93, 0xBE, 0x36, 0xC6, 0x18, +0xB5, 0x96, 0x73, 0xAF, 0x3A, 0x05, 0x84, 0xE9, +0x7D, 0x07, 0x85, 0x68, 0x6C, 0x87, 0x32, 0xC2, +0x2A, 0x82, 0x4B, 0x85, 0x3A, 0xE4, 0x19, 0xC2, +0x4B, 0x08, 0x8D, 0x31, 0x32, 0x45, 0x21, 0xC3, +0x53, 0x88, 0x53, 0x87, 0x2A, 0x23, 0x3A, 0x85, +0x19, 0x82, 0x2A, 0x04, 0x2A, 0x44, 0x3A, 0x86, +0x42, 0xC7, 0x5B, 0xAA, 0x43, 0x28, 0x3A, 0xE7, +0x53, 0x89, 0x5B, 0xEA, 0x4B, 0x48, 0x5B, 0xEB, +0x5A, 0xCA, 0x5A, 0xC9, 0x62, 0xEA, 0x6B, 0x0A, +0x73, 0x4B, 0x83, 0xCC, 0x83, 0xED, 0x94, 0x4E, +0x9C, 0x8F, 0xA4, 0xF0, 0xBD, 0x93, 0xB5, 0x72, +0xAC, 0xF0, 0x94, 0x4D, 0x9C, 0x4E, 0xAC, 0xF0, +0xA4, 0xAF, 0xA4, 0xD0, 0xA4, 0xD0, 0xAC, 0xF0, +0xB5, 0x11, 0xBD, 0x72, 0xB5, 0x31, 0xBD, 0x51, +0xDE, 0x55, 0xDE, 0x35, 0xCD, 0xF3, 0xCD, 0xD3, +0xC5, 0x71, 0xBD, 0x51, 0xB5, 0x31, 0xB5, 0x10, +0xAC, 0xF0, 0xB5, 0x10, 0xB5, 0x31, 0xAC, 0xF0, +0x9C, 0x8E, 0x94, 0x4E, 0x9C, 0xAF, 0xAC, 0xEF, +0xAC, 0xCF, 0xAC, 0xEF, 0xAC, 0xCF, 0xAC, 0xCF, +0xB5, 0x10, 0xB5, 0x51, 0xB5, 0x51, 0xB5, 0x30, +0xB5, 0x10, 0xB5, 0x30, 0xAC, 0xF0, 0x94, 0x4D, +0x94, 0x4D, 0x9C, 0x8E, 0xAD, 0x30, 0x63, 0x48, +0x42, 0xA5, 0x53, 0x06, 0x73, 0xEB, 0xB5, 0xB3, +0x5B, 0x48, 0x4B, 0x47, 0x53, 0x86, 0x4B, 0x44, +0x43, 0x24, 0x6C, 0x09, 0xB5, 0xB2, 0xCE, 0x35, +0xCE, 0x15, 0xCE, 0x14, 0x9C, 0x8F, 0xA4, 0xF1, +0x7B, 0xAC, 0x83, 0xCD, 0x94, 0x4D, 0x8C, 0x4E, +0x8C, 0x4E, 0x9C, 0x8F, 0x9C, 0xB0, 0xAD, 0x11, +0xAD, 0x32, 0x9C, 0x90, 0x73, 0x6C, 0x42, 0x27, +0x42, 0x88, 0x8D, 0x2E, 0x95, 0x6D, 0xA5, 0xEF, +0xC6, 0xD3, 0xAD, 0xAF, 0x52, 0xA7, 0x52, 0xA8, +0x7C, 0x0D, 0xAD, 0xB3, 0xC6, 0xF6, 0xB6, 0x53, +0x74, 0x4C, 0xA5, 0xD2, 0x84, 0x8D, 0x73, 0xEB, +0x84, 0x6D, 0x8C, 0xCE, 0x9D, 0x2F, 0x9D, 0x2D, +0x6C, 0x47, 0x6B, 0xE8, 0x7C, 0x0B, 0x73, 0xAB, +0x6B, 0x8B, 0x8C, 0xAE, 0xDF, 0x59, 0xB6, 0x13, +0x7C, 0x8D, 0x7C, 0x6B, 0x5B, 0xA8, 0x4B, 0x46, +0x74, 0x4B, 0x6B, 0xCA, 0x9D, 0x30, 0xE7, 0x37, +0xAD, 0x70, 0xC6, 0x74, 0x9D, 0x70, 0xAD, 0xF2, +0x9D, 0x6F, 0xAD, 0xF1, 0x9D, 0x90, 0x74, 0x6B, +0x8D, 0x0E, 0x63, 0xEA, 0x74, 0x8C, 0x74, 0xAB, +0x6C, 0x89, 0x5C, 0x26, 0x6C, 0x87, 0x95, 0x8C, +0x9D, 0x8D, 0x63, 0xE7, 0xAD, 0xF0, 0x7C, 0x4B, +0x95, 0x0E, 0xAD, 0xF1, 0x95, 0x4D, 0x6C, 0x68, +0x4B, 0xC4, 0x4B, 0x84, 0x7D, 0x2B, 0x85, 0x4D, +0x53, 0xA7, 0x3A, 0xE4, 0x3B, 0x24, 0x64, 0x68, +0x85, 0x6B, 0x95, 0xCE, 0xA6, 0x10, 0xAE, 0x51, +0x95, 0xAE, 0x85, 0x0C, 0x53, 0xA7, 0x32, 0xA4, +0x21, 0xE3, 0x11, 0x61, 0x21, 0xE3, 0x21, 0xE3, +0x21, 0xE3, 0x3A, 0x85, 0x3A, 0xC5, 0x2A, 0x23, +0x21, 0xE2, 0x5C, 0x27, 0x53, 0xC5, 0x43, 0x24, +0x5C, 0x07, 0x64, 0x28, 0x53, 0xC6, 0x53, 0xC6, +0x64, 0x48, 0x3A, 0xA4, 0x21, 0xC3, 0x32, 0x65, +0x4B, 0x27, 0x53, 0x89, 0x4B, 0x68, 0x6C, 0x6B, +0x64, 0x4A, 0x5C, 0x08, 0x5B, 0xE8, 0x5C, 0x08, +0x74, 0xAB, 0x7C, 0xEC, 0x6C, 0x6A, 0x63, 0xE8, +0x53, 0x87, 0x42, 0xC5, 0x2A, 0x43, 0x7D, 0x0D, +0x95, 0xCF, 0x8D, 0x8E, 0x9D, 0xF0, 0x85, 0x2C, +0x9D, 0xEF, 0x64, 0x28, 0x5C, 0x07, 0x64, 0x68, +0x53, 0xA6, 0x4B, 0x87, 0x64, 0x6A, 0x85, 0x6D, +0x6C, 0x69, 0x3B, 0x05, 0x6C, 0x8B, 0xB6, 0xB4, +0xB6, 0xB4, 0x74, 0x6B, 0x53, 0x86, 0x7C, 0x6A, +0x7B, 0xCA, 0x73, 0xCA, 0x52, 0x66, 0x72, 0xC9, +0x9B, 0xAC, 0x7A, 0xEA, 0x7B, 0x2B, 0x5A, 0xAA, +0x6B, 0x2C, 0x7B, 0xAE, 0x94, 0x51, 0x9C, 0xB2, +0x7B, 0xAE, 0x83, 0xEF, 0xAD, 0x34, 0xC6, 0x18, +0xCE, 0x18, 0xC6, 0x17, 0xC6, 0x18, 0xC5, 0xD7, +0x7B, 0xAF, 0x39, 0x87, 0x29, 0x25, 0x20, 0xE4, +0x39, 0x86, 0x62, 0xCA, 0x6B, 0x0C, 0x73, 0x4C, +0x83, 0xAE, 0x6B, 0x2C, 0x73, 0x6D, 0x62, 0xCB, +0x8C, 0x10, 0xDE, 0x79, 0xD6, 0x38, 0x9C, 0x92, +0x8C, 0x31, 0xA4, 0xF4, 0xB5, 0x76, 0xBD, 0xB7, +0xBD, 0xD8, 0xCE, 0x59, 0xC6, 0x38, 0xCE, 0x38, +0x8C, 0x51, 0x84, 0x10, 0x6B, 0x2B, 0x63, 0x4B, +0x4A, 0xE8, 0x84, 0xED, 0xA6, 0x2E, 0xA5, 0xEB, +0x64, 0x41, 0x6C, 0x82, 0x74, 0xE3, 0x8D, 0x67, +0xCF, 0x32, 0x95, 0xAD, 0x85, 0x26, 0x9D, 0xC5, +0x9D, 0xC4, 0x8D, 0x62, 0x95, 0x83, 0xA6, 0x08, +0xAE, 0x6E, 0xB6, 0x50, 0xBE, 0x8F, 0xA5, 0xE9, +0x9D, 0xEB, 0xA5, 0xF1, 0xBE, 0x37, 0xC6, 0x38, +0xA5, 0x55, 0x63, 0x2C, 0x4A, 0xE6, 0x85, 0x28, +0x75, 0x05, 0x64, 0x85, 0x32, 0xE1, 0x2A, 0x61, +0x3A, 0xE4, 0x53, 0x86, 0x19, 0xC1, 0x32, 0x64, +0x53, 0x89, 0x5B, 0x8A, 0x32, 0x45, 0x19, 0x82, +0x42, 0xE5, 0x21, 0xE2, 0x2A, 0x23, 0x2A, 0x23, +0x21, 0xE3, 0x42, 0xE6, 0x5B, 0xE9, 0x5C, 0x09, +0x4B, 0x87, 0x4B, 0x87, 0x4B, 0x87, 0x43, 0x47, +0x43, 0x47, 0x43, 0x26, 0x32, 0xA5, 0x43, 0x08, +0x7B, 0xAD, 0x73, 0x6C, 0x63, 0x0B, 0x73, 0x6C, +0x7B, 0xCD, 0x94, 0x4F, 0x9C, 0x90, 0x94, 0x4F, +0x83, 0xCD, 0x83, 0xCD, 0x84, 0x0D, 0x7B, 0xCD, +0x73, 0x8B, 0x94, 0x2D, 0x94, 0x0D, 0x94, 0x2D, +0x94, 0x4E, 0x8C, 0x4E, 0x83, 0xED, 0x9C, 0x90, +0xA4, 0xF1, 0xB5, 0x73, 0xBD, 0xB3, 0xCD, 0xF4, +0xCD, 0xF4, 0xC5, 0xB2, 0xD6, 0x14, 0xCD, 0xD3, +0xBD, 0x92, 0xBD, 0x93, 0xC5, 0xF4, 0xCD, 0xF4, +0xD6, 0x35, 0xD6, 0x35, 0xDE, 0x55, 0xDE, 0x55, +0xDE, 0x55, 0xA4, 0xAF, 0xBD, 0x72, 0xCD, 0xF4, +0xA4, 0x8E, 0xAC, 0xF0, 0xB5, 0x10, 0xB5, 0x31, +0xB5, 0x30, 0xAC, 0xCF, 0xB5, 0x10, 0xBD, 0x92, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x92, 0xCD, 0xD3, +0xC5, 0xB3, 0xC5, 0xB3, 0xBD, 0x71, 0xAC, 0xEF, +0x63, 0x48, 0x42, 0xA5, 0x5B, 0x89, 0x7C, 0x4D, +0x6C, 0x0B, 0x53, 0xA7, 0x43, 0x45, 0x4B, 0x45, +0x53, 0x66, 0x9D, 0x4E, 0xAD, 0x0F, 0x9C, 0xAE, +0x9C, 0x6E, 0x94, 0x6E, 0x8C, 0x4E, 0x8C, 0x2E, +0x94, 0x6F, 0x6B, 0x6A, 0xCE, 0xB5, 0xC6, 0x74, +0x9C, 0xEF, 0xBD, 0xD2, 0x9C, 0xAE, 0x94, 0x4E, +0x94, 0x4E, 0x94, 0x4D, 0x7B, 0xAC, 0x6B, 0x2A, +0x62, 0xE9, 0x5B, 0x09, 0x95, 0x0D, 0x9D, 0x6D, +0xBE, 0xB3, 0xAE, 0x32, 0x8C, 0xCF, 0xBE, 0x74, +0xC6, 0xF4, 0xC6, 0xD4, 0xB6, 0x52, 0xB6, 0x73, +0x74, 0x6C, 0x7C, 0xAD, 0x6B, 0xCA, 0x63, 0xAA, +0x7C, 0x4C, 0x84, 0x8C, 0x94, 0xED, 0x8C, 0xEC, +0x74, 0x68, 0x84, 0xCB, 0xA5, 0x30, 0x84, 0x2D, +0x6B, 0x8B, 0xD6, 0xD7, 0xDF, 0x59, 0x7C, 0x8D, +0x6C, 0x2A, 0x74, 0x6A, 0x7C, 0xAB, 0x74, 0x8B, +0x7C, 0x6C, 0x6B, 0xA9, 0xB6, 0x13, 0xCE, 0xB5, +0xBE, 0x74, 0xBE, 0x54, 0xAD, 0x70, 0xC6, 0x32, +0xD6, 0xD5, 0x8C, 0xED, 0x6C, 0x09, 0x53, 0xA7, +0x74, 0x8B, 0x74, 0x8B, 0x32, 0x83, 0x3A, 0xE4, +0x6C, 0x88, 0x53, 0xE4, 0x64, 0x27, 0x74, 0x29, +0x9D, 0x4E, 0x74, 0x69, 0x84, 0xCB, 0x6B, 0xEA, +0x84, 0xAF, 0xAD, 0xB2, 0x9D, 0x71, 0x74, 0x4B, +0x3B, 0x23, 0x4B, 0xA5, 0x64, 0x47, 0x2A, 0x81, +0x19, 0xE1, 0x22, 0x02, 0x3A, 0xE4, 0x64, 0x68, +0x95, 0xAD, 0xA6, 0x10, 0xAE, 0x51, 0x9D, 0xF0, +0x53, 0x88, 0x19, 0xC2, 0x22, 0x03, 0x2A, 0x44, +0x53, 0xA8, 0x43, 0x06, 0x3A, 0xE5, 0x32, 0xA4, +0x53, 0x87, 0x63, 0xE9, 0x43, 0x05, 0x43, 0x26, +0x2A, 0x42, 0x53, 0xC7, 0x5C, 0x26, 0x4B, 0x64, +0x64, 0x27, 0x7C, 0xEA, 0x6C, 0x69, 0x43, 0x45, +0x6C, 0xA9, 0x42, 0xE5, 0x19, 0xA2, 0x32, 0x65, +0x3A, 0xC5, 0x43, 0x06, 0x53, 0xA9, 0x9D, 0xF1, +0x8D, 0x6F, 0x85, 0x2D, 0x85, 0x4E, 0x8D, 0x8F, +0x9E, 0x11, 0x53, 0x88, 0x4B, 0x66, 0x5B, 0xE8, +0x3A, 0xE4, 0x2A, 0x23, 0x3A, 0xA4, 0x64, 0x69, +0x95, 0xCF, 0x95, 0xAF, 0xA6, 0x31, 0x7D, 0x0C, +0x7C, 0xEB, 0x4B, 0xA6, 0x95, 0xAE, 0x6C, 0x68, +0x5C, 0x47, 0x6C, 0xA9, 0x7D, 0x0B, 0x85, 0x6C, +0x8D, 0x8D, 0x95, 0x8D, 0x6C, 0x8A, 0x8D, 0x4E, +0xAE, 0x52, 0x6C, 0x4A, 0x6C, 0x49, 0x95, 0x6D, +0x63, 0x68, 0x5B, 0x47, 0x63, 0x68, 0x83, 0x69, +0x83, 0x09, 0x6A, 0xA8, 0x62, 0x89, 0x83, 0xCF, +0x94, 0x91, 0x9C, 0xB2, 0x94, 0x92, 0x8C, 0x30, +0x83, 0xEF, 0x9C, 0xB2, 0xA4, 0xD3, 0xBD, 0xB6, +0xBD, 0xB6, 0xAD, 0x34, 0xAD, 0x14, 0xCE, 0x38, +0xD6, 0x99, 0x9C, 0x92, 0x83, 0xAF, 0x5A, 0xAB, +0x20, 0xE4, 0x31, 0x65, 0x5A, 0x8A, 0x73, 0x6D, +0x73, 0x6D, 0x83, 0xAE, 0x73, 0x2C, 0x6B, 0x0C, +0x94, 0x72, 0xD6, 0x58, 0xDE, 0x79, 0xA4, 0xD3, +0xAD, 0x14, 0xAD, 0x55, 0xB5, 0x76, 0xB5, 0x96, +0xD6, 0x9A, 0xDE, 0xBB, 0x9C, 0xD3, 0x73, 0x8E, +0x73, 0x8E, 0x94, 0x71, 0x8C, 0x30, 0x73, 0x8D, +0x63, 0x4B, 0x84, 0xAD, 0x8D, 0x4D, 0x9D, 0xCC, +0x74, 0xC5, 0x74, 0xC2, 0x85, 0x44, 0x9D, 0xE9, +0xB6, 0x71, 0xCF, 0x35, 0x95, 0xAE, 0x95, 0xA8, +0x8D, 0x64, 0x7D, 0x00, 0x85, 0x42, 0x9D, 0xC7, +0xA6, 0x0B, 0xAE, 0x4D, 0xB6, 0x6D, 0xAE, 0x49, +0x95, 0x88, 0xAD, 0xD1, 0xC6, 0x58, 0xC6, 0x38, +0x9D, 0x14, 0x42, 0x49, 0x5B, 0x68, 0x85, 0x48, +0x74, 0xE5, 0x53, 0xE3, 0x32, 0xC1, 0x2A, 0x61, +0x74, 0x8A, 0x85, 0x4B, 0x2A, 0x41, 0x3A, 0xA4, +0x7C, 0xCD, 0xAE, 0x12, 0x5B, 0xAA, 0x21, 0xC3, +0x74, 0x8A, 0x53, 0x66, 0x4B, 0x46, 0x53, 0x68, +0x64, 0x0A, 0x5B, 0xE9, 0x43, 0x46, 0x32, 0xC4, +0x2A, 0x83, 0x2A, 0x63, 0x4B, 0x67, 0x4B, 0x87, +0x53, 0xE8, 0x4B, 0x87, 0x2A, 0x63, 0x32, 0x86, +0xB5, 0x53, 0xA4, 0xF2, 0x83, 0xEE, 0x94, 0x6F, +0xAD, 0x32, 0xC5, 0xD4, 0xCD, 0xF5, 0xC5, 0xB4, +0xAD, 0x32, 0x94, 0x90, 0x94, 0x6F, 0x94, 0x6F, +0x9C, 0xD1, 0x94, 0x6E, 0x94, 0x0C, 0xB5, 0x31, +0xCE, 0x15, 0xD6, 0x76, 0xD6, 0x57, 0xD6, 0x57, +0xD6, 0x77, 0xD6, 0x57, 0xDE, 0x97, 0xC5, 0xD4, +0xD6, 0x15, 0xDE, 0x96, 0xDE, 0x96, 0xD6, 0x75, +0xD6, 0x55, 0xD6, 0x76, 0xD6, 0x77, 0xD6, 0x56, +0xD6, 0x56, 0xD6, 0x76, 0xDE, 0x96, 0xD6, 0x55, +0xDE, 0x76, 0x9C, 0x4D, 0xAC, 0xF0, 0xB5, 0x52, +0x94, 0x4E, 0x9C, 0xB0, 0xAC, 0xF0, 0xB5, 0x31, +0xC5, 0xD4, 0xC5, 0xD4, 0x9C, 0xAF, 0xA4, 0xD0, +0x94, 0x6E, 0x83, 0xCC, 0x7B, 0xAC, 0x8C, 0x0D, +0x8C, 0x2E, 0x9C, 0x8F, 0xBD, 0x92, 0xC5, 0x92, +0x9C, 0xCD, 0x63, 0x88, 0x4B, 0x06, 0x53, 0x27, +0x6C, 0x2B, 0x5B, 0xE8, 0x4B, 0x65, 0x43, 0x45, +0x53, 0x66, 0x9D, 0x2E, 0xB5, 0xAF, 0xB5, 0xAE, +0x94, 0xAC, 0x63, 0x48, 0x8C, 0x6E, 0x9C, 0xAF, +0xAD, 0x11, 0x63, 0x29, 0xC6, 0xB3, 0xC6, 0x71, +0xCE, 0xB3, 0xC6, 0x52, 0xB5, 0x90, 0xA4, 0xEE, +0xA4, 0xEE, 0xAD, 0x2E, 0xC5, 0xF2, 0xB5, 0x51, +0xB5, 0x51, 0xAD, 0x10, 0xA5, 0x0F, 0xAD, 0xD0, +0xBE, 0xB4, 0xC7, 0x16, 0xAE, 0x32, 0x9D, 0xCE, +0x7C, 0xEA, 0x8D, 0x2D, 0xB6, 0x72, 0xB6, 0x32, +0x8D, 0x0E, 0x74, 0x6C, 0x74, 0x2B, 0x63, 0xC9, +0x6B, 0xE9, 0x5B, 0x66, 0x63, 0xA7, 0x8D, 0x0C, +0x7C, 0x89, 0x8C, 0xEB, 0x9D, 0x6F, 0x7C, 0x4C, +0x95, 0x10, 0xE7, 0x79, 0x9D, 0x30, 0x74, 0x6B, +0x74, 0xAB, 0x6C, 0x28, 0x7C, 0xAB, 0x8D, 0x0E, +0x6B, 0xCA, 0x6B, 0xAA, 0xC6, 0x53, 0xAD, 0xD0, +0xBE, 0x94, 0xBE, 0x95, 0xBE, 0x54, 0xB5, 0xB0, +0xD6, 0x93, 0xCE, 0xB3, 0x9D, 0x4E, 0x74, 0x8A, +0x7C, 0xCB, 0xA5, 0xCF, 0x43, 0x26, 0x3A, 0xE4, +0x5B, 0xE5, 0x4B, 0xA4, 0x7C, 0xCA, 0x5B, 0x67, +0x6B, 0xE9, 0x7C, 0xAA, 0x53, 0x86, 0x3A, 0x84, +0x9D, 0x73, 0xAD, 0xB4, 0xA5, 0xB4, 0x6C, 0x0C, +0x43, 0x45, 0x5C, 0x27, 0x32, 0xC2, 0x19, 0xE1, +0x19, 0xA1, 0x11, 0x80, 0x19, 0xE2, 0x3A, 0xC4, +0x8D, 0x6D, 0xA6, 0x51, 0x9D, 0xF0, 0x4A, 0xE7, +0x09, 0x00, 0x19, 0x62, 0x2A, 0x24, 0x4B, 0x27, +0x7D, 0x0C, 0x64, 0x48, 0x5C, 0x07, 0x53, 0xC6, +0x6C, 0x8A, 0x6C, 0x8A, 0x4B, 0x65, 0x53, 0xC7, +0x4B, 0x45, 0x32, 0xA2, 0x4B, 0x84, 0x53, 0xE5, +0x64, 0x47, 0x53, 0xC6, 0x2A, 0x02, 0x09, 0x00, +0x42, 0xE6, 0x42, 0xC6, 0x21, 0xA2, 0x22, 0x03, +0x22, 0x22, 0x2A, 0x43, 0x64, 0x2A, 0x95, 0x90, +0x95, 0xB0, 0x9D, 0xF1, 0xA6, 0x12, 0xA6, 0x52, +0x74, 0x8C, 0x32, 0x85, 0x4B, 0x47, 0x5C, 0x09, +0x4B, 0x46, 0x3A, 0x84, 0x3A, 0xA5, 0x5B, 0xE7, +0x74, 0xCB, 0x95, 0xAF, 0xA6, 0x31, 0x7D, 0x0C, +0x8D, 0x6E, 0x64, 0x49, 0xBE, 0xF3, 0x8D, 0x6C, +0x5C, 0x47, 0x53, 0xE6, 0x43, 0x64, 0x3B, 0x44, +0x8D, 0x4C, 0x9D, 0xCE, 0x9D, 0xCD, 0x85, 0x2B, +0x85, 0x2C, 0x6C, 0x89, 0x95, 0x8C, 0x95, 0x8D, +0x8C, 0xCC, 0x6B, 0xE8, 0x5B, 0x86, 0x73, 0xA7, +0x7B, 0x28, 0x52, 0x07, 0x73, 0x2C, 0x83, 0xEF, +0x94, 0x71, 0x94, 0x50, 0x94, 0x71, 0x8C, 0x0F, +0x8C, 0x30, 0xA4, 0xF3, 0x8C, 0x10, 0x9C, 0xB3, +0x9C, 0x92, 0x94, 0x51, 0xA4, 0xD3, 0xB5, 0x75, +0xC5, 0xF7, 0xAD, 0x55, 0xD6, 0x58, 0xBD, 0xB6, +0x73, 0x8E, 0x4A, 0x08, 0x41, 0xC7, 0x62, 0xEB, +0x62, 0xCA, 0x83, 0xCF, 0x73, 0x2C, 0x52, 0x69, +0xA4, 0xD3, 0xD6, 0x58, 0xCD, 0xF7, 0xAD, 0x14, +0x7B, 0xCF, 0xAD, 0x55, 0xB5, 0x96, 0xDE, 0xBB, +0xDE, 0xBB, 0xB5, 0x96, 0x6B, 0x4D, 0x94, 0x93, +0xAD, 0x35, 0x7B, 0xCF, 0x6B, 0x2C, 0xAD, 0x34, +0x84, 0x2F, 0x63, 0x8A, 0x84, 0xED, 0x85, 0x2B, +0x85, 0x27, 0x7C, 0xE4, 0x95, 0xA7, 0xA6, 0x2B, +0x95, 0xAD, 0xBE, 0xF4, 0xBE, 0xF4, 0x9D, 0xCC, +0x7D, 0x03, 0x74, 0xC0, 0x85, 0x43, 0x8D, 0x86, +0x9D, 0xE9, 0x9E, 0x09, 0x9D, 0xE8, 0xA6, 0x26, +0x95, 0x68, 0xA5, 0xB1, 0xCE, 0x99, 0xC6, 0x38, +0x94, 0xB3, 0x3A, 0x08, 0x74, 0x4B, 0x8D, 0x49, +0x7D, 0x05, 0x4B, 0xA2, 0x32, 0xC2, 0x32, 0xA2, +0x95, 0xAC, 0x95, 0xCA, 0x53, 0xC4, 0x22, 0x01, +0x8D, 0x4F, 0xBE, 0xD5, 0x63, 0xCB, 0x53, 0x47, +0x9D, 0x8B, 0x63, 0xE5, 0x5B, 0xE8, 0x74, 0xAC, +0x6C, 0x6B, 0x3A, 0xE6, 0x11, 0x81, 0x32, 0x44, +0x3A, 0xE5, 0x4B, 0x87, 0x5C, 0x29, 0x53, 0xC7, +0x64, 0x49, 0x4B, 0x86, 0x22, 0x22, 0x4B, 0x07, +0xBD, 0xB4, 0xC5, 0xD4, 0xBD, 0x93, 0xC5, 0xD4, +0xCE, 0x35, 0xC5, 0xD4, 0xBD, 0x73, 0xCE, 0x15, +0xD6, 0x55, 0xCE, 0x35, 0xCE, 0x15, 0xC5, 0xF5, +0xCE, 0x15, 0x94, 0x4E, 0x8B, 0xEC, 0xCD, 0xF3, +0xD6, 0x76, 0xD6, 0x76, 0xDE, 0x97, 0xDE, 0xB7, +0xDE, 0xB8, 0xCE, 0x36, 0xD6, 0x56, 0xCD, 0xF4, +0xBD, 0xB3, 0xC5, 0xF4, 0xD6, 0x76, 0xDE, 0x96, +0xD6, 0x56, 0xD6, 0x76, 0xDE, 0x97, 0xD6, 0x76, +0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x76, 0xD6, 0x56, +0xDE, 0x76, 0x9C, 0x6E, 0xA4, 0xD0, 0xBD, 0x93, +0x94, 0x6F, 0xA4, 0xF1, 0xAC, 0xF1, 0xA4, 0xD0, +0xA4, 0xF1, 0xAD, 0x12, 0xAD, 0x11, 0xBD, 0xB4, +0xBD, 0x93, 0x9C, 0x70, 0x6B, 0x0A, 0x73, 0x6C, +0x73, 0x6C, 0x84, 0x0E, 0x94, 0x4E, 0x8C, 0x0C, +0x8C, 0x4B, 0x5B, 0x47, 0x32, 0x84, 0x32, 0x84, +0x42, 0xE5, 0x53, 0xA7, 0x4B, 0x65, 0x64, 0x28, +0x74, 0x6A, 0x9D, 0x4D, 0xA5, 0xAC, 0x9D, 0xAA, +0x9D, 0x8B, 0x8D, 0x0B, 0x74, 0x4A, 0x84, 0x6D, +0xAD, 0x92, 0x63, 0x4A, 0xAD, 0xD0, 0xAD, 0xEF, +0x9D, 0x0D, 0xA5, 0x2E, 0xA5, 0x0E, 0xAD, 0x4E, +0xA5, 0x6D, 0xAD, 0xAF, 0xC6, 0x12, 0xB5, 0x71, +0xB5, 0x51, 0x94, 0x6E, 0x7B, 0xEC, 0x94, 0xEE, +0xA5, 0xF2, 0xB6, 0x94, 0xAE, 0x12, 0x7C, 0xAB, +0x4B, 0x85, 0x8D, 0x6E, 0x9D, 0x8F, 0x95, 0x4E, +0x95, 0x6F, 0xA5, 0xD2, 0x74, 0x4B, 0x63, 0xA9, +0x8C, 0xCD, 0x84, 0x6A, 0x63, 0xA7, 0x95, 0x4D, +0x84, 0xCB, 0x7C, 0xCA, 0x8C, 0xEB, 0x94, 0xEC, +0xB6, 0x33, 0x9D, 0x50, 0x7C, 0x8C, 0x74, 0x8A, +0x5B, 0xE8, 0x5B, 0xA7, 0x74, 0x8B, 0x84, 0xCD, +0x9D, 0x71, 0xAD, 0xD3, 0xB6, 0x12, 0xB5, 0xF0, +0xBE, 0x53, 0x9D, 0x50, 0xB6, 0x54, 0xC6, 0x95, +0xB5, 0xD0, 0xCE, 0xB2, 0xBE, 0x30, 0x84, 0xAA, +0x63, 0xE8, 0x5B, 0xC7, 0x4B, 0x86, 0x4B, 0x65, +0x5B, 0xE6, 0x3A, 0xE2, 0x53, 0x87, 0x5B, 0xC8, +0x6C, 0x6A, 0x63, 0xE7, 0x43, 0x25, 0x53, 0x28, +0x9D, 0x53, 0xBE, 0x77, 0xBE, 0x77, 0x7C, 0xAE, +0x64, 0x49, 0x43, 0x64, 0x2A, 0x81, 0x19, 0xE1, +0x53, 0x67, 0x42, 0xC5, 0x2A, 0x23, 0x2A, 0x23, +0x32, 0x63, 0x4B, 0x67, 0x32, 0x44, 0x11, 0x21, +0x11, 0x41, 0x19, 0x82, 0x2A, 0x44, 0x43, 0x06, +0x74, 0xAA, 0x74, 0xCA, 0x6C, 0x89, 0x64, 0x28, +0x7C, 0xCB, 0x74, 0xAA, 0x53, 0xC6, 0x53, 0xE6, +0x5B, 0xE7, 0x4B, 0x85, 0x53, 0xA6, 0x5C, 0x26, +0x53, 0xE6, 0x32, 0x82, 0x2A, 0x03, 0x19, 0x82, +0x21, 0xE3, 0x21, 0xA2, 0x3A, 0xA5, 0x3A, 0xA5, +0x19, 0xE1, 0x32, 0xA4, 0x6C, 0x8A, 0x8D, 0x6F, +0xA6, 0x32, 0xAE, 0x53, 0x95, 0xD0, 0x7C, 0xCD, +0x2A, 0x64, 0x32, 0x85, 0x43, 0x26, 0x5B, 0xC8, +0x5C, 0x09, 0x53, 0xA7, 0x74, 0xCB, 0x74, 0xEA, +0x7D, 0x0C, 0x95, 0xD0, 0xA6, 0x31, 0x74, 0xCB, +0x53, 0xC8, 0x7C, 0xCB, 0xAE, 0x70, 0xA6, 0x2F, +0x95, 0xCE, 0x85, 0x4B, 0x7D, 0x0B, 0x53, 0xE6, +0x95, 0x8D, 0xA6, 0x0F, 0x95, 0x8C, 0x95, 0xAC, +0x8D, 0x4C, 0x7D, 0x0A, 0x7C, 0xE9, 0x4B, 0x24, +0x31, 0xA2, 0x42, 0x24, 0x5B, 0x66, 0x74, 0x68, +0x84, 0x2A, 0x8C, 0x0F, 0x9C, 0x92, 0x8C, 0x10, +0x9C, 0xB2, 0xA4, 0xD3, 0xA4, 0xF3, 0x8C, 0x30, +0x83, 0xEF, 0xCE, 0x38, 0xA5, 0x13, 0x62, 0xCB, +0x73, 0x8E, 0x9C, 0x92, 0x8C, 0x51, 0x84, 0x10, +0x94, 0x92, 0xB5, 0x75, 0xD6, 0x79, 0xAD, 0x55, +0xC6, 0x18, 0xBD, 0x96, 0x8C, 0x31, 0x7B, 0xAE, +0x52, 0x49, 0x73, 0x2C, 0x7B, 0xAE, 0x7B, 0xAE, +0xAD, 0x34, 0xD6, 0x38, 0xD6, 0x58, 0xBD, 0x96, +0x94, 0x51, 0x9C, 0xB3, 0xDE, 0xBB, 0xD6, 0x7A, +0xAD, 0x76, 0x73, 0xAF, 0x6B, 0x4D, 0x84, 0x10, +0x94, 0x71, 0x8C, 0x51, 0x7B, 0xCF, 0xA4, 0xF3, +0x7B, 0xEF, 0x5B, 0x0B, 0xA5, 0x92, 0x84, 0xED, +0x85, 0x09, 0x8D, 0x48, 0x95, 0xCA, 0x9D, 0xEB, +0x95, 0x8A, 0x9D, 0xCD, 0xA6, 0x10, 0x9E, 0x0D, +0x7D, 0x26, 0x64, 0x60, 0x6C, 0xC2, 0x8D, 0x46, +0x9E, 0x09, 0x95, 0xA6, 0x95, 0xA4, 0xA6, 0x26, +0x8D, 0x48, 0xA5, 0x92, 0xCE, 0x79, 0xBE, 0x38, +0x84, 0x31, 0x3A, 0x06, 0x84, 0xED, 0x85, 0x29, +0x74, 0xC6, 0x5C, 0x25, 0x32, 0xC1, 0x53, 0xA6, +0x95, 0xCC, 0x85, 0x47, 0x74, 0xE6, 0x32, 0x82, +0x84, 0xED, 0xB6, 0x94, 0x53, 0x69, 0x63, 0xA8, +0x9D, 0xAC, 0x53, 0x65, 0x42, 0xE5, 0x2A, 0x63, +0x22, 0x23, 0x3A, 0xA5, 0x3A, 0xC5, 0x43, 0x27, +0x43, 0x46, 0x3A, 0xC4, 0x3B, 0x05, 0x53, 0xC7, +0x64, 0x29, 0x3A, 0xC4, 0x09, 0x00, 0x21, 0xE4, diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c new file mode 100644 index 00000000..7b222be7 --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c @@ -0,0 +1,306 @@ +/* + * lws-minimal-esp32 + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * Configured for ESP32 WROVER KIT + */ + +#define LWIP_PROVIDE_ERRNO 1 +#define _ESP_PLATFORM_ERRNO_H_ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_spi_flash.h" +#include "esp_wifi.h" +#include +#include +#include + +#include + +struct lws_context *context; +lws_sorted_usec_list_t sul; +struct lws_led_state *lls; +lws_display_state_t lds; +int interrupted; + +static const uint8_t logo[] = { +#include "cat-565.h" +}; + +/* + * Button controller + * + * On the WROVER KIT, it's a bit overloaded... the two buttons are reset and + * gpio0, gpio is also used for one of the RGB LEDs channels control so it's not + * really usable as a general user button. + * + * Instead we use GPIO 14 (available on J1) for a button with the other side + * of the switch connected to 0V. + */ + +static const lws_button_map_t bcm[] = { + { + .gpio = GPIO_NUM_14, + .smd_interaction_name = "user" + }, +}; + +static const lws_button_controller_t bc = { + .smd_bc_name = "bc", + .gpio_ops = &lws_gpio_plat, + .button_map = &bcm[0], + .active_state_bitmap = 0, + .count_buttons = LWS_ARRAY_SIZE(bcm), +}; + +/* + * pwm controller + */ + +static const lws_pwm_map_t pwm_map[] = { + { .gpio = GPIO_NUM_2, .index = 0, .active_level = 1 }, + { .gpio = GPIO_NUM_0, .index = 1, .active_level = 1 }, + { .gpio = GPIO_NUM_4, .index = 2, .active_level = 1 }, + { .gpio = GPIO_NUM_5, .index = 3, .active_level = 0 } +}; + +static const lws_pwm_ops_t pwm_ops = { + lws_pwm_plat_ops, + .pwm_map = &pwm_map[0], + .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) +}; + +/* + * led controller + */ + +static const lws_led_gpio_map_t lgm[] = { + { + .name = "red", + .gpio = GPIO_NUM_2, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, + { + .name = "green", + .gpio = GPIO_NUM_0, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, + { + .name = "blue", + .gpio = GPIO_NUM_4, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, + { + .name = "backlight", + .gpio = GPIO_NUM_5, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 0, + /* + * The wrover kit uses a 2 NPN in series to drive the backlight + * which means if the GPIO provides no current, the backlight is + * full-on. This causes a white flash during boot... they mark + * the first stage with "Modify In ESP-WROVER-KIT!" on the + * schematics but on Kit v4.1, it's still like that. + */ + }, +}; + +static const lws_led_gpio_controller_t lgc = { + .led_ops = lws_led_gpio_ops, + .gpio_ops = &lws_gpio_plat, + .led_map = &lgm[0], + .count_leds = LWS_ARRAY_SIZE(lgm) +}; + +/* + * Bitbang SPI configuration for display + */ + +static const lws_bb_spi_t lbspi = { + .bb_ops = { + lws_bb_spi_ops, + .bus_mode = LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_RISING + }, + .gpio = &lws_gpio_plat, + .clk = GPIO_NUM_19, + .ncs = { GPIO_NUM_22 }, + .ncmd = { GPIO_NUM_21 }, + .mosi = GPIO_NUM_23, + .miso = GPIO_NUM_25, + .flags = LWSBBSPI_FLAG_USE_NCS0 | + LWSBBSPI_FLAG_USE_NCMD0 +}; + +/* + * SPI display + */ + +static const lws_display_ili9341_t disp = { + .disp = { + lws_display_ili9341_ops, + .bl_pwm_ops = &pwm_ops, + .bl_active = &lws_pwmseq_static_on, + .bl_dim = &lws_pwmseq_static_half, + .bl_transition = &lws_pwmseq_linear_wipe, + .bl_index = 3, + .w = 320, + .h = 240, + .latency_wake_ms = 150, + }, + .spi = (lws_spi_ops_t *)&lbspi, + .gpio = &lws_gpio_plat, + .reset_gpio = GPIO_NUM_18, + .spi_index = 0 +}; + + + +static uint8_t flip; + +static const lws_led_sequence_def_t *seqs[] = { + &lws_pwmseq_static_on, + &lws_pwmseq_static_off, + &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_sine_endless_fast, +}; + +static int +smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf, + size_t len) +{ + + if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user")) { + if (!lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { + lws_led_transition(lls, "blue", seqs[flip & 3], + &lws_pwmseq_linear_wipe); + flip++; + } + } + + lwsl_hexdump_notice(buf, len); + + /* + * Any kind of user interaction brings the display back up and resets + * the dimming and blanking timers + */ + lws_display_state_active(&lds); + + return 0; +} + +static void +sul_cb(lws_sorted_usec_list_t *sul) +{ + /* In CI, we use sai-expect to look for this string for success */ + lwsl_notice("Completed: PASS\n"); +} + +void +app_main(void) +{ + wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); + struct lws_context_creation_info info; + struct lws_button_state *bcs; + int n = 0; + + lws_set_log_level(1024 | 15, NULL); + nvs_flash_init(); + esp_netif_init(); + + n = esp_wifi_init(&wic); + if (n) { + lwsl_err("%s: wifi init fail: %d\n", __func__, n); + goto spin; + } + + memset(&info, 0, sizeof(info)); + + lwsl_notice("LWS test for Espressif ESP32 WROVER KIT\n"); + + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN; + info.early_smd_cb = smd_cb; + info.early_smd_class_filter = LWSSMDCL_INTERACTION; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return; + } + + /* bring up the led controller */ + + lls = lgc.led_ops.create(&lgc.led_ops); + if (!lls) { + lwsl_err("%s: could not create led\n", __func__); + goto spin; + } + + /* pwm init must go after the led controller init */ + + pwm_ops.init(&pwm_ops); + + /* ... and the button controller */ + + bcs = lws_button_controller_create(context, &bc); + if (!bcs) { + lwsl_err("%s: could not create buttons\n", __func__); + goto spin; + } + + lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); + + /* ... bring up spi bb and the display */ + + lbspi.bb_ops.init(&lbspi.bb_ops); + lws_display_state_init(&lds, context, 30000, 10000, lls, &disp.disp); + + /* put the cat picture up there and enable the backlight */ + + disp.disp.blit(lds.disp, logo, 0, 0, 320, 240); + lws_display_state_active(&lds); + + /* + * Make the RGB LED do something using sequenced PWM... pressing the + * GPIO14 button with single-presses advances the blue channel between + * different sequences + */ + + lws_sul_schedule(context, 0, &sul, sul_cb, 3 * LWS_USEC_PER_SEC); + lws_led_transition(lls, "blue", &lws_pwmseq_sine_endless_fast, + &lws_pwmseq_linear_wipe); + lws_led_transition(lls, "green", &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_linear_wipe); + lws_led_transition(lls, "red", &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_linear_wipe); + + /* + * We say the test succeeded if we survive 3s around the event loop + */ + + while (n >= 0 && !interrupted) { + n = lws_service(context, 0); + taskYIELD(); + } + + lws_context_destroy(context); + +// fflush(stdout); +// esp_restart(); + +spin: + vTaskDelay(10); + taskYIELD(); + goto spin; +} diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/partitions.csv b/minimal-examples/embedded/esp32/esp-wrover-kit/partitions.csv new file mode 100644 index 00000000..e261b7cb --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/partitions.csv @@ -0,0 +1,5 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 2M, diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/rgb565/rgb565.c b/minimal-examples/embedded/esp32/esp-wrover-kit/rgb565/rgb565.c new file mode 100644 index 00000000..89b49991 --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/rgb565/rgb565.c @@ -0,0 +1,26 @@ +/* + * gcc /tmp/q.c && convert cat-565.png -depth 8 rgb:- | ./a.out > cat-565.h + */ + +#include + +int main() +{ + int r, g, b, w, m = 0; + + while (1) { + r = getchar(); + g = getchar(); + b = getchar(); + + if (r == EOF || g == EOF || b == EOF) + return r == EOF; + + w = (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); + printf("0x%02X, 0x%02X, ", (w >> 8) & 0xFF, w & 0xFF); + + if (((++m) & 3) == 0) + printf("\n"); + } +} + diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig b/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig new file mode 100644 index 00000000..b60902c0 --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig @@ -0,0 +1,1151 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_TARGET_ESP32=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +# +# Bootloader config +# +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +# CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V is not set +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_TRAX is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 +CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 +CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1 +CONFIG_BT_RESERVE_DRAM=0 +# end of Bluetooth + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# end of ADC configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# RTCIO configuration +# +# CONFIG_RTCIO_SUPPORT_RTC_GPIO_DESC is not set +# end of RTCIO configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE is not set +CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT is not set +CONFIG_EFUSE_MAX_BLK_LEN=192 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# end of ESP-TLS + +# +# ESP32-specific +# +CONFIG_ESP32_REV_MIN_0=y +# CONFIG_ESP32_REV_MIN_1 is not set +# CONFIG_ESP32_REV_MIN_2 is not set +# CONFIG_ESP32_REV_MIN_3 is not set +CONFIG_ESP32_REV_MIN=0 +CONFIG_ESP32_DPORT_WORKAROUND=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 +# CONFIG_ESP32_SPIRAM_SUPPORT is not set +# CONFIG_ESP32_TRAX is not set +CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32_ULP_COPROC_ENABLED is not set +CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_BROWNOUT_DET=y +CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_ESP32_BROWNOUT_DET_LVL=0 +CONFIG_ESP32_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32_XTAL_FREQ_40=y +# CONFIG_ESP32_XTAL_FREQ_26 is not set +# CONFIG_ESP32_XTAL_FREQ_AUTO is not set +CONFIG_ESP32_XTAL_FREQ=40 +# CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_ESP32_NO_BLOBS is not set +# CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +# CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set +CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5 +# end of ESP32-specific + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +# end of Power Management + +# +# ADC-Calibration +# +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_TX_GPIO=1 +CONFIG_ESP_CONSOLE_UART_RX_GPIO=3 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ETH_PHY_INTERFACE_RMII=y +# CONFIG_ETH_PHY_INTERFACE_MII is not set +CONFIG_ETH_RMII_CLK_INPUT=y +# CONFIG_ETH_RMII_CLK_OUTPUT is not set +CONFIG_ETH_RMII_CLK_IN_GPIO=0 +CONFIG_ETH_DMA_BUFFER_SIZE=512 +CONFIG_ETH_DMA_RX_BUFFER_NUM=10 +CONFIG_ETH_DMA_TX_BUFFER_NUM=10 +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIMER_TASK_STACK_SIZE=6584 +# CONFIG_ESP_TIMER_IMPL_FRC2 is not set +CONFIG_ESP_TIMER_IMPL_TG0_LAC=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +# CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# end of Wi-Fi + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# end of PHY + +# +# Core dump +# +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_SERIAL_TASK_PRIO=10 +# CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_FMB_TIMER_PORT_ENABLED=y +CONFIG_FMB_TIMER_GROUP=0 +CONFIG_FMB_TIMER_INDEX=0 +# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set +# end of Modbus configuration + +# +# FreeRTOS +# +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=6048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +# end of FreeRTOS + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_FRAG=y +# CONFIG_LWIP_IP_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set + +# +# DHCP server +# +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=6 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set + +# +# ICMP +# +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_ESP_LWIP_ASSERT=y +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# end of NVS + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +# end of Auto-detect flash chips +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TinyUSB +# + +# +# Descriptor configuration +# +CONFIG_USB_DESC_CUSTOM_VID=0x1234 +CONFIG_USB_DESC_CUSTOM_PID=0x5678 +# end of Descriptor configuration +# end of TinyUSB + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_TLS_V12 is not set +# CONFIG_WPA_WPS_WARS is not set +# end of Supplicant +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_SPIRAM_SUPPORT is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set +# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_TX_GPIO=1 +CONFIG_CONSOLE_UART_RX_GPIO=3 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_GDBSTUB is not set +CONFIG_TIMER_TASK_STACK_SIZE=6584 +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +# CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_MB_TIMER_PORT_ENABLED=y +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=6048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# End of deprecated options diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h b/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h new file mode 100644 index 00000000..b2cc0030 --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h @@ -0,0 +1,426 @@ +/* + * Automatically generated file. DO NOT EDIT. + * Espressif IoT Development Framework (ESP-IDF) Configuration Header + */ +#pragma once +#define CONFIG_IDF_CMAKE 1 +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 +#define CONFIG_SDK_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1 +#define CONFIG_APP_BUILD_GENERATE_BINARIES 1 +#define CONFIG_APP_BUILD_BOOTLOADER 1 +#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1 +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 16 +#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL_INFO 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL 3 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_ESPTOOLPY_FLASHSIZE_4MB 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "4MB" +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B 1 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_COMPILER_OPTIMIZATION_DEFAULT 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE 1 +#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1 +#define CONFIG_APPTRACE_DEST_NONE 1 +#define CONFIG_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0 +#define CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0 +#define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1 +#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_COAP_MBEDTLS_PSK 1 +#define CONFIG_COAP_LOG_DEFAULT_LEVEL 0 +#define CONFIG_ADC_DISABLE_DAC 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_ESP_TLS_USING_MBEDTLS 1 +#define CONFIG_ESP32_REV_MIN_0 1 +#define CONFIG_ESP32_REV_MIN 0 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ESP32_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_ESP32_BROWNOUT_DET 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP32_BROWNOUT_DET_LVL 0 +#define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESP32_RTC_CLK_SRC_INT_RC 1 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_ESP32_XTAL_FREQ_40 1 +#define CONFIG_ESP32_XTAL_FREQ 40 +#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 +#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 +#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 +#define CONFIG_ESP_CONSOLE_UART_NUM 0 +#define CONFIG_ESP_CONSOLE_UART_TX_GPIO 1 +#define CONFIG_ESP_CONSOLE_UART_RX_GPIO 3 +#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_ESP_INT_WDT 1 +#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESP_INT_WDT_CHECK_CPU1 1 +#define CONFIG_ESP_TASK_WDT 1 +#define CONFIG_ESP_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH 1 +#define CONFIG_ETH_ENABLED 1 +#define CONFIG_ETH_USE_ESP32_EMAC 1 +#define CONFIG_ETH_PHY_INTERFACE_RMII 1 +#define CONFIG_ETH_RMII_CLK_INPUT 1 +#define CONFIG_ETH_RMII_CLK_IN_GPIO 0 +#define CONFIG_ETH_DMA_BUFFER_SIZE 512 +#define CONFIG_ETH_DMA_RX_BUFFER_NUM 10 +#define CONFIG_ETH_DMA_TX_BUFFER_NUM 10 +#define CONFIG_ETH_USE_SPI_ETHERNET 1 +#define CONFIG_ESP_EVENT_POST_FROM_ISR 1 +#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_ESP_NETIF_TCPIP_LWIP 1 +#define CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER 1 +#define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 +#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 6584 +#define CONFIG_ESP_TIMER_IMPL_TG0_LAC 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_ESP32_WIFI_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_RX_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_FMB_COMM_MODE_RTU_EN 1 +#define CONFIG_FMB_COMM_MODE_ASCII_EN 1 +#define CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND 150 +#define CONFIG_FMB_MASTER_DELAY_MS_CONVERT 200 +#define CONFIG_FMB_QUEUE_LENGTH 20 +#define CONFIG_FMB_SERIAL_TASK_STACK_SIZE 2048 +#define CONFIG_FMB_SERIAL_BUF_SIZE 256 +#define CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB 8 +#define CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS 1000 +#define CONFIG_FMB_SERIAL_TASK_PRIO 10 +#define CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT 20 +#define CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 +#define CONFIG_FMB_CONTROLLER_STACK_SIZE 4096 +#define CONFIG_FMB_EVENT_QUEUE_TIMEOUT 20 +#define CONFIG_FMB_TIMER_PORT_ENABLED 1 +#define CONFIG_FMB_TIMER_GROUP 0 +#define CONFIG_FMB_TIMER_INDEX 0 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 +#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 6048 +#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1 +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_HEAP_TRACING_OFF 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 +#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif" +#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define CONFIG_LWIP_TIMERS_ONDEMAND 1 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_LWIP_IP_FRAG 1 +#define CONFIG_LWIP_ESP_GRATUITOUS_ARP 1 +#define CONFIG_LWIP_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_LWIP_TCP_MAXRTX 12 +#define CONFIG_LWIP_TCP_SYNMAXRTX 6 +#define CONFIG_LWIP_TCP_MSS 1440 +#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 +#define CONFIG_LWIP_TCP_MSL 60000 +#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_LWIP_TCP_WND_DEFAULT 5744 +#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1 +#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 +#define CONFIG_LWIP_ESP_LWIP_ASSERT 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN 1 +#define CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#define CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN 4096 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL 1 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_MBEDTLS_HARDWARE_MPI 1 +#define CONFIG_MBEDTLS_HARDWARE_SHA 1 +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_MBEDTLS_PSK_MODES 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_SSL_PROTO_DTLS 1 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_MDNS_MAX_SERVICES 10 +#define CONFIG_MDNS_TASK_PRIORITY 1 +#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 +#define CONFIG_MDNS_TASK_AFFINITY 0x0 +#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 2000 +#define CONFIG_MDNS_TIMER_PERIOD_MS 100 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_OPENSSL_ASSERT_EXIT 1 +#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY 1 +#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_USB_DESC_CUSTOM_VID 0x1234 +#define CONFIG_USB_DESC_CUSTOM_PID 0x5678 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_VFS_SUPPORT_IO 1 +#define CONFIG_VFS_SUPPORT_DIR 1 +#define CONFIG_VFS_SUPPORT_SELECT 1 +#define CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_VFS_SUPPORT_TERMIOS 1 +#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 +#define CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN 128 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30 +#define CONFIG_WPA_MBEDTLS_CRYPTO 1 + +/* List of deprecated options */ +#define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC +#define CONFIG_BROWNOUT_DET CONFIG_ESP32_BROWNOUT_DET +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0 +#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE +#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT +#define CONFIG_CONSOLE_UART_RX_GPIO CONFIG_ESP_CONSOLE_UART_RX_GPIO +#define CONFIG_CONSOLE_UART_TX_GPIO CONFIG_ESP_CONSOLE_UART_TX_GPIO +#define CONFIG_ESP32S2_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY +#define CONFIG_ESP32_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC CONFIG_ESP32_RTC_CLK_SRC_INT_RC +#define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP +#define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR +#define CONFIG_GARP_TMR_INTERVAL CONFIG_LWIP_GARP_TMR_INTERVAL +#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT +#define CONFIG_INT_WDT_CHECK_CPU1 CONFIG_ESP_INT_WDT_CHECK_CPU1 +#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS +#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO +#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT +#define CONFIG_MB_CONTROLLER_STACK_SIZE CONFIG_FMB_CONTROLLER_STACK_SIZE +#define CONFIG_MB_EVENT_QUEUE_TIMEOUT CONFIG_FMB_EVENT_QUEUE_TIMEOUT +#define CONFIG_MB_MASTER_DELAY_MS_CONVERT CONFIG_FMB_MASTER_DELAY_MS_CONVERT +#define CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND +#define CONFIG_MB_QUEUE_LENGTH CONFIG_FMB_QUEUE_LENGTH +#define CONFIG_MB_SERIAL_BUF_SIZE CONFIG_FMB_SERIAL_BUF_SIZE +#define CONFIG_MB_SERIAL_TASK_PRIO CONFIG_FMB_SERIAL_TASK_PRIO +#define CONFIG_MB_SERIAL_TASK_STACK_SIZE CONFIG_FMB_SERIAL_TASK_STACK_SIZE +#define CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP +#define CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX +#define CONFIG_MB_TIMER_PORT_ENABLED CONFIG_FMB_TIMER_PORT_ENABLED +#define CONFIG_MONITOR_BAUD_115200B CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR +#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR +#define CONFIG_REDUCE_PHY_TX_POWER CONFIG_ESP32_REDUCE_PHY_TX_POWER +#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN +#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS +#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE +#define CONFIG_SUPPORT_TERMIOS CONFIG_VFS_SUPPORT_TERMIOS +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE +#define CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 +#define CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S +#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY +#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE +#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX +#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL +#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS +#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS +#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ +#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE +#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT +#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX +#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT +#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH +#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY +#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH +#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE +#define CONFIG_TOOLPREFIX CONFIG_SDK_TOOLPREFIX +#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE -- Gitee From 65545d2d21eb744e1b8cb636d389d06d8e79a59d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 29 Jun 2020 09:31:21 +0100 Subject: [PATCH 0192/1062] lws-settings --- include/libwebsockets.h | 1 + include/libwebsockets/lws-settings.h | 72 ++++++++++++++++++++++ lib/drivers/CMakeLists.txt | 1 + lib/drivers/settings/settings.c | 44 +++++++++++++ lib/plat/freertos/CMakeLists.txt | 6 +- lib/plat/freertos/esp32/drivers/settings.c | 71 +++++++++++++++++++++ 6 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 include/libwebsockets/lws-settings.h create mode 100644 lib/drivers/settings/settings.c create mode 100644 lib/plat/freertos/esp32/drivers/settings.c diff --git a/include/libwebsockets.h b/include/libwebsockets.h index ac8e22fc..4d60592a 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -621,6 +621,7 @@ struct lws; #include #include #include +#include #ifdef __cplusplus } diff --git a/include/libwebsockets/lws-settings.h b/include/libwebsockets/lws-settings.h new file mode 100644 index 00000000..541c8c6d --- /dev/null +++ b/include/libwebsockets/lws-settings.h @@ -0,0 +1,72 @@ +/* + * Generic Settings storage + * + * Copyright (C) 2020 Andy Green + * + * 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. + * + * + * This is like an abstract class for non-volatile storage, whether in a file- + * system or flash-backed blocks, etc. Named blobs of variable size are stored + * in nonvolatile media of some sort. Typically, these are JSON objects under + * a naming scheme like, eg, "network". + * + * There's a platform-specific storage identifier opaque_plat provided when the + * storage object is instantiated, this describes eg the storage device or + * partition in instantiation-specific terms. + * + * Blobs have a further "filename" associated with them. + */ + +#defined LSOOPEN_FLAG_WRITEABLE (1 << 0) + +struct lws_settings_ops; + +typedef struct { + void *handle_plat; + const struct lws_settings_ops *so; + uint8_t refcount; + void *opaque_plat; +} lws_settings_instance_t; + +typedef struct lws_settings_ops { + int (*get)(lws_settings_instance_t *si, const char *name, + uint8_t *dest, size_t *max_actual); + /**< if dest is NULL, max_actual is set to the actual length without + * copying anything out */ + int (*set)(lws_settings_instance_t *si, const char *name, + const uint8_t *src, size_t len); +} lws_settings_ops_t; + +LWS_VISIBLE LWS_EXTERN int +lws_settings_plat_get(lws_settings_instance_t *si, const char *name, + uint8_t *dest, size_t *max_actual); +LWS_VISIBLE LWS_EXTERN int +lws_settings_plat_set(lws_settings_instance_t *si, const char *name, + const uint8_t *src, size_t len); + +#define lws_settings_ops_plat \ + .get = lws_settings_plat_get, \ + .set = lws_settings_plat_set, + +LWS_VISIBLE LWS_EXTERN lws_settings_instance_t * +lws_settings_init(lws_settings_ops_t *so, void *opaque_plat); + +LWS_VISIBLE LWS_EXTERN void +lws_settings_deinit(lws_settings_instance_t **si); diff --git a/lib/drivers/CMakeLists.txt b/lib/drivers/CMakeLists.txt index 1320d885..7404aae1 100644 --- a/lib/drivers/CMakeLists.txt +++ b/lib/drivers/CMakeLists.txt @@ -10,6 +10,7 @@ list(APPEND SOURCES drivers/led/led-gpio.c drivers/led/led-seq.c drivers/pwm/pwm.c + drivers/settings/settings.c ) if (LWS_ESP_PLATFORM) diff --git a/lib/drivers/settings/settings.c b/lib/drivers/settings/settings.c new file mode 100644 index 00000000..139e765b --- /dev/null +++ b/lib/drivers/settings/settings.c @@ -0,0 +1,44 @@ +/* + * lws_settings + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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. + */ + +lws_settings_instance_t * +lws_settings_init(lws_settings_ops_t *so, void *opaque_plat) +{ + lws_settings_instance_t *si = lws_zalloc(sizeof(*si), __func__); + + if (!si) + return NULL; + + si->so = so; + si->opaque_plat = opaque_plat; + + return si; +} + +void +lws_settings_deinit(lws_settings_instance_t **si) +{ + lws_free(*si); + *si = NULL; +} diff --git a/lib/plat/freertos/CMakeLists.txt b/lib/plat/freertos/CMakeLists.txt index 22b7e8d0..44fe8e13 100644 --- a/lib/plat/freertos/CMakeLists.txt +++ b/lib/plat/freertos/CMakeLists.txt @@ -39,6 +39,10 @@ list(APPEND SOURCES plat/freertos/freertos-service.c plat/freertos/freertos-sockets.c misc/romfs.c) + +if (LWS_ESP_PLATFORM AND LWS_WITH_DRIVERS) + list(APPEND SOURCES plat/freertos/esp32/drivers/settings.c) +endif() if (LWS_WITH_ESP32_HELPER) list(APPEND SOURCES plat/freertos/esp32/esp32-helpers.c) endif() @@ -53,4 +57,4 @@ endif() # Keep explicit parent scope exports at end # -exports_to_parent_scope() \ No newline at end of file +exports_to_parent_scope() diff --git a/lib/plat/freertos/esp32/drivers/settings.c b/lib/plat/freertos/esp32/drivers/settings.c new file mode 100644 index 00000000..2eb9dc5b --- /dev/null +++ b/lib/plat/freertos/esp32/drivers/settings.c @@ -0,0 +1,71 @@ +/* + * esp32 / esp-idf NV settings shim + * + * Copyright (C) 2019 - 2020 Andy Green + * + * 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 + +int +lws_settings_plat_get(lws_settings_instance_t si, const char *name, + uint8_t *dest, size_t *max_actual) +{ + int n; + + n = nvs_flash_init_partition((const char *)si->opaque_plat); + + lwsl_notice("%s: init partition %d\n", __func__, n); + if (n == ESP_ERR_NOT_FOUND) + return 1; + + if (nvs_open_from_partition((const char *)si->opaque_plat, + "_lws_settings", NVS_READONLY, + (nvs_handle_t *)&si->handle_plat)) + return 1; + + n = nvs_get_blob((nvs_handle_t)si->handle_plat, + name, dest, max_actual); + + nvs_close((nvs_handle_t)si->handle_plat); + + return !!n; +} + +int +lws_settings_plat_set(lws_settings_instance_t si, const char *name, + const uint8_t *src, size_t len) +{ + n = nvs_flash_init_partition((const char *)si->opaque_plat); + + lwsl_notice("%s: init partition %d\n", __func__, n); + if (n == ESP_ERR_NOT_FOUND) + return 1; + + if (nvs_open_from_partition((const char *)si->opaque_plat, + "_lws_settings", NVS_READWRITE, + (nvs_handle_t *)&si->handle_plat)) + return 1; + + n = nvs_set_blob((nvs_handle_t)si->handle_plat, name, src, len); + + nvs_commit((nvs_handle_t)si->handle_plat); + nvs_close((nvs_handle_t)si->handle_plat); +} -- Gitee From b72ab32c175dc4328e60f9e8cf7abf16b20d7279 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 22 Jun 2020 20:05:06 +0100 Subject: [PATCH 0193/1062] lws_netdev --- CMakeLists-implied-options.txt | 6 +- include/libwebsockets.h | 1 + include/libwebsockets/lws-freertos.h | 6 + include/libwebsockets/lws-netdev.h | 158 +++++++++ include/libwebsockets/lws-settings.h | 2 +- lib/core-net/vhost.c | 2 + lib/core/private-lib-core.h | 2 +- lib/plat/freertos/CMakeLists.txt | 3 +- lib/plat/freertos/esp32/drivers/netdev/wifi.c | 214 ++++++++++++ lib/plat/freertos/freertos-resolv.c | 17 +- lib/plat/freertos/freertos-sockets.c | 2 +- lib/roles/http/client/client-handshake.c | 5 +- lib/system/ntpclient/ntpclient.c | 21 +- .../esp32/esp-heltec-wb32/CMakeLists.txt | 4 + .../esp32/esp-heltec-wb32/main/CMakeLists.txt | 2 +- .../esp32/esp-heltec-wb32/main/devices.c | 0 .../esp-heltec-wb32/main/lws-minimal-esp32.c | 40 ++- .../esp32/esp-heltec-wb32/main/policy.h | 134 ++++++++ .../esp32/esp-heltec-wb32/sdkconfig.h | 2 +- .../esp32/esp-wrover-kit/CMakeLists.txt | 6 + .../esp32/esp-wrover-kit/main/CMakeLists.txt | 3 +- .../esp32/esp-wrover-kit/main/devices.c | 231 +++++++++++++ .../esp-wrover-kit/main/lws-minimal-esp32.c | 321 +++++++----------- .../esp32/esp-wrover-kit/main/policy.h | 134 ++++++++ .../embedded/esp32/esp-wrover-kit/sdkconfig | 2 +- .../embedded/esp32/esp-wrover-kit/sdkconfig.h | 2 +- 26 files changed, 1079 insertions(+), 241 deletions(-) create mode 100644 include/libwebsockets/lws-netdev.h create mode 100644 lib/plat/freertos/esp32/drivers/netdev/wifi.c create mode 100644 minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c create mode 100644 minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c create mode 100644 minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h diff --git a/CMakeLists-implied-options.txt b/CMakeLists-implied-options.txt index 197ad690..8ec12f15 100644 --- a/CMakeLists-implied-options.txt +++ b/CMakeLists-implied-options.txt @@ -30,10 +30,11 @@ endif() # Workaround for ESP-IDF # Detect ESP_PLATFORM environment flag, if exist, set LWS_WITH_ESP32. # Otherwise the user may not be able to run configuration ESP-IDF in the first time. -if(ESP_PLATFORM) +if (ESP_PLATFORM) message(STATUS "ESP-IDF enabled") set(LWS_WITH_ESP32 ON) set(LWS_WITH_ZLIB OFF) + set(LWS_HAVE_mbedtls_ssl_get_alpn_protocol 1) else() set(LWS_WITH_ESP32_HELPER OFF) endif() @@ -42,7 +43,7 @@ if (LWS_WITH_ESP32) set(LWS_PLAT_FREERTOS 1) endif() -if (LWS_PLAT_FREERTOS OR LWS_PLAT_OPTEE) +if (LWS_PLAT_OPTEE) set(LWS_WITH_UDP 0) endif() @@ -170,7 +171,6 @@ if (LWS_PLAT_FREERTOS) endif() if (LWS_PLAT_FREERTOS) - set(LWS_WITH_LWSAC 0) set(LWS_WITH_FTS 0) endif() diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 4d60592a..b015aa11 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -622,6 +622,7 @@ struct lws; #include #include #include +#include #ifdef __cplusplus } diff --git a/include/libwebsockets/lws-freertos.h b/include/libwebsockets/lws-freertos.h index 407b387d..2dd7ff45 100644 --- a/include/libwebsockets/lws-freertos.h +++ b/include/libwebsockets/lws-freertos.h @@ -70,6 +70,12 @@ struct pollfd { #include "driver/gpio.h" #include "esp_spi_flash.h" #include "freertos/timers.h" + +#if defined(LWS_ESP_PLATFORM) +#include "lwip/sockets.h" +#include "lwip/netdb.h" +#endif + #endif /* LWS_AMAZON_RTOS */ #if !defined(CONFIG_FREERTOS_HZ) diff --git a/include/libwebsockets/lws-netdev.h b/include/libwebsockets/lws-netdev.h new file mode 100644 index 00000000..8f2f0857 --- /dev/null +++ b/include/libwebsockets/lws-netdev.h @@ -0,0 +1,158 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + */ + +#define LWS_WIFI_MAX_SCAN_TRACK 16 + +typedef uint8_t lws_wifi_ch_t; +struct lws_netdev_instance; + +/* + * Base class for netdev configuration + */ + +typedef struct lws_netdev_config { + void *plat_config; +} lws_netdev_config_t; + +/* + * Const Logical generic network interface ops + */ + +typedef struct lws_netdev_ops { + struct lws_netdev_instance * (*create)(struct lws_context *ctx, + const struct lws_netdev_ops *ops, + const char *name, void *platinfo); + int (*configure)(struct lws_netdev_instance *nd, + lws_netdev_config_t *config); + int (*up)(struct lws_netdev_instance *nd); + int (*down)(struct lws_netdev_instance *nd); + void (*destroy)(struct lws_netdev_instance **pnd); +} lws_netdev_ops_t; + +/* + * Base class for an allocated instantiated derived object using lws_netdev_ops, + * ie, a specific ethernet device + */ + +typedef struct lws_netdev_instance { + const char *name; + const lws_netdev_ops_t *ops; + struct lws_context *ctx; + void *platinfo; + lws_dll2_t list; +} lws_netdev_instance_t; + +enum { + LNDIW_ALG_OPEN, + LNDIW_ALG_WPA2, + + LNDIW_MODE_STA = (1 << 0), + LNDIW_MODE_AP = (1 << 1), + LNDIW_UP = (1 << 7), + + LNDIW_ACQ_IPv4 = (1 << 0), + LNDIW_ACQ_IPv6 = (1 << 1), +}; + +typedef struct lws_wifi_credentials { + uint8_t bssid[6]; + char passphrase[64]; + char ssid[33]; + uint8_t alg; +} lws_wifi_credentials_t; + +typedef struct lws_netdev_instance_wifi { + lws_netdev_instance_t inst; + lws_dll2_owner_t scan; + + struct { + lws_wifi_credentials_t creds; + lws_sockaddr46 sa46[2]; + uint8_t flags; + } ap; + struct { + lws_wifi_credentials_t creds; + lws_sockaddr46 sa46[2]; + uint8_t flags; + } sta; + + uint8_t flags; +} lws_netdev_instance_wifi_t; + +/* + * Logical scan results sorted list item + */ + +typedef struct lws_wifi_sta { + lws_dll2_t list; + + uint8_t bssid[6]; + uint8_t ssid_len; + lws_wifi_ch_t ch; + int8_t rssi[4]; + uint8_t authmode; + + uint8_t rssi_count; + uint8_t rssi_next; + + /* ssid overallocated afterwards */ +} lws_wifi_sta_t; + +typedef struct lws_wifi_credentials_setting { + lws_dll2_t list; + + lws_wifi_credentials_t creds; +} lws_wifi_credentials_setting_t; + +LWS_VISIBLE LWS_EXTERN struct lws_netdev_instance * +lws_netdev_wifi_create_plat(struct lws_context *ctx, + const lws_netdev_ops_t *ops, const char *name, + void *platinfo); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd, + lws_netdev_config_t *config); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_up_plat(struct lws_netdev_instance *nd); +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_down_plat(struct lws_netdev_instance *nd); +LWS_VISIBLE LWS_EXTERN void +lws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd); + +#define lws_netdev_wifi_plat_ops \ + .create = lws_netdev_wifi_create_plat, \ + .configure = lws_netdev_wifi_configure_plat, \ + .up = lws_netdev_wifi_up_plat, \ + .down = lws_netdev_wifi_down_plat, \ + .destroy = lws_netdev_wifi_destroy_plat + +/* + * This is for plat / OS level init that is necessary to be able to use + * networking or wifi at all, without mentioning any specific device + */ + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_plat_init(void); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_plat_wifi_init(void); diff --git a/include/libwebsockets/lws-settings.h b/include/libwebsockets/lws-settings.h index 541c8c6d..9bfffd40 100644 --- a/include/libwebsockets/lws-settings.h +++ b/include/libwebsockets/lws-settings.h @@ -34,7 +34,7 @@ * Blobs have a further "filename" associated with them. */ -#defined LSOOPEN_FLAG_WRITEABLE (1 << 0) +#define LSOOPEN_FLAG_WRITEABLE (1 << 0) struct lws_settings_ops; diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index dd6349d0..a94855aa 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -126,7 +126,9 @@ lws_role_call_alpn_negotiated(struct lws *wsi, const char *alpn) if (!alpn) return 0; +#if !defined(LWS_ESP_PLATFORM) lwsl_info("%s: '%s'\n", __func__, alpn); +#endif LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) if (ar->alpn && !strcmp(ar->alpn, alpn) && ar->alpn_negotiated) diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 0a0062f5..3c1b0dd3 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -383,9 +383,9 @@ struct lws_context { lws_async_dns_t async_dns; #endif + struct lws_ss_handle *hss_fetch_policy; #if defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) struct lws_ss_handle *hss_auth; - struct lws_ss_handle *hss_fetch_policy; lws_sorted_usec_list_t sul_api_amazon_com; lws_sorted_usec_list_t sul_api_amazon_com_kick; #endif diff --git a/lib/plat/freertos/CMakeLists.txt b/lib/plat/freertos/CMakeLists.txt index 44fe8e13..dccdde7f 100644 --- a/lib/plat/freertos/CMakeLists.txt +++ b/lib/plat/freertos/CMakeLists.txt @@ -42,6 +42,7 @@ list(APPEND SOURCES if (LWS_ESP_PLATFORM AND LWS_WITH_DRIVERS) list(APPEND SOURCES plat/freertos/esp32/drivers/settings.c) + list(APPEND SOURCES plat/freertos/esp32/drivers/netdev/wifi.c) endif() if (LWS_WITH_ESP32_HELPER) list(APPEND SOURCES plat/freertos/esp32/esp32-helpers.c) @@ -49,7 +50,7 @@ endif() if (LWS_WITH_FILE_OPS) list(APPEND SOURCES plat/freertos/freertos-file.c) endif() -if (LWS_WITH_SYS_ASYNC_DNS) +if (LWS_WITH_SYS_ASYNC_DNS OR LWS_WITH_SYS_NTPCLIENT) list(APPEND SOURCES plat/freertos/freertos-resolv.c) endif() diff --git a/lib/plat/freertos/esp32/drivers/netdev/wifi.c b/lib/plat/freertos/esp32/drivers/netdev/wifi.c new file mode 100644 index 00000000..3d283238 --- /dev/null +++ b/lib/plat/freertos/esp32/drivers/netdev/wifi.c @@ -0,0 +1,214 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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 "private-lib-core.h" + +#include "esp_system.h" +#include "esp_spi_flash.h" +#include "esp_wifi.h" +#include +#include + +/* +static wifi_config_t config = { + .ap = { + .channel = 6, + .authmode = WIFI_AUTH_OPEN, + .max_connection = 1, + } }; + */ +static wifi_config_t sta_config = { + .sta = { + .bssid_set = 0, + } }; + +static void +event_handler_wifi(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg; + + switch (event_id) { + case WIFI_EVENT_STA_START: + esp_wifi_connect(); + break; + case WIFI_EVENT_STA_DISCONNECTED: + lwsl_err("%s: %s: disconnect -> wifi connect\n", __func__, + wnd->inst.name); + // !!! should only retry for a given amount of times + esp_wifi_connect(); + break; + } +} + +static void +event_handler_ip(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg; + + if (event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t *e = (ip_event_got_ip_t *)event_data; + char ip[16]; + lws_write_numeric_address((void *)&e->ip_info.ip, 4, ip, + sizeof(ip)); + lws_smd_msg_printf(wnd->inst.ctx, LWSSMDCL_NETWORK, + "{\"type\":\"ip\",\"if\":\"%s\"," + "\"ipv4\":\"%s\"}", wnd->inst.name, ip); + } +} + + +esp_event_handler_instance_t instance_any_id; +esp_event_handler_instance_t instance_got_ip; + +/* + * This is the platform (esp-idf) init for any kind of networking to be + * available at all + */ +int +lws_netdev_plat_init(void) +{ + nvs_flash_init(); + esp_netif_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + return 0; +} + +/* + * This is the platform (esp-idf) init for any wifi to be available at all + */ +int +lws_netdev_plat_wifi_init(void) +{ + wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); + int n; + + esp_netif_create_default_wifi_sta(); + + n = esp_wifi_init(&wic); + if (n) { + lwsl_err("%s: wifi init fail: %d\n", __func__, n); + return 1; + } + + return 0; +} + + +struct lws_netdev_instance * +lws_netdev_wifi_create_plat(struct lws_context *ctx, + const lws_netdev_ops_t *ops, + const char *name, void *platinfo) +{ + lws_netdev_instance_wifi_t *wnd = lws_zalloc(sizeof(*wnd), __func__); + + if (!wnd) + return NULL; + + wnd->inst.ops = ops; + wnd->inst.name = name; + wnd->inst.platinfo = platinfo; + wnd->inst.ctx = ctx; + + return &wnd->inst; +} + +int +lws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd, + lws_netdev_config_t *config) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; + + esp_wifi_set_mode(WIFI_MODE_STA); + + lws_strncpy((char *)sta_config.sta.ssid, wnd->sta.creds.ssid, + sizeof(sta_config.sta.ssid)); + lws_strncpy((char *)sta_config.sta.password, wnd->sta.creds.passphrase, + sizeof(sta_config.sta.password)); + + esp_wifi_set_config(WIFI_IF_STA, &sta_config); + + return 0; +} + +int +lws_netdev_wifi_up_plat(struct lws_netdev_instance *nd) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; + + if (wnd->flags & LNDIW_UP) + return 0; + + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, + &event_handler_ip, + nd, + &instance_got_ip)); + + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &event_handler_wifi, + nd, + &instance_any_id)); + + esp_wifi_start(); + wnd->flags |= LNDIW_UP; + + lws_smd_msg_printf(wnd->inst.ctx, LWSSMDCL_NETWORK, + "{\"type\":\"up\",\"if\":\"%s\"}", wnd->inst.name); + + return 0; +} + +int +lws_netdev_wifi_down_plat(struct lws_netdev_instance *nd) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; + + if (!(wnd->flags & LNDIW_UP)) + return 0; + + lws_smd_msg_printf(wnd->inst.ctx, LWSSMDCL_NETWORK, + "{\"type\":\"down\",\"if\":\"%s\"}", wnd->inst.name); + + esp_wifi_stop(); + + esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, + &instance_got_ip); + esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, + &instance_any_id); + + wnd->flags &= ~LNDIW_UP; + + return 0; +} + +void +lws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd) +{ + lws_free(*pnd); + *pnd = NULL; +} diff --git a/lib/plat/freertos/freertos-resolv.c b/lib/plat/freertos/freertos-resolv.c index cccd8340..383ec784 100644 --- a/lib/plat/freertos/freertos-resolv.c +++ b/lib/plat/freertos/freertos-resolv.c @@ -24,6 +24,7 @@ #include "private-lib-core.h" +#if defined(LWS_WITH_SYS_ASYNC_DNS) lws_async_dns_server_check_t lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) { @@ -40,20 +41,14 @@ lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) return s; } +#endif int lws_plat_ntpclient_config(struct lws_context *context) { -#if 0 - char *ntpsrv = getenv("LWS_NTP_SERVER"); - - if (ntpsrv && strlen(ntpsrv) < 64) { - lws_system_blob_heap_append(lws_system_get_blob(context, - LWS_SYSBLOB_TYPE_NTP_SERVER, 0), - (const uint8_t *)ntpsrv, - strlen(ntpsrv)); - return 1; - } -#endif + lws_system_blob_heap_append(lws_system_get_blob(context, + LWS_SYSBLOB_TYPE_NTP_SERVER, 0), + (const uint8_t *)"pool.ntp.org", 12); + return 0; } diff --git a/lib/plat/freertos/freertos-sockets.c b/lib/plat/freertos/freertos-sockets.c index 625b72d3..4b8c73c0 100644 --- a/lib/plat/freertos/freertos-sockets.c +++ b/lib/plat/freertos/freertos-sockets.c @@ -313,7 +313,7 @@ lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) if (errno == EPIPE || errno == ECONNRESET) return MBEDTLS_ERR_NET_CONN_RESET; - if (errno == EINTR) + if (errno == EINTR || !errno) return MBEDTLS_ERR_SSL_WANT_READ; return MBEDTLS_ERR_NET_RECV_FAILED; diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index f1fc266a..fd6cfd7d 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -705,13 +705,16 @@ ads_known: wsi->detlat.earliest_write_req_pre_write = lws_now_usecs(); #endif +#if defined(LWS_ESP_PLATFORM) + errno = 0; +#endif m = connect(wsi->desc.sockfd, (const struct sockaddr *)psa, n); if (m == -1) { int errno_copy = LWS_ERRNO; lwsl_debug("%s: connect says errno: %d\n", __func__, errno_copy); - if (errno_copy != LWS_EALREADY && + if (errno_copy && errno_copy != LWS_EALREADY && errno_copy != LWS_EINPROGRESS && errno_copy != LWS_EWOULDBLOCK #ifdef _WIN32 diff --git a/lib/system/ntpclient/ntpclient.c b/lib/system/ntpclient/ntpclient.c index b56efe09..012c0419 100644 --- a/lib/system/ntpclient/ntpclient.c +++ b/lib/system/ntpclient/ntpclient.c @@ -146,8 +146,10 @@ callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!lws_system_get_ops(wsi->context) || !lws_system_get_ops(wsi->context)->set_clock) { +#if !defined(LWS_ESP_PLATFORM) lwsl_err("%s: set up system ops for set_clock\n", __func__); +#endif // return -1; } @@ -163,8 +165,11 @@ callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_system_blob_get_single_ptr(lws_system_get_blob( v->context, LWS_SYSBLOB_TYPE_NTP_SERVER, 0), (const uint8_t **)&v->ntp_server_ads); + if (!v->ntp_server_ads || v->ntp_server_ads[0] == '\0') + v->ntp_server_ads = "pool.ntp.org"; - lwsl_info("%s: using ntp server %s\n", __func__, v->ntp_server_ads); + lwsl_info("%s: using ntp server %s\n", __func__, + v->ntp_server_ads); lws_ntpc_retry_conn(&v->sul_conn); break; @@ -222,7 +227,19 @@ do_close: lwsl_notice("%s: Unix time: %llu\n", __func__, (unsigned long long)ns / 1000000000); - // lws_system_get_ops(wsi->context)->set_clock(ns / 1000); +#if defined(LWS_ESP_PLATFORM) + { + struct timeval t; + + t.tv_sec = (unsigned long long)ns / 1000000000; + t.tv_usec = (ns % 1000000000) / 1000; + + settimeofday(&t, NULL); + } +#endif + if (lws_system_get_ops(wsi->context) && + lws_system_get_ops(wsi->context)->set_clock) + lws_system_get_ops(wsi->context)->set_clock(ns / 1000); v->set_time = 1; lws_state_transition_steps(&wsi->context->mgr_system, diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt index e17a99ca..eb8c5265 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt @@ -9,6 +9,10 @@ if (ESP_PLATFORM) option(LWS_WITH_DRIVERS "With generic drivers for gpio, i2c, display etc" ON) set(LWS_WITH_DRIVERS ON) + option(LWS_WITH_SECURE_STREAMS "With secure streams" ON) + set(LWS_WITH_SECURE_STREAMS ON) + option(LWS_WITH_LWSAC "With lwsac" ON) + set(LWS_WITH_LWSAC ON) add_subdirectory(libwebsockets) diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt index c38b4767..77040deb 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register(SRCS - "lws-minimal-esp32.c" + lws-minimal-esp32.c devices.c INCLUDE_DIRS "../libwebsockets/include;${IDF_PATH}/components/spi_flash/include;${IDF_PATH}/components/nvs_flash/include;${IDF_PATH}/components/mdns/include") target_link_libraries(${COMPONENT_LIB} websockets) diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c new file mode 100644 index 00000000..e69de29b diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c index 77221693..3f63aef3 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c @@ -16,11 +16,7 @@ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_system.h" -#include "esp_spi_flash.h" -#include "esp_wifi.h" -#include -#include + #include #include @@ -29,6 +25,7 @@ struct lws_context *context; lws_sorted_usec_list_t sul; struct lws_led_state *lls; lws_display_state_t lds; +lws_netdev_instance_wifi_t *wnd; int interrupted; /* @@ -114,6 +111,10 @@ static const lws_led_gpio_controller_t lgc = { .count_leds = LWS_ARRAY_SIZE(lgm) }; +static const lws_netdev_ops_t wifi_ops = { + lws_netdev_wifi_plat_ops +}; + static const uint8_t img[] = { #include "../banded-img.h" }; @@ -161,20 +162,14 @@ sul_cb(lws_sorted_usec_list_t *sul) void app_main(void) { - wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); struct lws_context_creation_info info; struct lws_button_state *bcs; int n = 0; lws_set_log_level(15, NULL); - nvs_flash_init(); - esp_netif_init(); - n = esp_wifi_init(&wic); - if (n) { - lwsl_err("%s: wifi init fail: %d\n", __func__, n); - goto spin; - } + lws_netdev_plat_init(); + lws_netdev_plat_wifi_init(); memset(&info, 0, sizeof(info)); @@ -191,6 +186,25 @@ app_main(void) return; } + /* create the wifi network device and configure it */ + + wnd = (lws_netdev_instance_wifi_t *) + wifi_ops.create(context, &wifi_ops, "wl0", NULL); + if (!wnd) { + lwsl_err("%s: failed to create wifi object\n", __func__); + goto spin; + } + + strcpy(wnd->sta.creds.ssid, "xxx"); + strcpy(wnd->sta.creds.passphrase, "yyy"); + wnd->flags |= LNDIW_MODE_STA; + + if (wifi_ops.configure(&wnd->inst, NULL)) { + lwsl_err("%s: failed to configure wifi object\n", __func__); + goto spin; + } + wifi_ops.up(&wnd->inst); + lls = lgc.led_ops.create(&lgc.led_ops); if (!lls) { lwsl_err("%s: could not create led\n", __func__); diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h new file mode 100644 index 00000000..03c44b68 --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/policy.h @@ -0,0 +1,134 @@ + +static const char * const ss_policy = + "{" + "\"release\":" "\"01234567\"," + "\"product\":" "\"myproduct\"," + "\"schema-version\":" "1," + + "\"retry\": [" /* named backoff / retry strategies */ + "{\"default\": {" + "\"backoff\": [" "1000," + "2000," + "3000," + "5000," + "10000" + "]," + "\"conceal\":" "25," + "\"jitterpc\":" "20," + "\"svalidping\":" "30," + "\"svalidhup\":" "35" + "}}" + "]," + "\"certs\": [" /* named individual certificates in BASE64 DER */ + /* + * Let's Encrypt certs for warmcat.com / libwebsockets.org + * + * We fetch the real policy from there using SS and switch to + * using that. + */ + "{\"isrg_root_x1\": \"" /* ISRG ROOT X1 */ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4" + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu" + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY" + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc" + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+" + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U" + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW" + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH" + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC" + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv" + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn" + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn" + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw" + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI" + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV" + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq" + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL" + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ" + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK" + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5" + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur" + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC" + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc" + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq" + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA" + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d" + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + "\"}," + "{\"LEX3_isrg_root_x1\": \"" /* LE X3 signed by ISRG X1 root */ + "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1" + "WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg" + "RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi" + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX" + "NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf" + "89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl" + "Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc" + "Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz" + "uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB" + "AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU" + "BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB" + "FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo" + "SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js" + "LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF" + "BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG" + "AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD" + "VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB" + "ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx" + "A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM" + "UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2" + "DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1" + "eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu" + "OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw" + "p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY" + "2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0" + "ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR" + "PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b" + "rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + "\"}" + "]," + "\"trust_stores\": [" /* named cert chains */ + "{" + "\"name\": \"le_via_isrg\"," + "\"stack\": [" + "\"isrg_root_x1\"," + "\"LEX3_isrg_root_x1\"" + "]" + "}" + "]," + "\"s\": [" + + "{\"test_stream\": {" + "\"endpoint\":" "\"warmcat.com\"," + "\"port\":" "443," + "\"protocol\":" "\"h2\"," + "\"http_method\":" "\"GET\"," + "\"http_url\":" "\"index.html\"," + "\"tls\":" "true," + "\"opportunistic\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"le_via_isrg\"" + "}},{" + /* + * "captive_portal_detect" describes + * what to do in order to check if the path to + * the Internet is being interrupted by a + * captive portal. + */ + "\"captive_portal_detect\": {" + "\"endpoint\":" "\"connectivitycheck.android.com\"," + "\"http_url\":" "\"generate_204\"," + "\"port\":" "80," + "\"protocol\":" "\"h1\"," + "\"http_method\":" "\"GET\"," + "\"opportunistic\":" "true," + "\"http_expect\":" "204," + "\"http_fail_redirect\": true" + "}}" + "]}" +; + + diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h b/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h index 7e4fcfe0..d00bac26 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h @@ -88,7 +88,7 @@ #define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 #define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 #define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 -#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 6584 #define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 #define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 #define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt index e17a99ca..c9dcb1d8 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt @@ -9,6 +9,12 @@ if (ESP_PLATFORM) option(LWS_WITH_DRIVERS "With generic drivers for gpio, i2c, display etc" ON) set(LWS_WITH_DRIVERS ON) + option(LWS_WITH_SECURE_STREAMS "With secure streams" ON) + set(LWS_WITH_SECURE_STREAMS ON) + option(LWS_WITH_LWSAC "With lwsac" ON) + set(LWS_WITH_LWSAC ON) + option(LWS_WITH_SYS_NTPCLIENT "With ntpclient" ON) + set(LWS_WITH_SYS_NTPCLIENT ON) add_subdirectory(libwebsockets) diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt index c38b4767..b7e19603 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/CMakeLists.txt @@ -1,5 +1,6 @@ idf_component_register(SRCS - "lws-minimal-esp32.c" + lws-minimal-esp32.c + devices.c INCLUDE_DIRS "../libwebsockets/include;${IDF_PATH}/components/spi_flash/include;${IDF_PATH}/components/nvs_flash/include;${IDF_PATH}/components/mdns/include") target_link_libraries(${COMPONENT_LIB} websockets) diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c b/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c new file mode 100644 index 00000000..c8d6321b --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c @@ -0,0 +1,231 @@ +/* + * devices for ESP WROVER KIT + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#define LWIP_PROVIDE_ERRNO 1 +#define _ESP_PLATFORM_ERRNO_H_ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include + +#include + +struct lws_led_state *lls; +lws_display_state_t lds; +struct lws_button_state *bcs; +lws_netdev_instance_wifi_t *wnd; + +/* + * Button controller + * + * On the WROVER KIT, it's a bit overloaded... the two buttons are reset and + * gpio0, gpio is also used for one of the RGB LEDs channels control so it's not + * really usable as a general user button. + * + * Instead we use GPIO 14 (available on J1) for a button with the other side + * of the switch connected to 0V. + */ + +static const lws_button_map_t bcm[] = { + { + .gpio = GPIO_NUM_14, + .smd_interaction_name = "user" + }, +}; + +static const lws_button_controller_t bc = { + .smd_bc_name = "bc", + .gpio_ops = &lws_gpio_plat, + .button_map = &bcm[0], + .active_state_bitmap = 0, + .count_buttons = LWS_ARRAY_SIZE(bcm), +}; + +/* + * pwm controller + */ + +static const lws_pwm_map_t pwm_map[] = { + { .gpio = GPIO_NUM_2, .index = 0, .active_level = 1 }, + { .gpio = GPIO_NUM_0, .index = 1, .active_level = 1 }, + { .gpio = GPIO_NUM_4, .index = 2, .active_level = 1 }, + { .gpio = GPIO_NUM_5, .index = 3, .active_level = 0 } +}; + +static const lws_pwm_ops_t pwm_ops = { + lws_pwm_plat_ops, + .pwm_map = &pwm_map[0], + .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) +}; + +/* + * led controller + */ + +static const lws_led_gpio_map_t lgm[] = { + { + .name = "red", + .gpio = GPIO_NUM_2, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, + { + .name = "green", + .gpio = GPIO_NUM_0, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, + { + .name = "blue", + .gpio = GPIO_NUM_4, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, + { + .name = "backlight", + .gpio = GPIO_NUM_5, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 0, + /* + * The wrover kit uses a 2 NPN in series to drive the backlight + * which means if the GPIO provides no current, the backlight is + * full-on. This causes a white flash during boot... they mark + * the first stage with "Modify In ESP-WROVER-KIT!" on the + * schematics but on Kit v4.1, it's still like that. + */ + }, +}; + +static const lws_led_gpio_controller_t lgc = { + .led_ops = lws_led_gpio_ops, + .gpio_ops = &lws_gpio_plat, + .led_map = &lgm[0], + .count_leds = LWS_ARRAY_SIZE(lgm) +}; + +/* + * Bitbang SPI configuration for display + */ + +static const lws_bb_spi_t lbspi = { + .bb_ops = { + lws_bb_spi_ops, + .bus_mode = LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_RISING + }, + .gpio = &lws_gpio_plat, + .clk = GPIO_NUM_19, + .ncs = { GPIO_NUM_22 }, + .ncmd = { GPIO_NUM_21 }, + .mosi = GPIO_NUM_23, + .miso = GPIO_NUM_25, + .flags = LWSBBSPI_FLAG_USE_NCS0 | + LWSBBSPI_FLAG_USE_NCMD0 +}; + +/* + * SPI display + */ + +static const lws_display_ili9341_t disp = { + .disp = { + lws_display_ili9341_ops, + .bl_pwm_ops = &pwm_ops, + .bl_active = &lws_pwmseq_static_on, + .bl_dim = &lws_pwmseq_static_half, + .bl_transition = &lws_pwmseq_linear_wipe, + .bl_index = 3, + .w = 320, + .h = 240, + .latency_wake_ms = 150, + }, + .spi = (lws_spi_ops_t *)&lbspi, + .gpio = &lws_gpio_plat, + .reset_gpio = GPIO_NUM_18, + .spi_index = 0 +}; + +/* + * + */ + +/* + * Wifi + */ + +static const lws_netdev_ops_t wifi_ops = { + lws_netdev_wifi_plat_ops +}; + +int +init_plat_devices(struct lws_context *context) +{ + /* create the wifi network device and configure it */ + + wnd = (lws_netdev_instance_wifi_t *) + wifi_ops.create(context, &wifi_ops, "wl0", NULL); + if (!wnd) { + lwsl_err("%s: failed to create wifi object\n", __func__); + return 1; + } + + strcpy(wnd->sta.creds.ssid, "xxx"); + strcpy(wnd->sta.creds.passphrase, "yyy"); + wnd->flags |= LNDIW_MODE_STA; + + if (wifi_ops.configure(&wnd->inst, NULL)) { + lwsl_err("%s: failed to configure wifi object\n", __func__); + return 1; + } + wifi_ops.up(&wnd->inst); + + /* bring up the led controller */ + + lls = lgc.led_ops.create(&lgc.led_ops); + if (!lls) { + lwsl_err("%s: could not create led\n", __func__); + return 1; + } + + /* pwm init must go after the led controller init */ + + pwm_ops.init(&pwm_ops); + + /* ... and the button controller */ + + bcs = lws_button_controller_create(context, &bc); + if (!bcs) { + lwsl_err("%s: could not create buttons\n", __func__); + return 1; + } + + lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); + + /* ... bring up spi bb and the display */ + + lbspi.bb_ops.init(&lbspi.bb_ops); + lws_display_state_init(&lds, context, 30000, 10000, lls, &disp.disp); + + /* + * Make the RGB LED do something using sequenced PWM... pressing the + * GPIO14 button with single-presses advances the blue channel between + * different sequences + */ + + lws_led_transition(lls, "blue", &lws_pwmseq_sine_endless_fast, + &lws_pwmseq_linear_wipe); + lws_led_transition(lls, "green", &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_linear_wipe); + lws_led_transition(lls, "red", &lws_pwmseq_sine_endless_slow, + &lws_pwmseq_linear_wipe); + + return 0; +} diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c index 7b222be7..2faa1827 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c @@ -7,6 +7,9 @@ * Universal Public Domain Dedication. * * Configured for ESP32 WROVER KIT + * + * What should be notable about this is there are no esp-idf apis used here or + * any related files, despite we are running on top of stock esp-idf. */ #define LWIP_PROVIDE_ERRNO 1 @@ -16,157 +19,96 @@ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_system.h" -#include "esp_spi_flash.h" -#include "esp_wifi.h" -#include -#include + #include #include struct lws_context *context; -lws_sorted_usec_list_t sul; -struct lws_led_state *lls; -lws_display_state_t lds; +extern struct lws_led_state *lls; +extern lws_display_state_t lds; +extern struct lws_button_state *bcs; +extern lws_netdev_instance_wifi_t *wnd; int interrupted; +extern int init_plat_devices(struct lws_context *); + static const uint8_t logo[] = { #include "cat-565.h" }; -/* - * Button controller - * - * On the WROVER KIT, it's a bit overloaded... the two buttons are reset and - * gpio0, gpio is also used for one of the RGB LEDs channels control so it's not - * really usable as a general user button. - * - * Instead we use GPIO 14 (available on J1) for a button with the other side - * of the switch connected to 0V. - */ +#include "policy.h" -static const lws_button_map_t bcm[] = { - { - .gpio = GPIO_NUM_14, - .smd_interaction_name = "user" - }, -}; +static uint8_t flip; -static const lws_button_controller_t bc = { - .smd_bc_name = "bc", - .gpio_ops = &lws_gpio_plat, - .button_map = &bcm[0], - .active_state_bitmap = 0, - .count_buttons = LWS_ARRAY_SIZE(bcm), -}; -/* - * pwm controller - */ +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ -static const lws_pwm_map_t pwm_map[] = { - { .gpio = GPIO_NUM_2, .index = 0, .active_level = 1 }, - { .gpio = GPIO_NUM_0, .index = 1, .active_level = 1 }, - { .gpio = GPIO_NUM_4, .index = 2, .active_level = 1 }, - { .gpio = GPIO_NUM_5, .index = 3, .active_level = 0 } -}; + size_t amount; -static const lws_pwm_ops_t pwm_ops = { - lws_pwm_plat_ops, - .pwm_map = &pwm_map[0], - .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) -}; +} myss_t; -/* - * led controller - */ +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); +// lwsl_hexdump_info(buf, len); + m->amount += len; + + if (flags & LWSSS_FLAG_EOM) { -static const lws_led_gpio_map_t lgm[] = { - { - .name = "red", - .gpio = GPIO_NUM_2, - .pwm_ops = &pwm_ops, /* managed by pwm */ - .active_level = 1, - }, - { - .name = "green", - .gpio = GPIO_NUM_0, - .pwm_ops = &pwm_ops, /* managed by pwm */ - .active_level = 1, - }, - { - .name = "blue", - .gpio = GPIO_NUM_4, - .pwm_ops = &pwm_ops, /* managed by pwm */ - .active_level = 1, - }, - { - .name = "backlight", - .gpio = GPIO_NUM_5, - .pwm_ops = &pwm_ops, /* managed by pwm */ - .active_level = 0, /* - * The wrover kit uses a 2 NPN in series to drive the backlight - * which means if the GPIO provides no current, the backlight is - * full-on. This causes a white flash during boot... they mark - * the first stage with "Modify In ESP-WROVER-KIT!" on the - * schematics but on Kit v4.1, it's still like that. + * If we received the whole message, for our example it means + * we are done. */ - }, -}; -static const lws_led_gpio_controller_t lgc = { - .led_ops = lws_led_gpio_ops, - .gpio_ops = &lws_gpio_plat, - .led_map = &lgm[0], - .count_leds = LWS_ARRAY_SIZE(lgm) -}; + lwsl_notice("%s: received %u bytes\n", __func__, + (unsigned int)m->amount); -/* - * Bitbang SPI configuration for display - */ + /* + * In CI, we use sai-expect to look for this + * string for success + */ -static const lws_bb_spi_t lbspi = { - .bb_ops = { - lws_bb_spi_ops, - .bus_mode = LWS_SPI_BUSMODE_CLK_IDLE_LOW_SAMP_RISING - }, - .gpio = &lws_gpio_plat, - .clk = GPIO_NUM_19, - .ncs = { GPIO_NUM_22 }, - .ncmd = { GPIO_NUM_21 }, - .mosi = GPIO_NUM_23, - .miso = GPIO_NUM_25, - .flags = LWSBBSPI_FLAG_USE_NCS0 | - LWSBBSPI_FLAG_USE_NCMD0 -}; + lwsl_notice("Completed: PASS\n"); + } -/* - * SPI display - */ + return 0; +} -static const lws_display_ili9341_t disp = { - .disp = { - lws_display_ili9341_ops, - .bl_pwm_ops = &pwm_ops, - .bl_active = &lws_pwmseq_static_on, - .bl_dim = &lws_pwmseq_static_half, - .bl_transition = &lws_pwmseq_linear_wipe, - .bl_index = 3, - .w = 320, - .h = 240, - .latency_wake_ms = 150, - }, - .spi = (lws_spi_ops_t *)&lbspi, - .gpio = &lws_gpio_plat, - .reset_gpio = GPIO_NUM_18, - .spi_index = 0 -}; +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + switch (state) { + case LWSSSCS_CREATING: + lws_ss_client_connect(m->ss); + break; + default: + break; + } -static uint8_t flip; + return 0; +} + +static const lws_ss_info_t ssi = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .rx = myss_rx, + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = "test_stream", +}; static const lws_led_sequence_def_t *seqs[] = { &lws_pwmseq_static_on, @@ -180,119 +122,94 @@ smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf, size_t len) { - if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user")) { - if (!lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { - lws_led_transition(lls, "blue", seqs[flip & 3], - &lws_pwmseq_linear_wipe); - flip++; - } + if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user") && + !lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { + lws_led_transition(lls, "blue", seqs[flip & 3], + &lws_pwmseq_linear_wipe); + flip++; } lwsl_hexdump_notice(buf, len); - /* - * Any kind of user interaction brings the display back up and resets - * the dimming and blanking timers - */ - lws_display_state_active(&lds); + if ((_class & LWSSMDCL_SYSTEM_STATE) && + !lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) { - return 0; -} + /* create the secure stream */ -static void -sul_cb(lws_sorted_usec_list_t *sul) -{ - /* In CI, we use sai-expect to look for this string for success */ - lwsl_notice("Completed: PASS\n"); + lwsl_notice("%s: creating test secure stream\n", __func__); + + if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + + if (_class & LWSSMDCL_INTERACTION) + /* + * Any kind of user interaction brings the display back up and + * resets the dimming / blanking timers + */ + lws_display_state_active(&lds); + + return 0; } void app_main(void) { - wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); - struct lws_context_creation_info info; - struct lws_button_state *bcs; - int n = 0; + struct lws_context_creation_info *info; lws_set_log_level(1024 | 15, NULL); - nvs_flash_init(); - esp_netif_init(); - n = esp_wifi_init(&wic); - if (n) { - lwsl_err("%s: wifi init fail: %d\n", __func__, n); - goto spin; - } + lws_netdev_plat_init(); + lws_netdev_plat_wifi_init(); - memset(&info, 0, sizeof(info)); + info = malloc(sizeof(*info)); + if (!info) + goto spin; + + memset(info, 0, sizeof(*info)); lwsl_notice("LWS test for Espressif ESP32 WROVER KIT\n"); - info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.port = CONTEXT_PORT_NO_LISTEN; - info.early_smd_cb = smd_cb; - info.early_smd_class_filter = LWSSMDCL_INTERACTION; + info->pss_policies_json = ss_policy; + info->options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info->port = CONTEXT_PORT_NO_LISTEN; + info->early_smd_cb = smd_cb; + info->early_smd_class_filter = LWSSMDCL_INTERACTION | + LWSSMDCL_SYSTEM_STATE | + LWSSMDCL_NETWORK; - context = lws_create_context(&info); + context = lws_create_context(info); if (!context) { lwsl_err("lws init failed\n"); - return; - } - - /* bring up the led controller */ - - lls = lgc.led_ops.create(&lgc.led_ops); - if (!lls) { - lwsl_err("%s: could not create led\n", __func__); goto spin; } - /* pwm init must go after the led controller init */ + /* + * We don't need this after context creation... things it pointed to + * still need to exist though since the context copied the pointers. + */ - pwm_ops.init(&pwm_ops); + free(info); - /* ... and the button controller */ + /* devices and init are in devices.c */ - bcs = lws_button_controller_create(context, &bc); - if (!bcs) { - lwsl_err("%s: could not create buttons\n", __func__); + if (init_plat_devices(context)) goto spin; - } - - lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); - - /* ... bring up spi bb and the display */ - - lbspi.bb_ops.init(&lbspi.bb_ops); - lws_display_state_init(&lds, context, 30000, 10000, lls, &disp.disp); /* put the cat picture up there and enable the backlight */ - disp.disp.blit(lds.disp, logo, 0, 0, 320, 240); + lds.disp->blit(lds.disp, logo, 0, 0, 320, 240); lws_display_state_active(&lds); - /* - * Make the RGB LED do something using sequenced PWM... pressing the - * GPIO14 button with single-presses advances the blue channel between - * different sequences - */ - - lws_sul_schedule(context, 0, &sul, sul_cb, 3 * LWS_USEC_PER_SEC); - lws_led_transition(lls, "blue", &lws_pwmseq_sine_endless_fast, - &lws_pwmseq_linear_wipe); - lws_led_transition(lls, "green", &lws_pwmseq_sine_endless_slow, - &lws_pwmseq_linear_wipe); - lws_led_transition(lls, "red", &lws_pwmseq_sine_endless_slow, - &lws_pwmseq_linear_wipe); - - /* - * We say the test succeeded if we survive 3s around the event loop - */ - - while (n >= 0 && !interrupted) { - n = lws_service(context, 0); + do { taskYIELD(); - } + } while (lws_service(context, 0) >= 0 && !interrupted); + + lwsl_notice("%s: exited event loop\n", __func__); lws_context_destroy(context); diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h b/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h new file mode 100644 index 00000000..03c44b68 --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/policy.h @@ -0,0 +1,134 @@ + +static const char * const ss_policy = + "{" + "\"release\":" "\"01234567\"," + "\"product\":" "\"myproduct\"," + "\"schema-version\":" "1," + + "\"retry\": [" /* named backoff / retry strategies */ + "{\"default\": {" + "\"backoff\": [" "1000," + "2000," + "3000," + "5000," + "10000" + "]," + "\"conceal\":" "25," + "\"jitterpc\":" "20," + "\"svalidping\":" "30," + "\"svalidhup\":" "35" + "}}" + "]," + "\"certs\": [" /* named individual certificates in BASE64 DER */ + /* + * Let's Encrypt certs for warmcat.com / libwebsockets.org + * + * We fetch the real policy from there using SS and switch to + * using that. + */ + "{\"isrg_root_x1\": \"" /* ISRG ROOT X1 */ + "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4" + "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu" + "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY" + "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc" + "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+" + "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U" + "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW" + "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH" + "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC" + "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv" + "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn" + "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn" + "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw" + "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI" + "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV" + "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq" + "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL" + "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ" + "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK" + "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5" + "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur" + "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC" + "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc" + "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq" + "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA" + "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d" + "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" + "\"}," + "{\"LEX3_isrg_root_x1\": \"" /* LE X3 signed by ISRG X1 root */ + "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw" + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1" + "WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg" + "RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi" + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX" + "NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf" + "89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl" + "Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc" + "Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz" + "uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB" + "AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU" + "BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB" + "FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo" + "SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js" + "LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF" + "BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG" + "AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD" + "VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB" + "ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx" + "A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM" + "UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2" + "DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1" + "eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu" + "OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw" + "p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY" + "2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0" + "ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR" + "PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b" + "rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt" + "\"}" + "]," + "\"trust_stores\": [" /* named cert chains */ + "{" + "\"name\": \"le_via_isrg\"," + "\"stack\": [" + "\"isrg_root_x1\"," + "\"LEX3_isrg_root_x1\"" + "]" + "}" + "]," + "\"s\": [" + + "{\"test_stream\": {" + "\"endpoint\":" "\"warmcat.com\"," + "\"port\":" "443," + "\"protocol\":" "\"h2\"," + "\"http_method\":" "\"GET\"," + "\"http_url\":" "\"index.html\"," + "\"tls\":" "true," + "\"opportunistic\":" "true," + "\"retry\":" "\"default\"," + "\"tls_trust_store\":" "\"le_via_isrg\"" + "}},{" + /* + * "captive_portal_detect" describes + * what to do in order to check if the path to + * the Internet is being interrupted by a + * captive portal. + */ + "\"captive_portal_detect\": {" + "\"endpoint\":" "\"connectivitycheck.android.com\"," + "\"http_url\":" "\"generate_204\"," + "\"port\":" "80," + "\"protocol\":" "\"h1\"," + "\"http_method\":" "\"GET\"," + "\"opportunistic\":" "true," + "\"http_expect\":" "204," + "\"http_fail_redirect\": true" + "}}" + "]}" +; + + diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig b/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig index b60902c0..859ff001 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig @@ -300,7 +300,7 @@ CONFIG_ADC_CAL_LUT_ENABLE=y CONFIG_ESP_ERR_TO_NAME_LOOKUP=y CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 -CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=6584 CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h b/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h index b2cc0030..0ace05ce 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/sdkconfig.h @@ -88,7 +88,7 @@ #define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 #define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 #define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 -#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 6584 #define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 #define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 #define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 -- Gitee From dfed5475295e552bdbf5165193eb7e40ece71a45 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 30 Jun 2020 21:08:05 +0100 Subject: [PATCH 0194/1062] glib: stop leaking idle and hrtimer source This gives a valgrind result for lws-minimal-http-server-event-lib-foreign that's clean for lws pieces, although glib is always dirty wrt thread local storage and hashtable. --- lib/event-libs/glib/glib.c | 63 ++++++++++--------- .../glib/private-lib-event-libs-glib.h | 14 +++-- .../minimal-http-server-eventlib-foreign.c | 32 ++++++++-- 3 files changed, 70 insertions(+), 39 deletions(-) diff --git a/lib/event-libs/glib/glib.c b/lib/event-libs/glib/glib.c index 386f144f..b83134b9 100644 --- a/lib/event-libs/glib/glib.c +++ b/lib/event-libs/glib/glib.c @@ -27,7 +27,7 @@ #include #if !defined(G_SOURCE_FUNC) -#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) +#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) #endif #define wsi_to_subclass(_w) ((_w)->w_read.glib.source) @@ -35,6 +35,12 @@ #define pt_to_loop(_pt) ((_pt)->glib.loop) #define pt_to_g_main_context(_pt) g_main_loop_get_context(pt_to_loop(_pt)) +#define lws_gs_valid(t) (t.gs) +#define lws_gs_destroy(t) if (lws_gs_valid(t)) { \ + g_source_remove(t.tag); \ + g_source_unref(t.gs); \ + t.gs = NULL; t.tag = 0; } + static gboolean lws_glib_idle_timer_cb(void *p); @@ -62,17 +68,17 @@ lws_glib_check(GSource *src) static int lws_glib_set_idle(struct lws_context_per_thread *pt) { - GSource *gis; - - if (pt->glib.idle_tag) + if (lws_gs_valid(pt->glib.idle)) return 0; - gis = g_idle_source_new(); - if (!gis) + pt->glib.idle.gs = g_idle_source_new(); + if (!pt->glib.idle.gs) return 1; - g_source_set_callback(gis, lws_glib_idle_timer_cb, pt, NULL); - pt->glib.idle_tag = g_source_attach(gis, pt_to_g_main_context(pt)); + g_source_set_callback(pt->glib.idle.gs, lws_glib_idle_timer_cb, pt, + NULL); + pt->glib.idle.tag = g_source_attach(pt->glib.idle.gs, + pt_to_g_main_context(pt)); return 0; } @@ -80,14 +86,16 @@ lws_glib_set_idle(struct lws_context_per_thread *pt) static int lws_glib_set_timeout(struct lws_context_per_thread *pt, unsigned int ms) { - GSource *gts; + lws_gs_destroy(pt->glib.hrtimer); - gts = g_timeout_source_new(ms); - if (!gts) + pt->glib.hrtimer.gs = g_timeout_source_new(ms); + if (!pt->glib.hrtimer.gs) return 1; - g_source_set_callback(gts, lws_glib_hrtimer_cb, pt, NULL); - pt->glib.hrtimer_tag = g_source_attach(gts, pt_to_g_main_context(pt)); + g_source_set_callback(pt->glib.hrtimer.gs, lws_glib_hrtimer_cb, pt, + NULL); + pt->glib.hrtimer.tag = g_source_attach(pt->glib.hrtimer.gs, + pt_to_g_main_context(pt)); return 0; } @@ -127,7 +135,7 @@ lws_glib_dispatch(GSource *src, GSourceFunc x, gpointer userData) lws_service_fd_tsi(sub->wsi->context, &eventfd, sub->wsi->tsi); - if (!pt->glib.idle_tag) + if (!lws_gs_valid(pt->glib.idle)) lws_glib_set_idle(pt); if (pt->destroy_self) @@ -157,6 +165,9 @@ lws_glib_hrtimer_cb(void *p) lws_usec_t us; lws_pt_lock(pt, __func__); + + lws_gs_destroy(pt->glib.hrtimer); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, lws_now_usecs()); if (us) { @@ -206,7 +217,7 @@ lws_glib_idle_timer_cb(void *p) * We reenable the idle callback on the next network or scheduled event */ - pt->glib.idle_tag = 0; + lws_gs_destroy(pt->glib.idle); return FALSE; } @@ -314,7 +325,7 @@ elops_init_pt_glib(struct lws_context *context, void *_loop, int tsi) if (pt->event_loop_foreign) return 0; - pt->glib.sigint_tag = g_unix_signal_add(SIGINT, + pt->glib.sigint.tag = g_unix_signal_add(SIGINT, G_SOURCE_FUNC(lws_glib_sigint_cb), pt); return 0; @@ -333,6 +344,9 @@ elops_io_glib(struct lws *wsi, int flags) if (!pt_to_loop(pt) || wsi->context->being_destroyed || pt->is_destroyed) return; + if (!wsi_to_subclass(wsi)) + return; + /* * We are being given individual set / clear operations using * LWS_EV_ common namespace, convert them to glib namespace bitfield @@ -357,16 +371,6 @@ elops_io_glib(struct lws *wsi, int flags) lwsl_debug("%s: wsi %p, fd %d, 0x%x/0x%x\n", __func__, wsi, wsi->desc.sockfd, flags, (int)cond); - if (!wsi_to_subclass(wsi)) { - lwsl_err("%s: glib wsi source pointer is NULL\n", __func__); - return; - } - - if (!wsi_to_subclass(wsi)) { - lwsl_err("%s: glib wsi source pointer is NULL\n", __func__); - return; - } - g_source_modify_unix_fd(wsi_to_gsource(wsi), wsi_to_subclass(wsi)->tag, cond); } @@ -402,6 +406,7 @@ elops_destroy_wsi_glib(struct lws *wsi) } g_source_destroy(wsi_to_gsource(wsi)); + g_source_unref(wsi_to_gsource(wsi)); wsi_to_subclass(wsi) = NULL; } @@ -424,12 +429,12 @@ elops_destroy_pt_glib(struct lws_context *context, int tsi) vh = vh->vhost_next; } - if (pt->glib.hrtimer_tag) - g_source_remove(pt->glib.hrtimer_tag); + lws_gs_destroy(pt->glib.idle); + lws_gs_destroy(pt->glib.hrtimer); if (!pt->event_loop_foreign) { g_main_loop_quit(pt_to_loop(pt)); - g_source_remove(pt->glib.sigint_tag); + lws_gs_destroy(pt->glib.sigint); g_main_loop_unref(pt_to_loop(pt)); } diff --git a/lib/event-libs/glib/private-lib-event-libs-glib.h b/lib/event-libs/glib/private-lib-event-libs-glib.h index 00bbf551..4de461f9 100644 --- a/lib/event-libs/glib/private-lib-event-libs-glib.h +++ b/lib/event-libs/glib/private-lib-event-libs-glib.h @@ -30,11 +30,17 @@ #endif #endif /* LWS_WITH_GLIB */ +typedef struct lws_glib_tag { + GSource *gs; + guint tag; +} lws_glib_tag_t; + struct lws_pt_eventlibs_glib { - GMainLoop *loop; - guint hrtimer_tag; - guint sigint_tag; - guint idle_tag; + GMainLoop *loop; + + lws_glib_tag_t hrtimer; + lws_glib_tag_t sigint; + lws_glib_tag_t idle; }; struct lws_io_watcher_glib_subclass { diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c index 332f08c5..90049232 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c +++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c @@ -210,9 +210,19 @@ foreign_event_loop_cleanup_libevent(void) #include #include +typedef struct lws_glib_tag { + GSource *gs; + guint tag; +} lws_glib_tag_t; + +#define lws_gs_valid(t) (t.gs) +#define lws_gs_destroy(t) if (lws_gs_valid(t)) { \ + g_source_remove(t.tag); \ + g_source_unref(t.gs); \ + t.gs = NULL; t.tag = 0; } + static GMainLoop *loop_glib; -static guint timer_outer_glib; -static guint sighandler_glib; +static lws_glib_tag_t timer_outer_glib, sighandler_glib; static int timer_cb_glib(void *p) @@ -234,10 +244,16 @@ foreign_event_loop_init_and_run_glib(void) loop_glib = g_main_loop_new(NULL, 0); - sighandler_glib = g_unix_signal_add(SIGINT, - G_SOURCE_FUNC(signal_cb_glib), NULL); + sighandler_glib.gs = g_unix_signal_source_new(SIGINT); + g_source_set_callback(sighandler_glib.gs, G_SOURCE_FUNC(signal_cb_glib), + NULL, NULL); + sighandler_glib.tag = g_source_attach(sighandler_glib.gs, + g_main_loop_get_context(loop_glib)); - timer_outer_glib = g_timeout_add(1000, timer_cb_glib, NULL); + timer_outer_glib.gs = g_timeout_source_new(1000); + g_source_set_callback(timer_outer_glib.gs, timer_cb_glib, NULL, NULL); + timer_outer_glib.tag = g_source_attach(timer_outer_glib.gs, + g_main_loop_get_context(loop_glib)); g_main_loop_run(loop_glib); } @@ -252,8 +268,12 @@ static void foreign_event_loop_cleanup_glib(void) { /* cleanup the foreign loop assets */ - g_source_remove(sighandler_glib); + + lws_gs_destroy(sighandler_glib); + lws_gs_destroy(timer_outer_glib); + g_main_loop_unref(loop_glib); + loop_glib = NULL; } #endif -- Gitee From 0f3b45bc204cb38c449505903837015c17cd020a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 1 Jul 2020 19:31:14 +0100 Subject: [PATCH 0195/1062] ss: h1: completed transaction needs to leave ss wsi intact for close --- lib/secure-streams/protocols/ss-h1.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index aa6c71a2..f412a229 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -459,7 +459,6 @@ malformed: if (lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE)) break; - h->wsi = NULL; h->txn_ok = 1; //bad = status != 200; -- Gitee From f90287363465b892d7e9bb299f4e724be181cb43 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 30 Jun 2020 16:42:37 +0100 Subject: [PATCH 0196/1062] ss: add timeout --- doc-assets/ss-state-flow.png | Bin 201758 -> 252286 bytes .../libwebsockets/lws-secure-streams-client.h | 32 +++++--- .../libwebsockets/lws-secure-streams-policy.h | 2 + include/libwebsockets/lws-secure-streams.h | 50 ++++++++++++- lib/secure-streams/README.md | 8 ++ lib/secure-streams/policy-common.c | 2 +- lib/secure-streams/policy-json.c | 6 ++ .../private-lib-secure-streams.h | 7 +- lib/secure-streams/protocols/ss-h1.c | 3 + lib/secure-streams/protocols/ss-mqtt.c | 2 + lib/secure-streams/protocols/ss-raw.c | 1 + lib/secure-streams/protocols/ss-ws.c | 1 + lib/secure-streams/secure-streams-client.c | 43 ++++++++++- lib/secure-streams/secure-streams-process.c | 18 +++-- lib/secure-streams/secure-streams-serialize.c | 69 ++++++++++++++---- lib/secure-streams/secure-streams.c | 38 ++++++++++ .../minimal-secure-streams.c | 2 + .../minimal-secure-streams.c | 10 +++ 18 files changed, 251 insertions(+), 43 deletions(-) diff --git a/doc-assets/ss-state-flow.png b/doc-assets/ss-state-flow.png index 078100fad286d3c9a26639c2947e197db08e460f..88dfca83d79235a9e38888ae41499eed1e4fdb91 100644 GIT binary patch literal 252286 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

YqHXug@6dGr@lPv=OQcUy}>u8;cd(EVHph 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⪼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 DqxQU1 literal 201758 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≺=MNhSmwC5o%D?yyB^Ty;j> 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

&1dQI<1KHilUt@h{tm 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 zm{policy, name); if (!omd) { - lwsl_err("%s: unknown metadata %s\n", __func__, name); + lwsl_info("%s: unknown metadata %s\n", __func__, name); return 1; } diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 253d36ca..c3f07467 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -54,6 +54,7 @@ static const char * const lejp_tokens_policy[] = { "s[].*.urgent_rx", "s[].*.long_poll", "s[].*.retry", + "s[].*.timeout_ms", "s[].*.tls_trust_store", "s[].*.metadata", "s[].*.metadata[].*", @@ -121,6 +122,7 @@ typedef enum { LSSPPT_URGENT_RX, LSSPPT_LONG_POLL, LSSPPT_RETRYPTR, + LSSPPT_DEFAULT_TIMEOUT_MS, LSSPPT_TRUST, LSSPPT_METADATA, LSSPPT_METADATA_ITEM, @@ -475,6 +477,10 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->u.http.resp_expect = atoi(ctx->buf); break; + case LSSPPT_DEFAULT_TIMEOUT_MS: + a->curr[LTY_POLICY].p->timeout_ms = atoi(ctx->buf); + break; + case LSSPPT_OPPORTUNISTIC: if (reason == LEJPCB_VAL_TRUE) a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_OPPORTUNISTIC; diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index d88561f9..f8298448 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -63,6 +63,7 @@ typedef struct lws_ss_handle { struct lws_ss_handle *h_sink; /**< sink we are bound to, or NULL */ void *sink_obj;/**< sink's private object representing us */ + lws_sorted_usec_list_t sul_timeout; lws_sorted_usec_list_t sul; lws_ss_tx_ordinal_t txord; @@ -254,10 +255,11 @@ typedef struct lws_sspc_handle { lws_ss_conn_states_t state; - int16_t temp16; - + uint32_t timeout_ms; uint32_t ord; + int16_t temp16; + uint8_t rideshare_ofs[4]; uint8_t conn_req; uint8_t rsidx; @@ -265,6 +267,7 @@ typedef struct lws_sspc_handle { uint8_t destroying:1; uint8_t non_wsi:1; uint8_t ignore_txc:1; + uint8_t pending_timeout_update:1; } lws_sspc_handle_t; typedef struct backoffs { diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index f412a229..3e134fa5 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -197,6 +197,8 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_CLOSED_CLIENT_HTTP: if (!h) break; + + lws_sul_cancel(&h->sul_timeout); lwsl_info("%s: h: %p, %s LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", __func__, h, h->policy ? h->policy->streamtype : "no policy"); @@ -451,6 +453,7 @@ malformed: h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM); wsi->http.writeable_len = h->writeable_len = 0; + lws_sul_cancel(&h->sul_timeout); if (h->u.http.good_respcode) { if (lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE)) diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index eb2e4bf6..80aa8588 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -55,6 +55,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_MQTT_CLIENT_CLOSED: if (!h) break; + lws_sul_cancel(&h->sul_timeout); f = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); if (h->wsi) lws_set_opaque_user_data(h->wsi, NULL); @@ -116,6 +117,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; case LWS_CALLBACK_MQTT_ACK: + lws_sul_cancel(&h->sul_timeout); lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE); break; diff --git a/lib/secure-streams/protocols/ss-raw.c b/lib/secure-streams/protocols/ss-raw.c index 05891268..7ed740bb 100644 --- a/lib/secure-streams/protocols/ss-raw.c +++ b/lib/secure-streams/protocols/ss-raw.c @@ -51,6 +51,7 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_RAW_CLOSE: if (!h) break; + lws_sul_cancel(&h->sul_timeout); lwsl_info("%s: h: %p, %s LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", __func__, h, h->policy ? h->policy->streamtype : "no policy"); diff --git a/lib/secure-streams/protocols/ss-ws.c b/lib/secure-streams/protocols/ss-ws.c index 08dc9cb9..06786e9b 100644 --- a/lib/secure-streams/protocols/ss-ws.c +++ b/lib/secure-streams/protocols/ss-ws.c @@ -52,6 +52,7 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_CLIENT_CLOSED: if (!h) break; + lws_sul_cancel(&h->sul_timeout); f = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); if (h->wsi) lws_set_opaque_user_data(h->wsi, NULL); diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index 38f045f9..24adac76 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -174,11 +174,33 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, if (!h) break; - lwsl_notice("%s: WRITEABLE %p: (%s) state %d\n", __func__, wsi, + lwsl_debug("%s: WRITEABLE %p: (%s) state %d\n", __func__, wsi, h->ssi.streamtype, h->state); + /* + * Management of ss timeout can happen any time and doesn't + * depend on wsi existence or state + */ + n = 0; cp = s; + + if (h->pending_timeout_update) { + s[0] = LWSSS_SER_TXPRE_TIMEOUT_UPDATE; + s[1] = 0; + s[2] = 4; + /* + * 0: use policy timeout value + * 0xffffffff: cancel the timeout + */ + lws_ser_wu32be(&s[3], h->timeout_ms); + /* in case anything else to write */ + lws_callback_on_writable(h->cwsi); + h->pending_timeout_update = 0; + n = 7; + goto do_write; + } + s[1] = 0; switch (h->state) { case LPCS_SENDING_INITIAL_TX: @@ -261,7 +283,9 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, len = sizeof(pkt) - LWS_PRE - 19; flags = 0; - if (h->ssi.tx(m, h->ord++, pkt + LWS_PRE + 19, &len, &flags)) + n = h->ssi.tx(m, h->ord++, pkt + LWS_PRE + 19, &len, + &flags); + if (n == LWSSSSRET_TX_DONT_SEND) break; h->txc.tx_cr -= len; @@ -291,6 +315,7 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, if (!n) break; +do_write: n = lws_write(wsi, (uint8_t *)cp, n, LWS_WRITE_RAW); if (n < 0) { lwsl_notice("%s: WRITEABLE: %d\n", __func__, n); @@ -578,3 +603,17 @@ lws_sspc_get_est_peer_tx_credit(struct lws_sspc_handle *h) { return h->txc.peer_tx_cr_est; } + +void +lws_sspc_start_timeout(struct lws_sspc_handle *h, unsigned int timeout_ms) +{ + h->timeout_ms = (uint32_t)timeout_ms; + h->pending_timeout_update = 1; + lws_callback_on_writable(h->cwsi); +} + +void +lws_sspc_cancel_timeout(struct lws_sspc_handle *h) +{ + lws_sspc_start_timeout(h, (unsigned int)-1); +} diff --git a/lib/secure-streams/secure-streams-process.c b/lib/secure-streams/secure-streams-process.c index cb9cbb16..dd25bf42 100644 --- a/lib/secure-streams/secure-streams-process.c +++ b/lib/secure-streams/secure-streams-process.c @@ -286,17 +286,21 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_RAW_CLOSE: lwsl_info("LWS_CALLBACK_RAW_CLOSE:\n"); - /* - * the client unix domain socket connection has closed... - * eg, client has exited or otherwise has definitively finished - * with the proxying and onward connection - */ - if (!conn) break; + /* + * the client unix domain socket connection (wsi / conn->wsi) + * has closed... eg, client has exited or otherwise has + * definitively finished with the proxying and onward connection + * + * But right now, the SS and possibly the SS onward wsi are + * still live... + */ + if (conn->ss) { - lwsl_info("%s: destroying ss\n", __func__); + lwsl_info("%s: destroying ss.h=%p, ss.wsi=%p\n", + __func__, conn->ss, conn->ss->wsi); /* sever relationship with ss about to be deleted */ lws_set_opaque_user_data(wsi, NULL); diff --git a/lib/secure-streams/secure-streams-serialize.c b/lib/secure-streams/secure-streams-serialize.c index db24f14a..d79fdc00 100644 --- a/lib/secure-streams/secure-streams-serialize.c +++ b/lib/secure-streams/secure-streams-serialize.c @@ -72,6 +72,8 @@ typedef enum { RPAR_TXCR0, + RPAR_TIMEOUT0, + RPAR_RESULT_CREATION, RPAR_STATEINDEX, @@ -379,16 +381,24 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, par->ctr = 0; break; + case LWSSS_SER_TXPRE_TIMEOUT_UPDATE: + if (client) + goto hangup; + if (par->rem != 4) + goto hangup; + par->ps = RPAR_TIMEOUT0; + par->ctr = 0; + break; + /* client side */ case LWSSS_SER_RXPRE_RX_PAYLOAD: if (!client) goto hangup; if (*state != LPCS_OPERATIONAL && - *state != LPCS_LOCAL_CONNECTED) { - lwsl_err("rx in state %d\n", *state); + *state != LPCS_LOCAL_CONNECTED) goto hangup; - } + par->rideshare[0] = '\0'; par->ps = RPAR_FLAG_B3; break; @@ -396,14 +406,12 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, case LWSSS_SER_RXPRE_CREATE_RESULT: if (!client) goto hangup; - if (*state != LPCS_WAITING_CREATE_RESULT) { - lwsl_err("a2\n"); + if (*state != LPCS_WAITING_CREATE_RESULT) goto hangup; - } - if (par->rem < 1) { - lwsl_err("a3\n"); + + if (par->rem < 1) goto hangup; - } + par->ps = RPAR_RESULT_CREATION; break; @@ -411,14 +419,12 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, if (!client) goto hangup; if (*state != LPCS_LOCAL_CONNECTED && - *state != LPCS_OPERATIONAL) { - lwsl_err("a4\n"); + *state != LPCS_OPERATIONAL) goto hangup; - } - if (par->rem < 4) { - lwsl_err("a5\n"); + + if (par->rem < 4) goto hangup; - } + par->ps = RPAR_STATEINDEX; break; @@ -690,6 +696,35 @@ payload_ff: par->ps = RPAR_TYPE; break; + case RPAR_TIMEOUT0: + + par->temp32 = (par->temp32 << 8) | *cp++; + if (++par->ctr < 4) { + if (!--par->rem) + goto hangup; + break; + } + + if (--par->rem) + goto hangup; + + if ((unsigned int)par->temp32 == 0xffffffff) { + lwsl_notice("%s: cancel ss timeout\n", __func__); + lws_ss_cancel_timeout(*pss); + } else { + + if (!par->temp32) + par->temp32 = (*pss)->policy->timeout_ms; + + lwsl_notice("%s: set ss timeout for +%ums\n", + __func__, par->temp32); + + lws_ss_start_timeout((*pss), par->temp32); + } + + par->ps = RPAR_TYPE; + break; + case RPAR_METADATA_NAMELEN: if (!--par->rem) goto hangup; @@ -916,11 +951,13 @@ payload_ff: lws_ss_serialize_state_transition(state, LPCS_OPERATIONAL); break; + case LWSSSCS_TIMEOUT: + break; default: break; } - if (par->ctr < 0 || par->ctr > 9) + if (par->ctr < 0 || par->ctr > 16) goto hangup; #if defined(_DEBUG) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 36880f7b..654facf1 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -63,6 +63,7 @@ static const char *state_names[] = { "LWSSSCS_QOS_NACK_REMOTE", "LWSSSCS_QOS_ACK_LOCAL", "LWSSSCS_QOS_NACK_LOCAL", + "LWSSSCS_TIMEOUT", }; const char * @@ -712,6 +713,7 @@ lws_ss_destroy(lws_ss_handle_t **ppss) *ppss = NULL; lws_dll2_remove(&h->list); lws_dll2_remove(&h->to_list); + lws_sul_cancel(&h->sul_timeout); /* no need to worry about return code since we are anyway destroying */ lws_ss_event_helper(h, LWSSSCS_DESTROYING); lws_pt_unlock(pt); @@ -845,3 +847,39 @@ lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h) return 0; } + +/* + * protocol-independent handler for ss timeout + */ + +static void +lws_ss_to_cb(lws_sorted_usec_list_t *sul) +{ + lws_ss_handle_t *h = lws_container_of(sul, lws_ss_handle_t, sul_timeout); + + lwsl_info("%s: ss %p timeout fired\n", __func__, h); + + if (lws_ss_event_helper(h, LWSSSCS_TIMEOUT) == LWSSSSRET_DESTROY_ME) + /* + * We're called from the sul handler, caller doesn't have any + * copy of the ss handle + */ + lws_ss_destroy(&h); +} + +void +lws_ss_start_timeout(struct lws_ss_handle *h, unsigned int timeout_ms) +{ + if (!timeout_ms && !h->policy->timeout_ms) + return; + + lws_sul_schedule(h->context, 0, &h->sul_timeout, lws_ss_to_cb, + (timeout_ms ? timeout_ms : h->policy->timeout_ms) * + LWS_US_PER_MS); +} + +void +lws_ss_cancel_timeout(struct lws_ss_handle *h) +{ + lws_sul_cancel(&h->sul_timeout); +} diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c index 4f0c0a46..92e6cbbb 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c @@ -521,6 +521,8 @@ int main(int argc, const char **argv) printf("\t.retry_bo = &_rbo_%zu,\n", a->offset); } + if (pol->timeout_ms) + printf("\t.timeout_ms = %u,\n", pol->timeout_ms); if (pol->flags) printf("\t.flags = 0x%x,\n", pol->flags); if (pol->port) diff --git a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c index 6ee06309..0e579a12 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c @@ -39,6 +39,7 @@ static int interrupted, bad = 1, force_cpd_fail_portal, force_cpd_fail_no_internet; +static unsigned int timeout_ms = 3000; static lws_state_notify_link_t nl; /* @@ -266,6 +267,7 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: + lws_ss_start_timeout(m->ss, timeout_ms); lws_ss_set_metadata(m->ss, "uptag", "myuptag123", 10); lws_ss_set_metadata(m->ss, "ctype", "myctype", 7); lws_ss_client_connect(m->ss); @@ -277,6 +279,10 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, case LWSSSCS_QOS_ACK_REMOTE: lwsl_notice("%s: LWSSSCS_QOS_ACK_REMOTE\n", __func__); break; + + case LWSSSCS_TIMEOUT: + lwsl_notice("%s: LWSSSCS_TIMEOUT\n", __func__); + break; default: break; } @@ -397,6 +403,7 @@ int main(int argc, const char **argv) { struct lws_context_creation_info info; struct lws_context *context; + const char *p; int n = 0; signal(SIGINT, sigint_handler); @@ -414,6 +421,9 @@ int main(int argc, const char **argv) if (lws_cmdline_option(argc, argv, "--force-no-internet")) force_cpd_fail_no_internet = 1; + if ((p = lws_cmdline_option(argc, argv, "--timeout_ms"))) + timeout_ms = atoi(p); + info.fd_limit_per_thread = 1 + 6 + 1; info.port = CONTEXT_PORT_NO_LISTEN; #if defined(LWS_SS_USE_SSPC) -- Gitee From 2e1969187da3601d376e85156004290f2673014e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 3 Jul 2020 06:42:31 +0100 Subject: [PATCH 0197/1062] sul: lws_sul_nonmonotonic_adjust FreeRTOS only supports nonmonotonic time, when we correct it by, eg, ntpclient, we offset all the existing sul timeouts. This adds an internal helper function to correct existing sul timeouts by the step amount, and call it in lws ntpclient implementation when adjusting the gettimeofday() time. --- lib/core-net/private-lib-core-net.h | 3 ++ lib/core-net/sorted-usec-list.c | 68 ++++++++++++++++++++++++++++- lib/system/ntpclient/ntpclient.c | 20 +++++++-- 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index a688e03b..c28a2964 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -1447,6 +1447,9 @@ lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len); int lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len); +lws_usec_t +lws_sul_nonmonotonic_adjust(struct lws_context *ctx, int64_t step_us); + enum { LW5CHS_RET_RET0, diff --git a/lib/core-net/sorted-usec-list.c b/lib/core-net/sorted-usec-list.c index 04de5916..895865c5 100644 --- a/lib/core-net/sorted-usec-list.c +++ b/lib/core-net/sorted-usec-list.c @@ -103,7 +103,7 @@ __lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow) lws_system_do_attach(pt); /* must be at least 1 */ - assert(own_len); + assert(own_len > 0); /* * Of the own_len sul owning lists, the earliest next sul could be on @@ -154,6 +154,72 @@ __lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow) return 0; } +/* + * Normally we use the OS monotonic time, which does not step when the + * gettimeofday() time is adjusted after, eg, ntpclient. But on some OSes, + * high resolution monotonic time doesn't exist; sul time is computed from and + * compared against gettimeofday() time and breaks when that steps. + * + * For those cases, this allows us to retrospectively adjust existing suls on + * all owning lists by the step amount, at the same time we adjust the + * nonmonotonic clock. Then nothing breaks so long as we do this when the + * gettimeofday() clock is stepped. + * + * Linux and so on offer Posix MONOTONIC, which lws uses. FreeRTOS doesn't + * have a high-resolution monotonic clock and has to use gettimeofday(), which + * requires this adjustment when it is stepped. + */ + +lws_usec_t +lws_sul_nonmonotonic_adjust(struct lws_context *ctx, int64_t step_us) +{ + struct lws_context_per_thread *pt = &ctx->pt[0]; + int n, m; + + /* + * for each pt + */ + + for (m = 0; m < ctx->count_threads; m++) { + + /* + * For each owning list... + */ + + lws_pt_lock(pt, __func__); + + for (n = 0; n < LWS_COUNT_PT_SUL_OWNERS; n++) { + + if (!pt->pt_sul_owner[n].count) + continue; + + /* ... and for every existing sul on a list... */ + + lws_start_foreach_dll(struct lws_dll2 *, p, + lws_dll2_get_head( + &pt->pt_sul_owner[n])) { + lws_sorted_usec_list_t *sul = lws_container_of( + p, lws_sorted_usec_list_t, list); + + /* + * ... retrospectively step its ripe time by the + * step we will adjust the gettimeofday() clock + * with + */ + + sul->us += step_us; + + } lws_end_foreach_dll(p); + } + + lws_pt_unlock(pt); + + pt++; + } + + return 0; +} + /* * Earliest wakeable event on any pt */ diff --git a/lib/system/ntpclient/ntpclient.c b/lib/system/ntpclient/ntpclient.c index 012c0419..04e2bad6 100644 --- a/lib/system/ntpclient/ntpclient.c +++ b/lib/system/ntpclient/ntpclient.c @@ -127,6 +127,8 @@ callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi)); uint8_t pkt[LWS_PRE + 48]; + struct timeval t1; + int64_t delta_us; uint64_t ns; switch (reason) { @@ -224,16 +226,28 @@ do_close: ns = lws_ser_ru32be(((uint8_t *)in) + 40) - 2208988800; ns = (ns * 1000000000) + lws_ser_ru32be(((uint8_t *)in) + 44); - lwsl_notice("%s: Unix time: %llu\n", __func__, - (unsigned long long)ns / 1000000000); + /* + * Compute the step + */ + + gettimeofday(&t1, NULL); -#if defined(LWS_ESP_PLATFORM) + delta_us = (ns / 1000) - + ((t1.tv_sec * LWS_US_PER_SEC) + t1.tv_usec); + + lwsl_notice("%s: Unix time: %llu, step: %lldus\n", __func__, + (unsigned long long)ns / 1000000000, + delta_us); + +#if defined(LWS_PLAT_FREERTOS) { struct timeval t; t.tv_sec = (unsigned long long)ns / 1000000000; t.tv_usec = (ns % 1000000000) / 1000; + lws_sul_nonmonotonic_adjust(wsi->context, delta_us); + settimeofday(&t, NULL); } #endif -- Gitee From 1a756ca17856be14416ff71dba9bb95fc0f45930 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 3 Jul 2020 08:57:24 +0100 Subject: [PATCH 0198/1062] ss-h1: close bound wsi when state handler requests ss destroy --- lib/secure-streams/protocols/ss-h1.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 3e134fa5..cf07fd8d 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -455,14 +455,14 @@ malformed: wsi->http.writeable_len = h->writeable_len = 0; lws_sul_cancel(&h->sul_timeout); + h->txn_ok = 1; + if (h->u.http.good_respcode) { if (lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE)) - break; + return -1; } else if (lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE)) - break; - - h->txn_ok = 1; + return -1; //bad = status != 200; lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ -- Gitee From c410956a3132598d174de75592eb14e4298e5a29 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 4 Jul 2020 21:16:49 +0100 Subject: [PATCH 0199/1062] ss: event_helper handles destroy requests itself Callbacks can ask the caller to, eg, destroy the ss handle now. But some callback returns are handled and produced inside other helper apis, eg lws_ss_backoff() may have to had fulfilled the callback request to destroy the ss... therefore it has to signal to its caller, and its callers have to check and exit their flow accordingly. --- include/libwebsockets/lws-secure-streams.h | 2 + lib/secure-streams/protocols/ss-h1.c | 30 ++++++++------- lib/secure-streams/protocols/ss-mqtt.c | 5 ++- lib/secure-streams/protocols/ss-raw.c | 9 +++-- lib/secure-streams/protocols/ss-ws.c | 17 ++++----- lib/secure-streams/secure-streams.c | 44 ++++++++++++++-------- 6 files changed, 66 insertions(+), 41 deletions(-) diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index b85e437a..c3d20da9 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -257,6 +257,8 @@ enum lws_ss_state_return_t { LWSSSSRET_OK = 0, LWSSSSRET_DISCONNECT_ME = -1, LWSSSSRET_DESTROY_ME = -2, + + LWSSSSRET_SS_HANDLE_DESTROYED = -3, }; /** diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index cf07fd8d..0e267c88 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -178,13 +178,15 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, lwsl_info("%s: h: %p, %s CLIENT_CONNECTION_ERROR: %s\n", __func__, h, h->policy->streamtype, in ? (char *)in : "(null)"); /* already disconnected, no action for DISCONNECT_ME */ - if (lws_ss_event_helper(h, LWSSSCS_UNREACHABLE) == - LWSSSSRET_DESTROY_ME) { - lws_ss_destroy(&h); + if (lws_ss_event_helper(h, LWSSSCS_UNREACHABLE)) + /* h has been destroyed */ break; - } + h->wsi = NULL; - lws_ss_backoff(h); + lwsl_notice("a4\n"); + if (lws_ss_backoff(h)) + /* was destroyed */ + return -1; break; case LWS_CALLBACK_CLIENT_HTTP_REDIRECT: @@ -206,14 +208,14 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, //bad = status != 200; //lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && - !h->txn_ok && !wsi->context->being_destroyed) - lws_ss_backoff(h); - else + !h->txn_ok && !wsi->context->being_destroyed) { + if (lws_ss_backoff(h)) + break; + } else h->seqstate = SSSEQ_IDLE; /* already disconnected, no action for DISCONNECT_ME */ - if (lws_ss_event_helper(h, LWSSSCS_DISCONNECTED) == - LWSSSSRET_DESTROY_ME) - lws_ss_destroy(&h); + lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); + /* may have been destroyed */ break; @@ -243,9 +245,9 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->retry = 0; h->seqstate = SSSEQ_CONNECTED; lws_sul_cancel(&h->sul); - if (lws_ss_event_helper(h, LWSSSCS_CONNECTED)) { + if (lws_ss_event_helper(h, LWSSSCS_CONNECTED)) + /* was destroyed */ return -1; - } /* * Since it's an http transaction we initiated... this is @@ -459,9 +461,11 @@ malformed: if (h->u.http.good_respcode) { if (lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE)) + /* was destroyed */ return -1; } else if (lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE)) + /* was destroyed */ return -1; //bad = status != 200; diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 80aa8588..0e857258 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -50,6 +50,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, } lws_ss_backoff(h); + /* may have been destroyed */ break; case LWS_CALLBACK_MQTT_CLIENT_CLOSED: @@ -73,7 +74,9 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && !h->txn_ok && !wsi->context->being_destroyed) - lws_ss_backoff(h); + if (lws_ss_backoff(h)) + /* has been destroyed */ + return -1; break; case LWS_CALLBACK_MQTT_CLIENT_ESTABLISHED: diff --git a/lib/secure-streams/protocols/ss-raw.c b/lib/secure-streams/protocols/ss-raw.c index 7ed740bb..1d0c8a25 100644 --- a/lib/secure-streams/protocols/ss-raw.c +++ b/lib/secure-streams/protocols/ss-raw.c @@ -46,6 +46,7 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); h->wsi = NULL; lws_ss_backoff(h); + /* may have been destroyed */ break; case LWS_CALLBACK_RAW_CLOSE: @@ -58,9 +59,11 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->wsi = NULL; if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && !h->txn_ok && !wsi->context->being_destroyed) - lws_ss_backoff(h); - if (lws_ss_event_helper(h, LWSSSCS_DISCONNECTED)) - lws_ss_destroy(&h); + if (lws_ss_backoff(h)) + /* has been destroyed */ + break; + /* wsi is going down anyway */ + lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); break; case LWS_CALLBACK_RAW_CONNECTED: diff --git a/lib/secure-streams/protocols/ss-ws.c b/lib/secure-streams/protocols/ss-ws.c index 06786e9b..10a3bd5f 100644 --- a/lib/secure-streams/protocols/ss-ws.c +++ b/lib/secure-streams/protocols/ss-ws.c @@ -41,31 +41,30 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, in ? (char *)in : "(null)"); if (!h) break; - if (lws_ss_event_helper(h, LWSSSCS_UNREACHABLE)) { - lws_ss_destroy(&h); + if (lws_ss_event_helper(h, LWSSSCS_UNREACHABLE)) + /* h has been destroyed */ break; - } + h->wsi = NULL; lws_ss_backoff(h); + /* may have been destroyed */ break; case LWS_CALLBACK_CLIENT_CLOSED: if (!h) break; lws_sul_cancel(&h->sul_timeout); - f = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); + if (lws_ss_event_helper(h, LWSSSCS_DISCONNECTED)) + /* has been destroyed */ + break; if (h->wsi) lws_set_opaque_user_data(h->wsi, NULL); h->wsi = NULL; - if (f) { - lws_ss_destroy(&h); - break; - } - if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && !h->txn_ok && !wsi->context->being_destroyed) lws_ss_backoff(h); + /* may have been destroyed */ break; case LWS_CALLBACK_CLIENT_ESTABLISHED: diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 654facf1..8b9d640e 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -99,6 +99,7 @@ lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); h->wsi = NULL; /* stop destroy trying to repeat this */ if (n == LWSSSSRET_DESTROY_ME) { + lwsl_info("%s: DESTROYING ss %p\n", __func__, h); lws_ss_destroy(&h); return 1; } @@ -114,7 +115,7 @@ lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) if (h->wsi) lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); if (n == LWSSSSRET_DESTROY_ME) { - lwsl_info("%s: ss %p asks to be destroyed\n", __func__, h); + lwsl_info("%s: DESTROYING ss %p\n", __func__, h); /* disconnect ss from the wsi */ if (h->wsi) lws_set_opaque_user_data(h->wsi, NULL); @@ -209,7 +210,9 @@ lws_ss_backoff(lws_ss_handle_t *h) if (!conceal) { lwsl_info("%s: ss %p: abandon conn attempt \n",__func__, h); h->seqstate = SSSEQ_IDLE; - lws_ss_event_helper(h, LWSSSCS_ALL_RETRIES_FAILED); + if (lws_ss_event_helper(h, LWSSSCS_ALL_RETRIES_FAILED)) + lwsl_notice("%s: was desroyed on ARF event\n", __func__); + /* may have been destroyed */ return 1; } @@ -461,11 +464,16 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry) h->txn_ok = 0; if (lws_ss_event_helper(h, LWSSSCS_CONNECTING)) - return -1; + return LWSSSSRET_SS_HANDLE_DESTROYED; if (!lws_client_connect_via_info(&i)) { - lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); - lws_ss_backoff(h); + if (lws_ss_event_helper(h, LWSSSCS_UNREACHABLE)) { + /* was destroyed */ + lwsl_err("%s: client connect UNREACHABLE destroyed the ss\n", __func__); + return LWSSSSRET_SS_HANDLE_DESTROYED; + } + if (lws_ss_backoff(h)) + return LWSSSSRET_SS_HANDLE_DESTROYED; return 1; } @@ -667,8 +675,11 @@ late_bail: ) #endif )) - if (_lws_ss_client_connect(h, 0)) - lws_ss_backoff(h); + if (_lws_ss_client_connect(h, 0)) { + if (lws_ss_backoff(h)) + /* has been destroyed */ + return 1; + } return 0; } @@ -714,7 +725,7 @@ lws_ss_destroy(lws_ss_handle_t **ppss) lws_dll2_remove(&h->list); lws_dll2_remove(&h->to_list); lws_sul_cancel(&h->sul_timeout); - /* no need to worry about return code since we are anyway destroying */ + lws_ss_event_helper(h, LWSSSCS_DESTROYING); lws_pt_unlock(pt); @@ -736,6 +747,8 @@ lws_ss_destroy(lws_ss_handle_t **ppss) void lws_ss_request_tx(lws_ss_handle_t *h) { + int n; + lwsl_info("%s: wsi %p\n", __func__, h->wsi); if (h->wsi) { @@ -771,7 +784,11 @@ lws_ss_request_tx(lws_ss_handle_t *h) * Retries operate via lws_ss_request_tx(), explicitly ask for a * reconnection to clear the retry limit */ - if (_lws_ss_client_connect(h, 1)) + n = _lws_ss_client_connect(h, 1); + if (n == LWSSSSRET_SS_HANDLE_DESTROYED) + return; + + if (n) lws_ss_backoff(h); } @@ -859,12 +876,9 @@ lws_ss_to_cb(lws_sorted_usec_list_t *sul) lwsl_info("%s: ss %p timeout fired\n", __func__, h); - if (lws_ss_event_helper(h, LWSSSCS_TIMEOUT) == LWSSSSRET_DESTROY_ME) - /* - * We're called from the sul handler, caller doesn't have any - * copy of the ss handle - */ - lws_ss_destroy(&h); + lws_ss_event_helper(h, LWSSSCS_TIMEOUT); + + /* may have been destroyed */ } void -- Gitee From e09430c48dcfa9bf09523d319e14bac472361daa Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 7 Jul 2020 15:13:37 +0100 Subject: [PATCH 0200/1062] ss: smd: no need to log msg alloc rejection --- lib/secure-streams/secure-streams.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 8b9d640e..d0097e98 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -285,7 +285,8 @@ lws_ss_smd_tx_cb(lws_sorted_usec_list_t *sul) _class = (lws_smd_class_t)lws_ser_ru64be(buf); p = lws_smd_msg_alloc(h->context, _class, len - LWS_SMD_SS_RX_HEADER_LEN); if (!p) { - lwsl_notice("%s: failed to alloc\n", __func__); + // this can be rejected if nobody listening for this class + //lwsl_notice("%s: failed to alloc\n", __func__); return; } -- Gitee From ed528b59f7572ca6a3c94aa36672e7427f693d75 Mon Sep 17 00:00:00 2001 From: Jed Lu Date: Tue, 7 Jul 2020 15:14:30 +0100 Subject: [PATCH 0201/1062] ss: client: add sspc_to_user_obj Helper api exists in direct lws_ss_ apis but not in lws_sspc_, align it. --- include/libwebsockets/lws-secure-streams-client.h | 5 +++++ lib/secure-streams/secure-streams-client.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/include/libwebsockets/lws-secure-streams-client.h b/include/libwebsockets/lws-secure-streams-client.h index 4c4a72b2..e749769f 100644 --- a/include/libwebsockets/lws-secure-streams-client.h +++ b/include/libwebsockets/lws-secure-streams-client.h @@ -55,6 +55,7 @@ #define lws_ss_get_est_peer_tx_credit lws_sspc_get_est_peer_tx_credit #define lws_ss_start_timeout lws_sspc_start_timeout #define lws_ss_cancel_timeout lws_sspc_cancel_timeout +#define lws_ss_to_user_object lws_sspc_to_user_object #endif @@ -178,3 +179,7 @@ lws_sspc_start_timeout(struct lws_sspc_handle *h, unsigned int timeout_ms); LWS_VISIBLE LWS_EXTERN void lws_sspc_cancel_timeout(struct lws_sspc_handle *h); + +LWS_VISIBLE LWS_EXTERN void * +lws_sspc_to_user_object(struct lws_sspc_handle *h); + diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index 24adac76..57c00426 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -617,3 +617,9 @@ lws_sspc_cancel_timeout(struct lws_sspc_handle *h) { lws_sspc_start_timeout(h, (unsigned int)-1); } + +void * +lws_sspc_to_user_object(struct lws_sspc_handle *h) +{ + return (void *)&h[1]; +} -- Gitee From 4939b87e66655b5343b987fc2d31a7137a0446ce Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 2 Jul 2020 15:38:53 +0100 Subject: [PATCH 0202/1062] lws_netdev: use lws_settings Perform the AP selection using lws_settings and a generic scan state machine --- cmake/lws_config.h.in | 1 + include/libwebsockets/lws-async-dns.h | 2 + include/libwebsockets/lws-netdev.h | 165 +++++- include/libwebsockets/lws-settings.h | 42 +- lib/core-net/private-lib-core-net.h | 47 ++ lib/core-net/service.c | 2 +- lib/core-net/vhost.c | 2 +- lib/core/alloc.c | 2 +- lib/core/context.c | 59 ++- lib/core/private-lib-core.h | 20 +- lib/drivers/CMakeLists.txt | 6 + lib/drivers/netdev/netdev.c | 272 ++++++++++ lib/drivers/netdev/wifi.c | 242 +++++++++ lib/drivers/settings/settings.c | 27 +- lib/misc/CMakeLists.txt | 7 +- lib/plat/freertos/CMakeLists.txt | 6 +- .../esp32/drivers/netdev/wifi-esp32.c | 494 ++++++++++++++++++ lib/plat/freertos/esp32/drivers/netdev/wifi.c | 214 -------- .../drivers/{settings.c => settings-esp32.c} | 12 +- lib/plat/freertos/freertos-service.c | 10 +- lib/secure-streams/protocols/ss-h2.c | 2 +- lib/secure-streams/secure-streams-client.c | 13 +- lib/system/dhcpclient/dhcpclient.c | 35 +- lib/system/ntpclient/ntpclient.c | 38 +- .../api-tests/api-test-lws_struct-json/main.c | 64 ++- .../esp32/esp-heltec-wb32/CMakeLists.txt | 6 + .../esp32/esp-heltec-wb32/main/devices.c | 207 ++++++++ .../esp-heltec-wb32/main/lws-minimal-esp32.c | 279 +++++----- .../esp32/esp-heltec-wb32/partitions.csv | 5 + .../embedded/esp32/esp-heltec-wb32/sdkconfig | 10 +- .../esp32/esp-heltec-wb32/sdkconfig.h | 2 +- .../esp32/esp-wrover-kit/CMakeLists.txt | 2 + .../esp32/esp-wrover-kit/main/devices.c | 55 +- .../esp-wrover-kit/main/lws-minimal-esp32.c | 9 +- 34 files changed, 1857 insertions(+), 502 deletions(-) create mode 100644 lib/drivers/netdev/netdev.c create mode 100644 lib/drivers/netdev/wifi.c create mode 100644 lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c delete mode 100644 lib/plat/freertos/esp32/drivers/netdev/wifi.c rename lib/plat/freertos/esp32/drivers/{settings.c => settings-esp32.c} (88%) create mode 100644 minimal-examples/embedded/esp32/esp-heltec-wb32/partitions.csv diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index b45302a6..327adff0 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -124,6 +124,7 @@ #cmakedefine LWS_WITH_DEPRECATED_LWS_DLL #cmakedefine LWS_WITH_DETAILED_LATENCY #cmakedefine LWS_WITH_DIR +#cmakedefine LWS_WITH_DRIVERS #cmakedefine LWS_WITH_ESP32 #cmakedefine LWS_HAVE_EVBACKEND_LINUXAIO #cmakedefine LWS_HAVE_EVBACKEND_IOURING diff --git a/include/libwebsockets/lws-async-dns.h b/include/libwebsockets/lws-async-dns.h index 773867d4..7387ca0f 100644 --- a/include/libwebsockets/lws-async-dns.h +++ b/include/libwebsockets/lws-async-dns.h @@ -40,6 +40,8 @@ typedef enum { LADNS_RET_CONTINUING } lws_async_dns_retcode_t; +struct addrinfo; + typedef struct lws * (*lws_async_dns_cb_t)(struct lws *wsi, const char *ads, const struct addrinfo *result, int n, void *opaque); diff --git a/include/libwebsockets/lws-netdev.h b/include/libwebsockets/lws-netdev.h index 8f2f0857..bf625121 100644 --- a/include/libwebsockets/lws-netdev.h +++ b/include/libwebsockets/lws-netdev.h @@ -23,10 +23,18 @@ */ #define LWS_WIFI_MAX_SCAN_TRACK 16 +#define LWS_ETH_ALEN 6 typedef uint8_t lws_wifi_ch_t; +typedef int8_t lws_wifi_rssi_t; struct lws_netdev_instance; +typedef enum { + LWSNDTYP_UNKNOWN, + LWSNDTYP_WIFI, + LWSNDTYP_ETH, +} lws_netdev_type_t; + /* * Base class for netdev configuration */ @@ -47,9 +55,39 @@ typedef struct lws_netdev_ops { lws_netdev_config_t *config); int (*up)(struct lws_netdev_instance *nd); int (*down)(struct lws_netdev_instance *nd); + int (*event)(struct lws_netdev_instance *nd, lws_usec_t timestamp, + void *buf, size_t len); + /**< these are SMD events coming from lws event loop thread context */ void (*destroy)(struct lws_netdev_instance **pnd); + int (*connect)(struct lws_netdev_instance *wnd, const char *ssid, + const char *passphrase, uint8_t *bssid); + void (*scan)(struct lws_netdev_instance *nd); } lws_netdev_ops_t; +/* + * Network devices on this platform + * + * We also hold a list of all known network credentials (when they are needed + * because there is a network interface without anything to connect to) and + * the lws_settings instance they are stored in + */ + +typedef struct lws_netdevs { + lws_dll2_owner_t owner; + /**< list of netdevs / lws_netdev_instance_t -based objects */ + + lws_dll2_owner_t owner_creds; + /**< list of known credentials */ + struct lwsac *ac_creds; + /**< lwsac holding retreived credentials settings, or NULL */ + lws_settings_instance_t *si; + + lws_sockaddr46 sa46_dns_resolver; + + uint8_t refcount_creds; + /**< when there are multiple netdevs, must refcount creds in mem */ +} lws_netdevs_t; + /* * Base class for an allocated instantiated derived object using lws_netdev_ops, * ie, a specific ethernet device @@ -58,9 +96,10 @@ typedef struct lws_netdev_ops { typedef struct lws_netdev_instance { const char *name; const lws_netdev_ops_t *ops; - struct lws_context *ctx; void *platinfo; lws_dll2_t list; + uint8_t mac[LWS_ETH_ALEN]; + uint8_t type; /* lws_netdev_type_t */ } lws_netdev_instance_t; enum { @@ -75,29 +114,88 @@ enum { LNDIW_ACQ_IPv6 = (1 << 1), }; -typedef struct lws_wifi_credentials { - uint8_t bssid[6]; +/* + * Group AP / Station State + */ + +typedef enum { + LWSNDVWIFI_STATE_INITIAL, + /* + * We should gratuitously try whatever last worked for us, then + * if that fails, worry about the rest of the logic + */ + LWSNDVWIFI_STATE_SCAN, + /* + * Unconnected, scanning: AP known in one of the config slots -> + * configure it, start timeout + LWSNDVWIFI_STATE_STAT, if no AP + * already up in same group with lower MAC, after a random + * period start up our AP (LWSNDVWIFI_STATE_AP) + */ + LWSNDVWIFI_STATE_AP, + /* Trying to be the group AP... periodically do a scan + * LWSNDVWIFI_STATE_AP_SCAN, faster and then slower + */ + LWSNDVWIFI_STATE_AP_SCAN, + /* + * doing a scan while trying to be the group AP... if we see a + * lower MAC being the AP for the same group AP, abandon being + * an AP and join that AP as a station + */ + LWSNDVWIFI_STATE_STAT_GRP_AP, + /* + * We have decided to join another group member who is being the + * AP, as its MAC is lower than ours. This is a stable state, + * but we still do periodic scans + * LWSNDVWIFI_STATE_STAT_GRP_AP_SCAN and will always prefer an + * AP configured in a slot. + */ + LWSNDVWIFI_STATE_STAT_GRP_AP_SCAN, + /* + * We have joined a group member who is doing the AP job... we + * want to check every now and then if a configured AP has + * appeared that we should better use instead. Otherwise stay + * in LWSNDVWIFI_STATE_STAT_GRP_AP + */ + LWSNDVWIFI_STATE_STAT, + /* + * trying to connect to another non-group AP. If we don't get an + * IP within a timeout and retries, blacklist it and go back + */ + LWSNDVWIFI_STATE_STAT_HAPPY, +} lws_netdev_wifi_state_t; + +/* + * Generic WIFI credentials + */ + +typedef struct lws_wifi_creds { + lws_dll2_t list; + + uint8_t bssid[LWS_ETH_ALEN]; char passphrase[64]; char ssid[33]; uint8_t alg; -} lws_wifi_credentials_t; +} lws_wifi_creds_t; + +/* + * Generic WIFI Network Device Instance + */ typedef struct lws_netdev_instance_wifi { lws_netdev_instance_t inst; - lws_dll2_owner_t scan; - - struct { - lws_wifi_credentials_t creds; - lws_sockaddr46 sa46[2]; - uint8_t flags; - } ap; - struct { - lws_wifi_credentials_t creds; - lws_sockaddr46 sa46[2]; - uint8_t flags; - } sta; + lws_dll2_owner_t scan; /* sorted scan results */ + lws_sorted_usec_list_t sul_scan; + + lws_wifi_creds_t *ap_cred; + const char *ap_ip; + + const char *sta_ads; + + char current_attempt_ssid[33]; + uint8_t current_attempt_bssid[LWS_ETH_ALEN]; uint8_t flags; + uint8_t state; /* lws_netdev_wifi_state_t */ } lws_netdev_instance_wifi_t; /* @@ -107,10 +205,15 @@ typedef struct lws_netdev_instance_wifi { typedef struct lws_wifi_sta { lws_dll2_t list; - uint8_t bssid[6]; + uint32_t last_seen; /* unix time */ + uint32_t last_tried; /* unix time */ + + uint8_t bssid[LWS_ETH_ALEN]; + char *ssid; /* points to overallocation */ uint8_t ssid_len; lws_wifi_ch_t ch; - int8_t rssi[4]; + lws_wifi_rssi_t rssi[8]; + int16_t rssi_avg; uint8_t authmode; uint8_t rssi_count; @@ -119,11 +222,14 @@ typedef struct lws_wifi_sta { /* ssid overallocated afterwards */ } lws_wifi_sta_t; -typedef struct lws_wifi_credentials_setting { - lws_dll2_t list; +LWS_VISIBLE LWS_EXTERN lws_netdevs_t * +lws_netdevs_from_ctx(struct lws_context *ctx); - lws_wifi_credentials_t creds; -} lws_wifi_credentials_setting_t; +LWS_VISIBLE LWS_EXTERN int +lws_netdev_credentials_settings_set(lws_netdevs_t *nds); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_credentials_settings_get(lws_netdevs_t *nds); LWS_VISIBLE LWS_EXTERN struct lws_netdev_instance * lws_netdev_wifi_create_plat(struct lws_context *ctx, @@ -133,17 +239,32 @@ LWS_VISIBLE LWS_EXTERN int lws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd, lws_netdev_config_t *config); LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_event_plat(struct lws_netdev_instance *nd, lws_usec_t timestamp, + void *buf, size_t len); +LWS_VISIBLE LWS_EXTERN int lws_netdev_wifi_up_plat(struct lws_netdev_instance *nd); LWS_VISIBLE LWS_EXTERN int lws_netdev_wifi_down_plat(struct lws_netdev_instance *nd); LWS_VISIBLE LWS_EXTERN void lws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd); +LWS_VISIBLE LWS_EXTERN void +lws_netdev_wifi_scan_plat(lws_netdev_instance_t *nd); + +LWS_VISIBLE LWS_EXTERN int +lws_netdev_wifi_connect_plat(lws_netdev_instance_t *wnd, const char *ssid, + const char *passphrase, uint8_t *bssid); + +LWS_VISIBLE LWS_EXTERN lws_netdev_instance_t * +lws_netdev_find(lws_netdevs_t *netdevs, const char *ifname); #define lws_netdev_wifi_plat_ops \ .create = lws_netdev_wifi_create_plat, \ .configure = lws_netdev_wifi_configure_plat, \ + .event = lws_netdev_wifi_event_plat, \ .up = lws_netdev_wifi_up_plat, \ .down = lws_netdev_wifi_down_plat, \ + .connect = lws_netdev_wifi_connect_plat, \ + .scan = lws_netdev_wifi_scan_plat, \ .destroy = lws_netdev_wifi_destroy_plat /* diff --git a/include/libwebsockets/lws-settings.h b/include/libwebsockets/lws-settings.h index 9bfffd40..56b47119 100644 --- a/include/libwebsockets/lws-settings.h +++ b/include/libwebsockets/lws-settings.h @@ -54,19 +54,59 @@ typedef struct lws_settings_ops { const uint8_t *src, size_t len); } lws_settings_ops_t; +/** + * lws_settings_plat_get() - read a named blob from a settings instance + * + * \param si: the settings instance + * \param name: the name of the setting blob in the instance + * \param dest: NULL, or the buffer to copy the setting blob info + * \param max_actual: point to size of dest, or zero; actual blob size on exit + * + * If the named blob doesn't exist in the si, or can't read, returns nonzero. + * Otherwise, returns 0 and sets *max_actual to the true blob size. If dest is + * non-NULL, as much of the blob as will fit in the amount specified by + * *max_actual on entry is copied to dest. + */ LWS_VISIBLE LWS_EXTERN int lws_settings_plat_get(lws_settings_instance_t *si, const char *name, uint8_t *dest, size_t *max_actual); + +/** + * lws_settings_plat_get() - read a named blob from a settings instance + * + * \param si: the settings instance + * \param name: the name of the setting blob in the instance + * \param src: blob to copy to settings instance + * \param len: length of blob to copy + * + * Creates or replaces a settings blob of the given name made up of the \p len + * bytes of data from \p src. + */ LWS_VISIBLE LWS_EXTERN int lws_settings_plat_set(lws_settings_instance_t *si, const char *name, const uint8_t *src, size_t len); +/** + * lws_settings_plat_printf() - read a named blob from a settings instance + * + * \param si: the settings instance + * \param name: the name of the setting blob in the instance + * \param format: printf-style format string + * + * Creates or replaces a settings blob of the given name from the printf-style + * format string and arguments provided. There's no specific limit to the size, + * the size is computed and then a temp heap buffer used. + */ +LWS_VISIBLE LWS_EXTERN int +lws_settings_plat_printf(lws_settings_instance_t *si, const char *name, + const char *format, ...) LWS_FORMAT(3); + #define lws_settings_ops_plat \ .get = lws_settings_plat_get, \ .set = lws_settings_plat_set, LWS_VISIBLE LWS_EXTERN lws_settings_instance_t * -lws_settings_init(lws_settings_ops_t *so, void *opaque_plat); +lws_settings_init(const lws_settings_ops_t *so, void *opaque_plat); LWS_VISIBLE LWS_EXTERN void lws_settings_deinit(lws_settings_instance_t **si); diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index c28a2964..7466dc93 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -1450,6 +1450,53 @@ lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len); lws_usec_t lws_sul_nonmonotonic_adjust(struct lws_context *ctx, int64_t step_us); +void +lws_netdev_instance_remove_destroy(struct lws_netdev_instance *ni); + +int +lws_netdev_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len); + +void +lws_netdev_instance_create(lws_netdev_instance_t *ni, struct lws_context *ctx, + const lws_netdev_ops_t *ops, const char *name, + void *platinfo); + +int +lws_netdev_wifi_rssi_sort_compare(const lws_dll2_t *d, const lws_dll2_t *i); +void +lws_netdev_wifi_scan_empty(lws_netdev_instance_wifi_t *wnd); + +lws_wifi_sta_t * +lws_netdev_wifi_scan_find(lws_netdev_instance_wifi_t *wnd, const char *ssid, + const uint8_t *bssid); + +int +lws_netdev_wifi_scan_select(lws_netdev_instance_wifi_t *wnd); + +lws_wifi_creds_t * +lws_netdev_credentials_find(lws_netdevs_t *netdevs, const char *ssid, + const uint8_t *bssid); + +int +lws_netdev_wifi_redo_last(lws_netdev_instance_wifi_t *wnd); + +void +lws_ntpc_trigger(struct lws_context *ctx); + +void +lws_netdev_wifi_scan(lws_sorted_usec_list_t *sul); + +#define lws_netdevs_from_ndi(ni) \ + lws_container_of((ni)->list.owner, lws_netdevs_t, owner) + +#define lws_context_from_netdevs(nd) \ + lws_container_of(nd, struct lws_context, netdevs) + +/* get the owner of the ni, then compute the context the owner is embedded in */ +#define netdev_instance_to_ctx(ni) \ + lws_container_of(lws_netdevs_from_ndi(ni), \ + struct lws_context, netdevs) enum { LW5CHS_RET_RET0, diff --git a/lib/core-net/service.c b/lib/core-net/service.c index 67ba84f7..b13a14dd 100644 --- a/lib/core-net/service.c +++ b/lib/core-net/service.c @@ -395,7 +395,7 @@ lws_buflist_aware_read(struct lws_context_per_thread *pt, struct lws *wsi, ebuf->token = ep; ebuf->len = n = lws_ssl_capable_read(wsi, ep, e); - lwsl_info("%s: wsi %p: %s: ssl_capable_read %d\n", __func__, + lwsl_debug("%s: wsi %p: %s: ssl_capable_read %d\n", __func__, wsi, hint, ebuf->len); if (!bns && /* only acknowledge error when we handled buflist content */ diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index a94855aa..993a50c6 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -895,7 +895,7 @@ lws_cancel_service(struct lws_context *context) if (context->being_destroyed1) return; - lwsl_info("%s\n", __func__); + lwsl_debug("%s\n", __func__); while (m--) { if (pt->pipe_wsi) diff --git a/lib/core/alloc.c b/lib/core/alloc.c index 71940686..b9ca8f0e 100644 --- a/lib/core/alloc.c +++ b/lib/core/alloc.c @@ -111,7 +111,7 @@ _realloc(void *ptr, size_t size, const char *reason) if (size) { #if defined(LWS_PLAT_FREERTOS) - lwsl_notice("%s: size %lu: %s (free heap %d)\n", __func__, + lwsl_debug("%s: size %lu: %s (free heap %d)\n", __func__, #if defined(LWS_AMAZON_RTOS) (unsigned long)size, reason, (unsigned int)xPortGetFreeHeapSize() - (int)size); #else diff --git a/lib/core/context.c b/lib/core/context.c index b3d3d51b..1f2a73e3 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -135,6 +135,15 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, } #endif +#if defined(LWS_WITH_SYS_NTPCLIENT) + if (target == LWS_SYSTATE_TIME_VALID && + lws_now_secs() < 1594017754) /* 06:42 Mon Jul 6 2020 UTC */ { + lws_ntpc_trigger(context); + + return 1; + } +#endif + #if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM) /* * Skip this if we are running something without the policy for it @@ -160,19 +169,22 @@ lws_state_notify_protocol_init(struct lws_state_manager *mgr, #endif #if defined(LWS_WITH_SECURE_STREAMS) +#if defined(LWS_WITH_DRIVERS) /* * See if we should do the SS Captive Portal Detection */ if (target == LWS_SYSTATE_CPD_PRE_TIME) { - if (lws_system_cpd_state_get(context)) + if (lws_system_cpd_state_get(context) == LWS_CPD_INTERNET_OK) return 0; /* allow it */ - lwsl_info("%s: LWS_SYSTATE_CPD_PRE_TIME\n", __func__); - if (!lws_system_cpd_start(context)) - return 1; + /* + * Don't allow it to move past here until we get an IP and + * CPD passes, driven by SMD + */ - /* it failed, eg, no streamtype for it in the policy */ + return 1; } +#endif #if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) /* @@ -226,11 +238,40 @@ lws_system_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, if (_class != LWSSMDCL_NETWORK) return 0; - if (!lws_json_simple_strcmp(buf, len, "\"trigger\":", "cpdcheck")) { - lwsl_notice("%s: SMD -> Captive Portal Detect request\n", - __func__); + /* something external requested CPD check */ + + if (!lws_json_simple_strcmp(buf, len, "\"trigger\":", "cpdcheck")) lws_system_cpd_start(cx); - } + else + /* + * IP acquisition on any interface triggers captive portal + * check on default route + */ + if (!lws_json_simple_strcmp(buf, len, "\"type\":", "ipacq")) + lws_system_cpd_start(cx); + +#if defined(LWS_WITH_SYS_NTPCLIENT) + /* + * Captive portal detect showing internet workable triggers NTP Client + */ + if (!lws_json_simple_strcmp(buf, len, "\"type\":", "cps") && + !lws_json_simple_strcmp(buf, len, "\"result\":", "OK") && + lws_now_secs() < 1594017754) /* 06:42 Mon Jul 6 2020 UTC */ + lws_ntpc_trigger(cx); +#endif + +#if defined(LWS_WITH_SYS_DHCP_CLIENT) + /* + * Any network interface linkup triggers DHCP + */ + if (!lws_json_simple_strcmp(buf, len, "\"type\":", "linkup")) + lws_ntpc_trigger(cx); + +#endif + +#if defined(LWS_WITH_DRIVERS) && defined(LWS_WITH_NETWORK) + lws_netdev_smd_cb(opaque, _class, timestamp, buf, len); +#endif return 0; } diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 3c1b0dd3..13d2499c 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -362,6 +362,11 @@ struct lws_context { #endif #if defined(LWS_WITH_NETWORK) + +/* + * LWS_WITH_NETWORK =====> + */ + #if defined(LWS_WITH_LIBEV) struct lws_context_eventlibs_libev ev; #endif @@ -374,13 +379,19 @@ struct lws_context { #if defined(LWS_WITH_GLIB) struct lws_context_eventlibs_glib glib; #endif - #if defined(LWS_WITH_TLS) struct lws_context_tls tls; #endif +#if defined(LWS_WITH_DRIVERS) + lws_netdevs_t netdevs; +#endif #if defined(LWS_WITH_SYS_ASYNC_DNS) - lws_async_dns_t async_dns; + lws_async_dns_t async_dns; +#endif + +#if defined(LWS_WITH_SYS_NTPCLIENT) + void *ntpclient_priv; #endif struct lws_ss_handle *hss_fetch_policy; @@ -430,6 +441,11 @@ struct lws_context { struct lws **lws_lookup; #endif + +/* + * <====== LWS_WITH_NETWORK end + */ + #endif /* NETWORK */ #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) diff --git a/lib/drivers/CMakeLists.txt b/lib/drivers/CMakeLists.txt index 7404aae1..1e1354b5 100644 --- a/lib/drivers/CMakeLists.txt +++ b/lib/drivers/CMakeLists.txt @@ -13,6 +13,12 @@ list(APPEND SOURCES drivers/settings/settings.c ) +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + drivers/netdev/netdev.c + drivers/netdev/wifi.c) +endif() + if (LWS_ESP_PLATFORM) list(APPEND SOURCES plat/freertos/esp32/drivers/gpio-esp32.c diff --git a/lib/drivers/netdev/netdev.c b/lib/drivers/netdev/netdev.c new file mode 100644 index 00000000..f550df19 --- /dev/null +++ b/lib/drivers/netdev/netdev.c @@ -0,0 +1,272 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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 + +static const lws_struct_map_t lsm_wifi_creds[] = { + LSM_CARRAY (lws_wifi_creds_t, ssid, "ssid"), + LSM_CARRAY (lws_wifi_creds_t, passphrase, "passphrase"), + LSM_UNSIGNED (lws_wifi_creds_t, alg, "alg"), + LSM_STRING_PTR (lws_wifi_creds_t, bssid, "bssid"), +}; + +static const lws_struct_map_t lsm_netdev_credentials[] = { + LSM_LIST (lws_netdevs_t, owner_creds, lws_wifi_creds_t, list, + NULL, lsm_wifi_creds, "credentials"), +}; + +static const lws_struct_map_t lsm_netdev_schema[] = { + LSM_SCHEMA (lws_netdevs_t, NULL, lsm_netdev_credentials, + "lws-netdev-creds"), +}; + + +//LSM_CHILD_PTR (lws_netdev_instance_wifi_t, ap_cred, lws_wifi_creds_t, +// NULL, lsm_wifi_creds, "ap_cred"), +//LSM_STRING_PTR (lws_netdev_instance_wifi_t, ap_ip, "ap_ip"), + +int +lws_netdev_credentials_settings_set(lws_netdevs_t *nds) +{ + lws_struct_serialize_t *js; + size_t w = 0, max = 2048; + int n, r = 1; + uint8_t *buf; + + buf = lws_malloc(max, __func__); /* length should be computed */ + + js = lws_struct_json_serialize_create(lsm_netdev_schema, + LWS_ARRAY_SIZE(lsm_netdev_schema), 0, nds); + if (!js) + goto bail; + + n = lws_struct_json_serialize(js, buf, max, &w); + lws_struct_json_serialize_destroy(&js); + if (n != LSJS_RESULT_FINISH) + goto bail; + + lwsl_notice("%s: setting %s\n", __func__, buf); + + if (!lws_settings_plat_set(nds->si, "netdev.creds", buf, w)) + r = 0; + +bail: + if (r) + lwsl_err("%s: failed\n", __func__); + lws_free(buf); + + return r; +} + +int +lws_netdev_credentials_settings_get(lws_netdevs_t *nds) +{ + struct lejp_ctx ctx; + lws_struct_args_t a; + size_t l = 0; + uint8_t *buf; + int m; + + memset(&a, 0, sizeof(a)); + + if (lws_settings_plat_get(nds->si, "netdev.creds", NULL, &l)) { + lwsl_notice("%s: not in settings\n", __func__); + return 1; + } + + buf = lws_malloc(l, __func__); + if (!buf) + return 1; + + if (lws_settings_plat_get(nds->si, "netdev.creds", buf, &l)) { + lwsl_err("%s: unexpected settings get fail\n", __func__); + goto bail; + } + + a.map_st[0] = lsm_netdev_schema; + a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_netdev_schema); + a.ac_block_size = 512; + + lws_struct_json_init_parse(&ctx, NULL, &a); + m = lejp_parse(&ctx, (uint8_t *)buf, l); + lws_free(buf); + if (m < 0 || !a.dest) { + lwsl_notice("%s: JSON decode failed '%s'\n", + __func__, lejp_error_to_string(m)); + goto bail1; + } + + /* + * Forcibly set the state of the nds creds owner to the synthesized + * one in the ac, and keep the ac for as long as we keep the creds out + */ + nds->owner_creds = ((lws_netdevs_t *)a.dest)->owner_creds; + nds->ac_creds = a.ac; + + return 0; + +bail: + lws_free(buf); +bail1: + lwsac_free(&a.ac); + + return 1; +} + +lws_wifi_creds_t * +lws_netdev_credentials_find(lws_netdevs_t *netdevs, const char *ssid, + const uint8_t *bssid) +{ + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &netdevs->owner_creds)) { + lws_wifi_creds_t *w = lws_container_of(p, lws_wifi_creds_t, list); + + if (!strcmp(ssid, (const char *)&w[1]) && + !memcmp(bssid, w->bssid, 6)) + return w; + + } lws_end_foreach_dll(p); + + return NULL; +} + +lws_netdev_instance_t * +lws_netdev_find(lws_netdevs_t *netdevs, const char *ifname) +{ + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &netdevs->owner)) { + lws_netdev_instance_t *ni = lws_container_of(p, + lws_netdev_instance_t, list); + + if (!strcmp(ifname, ni->name)) + return ni; + + } lws_end_foreach_dll(p); + + return NULL; +} + +/* + * Context forwards NETWORK related smd here, in lws thread context + */ + +int +lws_netdev_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, + void *buf, size_t len) +{ + struct lws_context *ctx = (struct lws_context *)opaque; + const char *iface; + char setname[16]; + size_t al = 0; + + /* deal with anything from whole-network perspective */ + + /* pass through netdev-specific messages to correct platform handler */ + + iface = lws_json_simple_find(buf, len, "\"if\":", &al); + if (!iface) + return 0; + + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &ctx->netdevs.owner)) { + lws_netdev_instance_t *ni = lws_container_of( + p, lws_netdev_instance_t, list); + + if (!strncmp(ni->name, iface, al)) { + + /* + * IP assignment on our netif? We can deal with marking + * the last successful association generically... + */ + + if (ni->type == LWSNDTYP_WIFI && + !lws_json_simple_strcmp(buf, len, "\"type\":", + "ipacq")) { + const char *ev = lws_json_simple_find(buf, len, + "\"ipv4\":", &al); + lws_netdev_instance_wifi_t *wnd = + (lws_netdev_instance_wifi_t *)ni; + + if (!ev) + return 0; + + lws_snprintf(setname, sizeof(setname), + "netdev.last.%s", iface); + + lws_settings_plat_printf(ctx->netdevs.si, + setname, "{\"ssid\":\"%s\",\"bssid\":" + "\"%02X%02X%02X%02X%02X%02X\"}", + wnd->current_attempt_ssid, + wnd->current_attempt_bssid[0], + wnd->current_attempt_bssid[1], + wnd->current_attempt_bssid[2], + wnd->current_attempt_bssid[3], + wnd->current_attempt_bssid[4], + wnd->current_attempt_bssid[5]); + } + + /* + * Pass it through to related netdev instance for + * private actions + */ + + return ni->ops->event(ni, timestamp, buf, len); + } + + } lws_end_foreach_dll(p); + + return 0; +} + +/* + * This is the generic part of the netdev instance initialization that's always + * the same, regardless of the netdev type + */ + +void +lws_netdev_instance_create(lws_netdev_instance_t *ni, struct lws_context *ctx, + const lws_netdev_ops_t *ops, const char *name, + void *platinfo) +{ + ni->ops = ops; + ni->name = name; + ni->platinfo = platinfo; + + /* add us to the list of active netdevs */ + + lws_dll2_add_tail(&ni->list, &ctx->netdevs.owner); +} + +void +lws_netdev_instance_remove_destroy(struct lws_netdev_instance *ni) +{ + lws_dll2_remove(&ni->list); + lws_free(ni); +} + +lws_netdevs_t * +lws_netdevs_from_ctx(struct lws_context *ctx) +{ + return &ctx->netdevs; +} diff --git a/lib/drivers/netdev/wifi.c b/lib/drivers/netdev/wifi.c new file mode 100644 index 00000000..5df834b1 --- /dev/null +++ b/lib/drivers/netdev/wifi.c @@ -0,0 +1,242 @@ +/* + * libwebsockets - lws_netdev_wifi generic state handling + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + * + * The generic wifi netdevs follow a + */ + +#include "private-lib-core.h" + +int +lws_netdev_wifi_rssi_sort_compare(const lws_dll2_t *d, const lws_dll2_t *i) +{ + return (int)((lws_wifi_sta_t *)d)->rssi_avg > + (int)((lws_wifi_sta_t *)i)->rssi_avg; +} + +void +lws_netdev_wifi_scan_empty(lws_netdev_instance_wifi_t *wnd) +{ + lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, lws_dll2_get_head( + &wnd->scan)) { + lws_wifi_sta_t *s = lws_container_of(p, lws_wifi_sta_t, list); + + lws_dll2_remove(p); + lws_free(s); + + } lws_end_foreach_dll_safe(p, p1); +} + +void +lws_netdev_wifi_scan(lws_sorted_usec_list_t *sul) +{ + lws_netdev_instance_wifi_t *wnd = lws_container_of(sul, + lws_netdev_instance_wifi_t, sul_scan); + + wnd->inst.ops->scan(&wnd->inst); +} + +lws_wifi_sta_t * +lws_netdev_wifi_scan_find(lws_netdev_instance_wifi_t *wnd, const char *ssid, + const uint8_t *bssid) +{ + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &wnd->scan)) { + lws_wifi_sta_t *w = lws_container_of(p, lws_wifi_sta_t, list); + + if (!strcmp(ssid, (const char *)&w[1]) && + !memcmp(bssid, w->bssid, 6)) + return w; + + } lws_end_foreach_dll(p); + + return NULL; +} + +int +lws_netdev_wifi_scan_select(lws_netdev_instance_wifi_t *wnd) +{ + lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst); + struct lws_context *cx = lws_context_from_netdevs(netdevs); + uint32_t least_recent = 0xffffffff; + lws_wifi_creds_t *pc = NULL; + lws_wifi_sta_t *pw = NULL; + + /* + * Trim enough of the lowest RSSI guys in order to get us below the + * limit we are allowed to keep track of... + */ + + while (wnd->scan.count > LWS_WIFI_MAX_SCAN_TRACK) { + struct lws_dll2 *p = lws_dll2_get_tail(&wnd->scan); + lws_wifi_sta_t *w = lws_container_of(p, lws_wifi_sta_t, list); + + lws_dll2_remove(p); + lws_free(w); + } + + /* + * ... let's dump what's left + */ + + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head( + &wnd->scan)) { + lws_wifi_sta_t *w = lws_container_of(p, lws_wifi_sta_t, list); + + lwsl_notice("%s: %s, %02X:%02X:%02X:%02X:%02X:%02X, ch %d, rssi %d\n", + __func__, (const char *)&w[1], w->bssid[0], + w->bssid[1], w->bssid[2], w->bssid[3], w->bssid[4], + w->bssid[5], w->ch, w->rssi_avg); + + } lws_end_foreach_dll(p); + + /* + * make sure we have our device's connection credentials at hand + */ + + if (!netdevs->ac_creds && + lws_netdev_credentials_settings_get(netdevs)) + return 0; + netdevs->refcount_creds++; + + /* + * Let's go through each starting from the best RSSI seeing if we + * have credentials... if we do, pick the one we least-recently tried + */ + + lws_start_foreach_dll(struct lws_dll2 *, p1, wnd->scan.head) { + lws_wifi_sta_t *w = lws_container_of(p1, lws_wifi_sta_t, list); + + lws_start_foreach_dll(struct lws_dll2 *, q, + netdevs->owner_creds.head) { + lws_wifi_creds_t *c = lws_container_of(q, + lws_wifi_creds_t, + list); + + if (!strcmp((const char *)&w[1], c->ssid) && + w->last_seen < least_recent) { + /* + * Not <= so we stick with higher RSSI when + * all 0 + */ + pc = c; + pw = w; + least_recent = w->last_seen; + } + + } lws_end_foreach_dll(q); + + } lws_end_foreach_dll(p1); + + + if (least_recent != 0xffffffff) { + /* + * We picked one to try... note what we're trying so we can + * record it in settings as last successful + */ + lws_strncpy(wnd->current_attempt_ssid, (const char *)&pw[1], + sizeof(wnd->current_attempt_ssid)); + memcpy(wnd->current_attempt_bssid, pw->bssid, LWS_ETH_ALEN); + wnd->inst.ops->connect(&wnd->inst, pc->ssid, pc->passphrase, + pw->bssid); + } else { + /* + * We couldn't see anyone we recognized on this scan, let's + * rescan in a bit + */ + + lwsl_notice("%s: nothing usable in scan, redoing in 3s\n", __func__); + lws_sul_schedule(cx, 0, &wnd->sul_scan, lws_netdev_wifi_scan, + 3 * LWS_US_PER_SEC); + } + + if (!--netdevs->refcount_creds) { + lws_dll2_owner_clear(&netdevs->owner_creds); + lwsac_free(&netdevs->ac_creds); + } + + return 0; +} + +/* + * Initially our best bet is just try to reconnect to whatever we last + * succeeded to connect to + */ + +int +lws_netdev_wifi_redo_last(lws_netdev_instance_wifi_t *wnd) +{ + lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst); + uint8_t buf[256], bssid[LWS_ETH_ALEN]; + const char *ssid, *pp = "", *pb; + char setname[16], ssid_copy[33]; + size_t l = sizeof(buf), al; + lws_wifi_creds_t *cred; + + /* + * Let's try to retreive the last successful connect info for this + * netdev + */ + + lws_snprintf(setname, sizeof(setname), "netdev.last.%s", wnd->inst.name); + if (lws_settings_plat_get(netdevs->si, setname, buf, &l)) + return 1; + + lwsl_notice("%s: last successful %s\n", __func__, buf); + + ssid = lws_json_simple_find((const char *)buf, l, "\"ssid\":", &al); + if (!ssid || al > 32) + return 1; + + memcpy(ssid_copy, ssid, al); + ssid_copy[al + 1] = '\0'; + + pb = lws_json_simple_find((const char *)buf, l, "\"bssid\":", &al); + if (!pb) + return 1; + lws_hex_to_byte_array(pb, bssid, sizeof(bssid)); + + /* + * make sure we have our device's connection credentials at hand + */ + + if (!netdevs->ac_creds && + lws_netdev_credentials_settings_get(netdevs)) + return 1; + netdevs->refcount_creds++; + + cred = lws_netdev_credentials_find(netdevs, ssid_copy, bssid); + if (cred) + pp = cred->passphrase; + + lws_strncpy(wnd->current_attempt_ssid, ssid_copy, + sizeof(wnd->current_attempt_ssid)); + memcpy(wnd->current_attempt_bssid, bssid, LWS_ETH_ALEN); + wnd->inst.ops->connect(&wnd->inst, ssid_copy, pp, bssid); + + if (!--netdevs->refcount_creds) { + lws_dll2_owner_clear(&netdevs->owner_creds); + lwsac_free(&netdevs->ac_creds); + } + + return 0; +} diff --git a/lib/drivers/settings/settings.c b/lib/drivers/settings/settings.c index 139e765b..cc3e2cb9 100644 --- a/lib/drivers/settings/settings.c +++ b/lib/drivers/settings/settings.c @@ -22,8 +22,10 @@ * IN THE SOFTWARE. */ +#include + lws_settings_instance_t * -lws_settings_init(lws_settings_ops_t *so, void *opaque_plat) +lws_settings_init(const lws_settings_ops_t *so, void *opaque_plat) { lws_settings_instance_t *si = lws_zalloc(sizeof(*si), __func__); @@ -42,3 +44,26 @@ lws_settings_deinit(lws_settings_instance_t **si) lws_free(*si); *si = NULL; } + +int +lws_settings_plat_printf(lws_settings_instance_t *si, const char *name, + const char *format, ...) +{ + va_list ap; + uint8_t *p; + int n; + + va_start(ap, format); + n = vsnprintf(NULL, 0, format, ap); + va_end(ap); + + p = lws_malloc(n + 2, __func__); + va_start(ap, format); + vsnprintf((char *)p, n + 2, format, ap); + va_end(ap); + + n = si->so->set(si, name, p, n); + lws_free(p); + + return n; +} diff --git a/lib/misc/CMakeLists.txt b/lib/misc/CMakeLists.txt index a93961a7..d1ec93bf 100644 --- a/lib/misc/CMakeLists.txt +++ b/lib/misc/CMakeLists.txt @@ -75,8 +75,11 @@ endif() if (LWS_WITH_LWSAC) list(APPEND SOURCES - misc/lwsac/lwsac.c - misc/lwsac/cached-file.c) + misc/lwsac/lwsac.c) + if (NOT LWS_PLAT_FREERTOS) + list(APPEND SOURCES + misc/lwsac/cached-file.c) + endif() endif() if (NOT LWS_WITHOUT_BUILTIN_SHA1) diff --git a/lib/plat/freertos/CMakeLists.txt b/lib/plat/freertos/CMakeLists.txt index dccdde7f..1953ac22 100644 --- a/lib/plat/freertos/CMakeLists.txt +++ b/lib/plat/freertos/CMakeLists.txt @@ -41,8 +41,10 @@ list(APPEND SOURCES misc/romfs.c) if (LWS_ESP_PLATFORM AND LWS_WITH_DRIVERS) - list(APPEND SOURCES plat/freertos/esp32/drivers/settings.c) - list(APPEND SOURCES plat/freertos/esp32/drivers/netdev/wifi.c) + list(APPEND SOURCES plat/freertos/esp32/drivers/settings-esp32.c) + if (LWS_WITH_NETWORK) + list(APPEND SOURCES plat/freertos/esp32/drivers/netdev/wifi-esp32.c) + endif() endif() if (LWS_WITH_ESP32_HELPER) list(APPEND SOURCES plat/freertos/esp32/esp32-helpers.c) diff --git a/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c b/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c new file mode 100644 index 00000000..053dbdab --- /dev/null +++ b/lib/plat/freertos/esp32/drivers/netdev/wifi-esp32.c @@ -0,0 +1,494 @@ +/* + * libwebsockets - esp32 wifi -> lws_netdev_wifi + * + * Copyright (C) 2010 - 2020 Andy Green + * + * 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. + * + * + * These are the esp platform wifi-specific netdev pieces. Nothing else should + * know any esp-specific apis. + * + * Operations happen via the generic lws_detdev instantiation for the platform + * wifi device, which point in here for operations. We also set up native OS + * event hooks per device for wifi and IP stack events, and post them as lws_smd + * NETWORK events on the if in the "platform private" namespace. We then + * service the events in the lws event loop thread context, which may again + * generate lws_smd NETWORK events in the public namespace depending on what + * happened. + * + * Scan requests go through a sul to make sure we don't get "piling on" from + * scheduled, timed scans. Scan results go through the lws_smd "washing" and + * are actually parsed in lws thread context, where they are converted to lws + * netdev scan results and processed by generic code. + */ + +#include "private-lib-core.h" + +#include "esp_system.h" +#include "esp_spi_flash.h" +#include "esp_wifi.h" +#include +#include + +/* + * lws_netdev_instance_t: + * lws_netdev_instance_wifi_t: + * lws_netdev_instance_wifi_esp32_t + */ + +typedef struct lws_netdev_instance_wifi_esp32 { + lws_netdev_instance_wifi_t wnd; + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + wifi_config_t sta_config; +} lws_netdev_instance_wifi_esp32_t; + +/* +static wifi_config_t config = { + .ap = { + .channel = 6, + .authmode = WIFI_AUTH_OPEN, + .max_connection = 1, + } }; + */ + +/* + * Platform-specific connect / associate + */ + +int +lws_netdev_wifi_connect_plat(lws_netdev_instance_t *nd, const char *ssid, + const char *passphrase, uint8_t *bssid) +{ + lws_netdev_instance_wifi_esp32_t *wnde32 = + (lws_netdev_instance_wifi_esp32_t *)nd; + + wnde32->wnd.inst.ops->up(&wnde32->wnd.inst); + + wnde32->wnd.flags |= LNDIW_MODE_STA; + esp_wifi_set_mode(WIFI_MODE_STA); + +#if 0 + /* we will do our own dhcp */ + tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); +#endif + + lws_strncpy((char *)wnde32->sta_config.sta.ssid, ssid, + sizeof(wnde32->sta_config.sta.ssid)); + lws_strncpy((char *)wnde32->sta_config.sta.password, passphrase, + sizeof(wnde32->sta_config.sta.password)); + + esp_wifi_set_config(WIFI_IF_STA, &wnde32->sta_config); + esp_wifi_connect(); + + return 0; +} + +/* + * This is called from the SMD / lws thread context, after we heard there were + * scan results on this netdev + */ + +static void +lws_esp32_scan_update(lws_netdev_instance_wifi_t *wnd) +{ +// lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst); + wifi_ap_record_t ap_records[LWS_WIFI_MAX_SCAN_TRACK], *ar; + uint32_t now = lws_now_secs(); + uint16_t count_ap_records; + int n; + + count_ap_records = LWS_ARRAY_SIZE(ap_records); + if (esp_wifi_scan_get_ap_records(&count_ap_records, ap_records)) { + lwsl_err("%s: failed\n", __func__); + return; + } + + if (!count_ap_records) + return; + + if (wnd->state != LWSNDVWIFI_STATE_SCAN) + return; + + /* + * ... let's collect the OS-specific scan results, and convert then to + * lws_netdev sorted by rssi. If we already have it in the scan list, + * keep it and keep a little ringbuffer of its rssi along with an + * averaging. If it's new, add it into the linked-list sorted by rssi. + */ + + ar = &ap_records[0]; + for (n = 0; n < count_ap_records; n++) { + lws_wifi_sta_t *w; + int m; + + m = strlen((const char *)ar->ssid); + if (!m) + goto next; + + /* + * We know this guy from before? + */ + + w = lws_netdev_wifi_scan_find(wnd, (const char *)ar->ssid, + ar->bssid); + if (!w) { + w = lws_zalloc(sizeof(*w) + m + 1, __func__); + if (!w) + goto next; + + w->ssid = (char *)&w[1]; + memcpy(w->ssid, ar->ssid, m + 1); + w->ssid_len = m; + + memcpy(w->bssid, ar->bssid, 6); + + lws_dll2_add_sorted(&w->list, &wnd->scan, + lws_netdev_wifi_rssi_sort_compare); + } + + if (w->rssi_count == LWS_ARRAY_SIZE(w->rssi)) + w->rssi_avg -= w->rssi[w->rssi_next]; + w->rssi[w->rssi_next] = ar->rssi; + w->rssi_avg += w->rssi[w->rssi_next++]; + w->rssi_next = w->rssi_next & (LWS_ARRAY_SIZE(w->rssi) - 1); + + w->ch = ar->primary; + w->authmode = ar->authmode; + w->last_seen = now; + +next: + ar++; + } + + /* + * We can do the rest of it using the generic scan list and credentials + */ + + lws_netdev_wifi_scan_select(wnd); +} + +static wifi_scan_config_t scan_config = { + .ssid = 0, + .bssid = 0, + .channel = 0, + .show_hidden = true +}; + +void +lws_netdev_wifi_scan_plat(lws_netdev_instance_t *nd) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; + + if (esp_wifi_scan_start(&scan_config, false)) + lwsl_err("%s: %s scan failed\n", __func__, wnd->inst.name); +} + +/* + * Platform-private interface events turn up here after going through SMD and + * passed down by matching network interface name via generic lws_netdev. All + * that messing around gets us from an OS-specific thread with an event to back + * here in lws event loop thread context, with the same event bound to a the + * netdev it belongs to. + */ + +int +lws_netdev_wifi_event_plat(struct lws_netdev_instance *nd, lws_usec_t timestamp, + void *buf, size_t len) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; + struct lws_context *ctx = netdev_instance_to_ctx(&wnd->inst); + size_t al; + + /* + * netdev-private sync messages? + */ + + if (!lws_json_simple_strcmp(buf, len, "\"type\":", "priv")) { + const char *ev = lws_json_simple_find(buf, len, "\"ev\":", &al); + + if (!ev) + return 0; + + lwsl_notice("%s: smd priv ev %.*s\n", __func__, (int)al, ev); + + switch (atoi(ev)) { + case WIFI_EVENT_STA_START: + wnd->state = LWSNDVWIFI_STATE_INITIAL; + if (!lws_netdev_wifi_redo_last(wnd)) + break; + + /* + * if the "try last successful" one fails, start the + * scan by falling through + */ + + case WIFI_EVENT_STA_DISCONNECTED: + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"linkdown\"," + "\"if\":\"%s\"}", wnd->inst.name); + wnd->state = LWSNDVWIFI_STATE_SCAN; + /* + * We do it via the sul so we don't get timed scans + * on top of each other + */ + lws_sul_schedule(ctx, 0, &wnd->sul_scan, + lws_netdev_wifi_scan, 1); + break; + + case WIFI_EVENT_STA_CONNECTED: + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"linkup\"," + "\"if\":\"%s\"}", wnd->inst.name); + break; + + case WIFI_EVENT_SCAN_DONE: + lws_esp32_scan_update(wnd); + break; + default: + return 0; + } + + return 0; + } + + return 0; +} + +/* + * This is coming from a thread context unrelated to lws... the first order is + * to turn these into lws_smd events synchronized on lws thread, since we want + * to change correspsonding lws netdev object states without locking. + */ + +static void +_event_handler_wifi(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg; + struct lws_context *ctx = netdev_instance_to_ctx(&wnd->inst); + + switch (event_id) { + case WIFI_EVENT_STA_START: + case WIFI_EVENT_STA_DISCONNECTED: + case WIFI_EVENT_SCAN_DONE: + case WIFI_EVENT_STA_CONNECTED: + /* + * These are events in the platform's private namespace, + * interpreted only by the lws_smd handler above, ** in the lws + * event thread context **. The point of this is to requeue the + * event in the lws thread context like a bottom-half. + * + * To save on registrations, the context's NETWORK smd + * participant passes messages to lws_netdev, who passes ones + * that have if matching the netdev name to that netdev's + * (*event) handler. + * + * The other handler may emit generic network state SMD events + * for other things to consume. + */ + + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"priv\",\"if\":\"%s\",\"ev\":%d}", + wnd->inst.name, event_id); + break; + default: + return; + } +} + +#if 0 +static int +espip_to_sa46(lws_sockaddr46 *sa46, esp_ip_addr_t *eip) +{ + memset(sa46, 0, sizeof(sa46)); + + switch (eip->type) { + case ESP_IPADDR_TYPE_V4: + sa46->sa4.sin_family = AF_INET; + memcpy(sa46->sa4.sin_addr, &eip->u_addr.ip4.addr, ); + return; + case ESP_IPADDR_TYPE_V6: + } +} +#endif + +/* + * This is coming from a thread context unrelated to lws + */ + +static void +_event_handler_ip(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) +{ + lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg; + lws_netdevs_t *netdevs = lws_netdevs_from_ndi(&wnd->inst); + struct lws_context *ctx = lws_context_from_netdevs(netdevs); + + if (event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t *e = (ip_event_got_ip_t *)event_data; + char ip[16]; +#if 0 + tcpip_adapter_dns_info_t e32ip; + + /* + * Since atm we get this via DHCP, presumably we can get ahold + * of related info set by the router + */ + + if (tcpip_adapter_get_dns_info(TCPIP_ADAPTER_IF_STA, + TCPIP_ADAPTER_DNS_MAIN, + /* also _BACKUP, _FALLBACK */ + &e32ip)) { + lwsl_err("%s: there's no dns server set\n", __func__); + e32ip.ip.u_addr.ipv4 = 0x08080808; + e32ip.ip.type = ESP_IPADDR_TYPE_V4; + } + + netdevs->sa46_dns_resolver. +#endif + + lws_write_numeric_address((void *)&e->ip_info.ip, 4, ip, + sizeof(ip)); + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"ipacq\",\"if\":\"%s\"," + "\"ipv4\":\"%s\"}", wnd->inst.name, ip); + } +} + +/* + * This is the platform (esp-idf) init for any kind of networking to be + * available at all + */ +int +lws_netdev_plat_init(void) +{ + nvs_flash_init(); + esp_netif_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + return 0; +} + +/* + * This is the platform (esp-idf) init for any wifi to be available at all + */ +int +lws_netdev_plat_wifi_init(void) +{ + wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); + int n; + + esp_netif_create_default_wifi_sta(); + + n = esp_wifi_init(&wic); + if (n) { + lwsl_err("%s: wifi init fail: %d\n", __func__, n); + return 1; + } + + return 0; +} + + +struct lws_netdev_instance * +lws_netdev_wifi_create_plat(struct lws_context *ctx, + const lws_netdev_ops_t *ops, + const char *name, void *platinfo) +{ + lws_netdev_instance_wifi_esp32_t *wnde32 = lws_zalloc( + sizeof(*wnde32), __func__); + + if (!wnde32) + return NULL; + + wnde32->wnd.inst.type = LWSNDTYP_WIFI; + lws_netdev_instance_create(&wnde32->wnd.inst, ctx, ops, name, platinfo); + + return &wnde32->wnd.inst; +} + +int +lws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd, + lws_netdev_config_t *config) +{ + return 0; +} + +int +lws_netdev_wifi_up_plat(struct lws_netdev_instance *nd) +{ + lws_netdev_instance_wifi_esp32_t *wnde32 = + (lws_netdev_instance_wifi_esp32_t *)nd; + struct lws_context *ctx = netdev_instance_to_ctx(&wnde32->wnd.inst); + + if (wnde32->wnd.flags & LNDIW_UP) + return 0; + + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, &_event_handler_ip, nd, + &wnde32->instance_got_ip)); + + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, &_event_handler_wifi, nd, + &wnde32->instance_any_id)); + + esp_wifi_start(); + wnde32->wnd.flags |= LNDIW_UP; + + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"up\",\"if\":\"%s\"}", + wnde32->wnd.inst.name); + + return 0; +} + +int +lws_netdev_wifi_down_plat(struct lws_netdev_instance *nd) +{ + lws_netdev_instance_wifi_esp32_t *wnde32 = + (lws_netdev_instance_wifi_esp32_t *)nd; + struct lws_context *ctx = netdev_instance_to_ctx(&wnde32->wnd.inst); + + if (!(wnde32->wnd.flags & LNDIW_UP)) + return 0; + + lws_smd_msg_printf(ctx, LWSSMDCL_NETWORK, + "{\"type\":\"down\",\"if\":\"%s\"}", + wnde32->wnd.inst.name); + + esp_wifi_stop(); + + esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, + &wnde32->instance_got_ip); + esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, + &wnde32->instance_any_id); + + wnde32->wnd.flags &= ~LNDIW_UP; + + return 0; +} + +void +lws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd) +{ + lws_free(*pnd); + *pnd = NULL; +} diff --git a/lib/plat/freertos/esp32/drivers/netdev/wifi.c b/lib/plat/freertos/esp32/drivers/netdev/wifi.c deleted file mode 100644 index 3d283238..00000000 --- a/lib/plat/freertos/esp32/drivers/netdev/wifi.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2020 Andy Green - * - * 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 "private-lib-core.h" - -#include "esp_system.h" -#include "esp_spi_flash.h" -#include "esp_wifi.h" -#include -#include - -/* -static wifi_config_t config = { - .ap = { - .channel = 6, - .authmode = WIFI_AUTH_OPEN, - .max_connection = 1, - } }; - */ -static wifi_config_t sta_config = { - .sta = { - .bssid_set = 0, - } }; - -static void -event_handler_wifi(void *arg, esp_event_base_t event_base, int32_t event_id, - void *event_data) -{ - lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg; - - switch (event_id) { - case WIFI_EVENT_STA_START: - esp_wifi_connect(); - break; - case WIFI_EVENT_STA_DISCONNECTED: - lwsl_err("%s: %s: disconnect -> wifi connect\n", __func__, - wnd->inst.name); - // !!! should only retry for a given amount of times - esp_wifi_connect(); - break; - } -} - -static void -event_handler_ip(void *arg, esp_event_base_t event_base, int32_t event_id, - void *event_data) -{ - lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)arg; - - if (event_id == IP_EVENT_STA_GOT_IP) { - ip_event_got_ip_t *e = (ip_event_got_ip_t *)event_data; - char ip[16]; - lws_write_numeric_address((void *)&e->ip_info.ip, 4, ip, - sizeof(ip)); - lws_smd_msg_printf(wnd->inst.ctx, LWSSMDCL_NETWORK, - "{\"type\":\"ip\",\"if\":\"%s\"," - "\"ipv4\":\"%s\"}", wnd->inst.name, ip); - } -} - - -esp_event_handler_instance_t instance_any_id; -esp_event_handler_instance_t instance_got_ip; - -/* - * This is the platform (esp-idf) init for any kind of networking to be - * available at all - */ -int -lws_netdev_plat_init(void) -{ - nvs_flash_init(); - esp_netif_init(); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - return 0; -} - -/* - * This is the platform (esp-idf) init for any wifi to be available at all - */ -int -lws_netdev_plat_wifi_init(void) -{ - wifi_init_config_t wic = WIFI_INIT_CONFIG_DEFAULT(); - int n; - - esp_netif_create_default_wifi_sta(); - - n = esp_wifi_init(&wic); - if (n) { - lwsl_err("%s: wifi init fail: %d\n", __func__, n); - return 1; - } - - return 0; -} - - -struct lws_netdev_instance * -lws_netdev_wifi_create_plat(struct lws_context *ctx, - const lws_netdev_ops_t *ops, - const char *name, void *platinfo) -{ - lws_netdev_instance_wifi_t *wnd = lws_zalloc(sizeof(*wnd), __func__); - - if (!wnd) - return NULL; - - wnd->inst.ops = ops; - wnd->inst.name = name; - wnd->inst.platinfo = platinfo; - wnd->inst.ctx = ctx; - - return &wnd->inst; -} - -int -lws_netdev_wifi_configure_plat(struct lws_netdev_instance *nd, - lws_netdev_config_t *config) -{ - lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; - - esp_wifi_set_mode(WIFI_MODE_STA); - - lws_strncpy((char *)sta_config.sta.ssid, wnd->sta.creds.ssid, - sizeof(sta_config.sta.ssid)); - lws_strncpy((char *)sta_config.sta.password, wnd->sta.creds.passphrase, - sizeof(sta_config.sta.password)); - - esp_wifi_set_config(WIFI_IF_STA, &sta_config); - - return 0; -} - -int -lws_netdev_wifi_up_plat(struct lws_netdev_instance *nd) -{ - lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; - - if (wnd->flags & LNDIW_UP) - return 0; - - ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, - IP_EVENT_STA_GOT_IP, - &event_handler_ip, - nd, - &instance_got_ip)); - - ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, - ESP_EVENT_ANY_ID, - &event_handler_wifi, - nd, - &instance_any_id)); - - esp_wifi_start(); - wnd->flags |= LNDIW_UP; - - lws_smd_msg_printf(wnd->inst.ctx, LWSSMDCL_NETWORK, - "{\"type\":\"up\",\"if\":\"%s\"}", wnd->inst.name); - - return 0; -} - -int -lws_netdev_wifi_down_plat(struct lws_netdev_instance *nd) -{ - lws_netdev_instance_wifi_t *wnd = (lws_netdev_instance_wifi_t *)nd; - - if (!(wnd->flags & LNDIW_UP)) - return 0; - - lws_smd_msg_printf(wnd->inst.ctx, LWSSMDCL_NETWORK, - "{\"type\":\"down\",\"if\":\"%s\"}", wnd->inst.name); - - esp_wifi_stop(); - - esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, - &instance_got_ip); - esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, - &instance_any_id); - - wnd->flags &= ~LNDIW_UP; - - return 0; -} - -void -lws_netdev_wifi_destroy_plat(struct lws_netdev_instance **pnd) -{ - lws_free(*pnd); - *pnd = NULL; -} diff --git a/lib/plat/freertos/esp32/drivers/settings.c b/lib/plat/freertos/esp32/drivers/settings-esp32.c similarity index 88% rename from lib/plat/freertos/esp32/drivers/settings.c rename to lib/plat/freertos/esp32/drivers/settings-esp32.c index 2eb9dc5b..9e74a139 100644 --- a/lib/plat/freertos/esp32/drivers/settings.c +++ b/lib/plat/freertos/esp32/drivers/settings-esp32.c @@ -24,8 +24,10 @@ #include +#include + int -lws_settings_plat_get(lws_settings_instance_t si, const char *name, +lws_settings_plat_get(lws_settings_instance_t *si, const char *name, uint8_t *dest, size_t *max_actual) { int n; @@ -50,10 +52,10 @@ lws_settings_plat_get(lws_settings_instance_t si, const char *name, } int -lws_settings_plat_set(lws_settings_instance_t si, const char *name, - const uint8_t *src, size_t len) +lws_settings_plat_set(lws_settings_instance_t *si, const char *name, + const uint8_t *src, size_t len) { - n = nvs_flash_init_partition((const char *)si->opaque_plat); + int n = nvs_flash_init_partition((const char *)si->opaque_plat); lwsl_notice("%s: init partition %d\n", __func__, n); if (n == ESP_ERR_NOT_FOUND) @@ -68,4 +70,6 @@ lws_settings_plat_set(lws_settings_instance_t si, const char *name, nvs_commit((nvs_handle_t)si->handle_plat); nvs_close((nvs_handle_t)si->handle_plat); + + return 0; } diff --git a/lib/plat/freertos/freertos-service.c b/lib/plat/freertos/freertos-service.c index 55b62276..b77ba811 100644 --- a/lib/plat/freertos/freertos-service.c +++ b/lib/plat/freertos/freertos-service.c @@ -57,19 +57,19 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) if (m > context->time_last_state_dump) { context->time_last_state_dump = m; -#if defined(LWS_AMAZON_RTOS) - n = xPortGetFreeHeapSize(); -#else +#if defined(LWS_ESP_PLATFORM) n = esp_get_free_heap_size(); +#else + n = xPortGetFreeHeapSize(); #endif if ((unsigned int)n != context->last_free_heap) { if ((unsigned int)n > context->last_free_heap) - lwsl_notice(" heap :%ld (+%ld)\n", + lwsl_debug(" heap :%ld (+%ld)\n", (unsigned long)n, (unsigned long)(n - context->last_free_heap)); else - lwsl_notice(" heap :%ld (-%ld)\n", + lwsl_debug(" heap :%ld (-%ld)\n", (unsigned long)n, (unsigned long)( context->last_free_heap - diff --git a/lib/secure-streams/protocols/ss-h2.c b/lib/secure-streams/protocols/ss-h2.c index 06332485..ac20a7b8 100644 --- a/lib/secure-streams/protocols/ss-h2.c +++ b/lib/secure-streams/protocols/ss-h2.c @@ -68,7 +68,7 @@ secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->txn_ok = 1; //bad = status != 200; lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ - break; + return 0; case LWS_CALLBACK_WSI_TX_CREDIT_GET: /* diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index 57c00426..d9e88a5e 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -141,9 +141,16 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, /* * our ss proxy Unix Domain socket has closed... */ - lwsl_notice("%s: LWS_CALLBACK_RAW_CLOSE: proxy conn down\n", __func__); - h->cwsi = NULL; - //lws_sspc_destroy(&h); + lwsl_notice("%s: LWS_CALLBACK_RAW_CLOSE: proxy conn down\n", + __func__); + if (h) { + h->cwsi = NULL; + /* + * schedule a reconnect in 1s + */ + lws_sul_schedule(h->context, 0, &h->sul_retry, + lws_sspc_sul_retry_cb, LWS_US_PER_SEC); + } break; case LWS_CALLBACK_RAW_RX: diff --git a/lib/system/dhcpclient/dhcpclient.c b/lib/system/dhcpclient/dhcpclient.c index d10520a9..be0251e9 100644 --- a/lib/system/dhcpclient/dhcpclient.c +++ b/lib/system/dhcpclient/dhcpclient.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -234,22 +234,6 @@ lws_dhcpc_retry_write(struct lws_sorted_usec_list *sul) lws_callback_on_writable(r->wsi_raw); } -#if 0 -static int -lws_sys_dhcpc_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *l, - int current, int target) -{ - lws_dhcpc_req_t *r = lws_container_of(l, lws_dhcpc_req_t, notify_link); - - if (target != LWS_SYSTATE_TIME_VALID || v->set_time) - return 0; - - /* it's trying to do it ever since the protocol / vhost was set up */ - - return 1; -} -#endif - static int lws_dhcpc_prep(uint8_t *start, int bufsiz, lws_dhcpc_req_t *r, int op) { @@ -337,8 +321,8 @@ callback_dhcpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_sul_cancel(&r->sul_write); if (r->state != LDHC_BOUND) { r->state = LDHC_INIT; - lws_retry_sul_schedule(r->context, 0, &r->sul_conn, &bo2, - lws_dhcpc_retry_conn, + lws_retry_sul_schedule(r->context, 0, &r->sul_conn, + &bo2, lws_dhcpc_retry_conn, &r->retry_count_conn); } break; @@ -479,7 +463,8 @@ broken: #if defined(_DEBUG) /* dump what we have parsed out */ - for (n = 0; n < (int)LWS_ARRAY_SIZE(dhcp_entry_names); n++) + for (n = 0; n < (int)LWS_ARRAY_SIZE(dhcp_entry_names); + n++) if (n >= IPV4_LEASE_SECS) lwsl_info("%s: %s: %ds\n", __func__, dhcp_entry_names[n], @@ -644,13 +629,6 @@ retry_conn: } return 0; - -#if 0 -cancel_conn_timer: - lws_sul_cancel(&r->sul_conn); - - return 0; -#endif } struct lws_protocols lws_system_protocol_dhcpc = @@ -683,7 +661,8 @@ lws_dhcpc_status(struct lws_context *context, lws_sockaddr46 *sa46) if (sa46) { memset(sa46, 0, sizeof(*sa46)); sa46->sa4.sin_family = AF_INET; - sa46->sa4.sin_addr.s_addr = r->ipv4[IPV4_DNS_SRV_1]; + sa46->sa4.sin_addr.s_addr = + r->ipv4[IPV4_DNS_SRV_1]; } return 1; } diff --git a/lib/system/ntpclient/ntpclient.c b/lib/system/ntpclient/ntpclient.c index 04e2bad6..55065019 100644 --- a/lib/system/ntpclient/ntpclient.c +++ b/lib/system/ntpclient/ntpclient.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2020 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -34,7 +34,6 @@ struct vhd_ntpc { const struct lws_protocols *protocol; lws_sorted_usec_list_t sul_conn; lws_sorted_usec_list_t sul_write; /* track write retries */ - lws_state_notify_link_t notify_link; const char *ntp_server_ads; struct lws *wsi_udp; uint16_t retry_count_conn; @@ -105,20 +104,6 @@ lws_ntpc_retry_write(struct lws_sorted_usec_list *sul) lws_callback_on_writable(v->wsi_udp); } -static int -lws_sys_ntpc_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *l, - int current, int target) -{ - struct vhd_ntpc *v = lws_container_of(l, struct vhd_ntpc, notify_link); - - if (target != LWS_SYSTATE_TIME_VALID || v->set_time) - return 0; - - /* it's trying to do it ever since the protocol / vhost was set up */ - - return 1; -} - static int callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -146,6 +131,8 @@ callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, v->vhost = lws_get_vhost(wsi); v->protocol = lws_get_protocol(wsi); + v->context->ntpclient_priv = v; + if (!lws_system_get_ops(wsi->context) || !lws_system_get_ops(wsi->context)->set_clock) { #if !defined(LWS_ESP_PLATFORM) @@ -158,10 +145,6 @@ callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, /* register our lws_system notifier */ - v->notify_link.notify_cb = lws_sys_ntpc_notify_cb; - v->notify_link.name = "ntpclient"; - lws_state_reg_notifier(&wsi->context->mgr_system, &v->notify_link); - v->ntp_server_ads = "pool.ntp.org"; lws_plat_ntpclient_config(v->context); lws_system_blob_get_single_ptr(lws_system_get_blob( @@ -172,8 +155,6 @@ callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, lwsl_info("%s: using ntp server %s\n", __func__, v->ntp_server_ads); - - lws_ntpc_retry_conn(&v->sul_conn); break; case LWS_CALLBACK_PROTOCOL_DESTROY: /* per vhost */ @@ -181,7 +162,6 @@ callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; if (v->wsi_udp) lws_set_timeout(v->wsi_udp, 1, LWS_TO_KILL_ASYNC); - lws_state_reg_deregister(&v->notify_link); v->wsi_udp = NULL; goto cancel_conn_timer; @@ -237,7 +217,7 @@ do_close: lwsl_notice("%s: Unix time: %llu, step: %lldus\n", __func__, (unsigned long long)ns / 1000000000, - delta_us); + (long long)delta_us); #if defined(LWS_PLAT_FREERTOS) { @@ -315,6 +295,16 @@ cancel_conn_timer: return 0; } +void +lws_ntpc_trigger(struct lws_context *ctx) +{ + struct vhd_ntpc *v = (struct vhd_ntpc *)ctx->ntpclient_priv; + + lwsl_notice("%s\n", __func__); + v->retry_count_conn = 0; + lws_ntpc_retry_conn(&v->sul_conn); +} + struct lws_protocols lws_system_protocol_ntpc = { "lws-ntpclient", callback_ntpc, 0, 128, }; diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/main.c b/minimal-examples/api-tests/api-test-lws_struct-json/main.c index 7f6ee20a..6148d607 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/main.c +++ b/minimal-examples/api-tests/api-test-lws_struct-json/main.c @@ -1,7 +1,7 @@ /* * lws-api-test-lws_struct-json * - * Written in 2010-2019 by Andy Green + * Written in 2010-2020 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -325,6 +325,34 @@ static const char *t2 = "{\"schema\":\"com.warmcat.sai.taskcan\"," "\"uuid\": \"071ab46ab4296e5de674c628fec17c55088254679f7714ad991f8c4873dca\"}\x01\x02\xff\xff\xff\xff"; +typedef struct xlws_wifi_creds { + lws_dll2_t list; + char ssid[33]; + char passphrase[64]; + int alg; + char bssid[6]; +} xlws_wifi_creds_t; + +typedef struct xlws_netdevs { + lws_dll2_owner_t owner_creds; +} xlws_netdevs_t; + +static const lws_struct_map_t lsm_wifi_creds[] = { + LSM_CARRAY (xlws_wifi_creds_t, ssid, "ssid"), + LSM_CARRAY (xlws_wifi_creds_t, passphrase, "passphrase"), + LSM_UNSIGNED (xlws_wifi_creds_t, alg, "alg"), + LSM_STRING_PTR (xlws_wifi_creds_t, bssid, "bssid"), +}; + +static const lws_struct_map_t lsm_netdev_credentials[] = { + LSM_LIST (xlws_netdevs_t, owner_creds, xlws_wifi_creds_t, list, + NULL, lsm_wifi_creds, "credentials"), +}; + +static const lws_struct_map_t lsm_netdev_schema[] = { + LSM_SCHEMA (xlws_netdevs_t, NULL, lsm_netdev_credentials, + "com.warmcat.sai.taskinfo"), +}; static int @@ -536,6 +564,40 @@ done: if (test2()) goto bail; + { + lws_struct_serialize_t *js; + xlws_wifi_creds_t creds; + xlws_netdevs_t netdevs; + unsigned char *buf; + size_t w; + int n; + + memset(&creds, 0, sizeof(creds)); + memset(&netdevs, 0, sizeof(netdevs)); + + lws_strncpy(creds.ssid, "xxx", sizeof(creds.ssid)); + lws_strncpy(creds.passphrase, "yyy", sizeof(creds.passphrase)); + lws_dll2_add_tail(&creds.list, &netdevs.owner_creds); + + buf = malloc(2048); /* length should be computed */ + + js = lws_struct_json_serialize_create(lsm_netdev_schema, + LWS_ARRAY_SIZE(lsm_netdev_schema), 0, &netdevs); + if (!js) + goto bail; + + n = lws_struct_json_serialize(js, buf, 2048, &w); + lws_struct_json_serialize_destroy(&js); + if (n != LSJS_RESULT_FINISH) + goto bail; + if (strcmp("{\"schema\":\"com.warmcat.sai.taskinfo\",\"credentials\":[{\"ssid\":\"xxx\",\"passphrase\":\"yyy\",\"alg\":0}]}", (const char *)buf)) { + puts((const char *)buf); + goto bail; + } + free(buf); + } + + lwsl_user("Completed: PASS\n"); return 0; diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt index eb8c5265..e2516648 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt @@ -11,8 +11,14 @@ if (ESP_PLATFORM) set(LWS_WITH_DRIVERS ON) option(LWS_WITH_SECURE_STREAMS "With secure streams" ON) set(LWS_WITH_SECURE_STREAMS ON) + option(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY "static ssp" OFF) + set(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY OFF) option(LWS_WITH_LWSAC "With lwsac" ON) set(LWS_WITH_LWSAC ON) + option(LWS_WITH_STRUCT_JSON "With lws_struct JSON" ON) + set(LWS_WITH_STRUCT_JSON ON) + option(LWS_WITH_SYS_NTPCLIENT "With ntpclient" ON) + set(LWS_WITH_SYS_NTPCLIENT ON) add_subdirectory(libwebsockets) diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c index e69de29b..a4dab2a0 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c @@ -0,0 +1,207 @@ +/* + * devices for ESP32 Heltec WB32 + * + * Written in 2010-2020 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + */ + +#define LWIP_PROVIDE_ERRNO 1 +#define _ESP_PLATFORM_ERRNO_H_ + +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include + +#include + +struct lws_led_state *lls; +lws_display_state_t lds; +struct lws_button_state *bcs; +lws_netdev_instance_wifi_t *wnd; + +/* + * Hook up bitbang i2c, display driver and display + */ + +static void +esp32_i2c_delay(void) +{ + ets_delay_us(1); +} + +static const lws_bb_i2c_t li2c = { + .bb_ops = lws_bb_i2c_ops, + .scl = GPIO_NUM_15, + .sda = GPIO_NUM_4, + .gpio = &lws_gpio_plat, + .delay = esp32_i2c_delay +}; + +/* + * Button controller + */ + +static const lws_button_map_t bcm[] = { + { + .gpio = GPIO_NUM_0, + .smd_interaction_name = "user" + }, +}; + +static const lws_button_controller_t bc = { + .smd_bc_name = "bc", + .gpio_ops = &lws_gpio_plat, + .button_map = &bcm[0], + .active_state_bitmap = 0, + .count_buttons = LWS_ARRAY_SIZE(bcm), +}; + +/* + * pwm controller + */ + +static const lws_pwm_map_t pwm_map[] = { + { .gpio = GPIO_NUM_25, .index = 0, .active_level = 1 } +}; + +static const lws_pwm_ops_t pwm_ops = { + lws_pwm_plat_ops, + .pwm_map = &pwm_map[0], + .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) +}; + +static const lws_display_ssd1306_t disp = { + .disp = { + lws_display_ssd1306_ops, + .w = 128, + .h = 64 + }, + .i2c = (lws_i2c_ops_t *)&li2c, + .gpio = &lws_gpio_plat, + .reset_gpio = GPIO_NUM_16, + .i2c7_address = SSD1306_I2C7_ADS1 +}; + +/* + * led controller + */ + +static const lws_led_gpio_map_t lgm[] = { + { + .name = "alert", + .gpio = GPIO_NUM_25, + .pwm_ops = &pwm_ops, /* managed by pwm */ + .active_level = 1, + }, +}; + +static const lws_led_gpio_controller_t lgc = { + .led_ops = lws_led_gpio_ops, + .gpio_ops = &lws_gpio_plat, + .led_map = &lgm[0], + .count_leds = LWS_ARRAY_SIZE(lgm) +}; + +/* + * Settings stored in platform nv + */ + +static const lws_settings_ops_t sett = { + lws_settings_ops_plat +}; + +/* + * Wifi + */ + +static const lws_netdev_ops_t wifi_ops = { + lws_netdev_wifi_plat_ops +}; + +int +init_plat_devices(struct lws_context *ctx) +{ + lws_settings_instance_t *si; + lws_netdevs_t *netdevs = lws_netdevs_from_ctx(ctx); + + si = lws_settings_init(&sett, (void *)"nvs"); + if (!si) { + lwsl_err("%s: failed to create settings instance\n", __func__); + return 1; + } + netdevs->si = si; + +#if 0 + /* + * This is a temp hack to bootstrap the settings to contain the test + * AP ssid and passphrase for one time, so the settings can be stored + * while there's no UI atm + */ + { + lws_wifi_creds_t creds; + + memset(&creds, 0, sizeof(creds)); + + lws_strncpy(creds.ssid, "xxx", sizeof(creds.ssid)); + lws_strncpy(creds.passphrase, "yyy", sizeof(creds.passphrase)); + lws_dll2_add_tail(&creds.list, &netdevs->owner_creds); + + if (lws_netdev_credentials_settings_set(netdevs)) { + lwsl_err("%s: failed to write bootstrap creds\n", + __func__); + return 1; + } + } +#endif + + /* create the wifi network device and configure it */ + + wnd = (lws_netdev_instance_wifi_t *) + wifi_ops.create(ctx, &wifi_ops, "wl0", NULL); + if (!wnd) { + lwsl_err("%s: failed to create wifi object\n", __func__); + return 1; + } + + wnd->flags |= LNDIW_MODE_STA; + + if (wifi_ops.configure(&wnd->inst, NULL)) { + lwsl_err("%s: failed to configure wifi object\n", __func__); + return 1; + } + + wifi_ops.up(&wnd->inst); + + lls = lgc.led_ops.create(&lgc.led_ops); + if (!lls) { + lwsl_err("%s: could not create led\n", __func__); + return 1; + } + + /* pwm init must go after the led controller init */ + + pwm_ops.init(&pwm_ops); + + bcs = lws_button_controller_create(ctx, &bc); + if (!bcs) { + lwsl_err("%s: could not create buttons\n", __func__); + return 1; + } + + /* + * Show the lws logo on the display + */ + + lws_display_state_init(&lds, ctx, 10000, 20000, lls, &disp.disp); + + lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); + lws_led_transition(lls, "alert", &lws_pwmseq_static_off, + &lws_pwmseq_static_on); + + return 0; +} diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c index 3f63aef3..ecde1a0b 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c @@ -22,104 +22,87 @@ #include struct lws_context *context; -lws_sorted_usec_list_t sul; -struct lws_led_state *lls; -lws_display_state_t lds; -lws_netdev_instance_wifi_t *wnd; -int interrupted; +extern struct lws_led_state *lls; +extern lws_display_state_t lds; +extern lws_netdev_instance_wifi_t *wnd; -/* - * Hook up bitbang i2c, display driver and display - */ - -static void -esp32_i2c_delay(void) -{ - ets_delay_us(1); -} +extern int init_plat_devices(struct lws_context *); -static const lws_bb_i2c_t li2c = { - .bb_ops = lws_bb_i2c_ops, - .scl = GPIO_NUM_15, - .sda = GPIO_NUM_4, - .gpio = &lws_gpio_plat, - .delay = esp32_i2c_delay +static const uint8_t img[] = { +#include "../banded-img.h" }; -/* - * Button controller - */ +#include "policy.h" -static const lws_button_map_t bcm[] = { - { - .gpio = GPIO_NUM_0, - .smd_interaction_name = "user" - }, -}; +static uint8_t flip; -static const lws_button_controller_t bc = { - .smd_bc_name = "bc", - .gpio_ops = &lws_gpio_plat, - .button_map = &bcm[0], - .active_state_bitmap = 0, - .count_buttons = LWS_ARRAY_SIZE(bcm), -}; +typedef struct myss { + struct lws_ss_handle *ss; + void *opaque_data; + /* ... application specific state ... */ -/* - * pwm controller - */ + size_t amount; -static const lws_pwm_map_t pwm_map[] = { - { .gpio = GPIO_NUM_25, .index = 0, .active_level = 1 } -}; +} myss_t; -static const lws_pwm_ops_t pwm_ops = { - lws_pwm_plat_ops, - .pwm_map = &pwm_map[0], - .count_pwm_map = LWS_ARRAY_SIZE(pwm_map) -}; +static int +myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ + myss_t *m = (myss_t *)userobj; -static const lws_display_ssd1306_t disp = { - .disp = { - lws_display_ssd1306_ops, - .w = 128, - .h = 64 - }, - .i2c = (lws_i2c_ops_t *)&li2c, - .gpio = &lws_gpio_plat, - .reset_gpio = GPIO_NUM_16, - .i2c7_address = SSD1306_I2C7_ADS1 -}; + lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); +// lwsl_hexdump_info(buf, len); + m->amount += len; -/* - * led controller - */ + if (flags & LWSSS_FLAG_EOM) { -static const lws_led_gpio_map_t lgm[] = { - { - .name = "alert", - .gpio = GPIO_NUM_25, - .pwm_ops = &pwm_ops, /* managed by pwm */ - .active_level = 1, - }, -}; + /* + * If we received the whole message, for our example it means + * we are done. + */ -static const lws_led_gpio_controller_t lgc = { - .led_ops = lws_led_gpio_ops, - .gpio_ops = &lws_gpio_plat, - .led_map = &lgm[0], - .count_leds = LWS_ARRAY_SIZE(lgm) -}; + lwsl_notice("%s: received %u bytes\n", __func__, + (unsigned int)m->amount); -static const lws_netdev_ops_t wifi_ops = { - lws_netdev_wifi_plat_ops -}; + /* + * In CI, we use sai-expect to look for this + * string for success + */ -static const uint8_t img[] = { -#include "../banded-img.h" -}; + lwsl_notice("Completed: PASS\n"); + } -static uint8_t flip; + return 0; +} + +static int +myss_state(void *userobj, void *sh, lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack) +{ + myss_t *m = (myss_t *)userobj; + + lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), + (unsigned int)ack); + + switch (state) { + case LWSSSCS_CREATING: + lws_ss_client_connect(m->ss); + break; + default: + break; + } + + return 0; +} + +static const lws_ss_info_t ssi = { + .handle_offset = offsetof(myss_t, ss), + .opaque_user_data_offset = offsetof(myss_t, opaque_data), + .rx = myss_rx, + .state = myss_state, + .user_alloc = sizeof(myss_t), + .streamtype = "test_stream", +}; static const lws_led_sequence_def_t *seqs[] = { &lws_pwmseq_static_on, @@ -133,121 +116,95 @@ smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp, void *buf, size_t len) { - if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user")) { - if (!lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { - lws_led_transition(lls, "alert", seqs[flip & 3], - &lws_pwmseq_linear_wipe); - flip++; - } + if (!lws_json_simple_strcmp(buf, len, "\"src\":", "bc/user") && + !lws_json_simple_strcmp(buf, len, "\"event\":", "click")) { + lws_led_transition(lls, "alert", seqs[flip & 3], + &lws_pwmseq_linear_wipe); + flip++; } lwsl_hexdump_notice(buf, len); - /* - * Any kind of user interaction brings the display back up and resets - * the dimming and blanking timers - */ - lws_display_state_active(&lds); + if ((_class & LWSSMDCL_SYSTEM_STATE) && + !lws_json_simple_strcmp(buf, len, "\"state\":", "OPERATIONAL")) { - return 0; -} + /* create the secure stream */ -static void -sul_cb(lws_sorted_usec_list_t *sul) -{ - //interrupted = 1; - lwsl_notice("Completed: PASS\n"); + lwsl_notice("%s: creating test secure stream\n", __func__); + + if (lws_ss_create(context, 0, &ssi, NULL, NULL, NULL, NULL)) { + lwsl_err("%s: failed to create secure stream\n", + __func__); + return -1; + } + } + + if (_class & LWSSMDCL_INTERACTION) + /* + * Any kind of user interaction brings the display back up and + * resets the dimming / blanking timers + */ + lws_display_state_active(&lds); + + return 0; } void app_main(void) { - struct lws_context_creation_info info; - struct lws_button_state *bcs; - int n = 0; + struct lws_context_creation_info *info; - lws_set_log_level(15, NULL); + lws_set_log_level(1024 | 15, NULL); lws_netdev_plat_init(); lws_netdev_plat_wifi_init(); - memset(&info, 0, sizeof(info)); + info = malloc(sizeof(*info)); + if (!info) + goto spin; + + memset(info, 0, sizeof(*info)); lwsl_notice("LWS test for Heltec WB32 ESP32 board\n"); - info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.port = CONTEXT_PORT_NO_LISTEN; - info.early_smd_cb = smd_cb; - info.early_smd_class_filter = LWSSMDCL_INTERACTION; + info->pss_policies_json = ss_policy; + info->options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | + LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info->port = CONTEXT_PORT_NO_LISTEN; + info->early_smd_cb = smd_cb; + info->early_smd_class_filter = LWSSMDCL_INTERACTION | + LWSSMDCL_SYSTEM_STATE | + LWSSMDCL_NETWORK; - context = lws_create_context(&info); + context = lws_create_context(info); if (!context) { lwsl_err("lws init failed\n"); return; } - /* create the wifi network device and configure it */ - - wnd = (lws_netdev_instance_wifi_t *) - wifi_ops.create(context, &wifi_ops, "wl0", NULL); - if (!wnd) { - lwsl_err("%s: failed to create wifi object\n", __func__); - goto spin; - } - - strcpy(wnd->sta.creds.ssid, "xxx"); - strcpy(wnd->sta.creds.passphrase, "yyy"); - wnd->flags |= LNDIW_MODE_STA; - - if (wifi_ops.configure(&wnd->inst, NULL)) { - lwsl_err("%s: failed to configure wifi object\n", __func__); - goto spin; - } - wifi_ops.up(&wnd->inst); - - lls = lgc.led_ops.create(&lgc.led_ops); - if (!lls) { - lwsl_err("%s: could not create led\n", __func__); - goto spin; - } + /* + * We don't need this after context creation... things it pointed to + * still need to exist though since the context copied the pointers. + */ - /* pwm init must go after the led controller init */ + free(info); - pwm_ops.init(&pwm_ops); + /* devices and init are in devices.c */ - bcs = lws_button_controller_create(context, &bc); - if (!bcs) { - lwsl_err("%s: could not create buttons\n", __func__); + if (init_plat_devices(context)) goto spin; - } - /* - * Show the lws logo on the display - */ + /* put the logo on the OLED display */ - lws_display_state_init(&lds, context, 10000, 20000, lls, &disp.disp); - disp.disp.blit(lds.disp, img, 0, 0, 128, 64); + lds.disp->blit(lds.disp, img, 0, 0, 128, 64); lws_display_state_active(&lds); - lws_button_enable(bcs, 0, lws_button_get_bit(bcs, "user")); - lws_led_transition(lls, "alert", &lws_pwmseq_static_off, - &lws_pwmseq_static_on); + /* the lws event loop */ - /* - * We say the test succeeded if we survive 3s around the event loop - */ - - lws_sul_schedule(context, 0, &sul, sul_cb, 3 * LWS_USEC_PER_SEC); - - while (n >= 0 && !interrupted) { - n = lws_service(context, 0); + do { taskYIELD(); - } - - lws_context_destroy(context); + } while (lws_service(context, 0) >= 0); -// fflush(stdout); -// esp_restart(); spin: vTaskDelay(10); diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/partitions.csv b/minimal-examples/embedded/esp32/esp-heltec-wb32/partitions.csv new file mode 100644 index 00000000..e261b7cb --- /dev/null +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/partitions.csv @@ -0,0 +1,5 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 2M, diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig b/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig index 6ed73d93..56008bfc 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig @@ -84,11 +84,11 @@ CONFIG_ESPTOOLPY_FLASHFREQ_26M=y # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set CONFIG_ESPTOOLPY_FLASHFREQ="26m" # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y -# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y CONFIG_ESPTOOLPY_BEFORE_RESET=y # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set @@ -110,9 +110,9 @@ CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 # # Partition Table # -CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set # CONFIG_PARTITION_TABLE_TWO_OTA is not set -# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" CONFIG_PARTITION_TABLE_OFFSET=0x8000 diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h b/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h index d00bac26..43d3c995 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/sdkconfig.h @@ -36,7 +36,7 @@ #define CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B 1 #define CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL 115200 #define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200 -#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_PARTITION_TABLE_CUSTOM 1 #define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" #define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" #define CONFIG_PARTITION_TABLE_OFFSET 0x8000 diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt index c9dcb1d8..4f8e21b9 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt @@ -13,6 +13,8 @@ if (ESP_PLATFORM) set(LWS_WITH_SECURE_STREAMS ON) option(LWS_WITH_LWSAC "With lwsac" ON) set(LWS_WITH_LWSAC ON) + option(LWS_WITH_STRUCT_JSON "With lws_struct JSON" ON) + set(LWS_WITH_STRUCT_JSON ON) option(LWS_WITH_SYS_NTPCLIENT "With ntpclient" ON) set(LWS_WITH_SYS_NTPCLIENT ON) diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c b/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c index c8d6321b..f27650f8 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c @@ -154,9 +154,13 @@ static const lws_display_ili9341_t disp = { }; /* - * + * Settings stored in platform nv */ +static const lws_settings_ops_t sett = { + lws_settings_ops_plat +}; + /* * Wifi */ @@ -166,25 +170,62 @@ static const lws_netdev_ops_t wifi_ops = { }; int -init_plat_devices(struct lws_context *context) +init_plat_devices(struct lws_context *ctx) { + lws_settings_instance_t *si; + lws_netdevs_t *netdevs = lws_netdevs_from_ctx(ctx); + + si = lws_settings_init(&sett, (void *)"nvs"); + if (!si) { + lwsl_err("%s: failed to create settings instance\n", __func__); + return 1; + } + netdevs->si = si; + +#if 0 + /* + * This is a temp hack to bootstrap the settings to contain the test + * AP ssid and passphrase for one time, so the settings can be stored + * while there's no UI atm + */ + { + lws_wifi_creds_t creds; + + memset(&creds, 0, sizeof(creds)); + + lws_strncpy(creds.ssid, "xxx", sizeof(creds.ssid)); + lws_strncpy(creds.passphrase, "yyy", sizeof(creds.passphrase)); + lws_dll2_add_tail(&creds.list, &netdevs->owner_creds); + + if (lws_netdev_credentials_settings_set(netdevs)) { + lwsl_err("%s: failed to write bootstrap creds\n", + __func__); + return 1; + } + } +#endif + +// if (lws_netdev_instance_wifi_settings_get(si, "netdev.wl0", &niw, &ac)) { +// lwsl_err("%s: unable to fetch wl0 settings\n", __func__); +// return 1; +// } + /* create the wifi network device and configure it */ wnd = (lws_netdev_instance_wifi_t *) - wifi_ops.create(context, &wifi_ops, "wl0", NULL); + wifi_ops.create(ctx, &wifi_ops, "wl0", NULL); if (!wnd) { lwsl_err("%s: failed to create wifi object\n", __func__); return 1; } - strcpy(wnd->sta.creds.ssid, "xxx"); - strcpy(wnd->sta.creds.passphrase, "yyy"); wnd->flags |= LNDIW_MODE_STA; if (wifi_ops.configure(&wnd->inst, NULL)) { lwsl_err("%s: failed to configure wifi object\n", __func__); return 1; } + wifi_ops.up(&wnd->inst); /* bring up the led controller */ @@ -201,7 +242,7 @@ init_plat_devices(struct lws_context *context) /* ... and the button controller */ - bcs = lws_button_controller_create(context, &bc); + bcs = lws_button_controller_create(ctx, &bc); if (!bcs) { lwsl_err("%s: could not create buttons\n", __func__); return 1; @@ -212,7 +253,7 @@ init_plat_devices(struct lws_context *context) /* ... bring up spi bb and the display */ lbspi.bb_ops.init(&lbspi.bb_ops); - lws_display_state_init(&lds, context, 30000, 10000, lls, &disp.disp); + lws_display_state_init(&lds, ctx, 30000, 10000, lls, &disp.disp); /* * Make the RGB LED do something using sequenced PWM... pressing the diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c index 2faa1827..39d201ab 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c @@ -29,7 +29,6 @@ extern struct lws_led_state *lls; extern lws_display_state_t lds; extern struct lws_button_state *bcs; extern lws_netdev_instance_wifi_t *wnd; -int interrupted; extern int init_plat_devices(struct lws_context *); @@ -205,16 +204,14 @@ app_main(void) lds.disp->blit(lds.disp, logo, 0, 0, 320, 240); lws_display_state_active(&lds); + /* the lws event loop */ + do { taskYIELD(); - } while (lws_service(context, 0) >= 0 && !interrupted); + } while (lws_service(context, 0) >= 0); lwsl_notice("%s: exited event loop\n", __func__); - lws_context_destroy(context); - -// fflush(stdout); -// esp_restart(); spin: vTaskDelay(10); -- Gitee From 6b639e6a814fbd3987cfe73fea460e46f10ce852 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 8 Jul 2020 18:27:47 +0100 Subject: [PATCH 0203/1062] coverity: force amount to 0 before read call --- lib/roles/http/server/server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index 0baba256..709f1c39 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -2902,6 +2902,7 @@ int lws_serve_http_file_fragment(struct lws *wsi) poss -= 10 + 128; } + amount = 0; if (lws_vfs_file_read(wsi->http.fop_fd, &amount, p, poss) < 0) goto file_had_it; /* caller will close */ -- Gitee From 650a8781e926f937db2afc70fcf13b4ce86bd17f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 8 Jul 2020 19:20:03 +0100 Subject: [PATCH 0204/1062] ss: client: clear timeout when connection acknowledged --- lib/secure-streams/secure-streams-client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index d9e88a5e..52ce6140 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -167,7 +167,8 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, (lws_ss_handle_t **)m, &h->ssi, 1)) return -1; - if (wsi && h->state == LPCS_LOCAL_CONNECTED) + if (wsi && (h->state == LPCS_LOCAL_CONNECTED || + h->state == LPCS_ONWARD_CONNECT)) lws_set_timeout(wsi, 0, 0); break; -- Gitee From 73424ae66a08715a4ab700e9afaa0f974d0fc232 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 8 Jul 2020 19:47:55 +0100 Subject: [PATCH 0205/1062] ss: proxy: smd: use correct zombie vs message check --- lib/system/smd/smd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/smd/smd.c b/lib/system/smd/smd.c index 2070fa0c..1ba0191d 100644 --- a/lib/system/smd/smd.c +++ b/lib/system/smd/smd.c @@ -94,7 +94,7 @@ _lws_smd_msg_assess_peers_interested(lws_smd_t *smd, lws_smd_msg_t *msg) (!pr->timestamp_left || /* if zombie, only contribute to * refcount if msg from before we * left */ - pr->timestamp_left < msg->timestamp) && + pr->timestamp_left >= msg->timestamp) && (msg->_class & pr->_class_filter)) /* * This peer wants to consume it -- Gitee From 6b3221ffc18a4ab3c7215fb7050464d0be4b76cd Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 9 Jul 2020 13:57:11 +0100 Subject: [PATCH 0206/1062] mbedtls: only free crt_parse when something came back Mbedtls mbedtls_x509_crt_parse() returns 0 for success which is good. But it has a complicated idea about what to return on fail... if it couldn't make even one cert from the data, then it returns a negative return indicating the parsing problem and there is nothing to free. If it managed to parse at least one cert, instead it retuns a positive number indicating the number of certs it didn't parse successfully, and there is something to free. Adapt the code to understand this quirk. --- lib/tls/mbedtls/mbedtls-x509.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tls/mbedtls/mbedtls-x509.c b/lib/tls/mbedtls/mbedtls-x509.c index f137a789..54d47b1e 100644 --- a/lib/tls/mbedtls/mbedtls-x509.c +++ b/lib/tls/mbedtls/mbedtls-x509.c @@ -240,7 +240,8 @@ lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len) ret = mbedtls_x509_crt_parse(&x509->cert, pem, len); if (ret) { - mbedtls_x509_crt_free(&x509->cert); + if (ret > 0) + mbedtls_x509_crt_free(&x509->cert); lwsl_err("%s: unable to parse PEM cert: -0x%x\n", __func__, -ret); -- Gitee From 1ae6ce37d34bbbd009009616729715aaf5a2a4a9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 9 Jul 2020 13:48:41 +0100 Subject: [PATCH 0207/1062] lws_dll2: add helper for typed object name from owner list There's a good pattern that's encouraged by using lws_struct pieces, that we have an lws_dll2 owner with an array of objects listed in it that exist in an lwsac. And because it came from JSON, there is tending to be a logical name for the objects. This adds a typed helper and wrapper to scan the owner list looking for a specific name (of a specified length, not NUL terminated) in a specific member of the listed objects, which must be a NUL-terminated const char *. Again this is a good pattern that's encouraged by use of lws_tokenize to recover the name we're looking for. So it leads to the helper that can cleanly search for a listed object of the right name from an owner, and return the typed object pointer or NULL, from a length-specified string. --- include/libwebsockets/lws-dll2.h | 15 +++++++++ lib/core/lws_dll2.c | 19 +++++++++++ lib/misc/lws-struct-lejp.c | 2 +- .../api-tests/api-test-lws_struct-json/main.c | 32 +++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/include/libwebsockets/lws-dll2.h b/include/libwebsockets/lws-dll2.h index 367c887d..151e7fcd 100644 --- a/include/libwebsockets/lws-dll2.h +++ b/include/libwebsockets/lws-dll2.h @@ -245,6 +245,21 @@ LWS_VISIBLE LWS_EXTERN void lws_dll2_add_sorted(lws_dll2_t *d, lws_dll2_owner_t *own, int (*compare)(const lws_dll2_t *d, const lws_dll2_t *i)); +LWS_VISIBLE LWS_EXTERN void * +_lws_dll2_search_sz_pl(lws_dll2_owner_t *own, const char *name, size_t namelen, + size_t dll2_ofs, size_t ptr_ofs); + +/* + * Searches objects in an owner list linearly and returns one with a given + * member C-string matching a supplied length-provided string if it exists, else + * NULL. + */ + +#define lws_dll2_search_sz_pl(own, name, namelen, type, membd2list, membptr) \ + ((type *)_lws_dll2_search_sz_pl(own, name, namelen, \ + offsetof(type, membd2list), \ + offsetof(type, membptr))) + #if defined(_DEBUG) void lws_dll2_describe(struct lws_dll2_owner *owner, const char *desc); diff --git a/lib/core/lws_dll2.c b/lib/core/lws_dll2.c index 7556695d..adca5659 100644 --- a/lib/core/lws_dll2.c +++ b/lib/core/lws_dll2.c @@ -209,6 +209,25 @@ lws_dll2_add_sorted(lws_dll2_t *d, lws_dll2_owner_t *own, lws_dll2_add_tail(d, own); } +void * +_lws_dll2_search_sz_pl(lws_dll2_owner_t *own, const char *name, size_t namelen, + size_t dll2_ofs, size_t ptr_ofs) +{ + lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(own)) { + uint8_t *ref = ((uint8_t *)p) - dll2_ofs; + /* + * We have to read the const char * at the computed place and + * the string is where that points + */ + const char *str = *((const char **)(ref + ptr_ofs)); + + if (str && !strncmp(str, name, namelen) && !str[namelen]) + return (void *)ref; + } lws_end_foreach_dll(p); + + return NULL; +} + #if defined(_DEBUG) void diff --git a/lib/misc/lws-struct-lejp.c b/lib/misc/lws-struct-lejp.c index c808adad..f083c980 100644 --- a/lib/misc/lws-struct-lejp.c +++ b/lib/misc/lws-struct-lejp.c @@ -256,7 +256,7 @@ lws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason) return 1; } - lwsl_notice("%s: created '%s' object size %d\n", __func__, + lwsl_info("%s: created '%s' object size %d\n", __func__, pmap->colname, (int)pmap->aux); if (pmap->type == LSMT_LIST) { diff --git a/minimal-examples/api-tests/api-test-lws_struct-json/main.c b/minimal-examples/api-tests/api-test-lws_struct-json/main.c index 6148d607..d6d02ae1 100644 --- a/minimal-examples/api-tests/api-test-lws_struct-json/main.c +++ b/minimal-examples/api-tests/api-test-lws_struct-json/main.c @@ -597,6 +597,38 @@ done: free(buf); } + { + struct x { lws_dll2_t list; const char *sz; }; + struct x x1, x2, *xp; + lws_dll2_owner_t o; + + lws_dll2_owner_clear(&o); + memset(&x1, 0, sizeof(x1)); + memset(&x2, 0, sizeof(x2)); + + x1.sz = "nope"; + x2.sz = "yes"; + + lws_dll2_add_tail(&x1.list, &o); + lws_dll2_add_tail(&x2.list, &o); + + xp = lws_dll2_search_sz_pl(&o, "yes", 3, struct x, list, sz); + if (xp != &x2) { + lwsl_err("%s: 1 xp %p\n", __func__, xp); + goto bail; + } + xp = lws_dll2_search_sz_pl(&o, "nope", 4, struct x, list, sz); + if (xp != &x1) { + lwsl_err("%s: 2 xp %p\n", __func__, xp); + goto bail; + } + xp = lws_dll2_search_sz_pl(&o, "wrong", 4, struct x, list, sz); + if (xp) { + lwsl_err("%s: 3 xp %p\n", __func__, xp); + goto bail; + } + } + lwsl_user("Completed: PASS\n"); -- Gitee From 4a5f1d83c2bd6737a44f60ac3a8545d49be97bd9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 10 Jul 2020 19:00:24 +0100 Subject: [PATCH 0208/1062] ss: proxy: make sure state is always available in ssi --- lib/secure-streams/secure-streams-process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/secure-streams/secure-streams-process.c b/lib/secure-streams/secure-streams-process.c index dd25bf42..c7080be1 100644 --- a/lib/secure-streams/secure-streams-process.c +++ b/lib/secure-streams/secure-streams-process.c @@ -344,8 +344,8 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, offsetof(ss_proxy_t, conn); ssi.rx = ss_proxy_onward_rx; ssi.tx = ss_proxy_onward_tx; - ssi.state = ss_proxy_onward_state; } + ssi.state = ss_proxy_onward_state; if (lws_ss_deserialize_parse(&conn->parser, lws_get_context(wsi), conn->dsh, in, len, -- Gitee From cf41c3e7938e5a3f557f5c4655627ad107f864e0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 10 Jul 2020 15:25:16 +0100 Subject: [PATCH 0209/1062] jws: compact representation helper must use dots --- lib/jose/jws/jws.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/jose/jws/jws.c b/lib/jose/jws/jws.c index b582a5b0..3c42259f 100644 --- a/lib/jose/jws/jws.c +++ b/lib/jose/jws/jws.c @@ -934,9 +934,15 @@ lws_jws_write_compact(struct lws_jws *jws, char *compact, size_t len) lws_strnncpy(compact + n, jws->map_b64.buf[LJWS_JOSE], jws->map_b64.len[LJWS_JOSE], len - n); n += strlen(compact + n); + if (n >= len - 1) + return 1; + compact[n++] = '.'; lws_strnncpy(compact + n, jws->map_b64.buf[LJWS_PYLD], jws->map_b64.len[LJWS_PYLD], len - n); n += strlen(compact + n); + if (n >= len - 1) + return 1; + compact[n++] = '.'; lws_strnncpy(compact + n, jws->map_b64.buf[LJWS_SIG], jws->map_b64.len[LJWS_SIG], len - n); n += strlen(compact + n); -- Gitee From 0bcfe883814755864cefc3b83f253181c2ad75ba Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 10 Jul 2020 12:48:10 +0100 Subject: [PATCH 0210/1062] lws_http_cookie_get --- include/libwebsockets/lws-http.h | 20 +++++++++++++++++ lib/core-net/dummy-callback.c | 35 +++++++++++++++++++---------- lib/roles/http/parsers.c | 38 ++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/include/libwebsockets/lws-http.h b/include/libwebsockets/lws-http.h index d5851101..b228497f 100644 --- a/include/libwebsockets/lws-http.h +++ b/include/libwebsockets/lws-http.h @@ -850,6 +850,26 @@ lws_http_compression_apply(struct lws *wsi, const char *name, LWS_VISIBLE LWS_EXTERN int lws_http_is_redirected_to_get(struct lws *wsi); +/** + * lws_http_cookie_get() - return copy of named cookie if present + * + * \param wsi: the wsi to check + * \param name: name of the cookie + * \param buf: buffer to store the cookie contents into + * \param max_len: on entry, maximum length of buf... on exit, used len of buf + * + * If no cookie header, or no cookie of the requested name, or the value is + * larger than can fit in buf, returns nonzero. + * + * If the cookie is found, copies its value into buf with a terminating NUL, + * sets *max_len to the used length, and returns 0. + * + * This handles the parsing of the possibly multi-cookie header string and + * terminating the requested cookie at the next ; if present. + */ +LWS_VISIBLE LWS_EXTERN int +lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, size_t *max); + /** * lws_http_client_http_error() - determine if the response code indicates an error * diff --git a/lib/core-net/dummy-callback.c b/lib/core-net/dummy-callback.c index 713b96bb..c2826712 100644 --- a/lib/core-net/dummy-callback.c +++ b/lib/core-net/dummy-callback.c @@ -24,6 +24,9 @@ #include "private-lib-core.h" +/* max individual proxied header payload size */ +#define MAXHDRVAL 1024 + #if defined(LWS_WITH_HTTP_PROXY) static int proxy_header(struct lws *wsi, struct lws *par, unsigned char *temp, @@ -33,16 +36,23 @@ proxy_header(struct lws *wsi, struct lws *par, unsigned char *temp, if (n < 1) { lwsl_debug("%s: no index %d:\n", __func__, index); + return 0; } - if (lws_hdr_copy(par, (char *)temp, temp_len, index) < 0) + if (lws_hdr_copy(par, (char *)temp, temp_len, index) < 0) { + lwsl_notice("%s: unable to copy par hdr idx %d (len %d)\n", + __func__, index, n); return -1; + } lwsl_debug("%s: index %d: %s\n", __func__, index, (char *)temp); - if (lws_add_http_header_by_token(wsi, index, temp, n, p, end)) + if (lws_add_http_header_by_token(wsi, index, temp, n, p, end)) { + lwsl_notice("%s: unable to append par hdr idx %d (len %d)\n", + __func__, index, n); return -1; + } return 0; } @@ -133,7 +143,7 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: { unsigned char **p = (unsigned char **)in, *end = (*p) + len, - tmp[128]; + tmp[MAXHDRVAL]; proxy_header(wsi, wsi->parent, tmp, sizeof(tmp), WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, p, end); @@ -250,6 +260,7 @@ const struct lws_protocols lws_ws_proxy = { #endif + int lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -482,7 +493,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, return 0; start = p = (unsigned char *)buf + LWS_PRE; - end = p + sizeof(buf) - LWS_PRE - 256; + end = p + sizeof(buf) - LWS_PRE - MAXHDRVAL; if (lws_add_http_header_status(lws_get_parent(wsi), lws_http_client_http_response(wsi), &p, end)) @@ -492,21 +503,21 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, * copy these headers from the client connection to the parent */ - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CONTENT_LENGTH, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CONTENT_TYPE, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_ETAG, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CONTENT_ENCODING, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_CACHE_CONTROL, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_SET_COOKIE, &p, end); - proxy_header(parent, wsi, end, 256, + proxy_header(parent, wsi, end, MAXHDRVAL, WSI_TOKEN_HTTP_LOCATION, &p, end); if (!parent->mux_substream) diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index b74669b1..1382e97e 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -1459,3 +1459,41 @@ forbid: return LPR_FORBIDDEN; } +int +lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, + size_t *max_len) +{ + int n, bl = (int)strlen(name); + size_t max = *max_len; + char *p, *bo = buf; + + n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE); + if (n < bl + 1) + return 1; + + p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COOKIE); + if (!p) + return 1; + + p += bl; + n -= bl; + while (n-- > bl) { + if (*p == '=' && !memcmp(p - bl, name, bl)) { + p++; + while (*p != ';' && n-- && max) { + *buf++ = *p++; + max--; + } + if (!max) + return 2; + + *buf = '\0'; + *max_len = lws_ptr_diff(buf, bo); + + return 0; + } + p++; + } + + return 1; +} -- Gitee From 5b3ea74b77d1b86608acdd83c2f5af0558d25484 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 10 Jul 2020 16:38:14 +0100 Subject: [PATCH 0211/1062] jwt: validate jws helper Introduce a signed JWT validation helper --- include/libwebsockets/lws-jws.h | 29 ++++++++++- lib/jose/jws/jws.c | 85 +++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/include/libwebsockets/lws-jws.h b/include/libwebsockets/lws-jws.h index 1e1fb8b2..6016c081 100644 --- a/include/libwebsockets/lws-jws.h +++ b/include/libwebsockets/lws-jws.h @@ -398,8 +398,35 @@ lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max); * Returns either -1 if problems, or the number of bytes written to \p out. * If the section is not the first one, '.' is prepended. */ - LWS_VISIBLE LWS_EXTERN int lws_jws_encode_section(const char *in, size_t in_len, int first, char **p, char *end); + +/** + * lws_jwt_signed_validate() - check a compact JWT against a key and alg + * + * \param ctx: the lws_context + * \param alg_list: the expected alg name, like "ES512" + * \param jwk: the key for checking the signature + * \param com: the compact JWT + * \param len: the length of com + * \param temp: a temp scratchpad + * \param tl: available length of temp scratchpad + * \param out: the output buffer to hold the validated plaintext + * \param out_len: on entry, max length of out; on exit, used length of out + * + * Returns nonzero if the JWT cannot be validated or the plaintext can't fit the + * provided output buffer, or 0 if it is validated as being signed by the + * provided jwk. + * + * If validated, the plaintext in the JWT is copied into out and out_len set to + * the used length. + * + * temp can be discarded or reused after the call returned, it's used to hold + * transformations of the B64 JWS in the JWT. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_signed_validate(struct lws_context *ctx, const char *alg_list, + struct lws_jwk *jwk, const char *com, size_t len, + char *temp, int tl, char *out, size_t *out_len); ///@} diff --git a/lib/jose/jws/jws.c b/lib/jose/jws/jws.c index 3c42259f..161e1ff6 100644 --- a/lib/jose/jws/jws.c +++ b/lib/jose/jws/jws.c @@ -949,3 +949,88 @@ lws_jws_write_compact(struct lws_jws *jws, char *compact, size_t len) return n >= len - 1; } + +int +lws_jwt_signed_validate(struct lws_context *ctx, const char *alg_list, + struct lws_jwk *jwk, const char *com, size_t len, + char *temp, int tl, char *out, size_t *out_len) +{ + struct lws_tokenize ts; + struct lws_jose jose; + struct lws_jws jws; + size_t n, r = 1; + + memset(&jws, 0, sizeof(jws)); + lws_jose_init(&jose); + + /* + * Decode the b64.b64[.b64] compact serialization + * blocks + */ + + n = lws_jws_compact_decode(com, len, &jws.map, &jws.map_b64, temp, &tl); + if (n != 3) { + lwsl_err("%s: concat_map failed: %d\n", __func__, (int)n); + goto bail; + } + + /* + * Parse the JOSE header + */ + + if (lws_jws_parse_jose(&jose, jws.map.buf[LJWS_JOSE], + jws.map.len[LJWS_JOSE], + lws_concat_temp(temp, tl), &tl) < 0) { + lwsl_err("%s: JOSE parse failed\n", __func__); + goto bail; + } + + /* + * Insist to see an alg in there that we list as acceptable + */ + + lws_tokenize_init(&ts, alg_list, LWS_TOKENIZE_F_COMMA_SEP_LIST | + LWS_TOKENIZE_F_RFC7230_DELIMS); + n = strlen(jose.alg->alg); + + do { + ts.e = lws_tokenize(&ts); + if (ts.e == LWS_TOKZE_TOKEN && ts.token_len == n && + !strncmp(jose.alg->alg, ts.token, ts.token_len)) + break; + } while (ts.e != LWS_TOKZE_ENDED); + + if (ts.e != LWS_TOKZE_TOKEN) { + lwsl_err("%s: JOSE using alg %s (accepted: %s)\n", __func__, + jose.alg->alg, alg_list); + goto bail; + } + + /* we liked the alg... now how about the crypto? */ + + if (lws_jws_sig_confirm(&jws.map_b64, &jws.map, jwk, ctx) < 0) { + lwsl_notice("%s: confirm JWT sig failed\n", + __func__); + goto bail; + } + + /* yeah, it's validated... see about copying it out */ + + if (*out_len < jws.map.len[LJWS_PYLD] + 1) { + /* we don't have enough room */ + r = 2; + goto bail; + } + + memcpy(out, jws.map.buf[LJWS_PYLD], jws.map.len[LJWS_PYLD]); + *out_len = jws.map.len[LJWS_PYLD]; + out[jws.map.len[LJWS_PYLD]] = '\0'; + + r = 0; + +bail: + lws_jws_destroy(&jws); + lws_jose_destroy(&jose); + + return r; +} -- Gitee From 77530f8ccb05012bfae01922434c433189c6ba65 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 10 Jul 2020 18:27:45 +0100 Subject: [PATCH 0212/1062] jwt: sign and create jws helper --- include/libwebsockets/lws-jws.h | 31 ++++- lib/jose/jws/jws.c | 120 +++++++++++++++++- .../api-tests/api-test-jose/jws.c | 37 ++++++ 3 files changed, 181 insertions(+), 7 deletions(-) diff --git a/include/libwebsockets/lws-jws.h b/include/libwebsockets/lws-jws.h index 6016c081..13fd26a3 100644 --- a/include/libwebsockets/lws-jws.h +++ b/include/libwebsockets/lws-jws.h @@ -406,8 +406,8 @@ lws_jws_encode_section(const char *in, size_t in_len, int first, char **p, * lws_jwt_signed_validate() - check a compact JWT against a key and alg * * \param ctx: the lws_context - * \param alg_list: the expected alg name, like "ES512" * \param jwk: the key for checking the signature + * \param alg_list: the expected alg name, like "ES512" * \param com: the compact JWT * \param len: the length of com * \param temp: a temp scratchpad @@ -426,7 +426,32 @@ lws_jws_encode_section(const char *in, size_t in_len, int first, char **p, * transformations of the B64 JWS in the JWT. */ LWS_VISIBLE LWS_EXTERN int -lws_jwt_signed_validate(struct lws_context *ctx, const char *alg_list, - struct lws_jwk *jwk, const char *com, size_t len, +lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk, + const char *alg_list, const char *com, size_t len, char *temp, int tl, char *out, size_t *out_len); + +/** + * lws_jwt_sign_compact() - generate a compact JWT using a key and alg + * + * \param ctx: the lws_context + * \param jwk: the signing key + * \param alg: the signing alg name, like "ES512" + * \param out: the output buffer to hold the signed JWT in compact form + * \param out_len: on entry, the length of out; on exit, the used amount of out + * \param temp: a temp scratchpad + * \param tl: available length of temp scratchpad + * \param format: a printf style format specification + * \param ...: zero or more args for the format specification + * + * Creates a JWT in a single step, from the format string and args through to + * outputting a well-formed compact JWT representation in out. + * + * Returns 0 if all is well and *out_len is the amount of data in out, else + * nonzero if failed. Temp must be large enough to hold various intermediate + * representations. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_sign_compact(struct lws_context *ctx, struct lws_jwk *jwk, + const char *alg, char *out, size_t *out_len, char *temp, + int tl, const char *format, ...) LWS_FORMAT(8); ///@} diff --git a/lib/jose/jws/jws.c b/lib/jose/jws/jws.c index 161e1ff6..27ca873a 100644 --- a/lib/jose/jws/jws.c +++ b/lib/jose/jws/jws.c @@ -951,14 +951,15 @@ lws_jws_write_compact(struct lws_jws *jws, char *compact, size_t len) } int -lws_jwt_signed_validate(struct lws_context *ctx, const char *alg_list, - struct lws_jwk *jwk, const char *com, size_t len, +lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk, + const char *alg_list, const char *com, size_t len, char *temp, int tl, char *out, size_t *out_len) { struct lws_tokenize ts; struct lws_jose jose; struct lws_jws jws; size_t n, r = 1; + int otl = tl; memset(&jws, 0, sizeof(jws)); lws_jose_init(&jose); @@ -974,13 +975,15 @@ lws_jwt_signed_validate(struct lws_context *ctx, const char *alg_list, goto bail; } + temp += otl - tl; + otl = tl; + /* * Parse the JOSE header */ if (lws_jws_parse_jose(&jose, jws.map.buf[LJWS_JOSE], - jws.map.len[LJWS_JOSE], - lws_concat_temp(temp, tl), &tl) < 0) { + jws.map.len[LJWS_JOSE], temp, &tl) < 0) { lwsl_err("%s: JOSE parse failed\n", __func__); goto bail; } @@ -1034,3 +1037,112 @@ bail: return r; } + +int +lws_jwt_sign_compact(struct lws_context *ctx, struct lws_jwk *jwk, + const char *alg, char *out, size_t *out_len, char *temp, + int tl, const char *format, ...) +{ + int n, r = 1, otl = tl; + struct lws_jose jose; + struct lws_jws jws; + va_list ap; + char *q; + + lws_jws_init(&jws, jwk, ctx); + lws_jose_init(&jose); + + if (lws_gencrypto_jws_alg_to_definition(alg, &jose.alg)) { + lwsl_err("%s: unknown alg %s\n", __func__, alg); + + goto bail; + } + + /* create JOSE header, also needed for output */ + + if (lws_jws_alloc_element(&jws.map, LJWS_JOSE, temp, &tl, + strlen(alg) + 10, 0)) { + lwsl_err("%s: temp space too small\n", __func__); + return 1; + } + + jws.map.len[LJWS_JOSE] = lws_snprintf((char *)jws.map.buf[LJWS_JOSE], + tl, "{\"alg\":\"%s\"}", alg); + + temp += otl - tl; + otl = tl; + + va_start(ap, format); + n = vsnprintf(NULL, 0, format, ap); + va_end(ap); + if (n + 2 >= tl) + goto bail; + + q = lws_malloc(n + 2, __func__); + if (!q) + goto bail; + + va_start(ap, format); + vsnprintf(q, n + 2, format, ap); + va_end(ap); + + /* add the plaintext from stdin to the map and a b64 version */ + + jws.map.buf[LJWS_PYLD] = q; + jws.map.len[LJWS_PYLD] = n; + + if (lws_jws_encode_b64_element(&jws.map_b64, LJWS_PYLD, temp, &tl, + jws.map.buf[LJWS_PYLD], + jws.map.len[LJWS_PYLD])) + goto bail1; + + temp += otl - tl; + otl = tl; + + /* add the b64 JOSE header to the b64 map */ + + if (lws_jws_encode_b64_element(&jws.map_b64, LJWS_JOSE, temp, &tl, + jws.map.buf[LJWS_JOSE], + jws.map.len[LJWS_JOSE])) + goto bail1; + + temp += otl - tl; + otl = tl; + + /* prepare the space for the b64 signature in the map */ + + if (lws_jws_alloc_element(&jws.map_b64, LJWS_SIG, temp, &tl, + lws_base64_size(LWS_JWE_LIMIT_KEY_ELEMENT_BYTES), + 0)) + goto bail1; + + /* sign the plaintext */ + + n = lws_jws_sign_from_b64(&jose, &jws, + (char *)jws.map_b64.buf[LJWS_SIG], + jws.map_b64.len[LJWS_SIG]); + if (n < 0) + goto bail1; + + /* set the actual b64 signature size */ + jws.map_b64.len[LJWS_SIG] = n; + + /* create the compact JWS representation */ + if (lws_jws_write_compact(&jws, out, *out_len)) + goto bail1; + + *out_len = strlen(out); + + r = 0; + +bail1: + lws_free(q); + +bail: + jws.map.buf[LJWS_PYLD] = NULL; + jws.map.len[LJWS_PYLD] = 0; + lws_jws_destroy(&jws); + lws_jose_destroy(&jose); + + return r; +} diff --git a/minimal-examples/api-tests/api-test-jose/jws.c b/minimal-examples/api-tests/api-test-jose/jws.c index 55ffcc97..cb1cb1e8 100644 --- a/minimal-examples/api-tests/api-test-jose/jws.c +++ b/minimal-examples/api-tests/api-test-jose/jws.c @@ -685,6 +685,43 @@ test_jws_ES512(struct lws_context *context) goto bail1; } + /* jwt test */ + + { + unsigned long long ull = lws_now_secs(); + char buf[8192]; + size_t cml = 2048, cml2 = 2048; + + if (lws_jwt_sign_compact(context, &jwk, "ES512", + (char *)buf, &cml2, + (char *)buf + 2048, 4096, + "{\"iss\":\"warmcat.com\",\"aud\":" + "\"https://libwebsockets.org/sai\"," + "\"iat\":%llu," + "\"nbf\":%llu," + "\"exp\":%llu," + "\"sub\":\"manage\"}", ull, + ull - 60, ull + (30 * 24 * 3600) + )) { + lwsl_err("%s: failed to create JWT\n", __func__); + goto bail1; + } + + lwsl_notice("%s: jwt test '%s'\n", __func__, buf); + + if (lws_jwt_signed_validate(context, &jwk, "ES512", + (const char *)buf, cml2, + (char *)buf + 2048, 2048, + (char *)buf + 4096, &cml)) { + lwsl_err("%s: failed to parse JWT\n", __func__); + + goto bail1; + } + + lwsl_notice("%s: jwt valid, payload '%s'\n", + __func__, buf + 4096); + } + /* end */ ret = 0; -- Gitee From 08b9a31e205c0e78a340526f869714a9712f7032 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 12 Jul 2020 15:09:16 +0100 Subject: [PATCH 0213/1062] lws_json_simple: allow running into end If the arg is unquoted, it's normal to run into the end finding its extent. --- lib/core/libwebsockets.c | 5 +---- .../api-tests/api-test-lejp/main.c | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index d034fe79..aae71555 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -405,7 +405,7 @@ lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen while (np < end && (*np == ' ' || *np == '\t')) np++; - if (np >= end - 1) + if (np >= end) return NULL; /* @@ -432,9 +432,6 @@ lws_json_simple_find(const char *buf, size_t len, const char *name, size_t *alen np++; } - if (np == end) - return NULL; - *alen = lws_ptr_diff(np, as); return as; diff --git a/minimal-examples/api-tests/api-test-lejp/main.c b/minimal-examples/api-tests/api-test-lejp/main.c index 91cd630f..352181bb 100644 --- a/minimal-examples/api-tests/api-test-lejp/main.c +++ b/minimal-examples/api-tests/api-test-lejp/main.c @@ -184,6 +184,27 @@ int main(int argc, const char **argv) } } + { + const char *cs; + size_t cslen; + cs = lws_json_simple_find("{\"blah\":123,\"ext\":{\"authorized\":1}}", 35, + "\"ext\":", &cslen); + if (!cs) { + lwsl_err("%s: simple_find failed\n", __func__); + e++; + } else { + if (lws_json_simple_strcmp(cs, cslen, + "\"authorized\":", "1")) + e++; + } + cs = lws_json_simple_find("{\"blah\":123,\"auth_user\":\"andy@warmcat.com\",\"thing\":\"yeah\"}", 57, + "\"auth_user\":", &cslen); + if (cslen != 16) { + lwsl_err("%s: wrong string len %d isolated\n", __func__, (int)cslen); + e++; + } + } + if (e) goto bail; -- Gitee From 634a97ad790c6d948c58c9fecedefe73e4483d59 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 11 Jul 2020 07:16:16 +0100 Subject: [PATCH 0214/1062] lws_jwt_token_sanity --- READMEs/README.jwt.md | 176 +++++++++++++++++++++++++++++++ include/libwebsockets/lws-jws.h | 102 ++++++++++++++++++ include/libwebsockets/lws-misc.h | 20 ++++ lib/core/libwebsockets.c | 21 ++++ lib/jose/jws/jws.c | 94 ++++++++++++++++- lib/roles/http/parsers.c | 117 ++++++++++++++++++++ 6 files changed, 527 insertions(+), 3 deletions(-) create mode 100644 READMEs/README.jwt.md diff --git a/READMEs/README.jwt.md b/READMEs/README.jwt.md new file mode 100644 index 00000000..e0c7e25f --- /dev/null +++ b/READMEs/README.jwt.md @@ -0,0 +1,176 @@ +# JWT support in lws + +lws supports the common usage scenarios of JWS (signed) JWT generation, +parsing and transferring in and out as http cookies. Care is taken to provide +helpers that implement the current security best practices for cookie handling +and JWT validation. All of the common algorithms like ES512 are supported +along with JWK generation and handling apis. + +The build options needed are `-DLWS_WITH_JOSE=1` `-DLWS_WITH_GENCRYPTO=1`. + +Underlying JOSE primitives are exposed as apis, some JWT specific primitives +and finally a JWT-via http cookie level creation apis each building on top of +what was underneath. + +The higher level APIs are provided additionally because they have the most +opportunity for implementation pitfalls like not validating alg carefully, or +not using the latest cookie security options; the provided APIs handle that +centrally for you. If your needs vary from what the higher level apis are +doing, you can cut-and-paste out those implementations and create your own +using the public lower level apis. + +## LWS JWT fields + +Lws JWT uses mainly well-known fields + +Field|Std|Meaning +---|---|--- +iss|yes|Issuer, typically the domain like "warmcat.com" +aud|yes|Audience, typically a url path like "https://warmcat.com/sai" +iat|yes|Unix-time "Issued At" +nbf|yes|Unix-time "Not Before" +exp|yes|Unix-time "Expired" +sub|yes|Subject, eg, a username or user email +csrf|no|A random 16-char hex token generated with the JWT for use in links specific to the JWT bearer +ext|no|Application-specific JSON sub-object with whatever fields you need, eg, `"authorization": 1` + +## Approach for JWT as session token + +Once JWTs are produced, they are autonomous bearer tokens, if they are not kept +secret between the browser and the site, they will be accepted as evidence for +having rights to the session from anyone. + +Requiring https, and various other cookie hardening techniques make it more +difficult for them to leak, but it is still necessary to strictly constrain the +token's validity time, usually to a few tens of minutes or how long it takes a +user to login and get stuff done on the site in one session. + +## CSRF mitigation + +Cross Site Request Forgery (CSRF) is a hacking scenario where an authorized +user with a valid token is tricked into clicking on an external link that +performs some action with side-effects on the site he has active auth on. For +example, he has a cookie that's logged into his bank, and the link posts a form +to the bank site transferring money to the attacker. + +Lws JWT mitigates this possibility by putting a random secret in the generated +JWT; when the authorized user presents his JWT to generate the page, generated +links that require auth to perform their actions include the CSRF string from +that user's current JWT. + +When the user clicks those links intentionally, the CSRF string in the link +matches the CSRF string in the currently valid JWT that was also provided to +the server along with the click, and all is well. + +An attacker does not know the random, ephemeral JWT CSRF secret to include in +forged links, so the attacker-controlled action gets rejected at the server as +having used an invalid link. + +The checking and link manipulation need to be implemented in user code / JS... +lws JWT provides the random CSRF secret in the JWT and makes it visible to the +server when the incoming JWT is processed. + +## Need for client tracking of short JWT validity times + +Many links or references on pages do not require CSRF strings, only those that +perform actions with side-effects like deletion or money transfer should need +protecting this way. + +Due to CSRF mitigation, generated pages containing the protected links +effectively have an expiry time linked to that of the JWT, since only the bearer +of the JWT used to generate the links on the page can use them; once that +expires actually nobody can use them and the page contents, which may anyway +be showing content that only authenticated users can see must be invalidated and +re-fetched. Even if the contents are visible without authentication, additional +UI elements like delete buttons that should only be shown when authenticated +will wrongly still be shown + +For that reason, the client should be informed by the server along with the +authentication status, the expiry time of it. The client should then by itself +make arrangements to refresh the page when this time is passed, +either showing an unauthenticated version of the same page if it exists, or by +redirecting to the site homepage if showing any of the contents required +authentication. The user can then log back in using his credientials typically +stored in the browser's password store and receive a new short-term JWT with a +new random csrf token along with a new page using the new csrf token in its +links. + +## Considerations for long-lived connections + +Once established as authorized, websocket links may be very long-lived and hold +their authorization state at the server. Although the browser monitoring the +JWT reloading the page on auth expiry should mitigate this, an attacker can +choose to just not do that and have an immortally useful websocket link. + +At least for actions on the long-lived connection, it should not only confirm +the JWT authorized it but that the current time is still before the "exp" time +in the JWT, this is made available as `expiry_unix_time` in the args struct +after successful validation. + +Ideally the server should close long-lived connections according to their auth +expiry time. + +## JWT lower level APIs + +The related apis are in `./include/libwebsockets/lws-jws.h` + +### Validation of JWT + +``` +int +lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk, + const char *alg_list, const char *com, size_t len, + char *temp, int tl, char *out, size_t *out_len); +``` + +### Composing and signing JWT + +``` +int +lws_jwt_sign_compact(struct lws_context *ctx, struct lws_jwk *jwk, + const char *alg, char *out, size_t *out_len, char *temp, + int tl, const char *format, ...); +``` + +## JWT creation and cookie get / set API + +Both the validation and signing apis use the same struct to contain their +aguments. + +``` +struct lws_jwt_sign_set_cookie { + struct lws_jwk *jwk; + /**< entry: required signing key */ + const char *alg; + /**< entry: required signing alg, eg, "ES512" */ + const char *iss; + /**< entry: issuer name to use */ + const char *aud; + /**< entry: audience */ + const char *cookie_name; + /**< entry: the name of the cookie */ + char sub[33]; + /**< sign-entry, validate-exit: subject */ + const char *extra_json; + /**< sign-entry, validate-exit: + * optional "ext" JSON object contents for the JWT */ + size_t extra_json_len; + /**< validate-exit: + * length of optional "ext" JSON object contents for the JWT */ + const char *csrf_in; + /**< validate-entry: + * NULL, or an external CSRF token to check against what is in the JWT */ + unsigned long expiry_unix_time; + /**< sign-entry: seconds the JWT and cookie may live, + * validate-exit: expiry unix time */ +}; + +int +lws_jwt_sign_token_set_http_cookie(struct lws *wsi, + const struct lws_jwt_sign_set_cookie *i, + uint8_t **p, uint8_t *end); +int +lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi, + struct lws_jwt_sign_set_cookie *i, + char *out, size_t *out_len); +``` diff --git a/include/libwebsockets/lws-jws.h b/include/libwebsockets/lws-jws.h index 13fd26a3..c59affb9 100644 --- a/include/libwebsockets/lws-jws.h +++ b/include/libwebsockets/lws-jws.h @@ -454,4 +454,106 @@ LWS_VISIBLE LWS_EXTERN int lws_jwt_sign_compact(struct lws_context *ctx, struct lws_jwk *jwk, const char *alg, char *out, size_t *out_len, char *temp, int tl, const char *format, ...) LWS_FORMAT(8); + +/** + * lws_jwt_token_sanity() - check a validated jwt payload for sanity + * + * \param in: the JWT payload + * \param in_len: the length of the JWT payload + * \param iss: the expected issuer of the token + * \param aud: the expected audience of the token + * \param csrf_in: NULL, or the csrf token that came in on a URL + * \param sub: a buffer to hold the subject name in the JWT (eg, account name) + * \param sub_len: the max length of the sub buffer + * \param secs_left: set to the number of seconds of valid auth left if valid + * + * This performs some generic sanity tests on validated JWT payload... + * + * - the issuer is as expected + * - the audience is us + * - current time is OK for nbf ("not before") in the token + * - current time is OK for exp ("expiry") in the token + * - if csrf_in is not NULL, that the JWK has a csrf and it matches it + * - if sub is not NULL, that the JWK provides a subject (and copies it to sub) + * + * If the tests pass, *secs_left is set to the number of remaining seconds the + * auth is valid. + * + * Returns 0 if no inconsistency, else nonzero. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_token_sanity(const char *in, size_t in_len, + const char *iss, const char *aud, const char *csrf_in, + char *sub, size_t sub_len, unsigned long *exp_unix_time); + +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) + +struct lws_jwt_sign_set_cookie { + struct lws_jwk *jwk; + /**< entry: required signing key */ + const char *alg; + /**< entry: required signing alg, eg, "ES512" */ + const char *iss; + /**< entry: issuer name to use */ + const char *aud; + /**< entry: audience */ + const char *cookie_name; + /**< entry: the name of the cookie */ + char sub[33]; + /**< sign-entry, validate-exit: subject */ + const char *extra_json; + /**< sign-entry, validate-exit: + * optional "ext" JSON object contents for the JWT */ + size_t extra_json_len; + /**< validate-exit: + * length of optional "ext" JSON object contents for the JWT */ + const char *csrf_in; + /**< validate-entry: + * NULL, or an external CSRF token to check against what is in the JWT */ + unsigned long expiry_unix_time; + /**< sign-entry: seconds the JWT and cookie may live, + * validate-exit: expiry unix time */ +}; + +/** + * lws_jwt_sign_token_set_cookie() - creates sets a JWT in a wsi cookie + * + * \param wsi: the wsi to create the cookie header on + * \param i: structure describing what should be in the JWT + * \param p: wsi headers area + * \param end: end of wsi headers area + * + * Creates a JWT specified \p i, and attaches it to the outgoing headers on + * wsi. Returns 0 if successful. + * + * Best-practice security restrictions are applied to the cookie set action, + * including forcing httponly, and __Host- prefix. As required by __Host-, the + * cookie Path is set to /. __Host- is applied by the function, the cookie_name + * should just be "xyz" for "__Host-xyz". + * + * \p extra_json should just be the bare JSON, a { } is provided around it by + * the function if it's non-NULL. For example, "\"authorization\": 1". + * + * It's recommended the secs parameter is kept as small as consistent with one + * user session on the site if possible, eg, 10 minutes or 20 minutes. At the + * server, it can determine how much time is left in the auth and inform the + * client; if the JWT validity expires, the page should reload so the UI always + * reflects what's possible to do with the authorization state correctly. If + * the JWT expires, the user can log back in using credentials usually stored in + * the browser and auto-filled-in, so this is not very inconvenient. + * + * This is a helper on top of the other JOSE and JWT apis that somewhat crosses + * over between JWT and HTTP, since it knows about cookies. So it is only built + * if both LWS_WITH_JOSE and one of the http-related roles enabled. + */ +LWS_VISIBLE LWS_EXTERN int +lws_jwt_sign_token_set_http_cookie(struct lws *wsi, + const struct lws_jwt_sign_set_cookie *i, + uint8_t **p, uint8_t *end); +LWS_VISIBLE LWS_EXTERN int +lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi, + struct lws_jwt_sign_set_cookie *i, + char *out, size_t *out_len); +#endif + ///@} diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index e9185504..2a33eba5 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -261,6 +261,26 @@ lws_json_simple_strcmp(const char *buf, size_t len, const char *name, const char LWS_VISIBLE LWS_EXTERN int lws_hex_to_byte_array(const char *h, uint8_t *dest, int max); + +/** + * lws_hex_random(): generate len - 1 or - 2 characters of random ascii hex + * + * \param context: the lws_context used to get the random + * \param dest: destination for hex ascii chars + * \param len: the number of bytes the buffer dest points to can hold + * + * This creates random ascii-hex strings up to a given length, with a + * terminating NUL. Hex characters are produced in pairs, if the length of + * the destination buffer is even, after accounting for the NUL there will be + * an unused byte at the end after the NUL. So lengths should be odd to get + * length - 1 characters exactly followed by the NUL. + * + * There will not be any characters produced that are not 0-9, a-f, so it's + * safe to go straight into, eg, JSON. + */ +LWS_VISIBLE LWS_EXTERN int +lws_hex_random(struct lws_context *context, char *dest, size_t len); + /* * lws_timingsafe_bcmp(): constant time memcmp * diff --git a/lib/core/libwebsockets.c b/lib/core/libwebsockets.c index aae71555..bcd3acee 100644 --- a/lib/core/libwebsockets.c +++ b/lib/core/libwebsockets.c @@ -153,6 +153,27 @@ lws_hex_to_byte_array(const char *h, uint8_t *dest, int max) return lws_ptr_diff(dest, odest); } +static char *hexch = "0123456789abcdef"; + +int +lws_hex_random(struct lws_context *context, char *dest, size_t len) +{ + size_t n = (len - 1) / 2; + uint8_t b, *r = (uint8_t *)dest + len - n; + + if (lws_get_random(context, r, n) != n) + return 1; + + while (n--) { + b = *r++; + *dest++ = hexch[b >> 4]; + *dest++ = hexch[b & 0xf]; + } + + *dest = '\0'; + + return 0; +} #if !defined(LWS_PLAT_OPTEE) diff --git a/lib/jose/jws/jws.c b/lib/jose/jws/jws.c index 27ca873a..e2c6f2a8 100644 --- a/lib/jose/jws/jws.c +++ b/lib/jose/jws/jws.c @@ -957,9 +957,9 @@ lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk, { struct lws_tokenize ts; struct lws_jose jose; + int otl = tl, r = 1; struct lws_jws jws; - size_t n, r = 1; - int otl = tl; + size_t n; memset(&jws, 0, sizeof(jws)); lws_jose_init(&jose); @@ -969,7 +969,8 @@ lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk, * blocks */ - n = lws_jws_compact_decode(com, len, &jws.map, &jws.map_b64, temp, &tl); + n = lws_jws_compact_decode(com, (int)len, &jws.map, &jws.map_b64, + temp, &tl); if (n != 3) { lwsl_err("%s: concat_map failed: %d\n", __func__, (int)n); goto bail; @@ -1146,3 +1147,90 @@ bail: return r; } + +int +lws_jwt_token_sanity(const char *in, size_t in_len, + const char *iss, const char *aud, + const char *csrf_in, + char *sub, size_t sub_len, unsigned long *expiry_unix_time) +{ + unsigned long now = lws_now_secs(), exp; + const char *cp; + size_t len; + + /* + * It has our issuer? + */ + + if (lws_json_simple_strcmp(in, in_len, "\"iss\":", iss)) { + lwsl_notice("%s: iss mismatch\n", __func__); + return 1; + } + + /* + * ... it is indended for us to consume? (this is set + * to the public base url for this sai instance) + */ + if (lws_json_simple_strcmp(in, in_len, "\"aud\":", aud)) { + lwsl_notice("%s: aud mismatch\n", __func__); + return 1; + } + + /* + * ...it's not too early for it? + */ + cp = lws_json_simple_find(in, in_len, "\"nbf\":", &len); + if (!cp || (unsigned long)atol(cp) > now) { + lwsl_notice("%s: nbf fail\n", __func__); + return 1; + } + + /* + * ... and not too late for it? + */ + cp = lws_json_simple_find(in, in_len, "\"exp\":", &len); + exp = (unsigned long)atol(cp); + if (!cp || (unsigned long)atol(cp) < now) { + lwsl_notice("%s: exp fail %lu vs %lu\n", __func__, + cp ? (unsigned long)atol(cp) : 0, now); + return 1; + } + + /* + * Caller cares about subject? Then we must have it, and it can't be + * empty. + */ + + if (sub) { + cp = lws_json_simple_find(in, in_len, "\"sub\":", &len); + if (!cp || !len) { + lwsl_notice("%s: missing subject\n", __func__); + return 1; + } + lws_strnncpy(sub, cp, len, sub_len); + } + + /* + * If caller has been told a Cross Site Request Forgery (CSRF) nonce, + * require this JWT to express the same CSRF... this makes generated + * links for dangerous privileged auth'd actions expire with the JWT + * that was accessing the site when the links were generated. And it + * leaves an attacker not knowing what links to synthesize unless he + * can read the token or pages generated with it. + * + * Using this is very good for security, but it implies you must refresh + * generated pages still when the auth token is expiring (and the user + * must log in again). + */ + + if (csrf_in && + lws_json_simple_strcmp(in, in_len, "\"csrf\":", csrf_in)) { + lwsl_notice("%s: csrf mismatch\n", __func__); + return 1; + } + + if (expiry_unix_time) + *expiry_unix_time = exp; + + return 0; +} diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index 1382e97e..5973b900 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -1468,6 +1468,7 @@ lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, char *p, *bo = buf; n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE); + lwsl_notice("%s: cookie hdr len %d\n", __func__, n); if (n < bl + 1) return 1; @@ -1475,6 +1476,8 @@ lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, if (!p) return 1; + lwsl_hexdump_notice(p, n); + p += bl; n -= bl; while (n-- > bl) { @@ -1497,3 +1500,117 @@ lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, return 1; } + +#if defined(LWS_WITH_JOSE) + +#define MAX_JWT_SIZE 1024 + +int +lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi, + struct lws_jwt_sign_set_cookie *i, + char *out, size_t *out_len) +{ + char temp[MAX_JWT_SIZE * 2]; + size_t cml = *out_len; + const char *cp; + + /* first use out to hold the encoded JWT */ + + if (lws_http_cookie_get(wsi, i->cookie_name, out, out_len)) { + lwsl_notice("%s: cookie %s not provided\n", __func__, + i->cookie_name); + return 1; + } + + /* decode the JWT into temp */ + + if (lws_jwt_signed_validate(wsi->context, i->jwk, i->alg, out, + *out_len, temp, sizeof(temp), out, &cml)) { + lwsl_notice("%s: jwt validation failed\n", __func__); + return 1; + } + + /* + * Copy out the decoded JWT payload into out, overwriting the + * original encoded JWT taken from the cookie (that has long ago been + * translated into allocated buffers in the JOSE object) + */ + + if (lws_jwt_token_sanity(out, cml, i->iss, i->aud, i->csrf_in, + i->sub, sizeof(i->sub), + &i->expiry_unix_time)) { + lwsl_notice("%s: jwt sanity failed\n", __func__); + return 1; + } + + /* + * If he's interested in his private JSON part, point him to that in + * the args struct (it's pointing to the data in out + */ + + cp = lws_json_simple_find(out, cml, "\"ext\":", &i->extra_json_len); + if (cp) + i->extra_json = cp; + + if (cp) + lwsl_hexdump_notice(cp, i->extra_json_len); + else + lwsl_notice("%s: no ext JWT payload\n", __func__); + + return 0; +} + +int +lws_jwt_sign_token_set_http_cookie(struct lws *wsi, + const struct lws_jwt_sign_set_cookie *i, + uint8_t **p, uint8_t *end) +{ + char plain[MAX_JWT_SIZE + 1], temp[MAX_JWT_SIZE * 2], csrf[17]; + size_t pl = sizeof(plain); + unsigned long long ull; + int n; + + /* + * Create a 16-char random csrf token with the same lifetime as the JWT + */ + + lws_hex_random(wsi->context, csrf, sizeof(csrf)); + ull = lws_now_secs(); + if (lws_jwt_sign_compact(wsi->context, i->jwk, i->alg, plain, &pl, + temp, sizeof(temp), + "{\"iss\":\"%s\",\"aud\":\"%s\"," + "\"iat\":%llu,\"nbf\":%llu,\"exp\":%llu," + "\"csrf\":\"%s\",\"sub\":\"%s\"%s%s%s}", + i->iss, i->aud, ull, ull - 60, + ull + i->expiry_unix_time, + csrf, i->sub, + i->extra_json ? ",\"ext\":{" : "", + i->extra_json ? i->extra_json : "", + i->extra_json ? "}" : "")) { + lwsl_err("%s: failed to create JWT\n", __func__); + + return 1; + } + + /* + * There's no point the browser holding on to a JWT beyond the JWT's + * expiry time, so set it to be the same. + */ + + n = lws_snprintf(temp, sizeof(temp), "__Host-%s=%s;" + "HttpOnly;" + "Secure;" + "SameSite=strict;" + "Path=/;" + "Max-Age=%lu", + i->cookie_name, plain, i->expiry_unix_time); + + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SET_COOKIE, + (uint8_t *)temp, n, p, end)) { + lwsl_err("%s: failed to add JWT cookie header\n", __func__); + return 1; + } + + return 0; +} +#endif -- Gitee From 599625be34c2db3121b4effc691c6d2a1ed3b241 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 13 Jul 2020 13:24:38 +0100 Subject: [PATCH 0215/1062] remove: generic sessions As far as I know there are no users of this, although it worked it's basically unmaintainable due to handling the sql and JSON manually. Gradually better capabilities have appeared in lws, like lws_struct abstracting out the sql and JSON, and now generic JWT... these have been used in Sai to great effect and displaced the only organic would-be user of this. There is a better path to do this stuff now and no point keeping this around. --- CMakeLists-implied-options.txt | 7 - CMakeLists.txt | 1 - plugins/CMakeLists.txt | 57 -- .../generic-sessions/assets/admin-login.html | 5 - .../generic-sessions/assets/failed-login.html | 3 - plugins/generic-sessions/assets/index.html | 56 -- .../generic-sessions/assets/lwsgs-logo.png | Bin 9729 -> 0 bytes plugins/generic-sessions/assets/lwsgs.css | 134 --- plugins/generic-sessions/assets/lwsgs.js | 627 ------------ plugins/generic-sessions/assets/md5.min.js | 2 - .../assets/post-forgot-fail.html | 5 - .../assets/post-forgot-ok.html | 6 - .../assets/post-register-fail.html | 1 - .../assets/post-register-ok.html | 27 - .../assets/post-verify-fail.html | 20 - .../assets/post-verify-ok.html | 25 - plugins/generic-sessions/assets/seats.jpg | Bin 122754 -> 0 bytes .../assets/sent-forgot-fail.html | 5 - .../assets/sent-forgot-ok.html | 4 - .../assets/successful-login.html | 4 - plugins/generic-sessions/handlers.c | 663 ------------- plugins/generic-sessions/private-lwsgs.h | 171 ---- .../protocol_generic_sessions.c | 920 ------------------ .../protocol_lws_messageboard.c | 438 --------- plugins/generic-sessions/utils.c | 465 --------- plugins/generic-table/assets/index.html | 75 -- plugins/generic-table/assets/lwsgt.js | 139 --- .../generic-table/protocol_table_dirlisting.c | 397 -------- 28 files changed, 4257 deletions(-) delete mode 100644 plugins/generic-sessions/assets/admin-login.html delete mode 100644 plugins/generic-sessions/assets/failed-login.html delete mode 100644 plugins/generic-sessions/assets/index.html delete mode 100644 plugins/generic-sessions/assets/lwsgs-logo.png delete mode 100644 plugins/generic-sessions/assets/lwsgs.css delete mode 100644 plugins/generic-sessions/assets/lwsgs.js delete mode 100644 plugins/generic-sessions/assets/md5.min.js delete mode 100644 plugins/generic-sessions/assets/post-forgot-fail.html delete mode 100644 plugins/generic-sessions/assets/post-forgot-ok.html delete mode 100644 plugins/generic-sessions/assets/post-register-fail.html delete mode 100644 plugins/generic-sessions/assets/post-register-ok.html delete mode 100644 plugins/generic-sessions/assets/post-verify-fail.html delete mode 100644 plugins/generic-sessions/assets/post-verify-ok.html delete mode 100644 plugins/generic-sessions/assets/seats.jpg delete mode 100644 plugins/generic-sessions/assets/sent-forgot-fail.html delete mode 100644 plugins/generic-sessions/assets/sent-forgot-ok.html delete mode 100644 plugins/generic-sessions/assets/successful-login.html delete mode 100644 plugins/generic-sessions/handlers.c delete mode 100644 plugins/generic-sessions/private-lwsgs.h delete mode 100644 plugins/generic-sessions/protocol_generic_sessions.c delete mode 100644 plugins/generic-sessions/protocol_lws_messageboard.c delete mode 100644 plugins/generic-sessions/utils.c delete mode 100644 plugins/generic-table/assets/index.html delete mode 100644 plugins/generic-table/assets/lwsgt.js delete mode 100644 plugins/generic-table/protocol_table_dirlisting.c diff --git a/CMakeLists-implied-options.txt b/CMakeLists-implied-options.txt index 8ec12f15..0da12124 100644 --- a/CMakeLists-implied-options.txt +++ b/CMakeLists-implied-options.txt @@ -134,7 +134,6 @@ if (NOT LWS_WITH_NETWORK) set(LWS_WITH_CGI 0) set(LWS_ROLE_RAW_PROXY 0) set(LWS_WITH_PEER_LIMITS 0) - set(LWS_WITH_GENERIC_SESSIONS 0) set(LWS_WITH_HTTP_STREAM_COMPRESSION 0) set(LWS_WITH_HTTP_BROTLI 0) set(LWS_WITH_POLL 0) @@ -228,12 +227,6 @@ if (LWS_WITH_PLUGINS OR LWS_WITH_CGI) set(LWS_WITH_GENCRYPTO 1) endif() -if (LWS_WITH_GENERIC_SESSIONS) - set(LWS_WITH_SQLITE3 1) - # set(LWS_WITH_SMTP 1) - set(LWS_WITH_STRUCT_SQLITE3 1) -endif() - if (LWS_PLAT_FREERTOS) set(LWS_WITH_SHARED OFF) set(LWS_WITH_MBEDTLS ON) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd74640a..f5b55007 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,6 @@ option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF) option(LWS_WITH_HTTP_PROXY "Support for active HTTP proxying" OFF) option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" OFF) option(LWS_WITH_SOCKS5 "Allow use of SOCKS5 proxy on client connections" OFF) -option(LWS_WITH_GENERIC_SESSIONS "With the Generic Sessions plugin" OFF) option(LWS_WITH_PEER_LIMITS "Track peers and restrict resources a single peer can allocate" OFF) option(LWS_WITH_ACCESS_LOG "Support generating Apache-compatible access logs" OFF) option(LWS_WITH_RANGES "Support http ranges (RFC7233)" OFF) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 0e1560eb..f99a65ef 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -90,8 +90,6 @@ if (LWS_ROLE_WS) "protocol_lws_mirror.c" "" "") create_plugin(protocol_lws_status "" "protocol_lws_status.c" "" "") - create_plugin(protocol_lws_table_dirlisting "" - "generic-table/protocol_table_dirlisting.c" "" "") if (NOT WIN32) create_plugin(protocol_lws_raw_test "" "protocol_lws_raw_test.c" "" "") @@ -143,29 +141,6 @@ if (LWS_WITH_ACME) "acme-client/protocol_lws_acme_client.c" "" "") endif() -if (LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS) - create_plugin(protocol_generic_sessions "" - "generic-sessions/protocol_generic_sessions.c" - "generic-sessions/utils.c" - "generic-sessions/handlers.c") - - if (WIN32) - target_link_libraries(protocol_generic_sessions ${LWS_SQLITE3_LIBRARIES}) - else() - target_link_libraries(protocol_generic_sessions sqlite3 ) - endif(WIN32) - - create_plugin(protocol_lws_messageboard "" - "generic-sessions/protocol_lws_messageboard.c" "" "") - if (WIN32) - target_link_libraries(protocol_lws_messageboard ${LWS_SQLITE3_LIBRARIES}) - else() - target_link_libraries(protocol_lws_messageboard sqlite3 ) - endif(WIN32) - -endif(LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS) - - endif(LWS_WITH_PLUGINS AND LWS_WITH_SHARED) @@ -189,36 +164,4 @@ if (LWS_WITH_SERVER_STATUS) DESTINATION share/libwebsockets-test-server/server-status COMPONENT examples) endif() -if (LWS_WITH_GENERIC_SESSIONS) - install(FILES - generic-sessions/assets/lwsgs-logo.png - generic-sessions/assets/seats.jpg - generic-sessions/assets/failed-login.html - generic-sessions/assets/lwsgs.js - generic-sessions/assets/lwsgs.css - generic-sessions/assets/post-register-fail.html - generic-sessions/assets/post-register-ok.html - generic-sessions/assets/post-verify-ok.html - generic-sessions/assets/post-verify-fail.html - generic-sessions/assets/sent-forgot-ok.html - generic-sessions/assets/sent-forgot-fail.html - generic-sessions/assets/post-forgot-ok.html - generic-sessions/assets/post-forgot-fail.html - generic-sessions/assets/index.html - DESTINATION share/libwebsockets-test-server/generic-sessions - COMPONENT examples) - install(FILES generic-sessions/assets/successful-login.html - DESTINATION share/libwebsockets-test-server/generic-sessions/needauth - COMPONENT examples) - install(FILES generic-sessions/assets/admin-login.html - DESTINATION share/libwebsockets-test-server/generic-sessions/needadmin - COMPONENT examples) -endif() - - install(FILES - generic-table/assets/lwsgt.js - generic-table/assets/index.html - DESTINATION share/libwebsockets-test-server/generic-table - COMPONENT examples) - endif() diff --git a/plugins/generic-sessions/assets/admin-login.html b/plugins/generic-sessions/assets/admin-login.html deleted file mode 100644 index 113df9cd..00000000 --- a/plugins/generic-sessions/assets/admin-login.html +++ /dev/null @@ -1,5 +0,0 @@ - -This is an example destination that will appear after successful Admin login. - -This URL cannot be served if you're not logged in as admin. - diff --git a/plugins/generic-sessions/assets/failed-login.html b/plugins/generic-sessions/assets/failed-login.html deleted file mode 100644 index 9ab065b5..00000000 --- a/plugins/generic-sessions/assets/failed-login.html +++ /dev/null @@ -1,3 +0,0 @@ - -This is an example destination that will appear after a failed login - diff --git a/plugins/generic-sessions/assets/index.html b/plugins/generic-sessions/assets/index.html deleted file mode 100644 index d40904af..00000000 --- a/plugins/generic-sessions/assets/index.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - -
-
-
- -
- - This is a demo application for lws generic-sessions.

- It's a simple messageboard.

- What's interesting about it is there is no serverside scripting,
- instead client js makes a wss:// connection back to the server
- and then reacts to JSON from the ws protocol. Sessions stuff is
- handled by lws generic sessions, making the actual
- test application
very small.

- And because it's natively websocket, it's naturally connected
- for dynamic events and easy to maintain. -

- Register / Login at the top right to see and create new messages. -
- -
-
- New message
-
- -
-
-
-
- -
- -
-
- - - - diff --git a/plugins/generic-sessions/assets/lwsgs-logo.png b/plugins/generic-sessions/assets/lwsgs-logo.png deleted file mode 100644 index 723a124431189c21c340de517bd9b82cb35374d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9729 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
`M|k*(&Q-fBLi|yvnrg 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 ARR910 diff --git a/plugins/generic-sessions/assets/lwsgs.css b/plugins/generic-sessions/assets/lwsgs.css deleted file mode 100644 index 9dfde757..00000000 --- a/plugins/generic-sessions/assets/lwsgs.css +++ /dev/null @@ -1,134 +0,0 @@ -.body { font-size: 12px } -.gstitle { font-size: 18px } - -.group1 { - vertical-align:middle; - text-align:center; - background:#f0f0e0; - padding:12px; - border-radius:10px; -} -.group2 { - display:none; - vertical-align:middle; - font-size: 22px; - text-align:center; - margin:auto; - align:center; - background-color: rgba(255, 255, 255, 0.8); - padding:12px; - border-radius:10px; -} - -body.seats { - background-image:url(seats.jpg) -} - -div.lwsgs { - z-index: 3; - text-align:right; - background-color: rgba(255, 255, 255, 0.8); -} - -table.lwsgs { - width:100%; - height:100%; - transition: max-height 2s; -} -table.c100 { - text-align:center; - width:100%; -} - -table.r { - vertical-align:top; - text-align:right; -} - -table.l { - vertical-align:top; - text-align:left; -} - -table.fixed { - table-layout: fixed; -} - -td.logo { - vertical-align:top; - text-align:left; - width:200px -} - -td.lwsgs { - vertical-align:top; - float:right; -} - -td.h99 { - height:99%; - vertical-align:middle; -} - -td.c { - margin:auto; - align:center -} - -td.tac { - text-align:center -} - -td.ava { - display:inline-block; - vertical-align:top; - word-wrap:break-word; -} - -iframe.hidden { - display:none; -} - -div.hidden { - display:none; -} - -div.hiddenr { - display:none; - text-align:right; -} - -input { - margin: 2px; - padding: 2px; -} - -input.em { - margin: 4px; - font-weight:bold; -} - -input.wide { - margin: 6px; - padding: 6px; -} - -input.hidden { - display: none; -} - -form.r { - text-align:right; -} - -span.bad { - color: red; -} - -span.small { - font-size:8pt; -} - -.green { - color: green; -} diff --git a/plugins/generic-sessions/assets/lwsgs.js b/plugins/generic-sessions/assets/lwsgs.js deleted file mode 100644 index bcfd3d14..00000000 --- a/plugins/generic-sessions/assets/lwsgs.js +++ /dev/null @@ -1,627 +0,0 @@ - - -var lwsgs_user = "$lwsgs_user"; -var lwsgs_auth = "$lwsgs_auth"; -var lwsgs_email = "$lwsgs_email"; - -var lwsgs_html = '\ -

\ -\ -
\ -
\ - \ - \ - \ - \ -
\ - \ -
\ - \ -
\ -
\ -\ - \ - \ - \ - \ - \ -'; - -/*-- this came from - -- https://raw.githubusercontent.com/blueimp/JavaScript-MD5/master/js/md5.min.js - -- under MIT license */ -!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t),e=(n>>16)+(t>>16)+(r>>16);return e<<16|65535&r}function r(n,t){return n<>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<>>9<<4)+14]=r;var e,i,a,h,d,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t>5]|=(255&n.charCodeAt(t/8))<16&&(o=i(o,8*n.length)),r=0;16>r;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="0123456789abcdef",o="";for(r=0;r>>4&15)+e.charAt(15&t);return o}function v(n){return unescape(encodeURIComponent(n))}function m(n){return d(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this); - -if (lwsgs_user.substring(0, 1) == "$") { - alert("lwsgs.js: lws generic sessions misconfigured and not providing vars"); -} -function lwsgs_san(s) -{ - if (s.search("<") != -1) - return "invalid string"; - - return s; -} - -function lwsgs_update() -{ - var en_login = 1, en_forgot = 1; - - if (document.getElementById('password').value.length && - document.getElementById('password').value.length < 8) - en_login = 0; - - if (!document.getElementById('username').value || - !document.getElementById('password').value) - en_login = 0; - - if (!document.getElementById('username').value || - document.getElementById('password').value) - en_forgot = 0; - - document.getElementById('login').disabled = !en_login; - document.getElementById('forgot').disabled = !en_forgot; - - if (lwsgs_user) - document.getElementById("curuser").innerHTML = lwsgs_san(lwsgs_user); - - if (lwsgs_user === "") - document.getElementById("dlogin").style.display = "inline"; - else - document.getElementById("dlogout").style.display = "inline"; - } - -function lwsgs_open_registration() -{ - document.getElementById("dadmin").style.display = "none"; - document.getElementById("dlogin").style.display = "none"; - document.getElementById("dlogout").style.display = "none"; - document.getElementById("dchange").style.display = "none"; - document.getElementById("dregister").style.display = "inline"; -} - -function lwsgs_cancel_registration() -{ - document.getElementById("dadmin").style.display = "none"; - document.getElementById("dregister").style.display = "none"; - document.getElementById("dchange").style.display = "none"; - - if (lwsgs_user === "") - document.getElementById("dlogin").style.display = "inline"; - else - document.getElementById("dlogout").style.display = "inline"; -} - -function lwsgs_select_change() -{ - document.getElementById("dlogin").style.display = "none"; - document.getElementById("dlogout").style.display = "none"; - document.getElementById("dregister").style.display = "none"; - if (lwsgs_auth & 2) { - document.getElementById("dadmin").style.display = "inline"; - document.getElementById("dchange").style.display = "none"; - } else { - document.getElementById("dadmin").style.display = "none"; - document.getElementById("dchange").style.display = "inline"; - } - - event.preventDefault() -} - -var lwsgs_user_check = '0'; -var lwsgs_email_check = '0'; - -function lwsgs_rupdate() -{ - var en_register = 1, en_forgot = 0, op; - - if (document.getElementById('rpassword').value == - document.getElementById('password2').value) { - if (document.getElementById('rpassword').value.length) - document.getElementById('match').innerHTML = - "\u2713"; - else - document.getElementById('match').innerHTML = ""; - document.getElementById('pw2').style = ""; - } else { - if (document.getElementById('password2').value || - document.getElementById('email').value) { // ie, he is filling in "register" path and cares - document.getElementById('match').innerHTML = - "\u2718 Passwords do not match"; - } else - document.getElementById('match').innerHTML = - "\u2718 Passwords do not match"; - - en_register = 0; - } - - if (document.getElementById('rpassword').value.length && - document.getElementById('rpassword').value.length < 8) { - en_register = 0; - document.getElementById('rpw1').innerHTML = "Need 8 chars"; - } else - if (document.getElementById('rpassword').value.length) - document.getElementById('rpw1').innerHTML = "\u2713"; - else - document.getElementById('rpw1').innerHTML = ""; - - if (!document.getElementById('rpassword').value || - !document.getElementById('password2').value || - !document.getElementById('rusername').value || - !document.getElementById('email').value || - lwsgs_email_check === '1'|| - lwsgs_user_check === '1') - en_register = 0; - - document.getElementById('register').disabled = !en_register; - document.getElementById('rpassword').disabled = lwsgs_user_check === '1'; - document.getElementById('password2').disabled = lwsgs_user_check === '1'; - document.getElementById('email').disabled = lwsgs_user_check === '1'; - - if (lwsgs_user_check === '0') { - var uc = document.getElementById('uchk'); - - if (uc) { - if (document.getElementById('rusername').value) - uc.innerHTML = "\u2713"; - else - uc.innerHTML = ""; - } - } else { - if (document.getElementById('uchk')) - ocument.getElementById('uchk').innerHTML = "\u2718 Already registered"; - en_forgot = 1; - } - - if (lwsgs_email_check === '0') { - var ec = document.getElementById('echk'); - - if (ec) { - if (document.getElementById('email').value) - ec.innerHTML = "\u2713"; - else - ec.innerHTML = ""; - } - } else { - if (document.getElementById('echk')) - document.getElementById('echk').innerHTML = "\u2718 Already registered"; - en_forgot = 1; - } - - if (en_forgot) - document.getElementById('rforgot').style.display = "inline"; - else - document.getElementById('rforgot').style.display = "none"; - - if (lwsgs_user_check === '1') - op = '0.5'; - else - op = '1.0'; - document.getElementById('rpassword').style.opacity = op; - document.getElementById('password2').style.opacity = op; - document.getElementById('email').style.opacity = op; - } - -function lwsgs_cupdate() -{ - var en_change = 1, en_forgot = 1, pwok = 1, op; - - if (lwsgs_auth & 8) { - document.getElementById('ccurpw').style.display = "none"; - document.getElementById('ccurpw_name').style.display = "none"; - } else { - if (!document.getElementById('ccurpw').value || - document.getElementById('ccurpw').value.length < 8) { - en_change = 0; - pwok = 0; - document.getElementById('cuchk').innerHTML = "\u2718"; - } else { - en_forgot = 0; - document.getElementById('cuchk').innerHTML = ""; - } - document.getElementById('ccurpw').style.display = "inline"; - document.getElementById('ccurpw_name').style.display = "inline"; - } - - if (document.getElementById('cpassword').value == - document.getElementById('cpassword2').value) { - if (document.getElementById('cpassword').value.length) - document.getElementById('cmatch').innerHTML = "\u2713"; - else - document.getElementById('cmatch').innerHTML = ""; - document.getElementById('pw2').style = ""; - } else { - if (document.getElementById('cpassword2').value //|| - //document.getElementById('cemail').value - ) { // ie, he is filling in "register" path and cares - document.getElementById('cmatch').innerHTML = - "\u2718 Passwords do not match"; - } else - document.getElementById('cmatch').innerHTML = "\u2718 Passwords do not match"; - - en_change = 0; - } - - if (document.getElementById('cpassword').value.length && - document.getElementById('cpassword').value.length < 8) { - en_change = 0; - document.getElementById('cpw1').innerHTML = "Need 8 chars"; - } else { - var cpw = document.getElementById('cpw1'); - - if (cpw) { - if (document.getElementById('cpassword').value.length) - cpw.innerHTML = "\u2713"; - else - cpw.innerHTML = ""; - } - } - - if (!document.getElementById('cpassword').value || - !document.getElementById('cpassword2').value || - pwok === 0) - en_change = 0; - - if (document.getElementById('showdel').checked) - document.getElementById('delete').style.display = "inline"; - else - document.getElementById('delete').style.display = "none"; - - document.getElementById('change').disabled = !en_change; - document.getElementById('cpassword').disabled = pwok === 0; - document.getElementById('cpassword2').disabled = pwok === 0; - document.getElementById('showdel').disabled = pwok === 0; - document.getElementById('delete').disabled = pwok === 0; - //document.getElementById('cemail').disabled = pwok === 0; - - /* - if (lwsgs_auth & 8) { - document.getElementById('cemail').style.display = "none"; - document.getElementById('cemail_name').style.display = "none"; - } else { - document.getElementById('cemail').style.display = "inline"; - document.getElementById('cemail_name').style.display = "inline"; - if (lwsgs_email_check === '0' && - document.getElementById('cemail').value != lwsgs_email) { - if (document.getElementById('cemail').value) - document.getElementById('cechk').innerHTML = "\u2713"; - else - document.getElementById('cechk').innerHTML = ""; - } else { - document.getElementById('cechk').innerHTML = "\u2718 Already registered"; - en_forgot = 1; - } - } */ - - if (lwsgs_auth & 8) - en_forgot = 0; - - if (en_forgot) - document.getElementById('cforgot').style.display = "inline"; - else - document.getElementById('cforgot').style.display = "none"; - - if (pwok === 0) - op = '0.5'; - else - op = '1.0'; - document.getElementById('cpassword').style.opacity = op; - document.getElementById('cpassword2').style.opacity = op; - // document.getElementById('cemail').style.opacity = op; - } - -function lwsgs_check_user() -{ - var xmlHttp = new XMLHttpRequest(); - xmlHttp.onreadystatechange = function() { - if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { - lwsgs_user_check = xmlHttp.responseText; - lwsgs_rupdate(); - } - } - xmlHttp.open("GET", "lwsgs-check?username="+document.getElementById('rusername').value, true); - xmlHttp.send(null); -} - -function lwsgs_check_email(id) -{ - var xmlHttp = new XMLHttpRequest(); - xmlHttp.onreadystatechange = function() { - if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { - lwsgs_email_check = xmlHttp.responseText; - lwsgs_rupdate(); - } - } - xmlHttp.open("GET", "lwsgs-check?email="+document.getElementById(id).value, true); - xmlHttp.send(null); -} - -function rupdate_user() -{ - lwsgs_rupdate(); - lwsgs_check_user(); -} - -function rupdate_email() -{ - lwsgs_rupdate(); - lwsgs_check_email('email'); -} - -function cupdate_email() -{ - lwsgs_cupdate(); - lwsgs_check_email('cemail'); -} - - -function lwsgs_initial() -{ - document.getElementById('lwsgs').innerHTML = lwsgs_html; - - if (lwsgs_user) { - document.getElementById("curuser").innerHTML = - "currently logged in as " + lwsgs_san(lwsgs_user) + "
"; - - document.getElementById("ccuruser").innerHTML = - "Login settings for " + - lwsgs_san(lwsgs_user) + "
"; - } - - document.getElementById('username').oninput = lwsgs_update; - document.getElementById('username').onchange = lwsgs_update; - document.getElementById('password').oninput = lwsgs_update; - document.getElementById('password').onchange = lwsgs_update; - document.getElementById('doreg').onclick = lwsgs_open_registration; - document.getElementById('clink').onclick = lwsgs_select_change; - document.getElementById('cancel').onclick =lwsgs_cancel_registration; - document.getElementById('cancel2').onclick =lwsgs_cancel_registration; - document.getElementById('rpassword').oninput = lwsgs_rupdate; - document.getElementById('password2').oninput = lwsgs_rupdate; - document.getElementById('rusername').oninput = rupdate_user; - document.getElementById('email').oninput = rupdate_email; - document.getElementById('ccurpw').oninput = lwsgs_cupdate; - document.getElementById('cpassword').oninput = lwsgs_cupdate; - document.getElementById('cpassword2').oninput = lwsgs_cupdate; - - document.getElementById('showdel').onchange = lwsgs_cupdate; - - if (lwsgs_email) - document.getElementById('grav').innerHTML = - ""; - //if (lwsgs_email) - //document.getElementById('cemail').placeholder = lwsgs_email; - document.getElementById('cusername').value = lwsgs_user; - lwsgs_update(); - lwsgs_cupdate(); -} - -window.addEventListener("load", function() { - lwsgs_initial(); - document.getElementById("nolog").style.display = !!lwsgs_user ? "none" : "inline-block"; - document.getElementById("logged").style.display = !lwsgs_user ? "none" : "inline-block"; - - document.getElementById("msg").onkeyup = mupd; - document.getElementById("msg").onchange = mupd; - - var ws; - - function mb_format(s) - { - var r = "", n, wos = 0; - - for (n = 0; n < s.length; n++) { - if (s[n] == ' ') - wos = 0; - else { - wos++; - if (wos === 40) { - wos = 0; - r = r + ' '; - } - } - if (s[n] == '<') { - r = r + "<"; - continue; - } - if (s[n] == '\n') { - r = r + "
"; - continue; - } - - r = r + s[n]; - } - - return r; - } - - function add_div(n, m) - { - var q = document.getElementById(n); - var d = new Date(m.time * 1000); - - q.innerHTML = "
" + - "
" + - "" + lwsgs_san(m.username) + "
" + - "" + d.toDateString() + - "
" + d.toTimeString() + "

" + - "IP: " + lwsgs_san(m.ip) + - "
" + - mb_format(m.content) + - "

" + q.innerHTML; - } - - function get_appropriate_ws_url() - { - var pcol; - var u = document.URL; - - if (u.substring(0, 5) == "https") { - pcol = "wss://"; - u = u.substr(8); - } else { - pcol = "ws://"; - if (u.substring(0, 4) == "http") - u = u.substr(7); - } - u = u.split('/'); - - return pcol + u[0] + "/xxx"; - } - - if (lwsgs_user) { - ws = new WebSocket(get_appropriate_ws_url(), - "protocol-lws-messageboard"); - - try { - ws.onopen = function() { - document.getElementById("debug").textContent = "ws opened"; - } - ws.onmessage =function got_packet(msg) { - add_div("messages", JSON.parse(msg.data)); - } - ws.onclose = function(){ - } - } catch(exception) { - alert('

Error' + exception); - } - } - - function mupd() - { - document.getElementById("send").disabled = !document.getElementById("msg").value; - } -}, false); diff --git a/plugins/generic-sessions/assets/md5.min.js b/plugins/generic-sessions/assets/md5.min.js deleted file mode 100644 index 4bd9de1e..00000000 --- a/plugins/generic-sessions/assets/md5.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t),e=(n>>16)+(t>>16)+(r>>16);return e<<16|65535&r}function r(n,t){return n<>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<>>9<<4)+14]=r;var e,i,a,h,d,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t>5]|=(255&n.charCodeAt(t/8))<16&&(o=i(o,8*n.length)),r=0;16>r;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="0123456789abcdef",o="";for(r=0;r>>4&15)+e.charAt(15&t);return o}function v(n){return unescape(encodeURIComponent(n))}function m(n){return d(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this); -//# sourceMappingURL=md5.min.js.map \ No newline at end of file diff --git a/plugins/generic-sessions/assets/post-forgot-fail.html b/plugins/generic-sessions/assets/post-forgot-fail.html deleted file mode 100644 index ead3d13e..00000000 --- a/plugins/generic-sessions/assets/post-forgot-fail.html +++ /dev/null @@ -1,5 +0,0 @@ - -Sorry, something went wrong. - -Click here to continue. - diff --git a/plugins/generic-sessions/assets/post-forgot-ok.html b/plugins/generic-sessions/assets/post-forgot-ok.html deleted file mode 100644 index 3e8e9cf5..00000000 --- a/plugins/generic-sessions/assets/post-forgot-ok.html +++ /dev/null @@ -1,6 +0,0 @@ - -This is a one-time password recovery login. - -Please click here and click your username at the top to reset your password. - - diff --git a/plugins/generic-sessions/assets/post-register-fail.html b/plugins/generic-sessions/assets/post-register-fail.html deleted file mode 100644 index 063c3c50..00000000 --- a/plugins/generic-sessions/assets/post-register-fail.html +++ /dev/null @@ -1 +0,0 @@ -Registration failed, sorry diff --git a/plugins/generic-sessions/assets/post-register-ok.html b/plugins/generic-sessions/assets/post-register-ok.html deleted file mode 100644 index c00c3f3d..00000000 --- a/plugins/generic-sessions/assets/post-register-ok.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - -
- -
- Your registration as is accepted,
- you will receive an email shortly with instructions
- to verify and enable the account for normal use.

- The link is only valid for an hour, after that if it has
- not been verified your account will be deleted. -
- - - - diff --git a/plugins/generic-sessions/assets/post-verify-fail.html b/plugins/generic-sessions/assets/post-verify-fail.html deleted file mode 100644 index d1d89ca5..00000000 --- a/plugins/generic-sessions/assets/post-verify-fail.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - -
- -
- Sorry, the link was invalid. -
- - - diff --git a/plugins/generic-sessions/assets/post-verify-ok.html b/plugins/generic-sessions/assets/post-verify-ok.html deleted file mode 100644 index ae647fc5..00000000 --- a/plugins/generic-sessions/assets/post-verify-ok.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - -
- -
- Thanks for signing up, your registration as is verified.
-
- Click here to continue. -
- - - - diff --git a/plugins/generic-sessions/assets/seats.jpg b/plugins/generic-sessions/assets/seats.jpg deleted file mode 100644 index 5bed40d919872359f2fcc00a8430e7dcfabaab4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122754 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 diff --git a/plugins/generic-sessions/assets/sent-forgot-fail.html b/plugins/generic-sessions/assets/sent-forgot-fail.html deleted file mode 100644 index ead3d13e..00000000 --- a/plugins/generic-sessions/assets/sent-forgot-fail.html +++ /dev/null @@ -1,5 +0,0 @@ - -Sorry, something went wrong. - -Click here to continue. - diff --git a/plugins/generic-sessions/assets/sent-forgot-ok.html b/plugins/generic-sessions/assets/sent-forgot-ok.html deleted file mode 100644 index 83df7510..00000000 --- a/plugins/generic-sessions/assets/sent-forgot-ok.html +++ /dev/null @@ -1,4 +0,0 @@ -An email has been sent to your registered address. - -Please follow the instructions to reset your password. - diff --git a/plugins/generic-sessions/assets/successful-login.html b/plugins/generic-sessions/assets/successful-login.html deleted file mode 100644 index dfc25cf7..00000000 --- a/plugins/generic-sessions/assets/successful-login.html +++ /dev/null @@ -1,4 +0,0 @@ - -This is an example destination that will appear after successful non-Admin login - - diff --git a/plugins/generic-sessions/handlers.c b/plugins/generic-sessions/handlers.c deleted file mode 100644 index 60484124..00000000 --- a/plugins/generic-sessions/handlers.c +++ /dev/null @@ -1,663 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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 "private-lwsgs.h" - -#if defined(LWS_WITH_SMTP) - -static int -lwsgs_smtp_client_done(struct lws_smtp_email *e, void *buf, size_t len) -{ - free(e); - - return 0; -} - -static int -lwsgs_smtp_client_done_sentvfy(struct lws_smtp_email *e, void *buf, size_t len) -{ - struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)e->data; - const char *username = (const char *)e->extra; - char s[200], esc[96]; - - lwsl_notice("%s: registration email sent: %s\n", __func__, username); - - /* mark the user as having sent the verification email */ - lws_snprintf(s, sizeof(s) - 1, - "update users set verified=1 where username='%s' and verified==0;", - lws_sql_purify(esc, username, sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("%s: Unable to update user: %s\n", __func__, - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - free(e); - - return 0; -} -#endif - -/* handle account confirmation links */ - -int -lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss) -{ - char cookie[1024], s[256], esc[90]; - struct lws_gs_event_args a; - struct lwsgs_user u; - - if (lws_hdr_copy_fragment(wsi, cookie, sizeof(cookie), - WSI_TOKEN_HTTP_URI_ARGS, 0) < 0) { - lwsl_err("%s: missing URI_ARGS\n", __func__); - goto verf_fail; - } - - if (strncmp(cookie, "token=", 6)) { - lwsl_err("%s: missing URI_ARGS token=\n", __func__); - goto verf_fail; - } - - u.username[0] = '\0'; - u.verified = -1; - lws_snprintf(s, sizeof(s) - 1, - "select username,email,verified from users where token = '%s';", - lws_sql_purify(esc, &cookie[6], sizeof(esc) - 1)); - puts(s); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - goto verf_fail; - } - - if (!u.username[0] || u.verified != 1) { - lwsl_notice("verify token %s doesn't map to unverified user (user='%s', verified=%d)\n", - &cookie[6], u.username, u.verified); - goto verf_fail; - } - - lwsl_notice("Verifying %s\n", u.username); - lws_snprintf(s, sizeof(s) - 1, - "update users set verified=%d where username='%s';", - LWSGS_VERIFIED_ACCEPTED, - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - - goto verf_fail; - } - - lwsl_notice("deleting account\n"); - - a.event = LWSGSE_CREATED; - a.username = u.username; - a.email = u.email; - lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi), - LWS_CALLBACK_GS_EVENT, &a, 0); - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s/post-verify-ok.html", vhd->email_confirm_url); - - pss->login_expires = lws_now_secs() + vhd->timeout_absolute_secs; - - pss->delete_session.id[0] = '\0'; - lwsgs_get_sid_from_wsi(wsi, &pss->delete_session); - - /* we need to create a new, authorized session */ - - if (lwsgs_new_session_id(vhd, &pss->login_session, u.username, - pss->login_expires)) - goto verf_fail; - - lwsl_notice("Creating new session: %s, redir to %s\n", - pss->login_session.id, pss->onward); - - return 0; - -verf_fail: - pss->delete_session.id[0] = '\0'; - lwsgs_get_sid_from_wsi(wsi, &pss->delete_session); - pss->login_expires = 0; - - lws_snprintf(pss->onward, sizeof(pss->onward), "%s/post-verify-fail.html", - vhd->email_confirm_url); - - return 1; -} - -/* handle forgot password confirmation links */ - -int -lwsgs_handler_forgot(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss) -{ - char cookie[1024], s[256], esc[96]; - struct lwsgs_user u; - const char *a; - - a = lws_get_urlarg_by_name(wsi, "token=", cookie, sizeof(cookie)); - if (!a) - goto forgot_fail; - - u.username[0] = '\0'; - lws_snprintf(s, sizeof(s) - 1, - "select username,verified from users where verified=%d and " - "token = '%s' and token_time != 0;", - LWSGS_VERIFIED_ACCEPTED, - lws_sql_purify(esc, &cookie[6], sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - - goto forgot_fail; - } - - if (!u.username[0]) { - puts(s); - lwsl_notice("forgot token doesn't map to verified user\n"); - goto forgot_fail; - } - - /* mark user as having validated forgot flow just now */ - - lws_snprintf(s, sizeof(s) - 1, - "update users set token_time=0,last_forgot_validated=%lu " - "where username='%s';", - (unsigned long)lws_now_secs(), - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - goto forgot_fail; - } - - a = lws_get_urlarg_by_name(wsi, "good=", cookie, sizeof(cookie)); - if (!a) - a = "broken-forget-post-good-url"; - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s/%s", vhd->email_confirm_url, a); - - pss->login_expires = lws_now_secs() + vhd->timeout_absolute_secs; - - pss->delete_session.id[0] = '\0'; - lwsgs_get_sid_from_wsi(wsi, &pss->delete_session); - - /* we need to create a new, authorized session */ - if (lwsgs_new_session_id(vhd, &pss->login_session, - u.username, - pss->login_expires)) - goto forgot_fail; - - lwsl_notice("Creating new session: %s, redir to %s\n", - pss->login_session.id, pss->onward); - - return 0; - -forgot_fail: - pss->delete_session.id[0] = '\0'; - lwsgs_get_sid_from_wsi(wsi, &pss->delete_session); - pss->login_expires = 0; - - a = lws_get_urlarg_by_name(wsi, "bad=", cookie, sizeof(cookie)); - if (!a) - a = "broken-forget-post-bad-url"; - - lws_snprintf(pss->onward, sizeof(pss->onward), "%s/%s", - vhd->email_confirm_url, a); - - return 1; -} - -/* support dynamic username / email checking */ - -int -lwsgs_handler_check(struct per_vhost_data__gs *vhd, - struct lws *wsi, struct per_session_data__gs *pss, - const char *in) -{ - static const char * const colname[] = { "username", "email" }; - char s[256], esc[96], *pc; - unsigned char *p, *start, *end, buffer[LWS_PRE + 1024]; - struct lwsgs_user u; - int n; - - /* - * either /check/email=xxx@yyy or: /check/username=xxx - * returns '0' if not already registered, else '1' - */ - - u.username[0] = '\0'; - - n = !strncmp(in, "email=", 6); - pc = strchr(in, '='); - if (!pc) { - lwsl_notice("cookie has no =\n"); - goto reply; - } - pc++; - - /* admin user cannot be registered in user db */ - if (!strcmp(vhd->admin_user, pc)) { - u.username[0] = 'a'; - goto reply; - } - - lws_snprintf(s, sizeof(s) - 1, - "select username, email from users where %s = '%s';", - colname[n], lws_sql_purify(esc, pc, sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - goto reply; - } - -reply: - s[0] = '0' + !!u.username[0]; - p = buffer + LWS_PRE; - start = p; - end = p + sizeof(buffer) - LWS_PRE; - - if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) - return -1; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"text/plain", 10, - &p, end)) - return -1; - - if (lws_add_http_header_content_length(wsi, 1, &p, end)) - return -1; - - if (lws_finalize_http_header(wsi, &p, end)) - return -1; - - n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS); - if (n != (p - start)) { - lwsl_err("_write returned %d from %ld\n", n, (long)(p - start)); - return -1; - } - - pss->check_response_value = s[0]; - pss->check_response = 1; - - lws_callback_on_writable(wsi); - - return 0; -} - -/* handle forgot password confirmation links */ - -int -lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss) -{ - char s[256], esc[96], username[96]; - struct lwsgs_user u; - lwsgw_hash sid; - int n = 0; - - /* see if he's logged in */ - username[0] = '\0'; - if (!lwsgs_get_sid_from_wsi(wsi, &sid)) { - u.username[0] = '\0'; - if (!lwsgs_lookup_session(vhd, &sid, username, sizeof(username))) { - n = 1; /* yes, logged in */ - if (lwsgs_lookup_user(vhd, username, &u)) - return 1; - - /* did a forgot pw ? */ - if (u.last_forgot_validated > (time_t)lws_now_secs() - 300) { - n |= LWSGS_AUTH_FORGOT_FLOW; - lwsl_debug("within forgot password flow\n"); - } - } - } - - lwsl_debug("auth value %d\n", n); - - /* if he just did forgot pw flow, don't need old pw */ - if ((n & (LWSGS_AUTH_FORGOT_FLOW | 1)) != (LWSGS_AUTH_FORGOT_FLOW | 1)) { - /* otherwise user:pass must be right */ - lwsl_debug("checking pw\n"); - if (lwsgs_check_credentials(vhd, - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_CURPW))) { - lwsl_notice("credentials bad\n"); - return 1; - } - - lwsl_debug("current pw checks out\n"); - - lws_strncpy(u.username, lws_spa_get_string(pss->spa, FGS_USERNAME), - sizeof(u.username)); - } - - /* does he want to delete his account? */ - - if (lws_spa_get_length(pss->spa, FGS_DELETE)) { - struct lws_gs_event_args a; - - lwsl_notice("deleting account\n"); - - a.event = LWSGSE_DELETED; - a.username = u.username; - a.email = ""; - lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi), - LWS_CALLBACK_GS_EVENT, &a, 0); - - lws_snprintf(s, sizeof(s) - 1, - "delete from users where username='%s';" - "delete from sessions where username='%s';", - lws_sql_purify(esc, u.username, sizeof(esc) - 1), - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - goto sql; - } - - if (lwsgs_hash_password(vhd, lws_spa_get_string(pss->spa, FGS_PASSWORD), &u)) - return 1; - - lwsl_notice("updating password hash\n"); - - lws_snprintf(s, sizeof(s) - 1, - "update users set pwhash='%s', pwsalt='%s', " - "last_forgot_validated=0 where username='%s';", - u.pwhash.id, u.pwsalt.id, - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - -sql: - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to update pw hash: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - return 0; -} - -int -lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd, - struct lws *wsi, struct per_session_data__gs *pss) -{ - char esc[96], esc1[96], esc2[96], esc3[96], esc4[96]; - char s[LWSGS_EMAIL_CONTENT_SIZE]; - unsigned char sid_rand[32]; -#if defined(LWS_WITH_SMTP) - lws_smtp_email_t *em; -#endif - struct lwsgs_user u; - lwsgw_hash hash; - int n; - - lwsl_notice("FORGOT %s %s\n", - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_EMAIL)); - - if (!lws_spa_get_string(pss->spa, FGS_USERNAME) && - !lws_spa_get_string(pss->spa, FGS_EMAIL)) { - lwsl_err("Form must provide either " - "username or email\n"); - return -1; - } - - if (!lws_spa_get_string(pss->spa, FGS_FORGOT_GOOD) || - !lws_spa_get_string(pss->spa, FGS_FORGOT_BAD) || - !lws_spa_get_string(pss->spa, FGS_FORGOT_POST_GOOD) || - !lws_spa_get_string(pss->spa, FGS_FORGOT_POST_BAD)) { - lwsl_err("Form must provide reg-good " - "and reg-bad (and post-*)" - "targets\n"); - return -1; - } - - u.username[0] = '\0'; - if (lws_spa_get_string(pss->spa, FGS_USERNAME)) - lws_snprintf(s, sizeof(s) - 1, - "select username,email " - "from users where username = '%s';", - lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_USERNAME), - sizeof(esc) - 1)); - else - lws_snprintf(s, sizeof(s) - 1, - "select username,email " - "from users where email = '%s';", - lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - if (!u.username[0]) { - lwsl_err("No match found %s\n", s); - return 1; - } - - lws_get_peer_simple(wsi, pss->ip, sizeof(pss->ip)); - if (lws_get_random(vhd->context, sid_rand, - sizeof(sid_rand)) != - sizeof(sid_rand)) { - lwsl_err("Problem getting random for token\n"); - return 1; - } - sha256_to_lwsgw_hash(sid_rand, &hash); - - lws_snprintf(s, sizeof(s) - 1, - "update users set token='%s',token_time='%ld' where username='%s';", - hash.id, (long)lws_now_secs(), - lws_sql_purify(esc, u.username, sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != - SQLITE_OK) { - lwsl_err("Unable to set token: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - n = lws_snprintf(s, sizeof(s), - "From: Forgot Password Assistant Noreply <%s>\n" - "To: %s <%s>\n" - "Subject: Password reset request\n" - "\n" - "Hello, %s\n\n" - "We received a password reset request from IP %s for this email,\n" - "to confirm you want to do that, please click the link below.\n\n", - lws_sql_purify(esc, vhd->email_from, sizeof(esc) - 1), - lws_sql_purify(esc1, u.username, sizeof(esc1) - 1), - lws_sql_purify(esc2, u.email, sizeof(esc2) - 1), - lws_sql_purify(esc3, u.username, sizeof(esc3) - 1), - lws_sql_purify(esc4, pss->ip, sizeof(esc4) - 1)); - lws_snprintf(s + n, sizeof(s) - n, - "%s/lwsgs-forgot?token=%s" - "&good=%s" - "&bad=%s\n\n" - "If this request is unexpected, please ignore it and\n" - "no further action will be taken.\n\n" - "If you have any questions or concerns about this\n" - "automated email, you can contact a real person at\n" - "%s.\n" - "\n.\n", - vhd->email_confirm_url, hash.id, - lws_urlencode(esc1, - lws_spa_get_string(pss->spa, FGS_FORGOT_POST_GOOD), - sizeof(esc1) - 1), - lws_urlencode(esc3, - lws_spa_get_string(pss->spa, FGS_FORGOT_POST_BAD), - sizeof(esc3) - 1), - vhd->email_contact_person); - - puts(s); -#if defined(LWS_WITH_SMTP) - - em = lws_smtpc_alloc_email_helper(s, n, vhd->email_from, u.email, - u.username, strlen(u.username), - vhd, lwsgs_smtp_client_done); - if (!em) - return 1; - if (lws_smtpc_add_email(vhd->smtp_client, em)) - return 1; -#endif - return 0; -} - -int -lwsgs_handler_register_form(struct per_vhost_data__gs *vhd, - struct lws *wsi, - struct per_session_data__gs *pss) -{ - unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE]; - char esc[96], esc1[96], esc2[96], esc3[96], esc4[96]; - char s[LWSGS_EMAIL_CONTENT_SIZE]; - unsigned char sid_rand[32]; -#if defined(LWS_WITH_SMTP) - lws_smtp_email_t *em; -#endif - struct lwsgs_user u; - lwsgw_hash hash; - size_t n; - - lwsl_notice("REGISTER %s %s %s\n", - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD), - lws_spa_get_string(pss->spa, FGS_EMAIL)); - if (lwsgs_get_sid_from_wsi(wsi, - &pss->login_session)) - return 1; - - lws_get_peer_simple(wsi, pss->ip, sizeof(pss->ip)); - lwsl_notice("IP=%s\n", pss->ip); - - if (!lws_spa_get_string(pss->spa, FGS_REG_GOOD) || - !lws_spa_get_string(pss->spa, FGS_REG_BAD)) { - lwsl_info("Form must provide reg-good and reg-bad targets\n"); - return -1; - } - - /* admin user cannot be registered in user db */ - if (!strcmp(vhd->admin_user, - lws_spa_get_string(pss->spa, FGS_USERNAME))) - return 1; - - if (!lwsgs_lookup_user(vhd, - lws_spa_get_string(pss->spa, FGS_USERNAME), &u)) { - lwsl_notice("user %s already registered\n", - lws_spa_get_string(pss->spa, FGS_USERNAME)); - return 1; - } - - u.username[0] = '\0'; - lws_snprintf(s, sizeof(s) - 1, "select username, email from users where email = '%s';", - lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_EMAIL), - sizeof(esc) - 1)); - - if (sqlite3_exec(vhd->pdb, s, - lwsgs_lookup_callback_user, &u, NULL) != SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - if (u.username[0]) { - lwsl_notice("email %s already in use\n", - lws_spa_get_string(pss->spa, FGS_USERNAME)); - return 1; - } - - if (lwsgs_hash_password(vhd, lws_spa_get_string(pss->spa, FGS_PASSWORD), - &u)) { - lwsl_err("Password hash failed\n"); - return 1; - } - - if (lws_get_random(vhd->context, sid_rand, sizeof(sid_rand)) != - sizeof(sid_rand)) { - lwsl_err("Problem getting random for token\n"); - return 1; - } - sha256_to_lwsgw_hash(sid_rand, &hash); - - lws_snprintf((char *)buffer, sizeof(buffer) - 1, - "insert into users(username," - " creation_time, ip, email, verified," - " pwhash, pwsalt, token, last_forgot_validated)" - " values ('%s', %lu, '%s', '%s', 0," - " '%s', '%s', '%s', 0);", - lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc) - 1), - (unsigned long)lws_now_secs(), - lws_sql_purify(esc1, pss->ip, sizeof(esc1) - 1), - lws_sql_purify(esc2, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc2) - 1), - u.pwhash.id, u.pwsalt.id, hash.id); - - if (sqlite3_exec(vhd->pdb, (char *)buffer, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to insert user: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - n = lws_snprintf(s, sizeof(s), - "From: Noreply <%s>\n" - "To: %s <%s>\n" - "Subject: Registration verification\n" - "\n" - "Hello, %s\n\n" - "We received a registration from IP %s using this email,\n" - "to confirm it is legitimate, please click the link below.\n\n" - "%s/lwsgs-confirm?token=%s\n\n" - "If this request is unexpected, please ignore it and\n" - "no further action will be taken.\n\n" - "If you have any questions or concerns about this\n" - "automated email, you can contact a real person at\n" - "%s.\n" - "\n.\n", - lws_sql_purify(esc, vhd->email_from, sizeof(esc) - 1), - lws_sql_purify(esc1, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc1) - 1), - lws_sql_purify(esc2, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc2) - 1), - lws_sql_purify(esc3, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc3) - 1), - lws_sql_purify(esc4, pss->ip, sizeof(esc4) - 1), - vhd->email_confirm_url, hash.id, - vhd->email_contact_person); - -#if defined(LWS_WITH_SMTP) - em = lws_smtpc_alloc_email_helper(s, n, vhd->email_from, - lws_spa_get_string(pss->spa, FGS_EMAIL), - lws_spa_get_string(pss->spa, FGS_USERNAME), - strlen(lws_spa_get_string(pss->spa, FGS_USERNAME)), - vhd, lwsgs_smtp_client_done_sentvfy); - if (!em) - return 1; - - if (lws_smtpc_add_email(vhd->smtp_client, em)) - return 1; -#else - (void)n; -#endif - - return 0; -} diff --git a/plugins/generic-sessions/private-lwsgs.h b/plugins/generic-sessions/private-lwsgs.h deleted file mode 100644 index 157679e7..00000000 --- a/plugins/generic-sessions/private-lwsgs.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - */ - -#define LWS_DLL -#define LWS_INTERNAL -#include - -#include -#include - -#define LWSGS_VERIFIED_ACCEPTED 100 - -enum { - FGS_USERNAME, - FGS_PASSWORD, - FGS_PASSWORD2, - FGS_EMAIL, - FGS_REGISTER, - FGS_GOOD, - FGS_BAD, - FGS_REG_GOOD, - FGS_REG_BAD, - FGS_ADMIN, - FGS_FORGOT, - FGS_FORGOT_GOOD, - FGS_FORGOT_BAD, - FGS_FORGOT_POST_GOOD, - FGS_FORGOT_POST_BAD, - FGS_CHANGE, - FGS_CURPW, - FGS_DELETE, -}; - -struct lwsgs_user { - char username[32]; - char ip[16]; - lwsgw_hash pwhash; - lwsgw_hash pwsalt; - lwsgw_hash token; - time_t created; - time_t last_forgot_validated; - char email[100]; - int verified; -}; - -struct per_vhost_data__gs { - lws_abs_t *smtp_client; - struct lwsgs_user u; - lws_token_map_t transport_tokens[3]; - lws_token_map_t protocol_tokens[2]; - char helo[64], ip[64]; - struct lws_context *context; - char session_db[256]; - char admin_user[32]; - char urlroot[48]; - char confounder[32]; - char email_contact_person[128]; - char email_title[128]; - char email_template[128]; - char email_confirm_url[128]; - char email_from[128]; - lwsgw_hash admin_password_sha256; - sqlite3 *pdb; - int timeout_idle_secs; - int timeout_absolute_secs; - int timeout_anon_absolute_secs; - int timeout_email_secs; - time_t last_session_expire; -}; - -struct per_session_data__gs { - struct lws_spa *spa; - lwsgw_hash login_session; - lwsgw_hash delete_session; - unsigned int login_expires; - char onward[256]; - char result[500 + LWS_PRE]; - char urldec[500 + LWS_PRE]; - int result_len; - char ip[46]; - struct lws_process_html_state phs; - int spos; - char check_response_value; - - unsigned int logging_out:1; - unsigned int check_response:1; -}; - -/* utils.c */ - -int -lwsgs_lookup_callback_user(void *priv, int cols, char **col_val, - char **col_name); -void -lwsgw_cookie_from_session(lwsgw_hash *sid, time_t expires, char **p, char *end); -int -lwsgs_get_sid_from_wsi(struct lws *wsi, lwsgw_hash *sid); -int -lwsgs_lookup_session(struct per_vhost_data__gs *vhd, - const lwsgw_hash *sid, char *username, int len); -int -lwsgs_get_auth_level(struct per_vhost_data__gs *vhd, - const char *username); -int -lwsgs_check_credentials(struct per_vhost_data__gs *vhd, - const char *username, const char *password); -void -sha256_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash); -unsigned int -lwsgs_now_secs(void); -int -lwsgw_check_admin(struct per_vhost_data__gs *vhd, - const char *username, const char *password); -int -lwsgs_hash_password(struct per_vhost_data__gs *vhd, - const char *password, struct lwsgs_user *u); -int -lwsgs_new_session_id(struct per_vhost_data__gs *vhd, - lwsgw_hash *sid, const char *username, int exp); -int -lwsgs_lookup_user(struct per_vhost_data__gs *vhd, - const char *username, struct lwsgs_user *u); -int -lwsgw_update_session(struct per_vhost_data__gs *vhd, - lwsgw_hash *hash, const char *user); -int -lwsgw_expire_old_sessions(struct per_vhost_data__gs *vhd); - - -/* handlers.c */ - -int -lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); -int -lwsgs_handler_forgot(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); -int -lwsgs_handler_check(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss, const char *in); -int -lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); -int -lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); -int -lwsgs_handler_register_form(struct per_vhost_data__gs *vhd, struct lws *wsi, - struct per_session_data__gs *pss); - diff --git a/plugins/generic-sessions/protocol_generic_sessions.c b/plugins/generic-sessions/protocol_generic_sessions.c deleted file mode 100644 index 7622187d..00000000 --- a/plugins/generic-sessions/protocol_generic_sessions.c +++ /dev/null @@ -1,920 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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 "private-lwsgs.h" -#include - -/* keep changes in sync with the enum in lwsgs.h */ -static const char * const param_names[] = { - "username", - "password", - "password2", - "email", - "register", - "good", - "bad", - "reg-good", - "reg-bad", - "admin", - "forgot", - "forgot-good", - "forgot-bad", - "forgot-post-good", - "forgot-post-bad", - "change", - "curpw", - "delete" -}; - -struct lwsgs_fill_args { - char *buf; - int len; -}; - -static const struct lws_protocols protocols[]; - -struct lwsgs_subst_args -{ - struct per_session_data__gs *pss; - struct per_vhost_data__gs *vhd; - struct lws *wsi; -}; - -static const char * -lwsgs_subst(void *data, int index) -{ - struct lwsgs_subst_args *a = (struct lwsgs_subst_args *)data; - struct lwsgs_user u; - lwsgw_hash sid; - char esc[96], s[100]; - int n; - - a->pss->result[0] = '\0'; - u.email[0] = '\0'; - if (!lwsgs_get_sid_from_wsi(a->wsi, &sid)) { - if (lwsgs_lookup_session(a->vhd, &sid, a->pss->result, 31)) { - lwsl_notice("sid lookup for %s failed\n", sid.id); - a->pss->delete_session = sid; - return NULL; - } - lws_snprintf(s, sizeof(s) - 1, "select username,email " - "from users where username = '%s';", - lws_sql_purify(esc, a->pss->result, sizeof(esc) - 1)); - if (sqlite3_exec(a->vhd->pdb, s, lwsgs_lookup_callback_user, - &u, NULL) != SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(a->vhd->pdb)); - a->pss->delete_session = sid; - return NULL; - } - } else - lwsl_notice("no sid\n"); - - lws_strncpy(a->pss->result + 32, u.email, 100); - - switch (index) { - case 0: - return a->pss->result; - - case 1: - n = lwsgs_get_auth_level(a->vhd, a->pss->result); - sprintf(a->pss->result, "%d", n); - return a->pss->result; - case 2: - return a->pss->result + 32; - } - - return NULL; -} - -static int -lws_get_effective_host(struct lws *wsi, char *buf, size_t buflen) -{ -#if defined(LWS_ROLE_H2) - /* h2 */ - if (lws_hdr_copy(wsi, buf, buflen - 1, - WSI_TOKEN_HTTP_COLON_AUTHORITY) > 0) - return 0; -#endif - /* h1 */ - if (lws_hdr_copy(wsi, buf, buflen - 1, WSI_TOKEN_HOST) > 0) - return 0; - - return 1; -} - -static int -callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__gs *pss = (struct per_session_data__gs *)user; - const struct lws_protocol_vhost_options *pvo; - struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), - lws_vhost_name_to_protocol(lws_get_vhost(wsi), - "protocol-generic-sessions")); - char cookie[1024], username[32], *pc = cookie; - unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE]; - struct lws_process_html_args *args = in; - struct lws_session_info *sinfo; - char s[LWSGS_EMAIL_CONTENT_SIZE]; - unsigned char *p, *start, *end; - const char *cp, *cp1; - sqlite3_stmt *sm; - lwsgw_hash sid; -#if defined(LWS_WITH_SMTP) - lws_abs_t abs; -#endif - int n; - - switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ - - vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), - lws_get_protocol(wsi), sizeof(struct per_vhost_data__gs)); - if (!vhd) - return 1; - vhd->context = lws_get_context(wsi); - - /* defaults */ - vhd->timeout_idle_secs = 600; - vhd->timeout_absolute_secs = 36000; - vhd->timeout_anon_absolute_secs = 1200; - vhd->timeout_email_secs = 24 * 3600; - - - strcpy(vhd->helo, "unconfigured.com"); - strcpy(vhd->ip, "127.0.0.1"); - strcpy(vhd->email_from, "noreply@unconfigured.com"); - strcpy(vhd->email_title, "Registration Email from unconfigured"); - vhd->urlroot[0] = '\0'; - - pvo = (const struct lws_protocol_vhost_options *)in; - while (pvo) { - if (!strcmp(pvo->name, "admin-user")) - lws_strncpy(vhd->admin_user, pvo->value, - sizeof(vhd->admin_user)); - if (!strcmp(pvo->name, "urlroot")) - lws_strncpy(vhd->urlroot, pvo->value, - sizeof(vhd->urlroot)); - if (!strcmp(pvo->name, "admin-password-sha256")) - lws_strncpy(vhd->admin_password_sha256.id, pvo->value, - sizeof(vhd->admin_password_sha256.id)); - if (!strcmp(pvo->name, "session-db")) - lws_strncpy(vhd->session_db, pvo->value, - sizeof(vhd->session_db)); - if (!strcmp(pvo->name, "confounder")) - lws_strncpy(vhd->confounder, pvo->value, - sizeof(vhd->confounder)); - if (!strcmp(pvo->name, "email-from")) - lws_strncpy(vhd->email_from, pvo->value, - sizeof(vhd->email_from)); - if (!strcmp(pvo->name, "email-helo")) - lws_strncpy(vhd->helo, pvo->value, sizeof(vhd->helo)); - if (!strcmp(pvo->name, "email-template")) - lws_strncpy(vhd->email_template, pvo->value, - sizeof(vhd->email_template)); - if (!strcmp(pvo->name, "email-title")) - lws_strncpy(vhd->email_title, pvo->value, - sizeof(vhd->email_title)); - if (!strcmp(pvo->name, "email-contact-person")) - lws_strncpy(vhd->email_contact_person, pvo->value, - sizeof(vhd->email_contact_person)); - if (!strcmp(pvo->name, "email-confirm-url-base")) - lws_strncpy(vhd->email_confirm_url, pvo->value, - sizeof(vhd->email_confirm_url)); - if (!strcmp(pvo->name, "email-server-ip")) - lws_strncpy(vhd->ip, pvo->value, sizeof(vhd->ip)); - - if (!strcmp(pvo->name, "timeout-idle-secs")) - vhd->timeout_idle_secs = atoi(pvo->value); - if (!strcmp(pvo->name, "timeout-absolute-secs")) - vhd->timeout_absolute_secs = atoi(pvo->value); - if (!strcmp(pvo->name, "timeout-anon-absolute-secs")) - vhd->timeout_anon_absolute_secs = atoi(pvo->value); - if (!strcmp(pvo->name, "email-expire")) - vhd->timeout_email_secs = atoi(pvo->value); - pvo = pvo->next; - } - if (!vhd->admin_user[0] || - !vhd->admin_password_sha256.id[0] || - !vhd->session_db[0]) { - lwsl_err("generic-sessions: " - "You must give \"admin-user\", " - "\"admin-password-sha256\", " - "and \"session_db\" per-vhost options\n"); - return 1; - } - - if (lws_struct_sq3_open(lws_get_context(wsi), - vhd->session_db, 1, &vhd->pdb)) { - lwsl_err("Unable to open session db %s: %s\n", - vhd->session_db, sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - if (sqlite3_prepare(vhd->pdb, - "create table if not exists sessions (" - " name char(65)," - " username varchar(32)," - " expire integer" - ");", - -1, &sm, NULL) != SQLITE_OK) { - lwsl_err("Unable to prepare session table init: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - if (sqlite3_step(sm) != SQLITE_DONE) { - lwsl_err("Unable to run session table init: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - sqlite3_finalize(sm); - - if (sqlite3_exec(vhd->pdb, - "create table if not exists users (" - " username varchar(32)," - " creation_time integer," - " ip varchar(46)," - " email varchar(100)," - " pwhash varchar(65)," - " pwsalt varchar(65)," - " pwchange_time integer," - " token varchar(65)," - " verified integer," - " token_time integer," - " last_forgot_validated integer," - " primary key (username)" - ");", - NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to create user table: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - -#if defined(LWS_WITH_SMTP) - - memset(&abs, 0, sizeof(abs)); - abs.vh = lws_get_vhost(wsi); - - /* select the protocol and bind its tokens */ - - abs.ap = lws_abs_protocol_get_by_name("smtp"); - if (!abs.ap) - return 1; - - vhd->protocol_tokens[0].name_index = LTMI_PSMTP_V_HELO; - vhd->protocol_tokens[0].u.value = vhd->helo; - - abs.ap_tokens = vhd->protocol_tokens; - - /* select the transport and bind its tokens */ - - abs.at = lws_abs_transport_get_by_name("raw_skt"); - if (!abs.at) - return 1; - - vhd->transport_tokens[0].name_index = LTMI_PEER_V_DNS_ADDRESS; - vhd->transport_tokens[0].u.value = vhd->ip; - vhd->transport_tokens[1].name_index = LTMI_PEER_LV_PORT; - vhd->transport_tokens[1].u.lvalue = 25; - - abs.at_tokens = vhd->transport_tokens; - - vhd->smtp_client = lws_abs_bind_and_create_instance(&abs); - if (!vhd->smtp_client) - return 1; - - lwsl_notice("%s: created SMTP client\n", __func__); -#endif - break; - - case LWS_CALLBACK_PROTOCOL_DESTROY: - // lwsl_notice("gs: LWS_CALLBACK_PROTOCOL_DESTROY: v=%p, ctx=%p\n", vhd, vhd->context); - if (vhd->pdb) { - sqlite3_close(vhd->pdb); - vhd->pdb = NULL; - } -#if defined(LWS_WITH_SMTP) - if (vhd->smtp_client) - lws_abs_destroy_instance(&vhd->smtp_client); -#endif - break; - - case LWS_CALLBACK_HTTP_WRITEABLE: - if (!pss->check_response) - break; - pss->check_response = 0; - n = lws_write(wsi, (unsigned char *)&pss->check_response_value, - 1, LWS_WRITE_HTTP | LWS_WRITE_H2_STREAM_END); - if (n != 1) - return -1; - goto try_to_reuse; - - case LWS_CALLBACK_HTTP: - if (!pss) { - lwsl_err("%s: no valid pss\n", __func__); - return 1; - } - - pss->login_session.id[0] = '\0'; - pss->phs.pos = 0; - - cp = in; - if ((*(const char *)in == '/')) - cp++; - - if (lws_get_effective_host(wsi, cookie, sizeof(cookie))) { - lwsl_err("%s: HTTP: no effective host\n", __func__); - return 1; - } - - lwsl_notice("LWS_CALLBACK_HTTP: %s, HOST '%s'\n", - (const char *)in, cookie); - - n = strlen(cp); - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, (const char *)in); - - if (n >= 12 && - !strcmp(cp + n - 12, "lwsgs-forgot")) { - lwsgs_handler_forgot(vhd, wsi, pss); - goto redirect_with_cookie; - } - - if (n >= 13 && - !strcmp(cp + n - 13, "lwsgs-confirm")) { - lwsgs_handler_confirm(vhd, wsi, pss); - goto redirect_with_cookie; - } - cp1 = strstr(cp, "lwsgs-check/"); - if (cp1) { - lwsgs_handler_check(vhd, wsi, pss, cp1 + 12); - /* second, async part will complete transaction */ - break; - } - - if (n >= 11 && cp && !strcmp(cp + n - 11, "lwsgs-login")) - break; - if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-logout")) - break; - if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-forgot")) - break; - if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-change")) - break; - - /* if no legitimate url for GET, return 404 */ - - lwsl_err("%s: http doing 404 on %s\n", __func__, cp ? cp : "null"); - lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL); - - return -1; - //goto try_to_reuse; - - case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: - args = (struct lws_process_html_args *)in; - if (!args->chunked) - break; - case LWS_CALLBACK_CHECK_ACCESS_RIGHTS: - n = 0; - username[0] = '\0'; - sid.id[0] = '\0'; - args = (struct lws_process_html_args *)in; - lwsl_notice("%s: LWS_CALLBACK_CHECK_ACCESS_RIGHTS: need 0x%x\n", - __func__, args->max_len); - if (!lwsgs_get_sid_from_wsi(wsi, &sid)) { - if (lwsgs_lookup_session(vhd, &sid, username, - sizeof(username))) { - - /* - * if we're authenticating for ws, we don't - * want to redirect it or gain a cookie on that, - * he'll need to get the cookie from http - * interactions outside of this. - */ - if (args->chunked) { - lwsl_notice("%s: ws auth failed\n", - __func__); - - return 1; - } - - lwsl_notice("session lookup for %s failed, " - "probably expired\n", sid.id); - pss->delete_session = sid; - args->final = 1; /* signal we dealt with it */ - lws_snprintf(pss->onward, sizeof(pss->onward) - 1, - "%s%s", vhd->urlroot, args->p); - lwsl_notice("redirecting to ourselves with " - "cookie refresh\n"); - /* we need a redirect to ourselves, - * session cookie is expired */ - goto redirect_with_cookie; - } - } else - lwsl_notice("%s: failed to get sid from wsi\n", __func__); - - n = lwsgs_get_auth_level(vhd, username); - lwsl_notice("%s: lwsgs_get_auth_level '%s' says %d\n", __func__, username, n); - - if ((args->max_len & n) != args->max_len) { - lwsl_notice("Access rights fail 0x%X vs 0x%X (cookie %s)\n", - args->max_len, n, sid.id); - return 1; - } - lwsl_debug("Access rights OK\n"); - break; - - case LWS_CALLBACK_SESSION_INFO: - { - struct lwsgs_user u; - sinfo = (struct lws_session_info *)in; - sinfo->username[0] = '\0'; - sinfo->email[0] = '\0'; - sinfo->ip[0] = '\0'; - sinfo->session[0] = '\0'; - sinfo->mask = 0; - - sid.id[0] = '\0'; - lwsl_debug("LWS_CALLBACK_SESSION_INFO\n"); - if (lwsgs_get_sid_from_wsi(wsi, &sid)) - break; - if (lwsgs_lookup_session(vhd, &sid, username, sizeof(username))) - break; - - lws_snprintf(s, sizeof(s) - 1, - "select username, email from users where username='%s';", - username); - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - break; - } - lws_strncpy(sinfo->username, u.username, sizeof(sinfo->username)); - lws_strncpy(sinfo->email, u.email, sizeof(sinfo->email)); - lws_strncpy(sinfo->session, sid.id, sizeof(sinfo->session)); - sinfo->mask = lwsgs_get_auth_level(vhd, username); - lws_get_peer_simple(wsi, sinfo->ip, sizeof(sinfo->ip)); - } - - break; - - case LWS_CALLBACK_PROCESS_HTML: - - args = (struct lws_process_html_args *)in; - { - static const char * const vars[] = { - "$lwsgs_user", - "$lwsgs_auth", - "$lwsgs_email" - }; - struct lwsgs_subst_args a; - - a.vhd = vhd; - a.pss = pss; - a.wsi = wsi; - - pss->phs.vars = vars; - pss->phs.count_vars = LWS_ARRAY_SIZE(vars); - pss->phs.replace = lwsgs_subst; - pss->phs.data = &a; - - if (lws_chunked_html_process(args, &pss->phs)) - return -1; - } - break; - - case LWS_CALLBACK_HTTP_BODY: - if (len < 2) { - lwsl_err("%s: HTTP_BODY: len %d < 2\n", __func__, (int)len); - break; - } - - if (!pss->spa) { - pss->spa = lws_spa_create(wsi, param_names, - LWS_ARRAY_SIZE(param_names), 1024, - NULL, NULL); - if (!pss->spa) - return -1; - } - - if (lws_spa_process(pss->spa, in, len)) { - lwsl_notice("spa process blew\n"); - return -1; - } - break; - - case LWS_CALLBACK_HTTP_BODY_COMPLETION: - - lwsl_debug("%s: LWS_CALLBACK_HTTP_BODY_COMPLETION\n", __func__); - - if (!pss->spa) - break; - - cp1 = (const char *)pss->onward; - if (*cp1 == '/') - cp1++; - - - lws_spa_finalize(pss->spa); - n = strlen(cp1); - - if (lws_get_effective_host(wsi, cookie, sizeof(cookie))) - return 1; - - if (!strcmp(cp1 + n - 12, "lwsgs-change")) { - if (!lwsgs_handler_change_password(vhd, wsi, pss)) { - cp = lws_spa_get_string(pss->spa, FGS_GOOD); - goto pass; - } - - cp = lws_spa_get_string(pss->spa, FGS_BAD); - lwsl_notice("user/password no good %s\n", - lws_spa_get_string(pss->spa, FGS_USERNAME)); - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, cp); - - pss->onward[sizeof(pss->onward) - 1] = '\0'; - goto completion_flow; - } - - if (!strcmp(cp1 + n - 11, "lwsgs-login")) { - lwsl_err("%s: lwsgs-login\n", __func__); - if (lws_spa_get_string(pss->spa, FGS_FORGOT) && - lws_spa_get_string(pss->spa, FGS_FORGOT)[0]) { - if (lwsgs_handler_forgot_pw_form(vhd, wsi, pss)) { - n = FGS_FORGOT_BAD; - goto reg_done; - } -#if defined(LWS_WITH_SMTP) - /* get the email monitor to take a look */ - lws_smtpc_kick(vhd->smtp_client); -#endif - n = FGS_FORGOT_GOOD; - goto reg_done; - } - - if (!lws_spa_get_string(pss->spa, FGS_USERNAME) || - !lws_spa_get_string(pss->spa, FGS_PASSWORD)) { - lwsl_notice("username '%s' or pw '%s' missing\n", - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD)); - return -1; - } - - if (lws_spa_get_string(pss->spa, FGS_REGISTER) && - lws_spa_get_string(pss->spa, FGS_REGISTER)[0]) { - - if (lwsgs_handler_register_form(vhd, wsi, pss)) - n = FGS_REG_BAD; - else { - n = FGS_REG_GOOD; -#if defined(LWS_WITH_SMTP) - /* get the email monitor to take a look */ - lws_smtpc_kick(vhd->smtp_client); -#endif - } -reg_done: - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, - lws_spa_get_string(pss->spa, n)); - - pss->login_expires = 0; - pss->logging_out = 1; - goto completion_flow; - } - - /* we have the username and password... check if admin */ - if (lwsgw_check_admin(vhd, lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD))) { - if (lws_spa_get_string(pss->spa, FGS_ADMIN)) - cp = lws_spa_get_string(pss->spa, FGS_ADMIN); - else - if (lws_spa_get_string(pss->spa, FGS_GOOD)) - cp = lws_spa_get_string(pss->spa, FGS_GOOD); - else { - lwsl_info("No admin or good target url in form\n"); - return -1; - } - lwsl_debug("admin\n"); - goto pass; - } - - /* check users in database */ - - if (!lwsgs_check_credentials(vhd, - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD))) { - lwsl_notice("pw hash check met\n"); - cp = lws_spa_get_string(pss->spa, FGS_GOOD); - goto pass; - } else - lwsl_notice("user/password no good %s %s\n", - lws_spa_get_string(pss->spa, FGS_USERNAME), - lws_spa_get_string(pss->spa, FGS_PASSWORD)); - - if (!lws_spa_get_string(pss->spa, FGS_BAD)) { - lwsl_info("No admin or good target url in form\n"); - return -1; - } - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, - lws_spa_get_string(pss->spa, FGS_BAD)); - - lwsl_notice("failed: %s\n", pss->onward); - - goto completion_flow; - } - - if (!strcmp(cp1 + n - 12, "lwsgs-logout")) { - - lwsl_notice("/logout\n"); - - if (lwsgs_get_sid_from_wsi(wsi, &pss->login_session)) { - lwsl_notice("not logged in...\n"); - return 1; - } - - /* - * We keep the same session, but mark it as not - * being associated to any authenticated user - */ - - lwsgw_update_session(vhd, &pss->login_session, ""); - - if (!lws_spa_get_string(pss->spa, FGS_GOOD)) { - lwsl_info("No admin or good target url in form\n"); - return -1; - } - - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, - lws_spa_get_string(pss->spa, FGS_GOOD)); - - pss->login_expires = 0; - pss->logging_out = 1; - - goto completion_flow; - } - - break; - -pass: - lws_snprintf(pss->onward, sizeof(pss->onward), - "%s%s", vhd->urlroot, cp); - - if (lwsgs_get_sid_from_wsi(wsi, &sid)) - sid.id[0] = '\0'; - - pss->login_expires = lws_now_secs() + - vhd->timeout_absolute_secs; - - if (!sid.id[0]) { - /* we need to create a new, authorized session */ - - if (lwsgs_new_session_id(vhd, &pss->login_session, - lws_spa_get_string(pss->spa, FGS_USERNAME), - pss->login_expires)) - goto try_to_reuse; - - lwsl_notice("%s: Creating new session: %s\n", __func__, - pss->login_session.id); - } else { - /* - * we can just update the existing session to be - * authorized - */ - lwsl_notice("%s: Authorizing existing session %s, name %s\n", - __func__, sid.id, - lws_spa_get_string(pss->spa, FGS_USERNAME)); - lwsgw_update_session(vhd, &sid, - lws_spa_get_string(pss->spa, FGS_USERNAME)); - pss->login_session = sid; - } - -completion_flow: - lwsgw_expire_old_sessions(vhd); - goto redirect_with_cookie; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - if (pss && pss->spa) { - lws_spa_destroy(pss->spa); - pss->spa = NULL; - } - break; - - case LWS_CALLBACK_ADD_HEADERS: - lwsgw_expire_old_sessions(vhd); - - lwsl_warn("ADD_HEADERS\n"); - - args = (struct lws_process_html_args *)in; - if (!pss) - return 1; - if (pss->delete_session.id[0]) { - pc = cookie; - lwsgw_cookie_from_session(&pss->delete_session, 0, &pc, - cookie + sizeof(cookie) - 1); - - lwsl_notice("deleting cookie '%s'\n", cookie); - - if (lws_add_http_header_by_name(wsi, - (unsigned char *)"set-cookie:", - (unsigned char *)cookie, pc - cookie, - (unsigned char **)&args->p, - (unsigned char *)args->p + args->max_len)) - return 1; - } - - if (!pss->login_session.id[0]) - lwsgs_get_sid_from_wsi(wsi, &pss->login_session); - - if (!pss->login_session.id[0] && !pss->logging_out) { - - pss->login_expires = lws_now_secs() + - vhd->timeout_anon_absolute_secs; - if (lwsgs_new_session_id(vhd, &pss->login_session, "", - pss->login_expires)) - goto try_to_reuse; - pc = cookie; - lwsgw_cookie_from_session(&pss->login_session, - pss->login_expires, &pc, - cookie + sizeof(cookie) - 1); - - lwsl_info("LWS_CALLBACK_ADD_HEADERS: setting cookie '%s'\n", cookie); - if (lws_add_http_header_by_name(wsi, - (unsigned char *)"set-cookie:", - (unsigned char *)cookie, pc - cookie, - (unsigned char **)&args->p, - (unsigned char *)args->p + args->max_len)) - return 1; - } - break; - - default: - break; - } - - return 0; - -redirect_with_cookie: - p = buffer + LWS_PRE; - start = p; - end = p + sizeof(buffer) - LWS_PRE; - - lwsl_warn("%s: redirect_with_cookie\n", __func__); - - if (lws_add_http_header_status(wsi, HTTP_STATUS_SEE_OTHER, &p, end)) - return 1; - - { - char loc[1024], uria[128]; - - uria[0] = '\0'; - lws_hdr_copy_fragment(wsi, uria, sizeof(uria), - WSI_TOKEN_HTTP_URI_ARGS, 0); - n = lws_snprintf(loc, sizeof(loc), "%s?%s", - pss->onward, uria); - lwsl_notice("%s: redirect to '%s'\n", __func__, loc); - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION, - (unsigned char *)loc, n, &p, end)) - return 1; - } - - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"text/html", 9, &p, end)) - return 1; - if (lws_add_http_header_content_length(wsi, 0, &p, end)) - return 1; - - if (pss->delete_session.id[0]) { - lwsgw_cookie_from_session(&pss->delete_session, 0, &pc, - cookie + sizeof(cookie) - 1); - - lwsl_notice("deleting cookie '%s'\n", cookie); - - if (lws_add_http_header_by_name(wsi, - (unsigned char *)"set-cookie:", - (unsigned char *)cookie, pc - cookie, - &p, end)) { - lwsl_err("fail0\n"); - return 1; - } - } - - if (!pss->login_session.id[0]) { - pss->login_expires = lws_now_secs() + - vhd->timeout_anon_absolute_secs; - if (lwsgs_new_session_id(vhd, &pss->login_session, "", - pss->login_expires)) { - lwsl_err("fail1\n"); - return 1; - } - } else - pss->login_expires = lws_now_secs() + - vhd->timeout_absolute_secs; - - if (pss->login_session.id[0] || pss->logging_out) { - /* - * we succeeded to login, we must issue a login - * cookie with the prepared data - */ - pc = cookie; - - lwsgw_cookie_from_session(&pss->login_session, - pss->login_expires, &pc, - cookie + sizeof(cookie) - 1); - - lwsl_err("%s: setting cookie '%s'\n", __func__, cookie); - - pss->logging_out = 0; - - if (lws_add_http_header_by_name(wsi, - (unsigned char *)"set-cookie:", - (unsigned char *)cookie, pc - cookie, - &p, end)) { - lwsl_err("fail2\n"); - return 1; - } - } - - if (lws_finalize_http_header(wsi, &p, end)) - return 1; - - // lwsl_hexdump_notice(start, p - start); - - n = lws_write(wsi, start, p - start, LWS_WRITE_H2_STREAM_END | - LWS_WRITE_HTTP_HEADERS); - if (n < 0) - return 1; - - /* fallthru */ - -try_to_reuse: - if (lws_http_transaction_completed(wsi)) - return -1; - - return 0; -} - -static const struct lws_protocols protocols[] = { - { - "protocol-generic-sessions", - callback_generic_sessions, - sizeof(struct per_session_data__gs), - 1024, - }, -}; - -LWS_VISIBLE int -init_protocol_generic_sessions(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_generic_sessions(struct lws_context *context) -{ - return 0; -} diff --git a/plugins/generic-sessions/protocol_lws_messageboard.c b/plugins/generic-sessions/protocol_lws_messageboard.c deleted file mode 100644 index 94c01ab8..00000000 --- a/plugins/generic-sessions/protocol_lws_messageboard.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - */ - - -#define LWS_DLL -#define LWS_INTERNAL -#include - -#include -#include -#include - -struct per_vhost_data__gs_mb { - struct lws_vhost *vh; - const struct lws_protocols *gsp; - sqlite3 *pdb; - char message_db[256]; - unsigned long last_idx; -}; - -struct per_session_data__gs_mb { - void *pss_gs; /* for use by generic-sessions */ - struct lws_session_info sinfo; - struct lws_spa *spa; - unsigned long last_idx; - unsigned int our_form:1; - char second_http_part; -}; - -static const char * const param_names[] = { - "send", - "msg", -}; -enum { - MBSPA_SUBMIT, - MBSPA_MSG, -}; - -#define MAX_MSG_LEN 512 - -struct message { - unsigned long idx; - unsigned long time; - char username[32]; - char email[100]; - char ip[72]; - char content[MAX_MSG_LEN]; -}; - -static int -lookup_cb(void *priv, int cols, char **col_val, char **col_name) -{ - struct message *m = (struct message *)priv; - int n; - - for (n = 0; n < cols; n++) { - - if (!strcmp(col_name[n], "idx") || - !strcmp(col_name[n], "MAX(idx)")) { - if (!col_val[n]) - m->idx = 0; - else - m->idx = atol(col_val[n]); - continue; - } - if (!strcmp(col_name[n], "time")) { - m->time = atol(col_val[n]); - continue; - } - if (!strcmp(col_name[n], "username")) { - lws_strncpy(m->username, col_val[n], sizeof(m->username)); - continue; - } - if (!strcmp(col_name[n], "email")) { - lws_strncpy(m->email, col_val[n], sizeof(m->email)); - continue; - } - if (!strcmp(col_name[n], "ip")) { - lws_strncpy(m->ip, col_val[n], sizeof(m->ip)); - continue; - } - if (!strcmp(col_name[n], "content")) { - lws_strncpy(m->content, col_val[n], sizeof(m->content)); - continue; - } - } - return 0; -} - -static unsigned long -get_last_idx(struct per_vhost_data__gs_mb *vhd) -{ - struct message m; - - if (sqlite3_exec(vhd->pdb, "SELECT MAX(idx) FROM msg;", - lookup_cb, &m, NULL) != SQLITE_OK) { - lwsl_err("Unable to lookup token: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 0; - } - - return m.idx; -} - -static int -post_message(struct lws *wsi, struct per_vhost_data__gs_mb *vhd, - struct per_session_data__gs_mb *pss) -{ - struct lws_session_info sinfo; - char s[MAX_MSG_LEN + 512]; - char esc[MAX_MSG_LEN + 256]; - - vhd->gsp->callback(wsi, LWS_CALLBACK_SESSION_INFO, - pss->pss_gs, &sinfo, 0); - - lws_snprintf((char *)s, sizeof(s) - 1, - "insert into msg(time, username, email, ip, content)" - " values (%lu, '%s', '%s', '%s', '%s');", - (unsigned long)lws_now_secs(), sinfo.username, sinfo.email, sinfo.ip, - lws_sql_purify(esc, lws_spa_get_string(pss->spa, MBSPA_MSG), - sizeof(esc) - 1)); - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to insert msg: %s\n", sqlite3_errmsg(vhd->pdb)); - return 1; - } - vhd->last_idx = get_last_idx(vhd); - - /* let everybody connected by this protocol on this vhost know */ - lws_callback_on_writable_all_protocol_vhost(lws_get_vhost(wsi), - lws_get_protocol(wsi)); - - return 0; -} - -static int -callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__gs_mb *pss = (struct per_session_data__gs_mb *)user; - const struct lws_protocol_vhost_options *pvo; - struct per_vhost_data__gs_mb *vhd = (struct per_vhost_data__gs_mb *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi)); - unsigned char *p, *start, *end, buffer[LWS_PRE + 4096]; - char s[512]; - int n; - - switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ - - vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), - lws_get_protocol(wsi), sizeof(struct per_vhost_data__gs_mb)); - if (!vhd) - return 1; - vhd->vh = lws_get_vhost(wsi); - vhd->gsp = lws_vhost_name_to_protocol(vhd->vh, - "protocol-generic-sessions"); - if (!vhd->gsp) { - lwsl_err("messageboard: requires generic-sessions\n"); - return 1; - } - - pvo = (const struct lws_protocol_vhost_options *)in; - while (pvo) { - if (!strcmp(pvo->name, "message-db")) - strncpy(vhd->message_db, pvo->value, - sizeof(vhd->message_db) - 1); - pvo = pvo->next; - } - if (!vhd->message_db[0]) { - lwsl_err("messageboard: \"message-db\" pvo missing\n"); - return 1; - } - - if (lws_struct_sq3_open(lws_get_context(wsi), - vhd->message_db, 1, &vhd->pdb)) { - lwsl_err("Unable to open message db %s: %s\n", - vhd->message_db, sqlite3_errmsg(vhd->pdb)); - - return 1; - } - if (sqlite3_exec(vhd->pdb, "create table if not exists msg (" - " idx integer primary key, time integer," - " username varchar(32), email varchar(100)," - " ip varchar(80), content blob);", - NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to create msg table: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - vhd->last_idx = get_last_idx(vhd); - break; - - case LWS_CALLBACK_PROTOCOL_DESTROY: - if (vhd && vhd->pdb) - sqlite3_close(vhd->pdb); - goto passthru; - - case LWS_CALLBACK_ESTABLISHED: - vhd->gsp->callback(wsi, LWS_CALLBACK_SESSION_INFO, - pss->pss_gs, &pss->sinfo, 0); - if (!pss->sinfo.username[0]) { - lwsl_notice("messageboard ws attempt with no session\n"); - - return -1; - } - - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_CLOSED: - lwsl_debug("%s: LWS_CALLBACK_CLOSED\n", __func__); - if (pss && pss->pss_gs) { - free(pss->pss_gs); - pss->pss_gs = NULL; - } - break; - - case LWS_CALLBACK_SERVER_WRITEABLE: - { - struct message m; - char j[MAX_MSG_LEN + 512], e[MAX_MSG_LEN + 512], - *p = j + LWS_PRE, *start = p, - *end = j + sizeof(j) - LWS_PRE; - - if (pss->last_idx == vhd->last_idx) - break; - - /* restrict to last 10 */ - if (!pss->last_idx) - if (vhd->last_idx >= 10) - pss->last_idx = vhd->last_idx - 10; - - sprintf(s, "select idx, time, username, email, ip, content " - "from msg where idx > %lu order by idx limit 1;", - pss->last_idx); - if (sqlite3_exec(vhd->pdb, s, lookup_cb, &m, NULL) != SQLITE_OK) { - lwsl_err("Unable to lookup msg: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 0; - } - - /* format in JSON */ - p += lws_snprintf(p, end - p, - "{\"idx\":\"%lu\",\"time\":\"%lu\",", - m.idx, m.time); - p += lws_snprintf(p, end - p, " \"username\":\"%s\",", - lws_json_purify(e, m.username, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"email\":\"%s\",", - lws_json_purify(e, m.email, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"ip\":\"%s\",", - lws_json_purify(e, m.ip, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"content\":\"%s\"}", - lws_json_purify(e, m.content, sizeof(e), NULL)); - - if (lws_write(wsi, (unsigned char *)start, p - start, - LWS_WRITE_TEXT) < 0) - return -1; - - pss->last_idx = m.idx; - if (pss->last_idx == vhd->last_idx) - break; - - lws_callback_on_writable(wsi); /* more to do */ - } - break; - - case LWS_CALLBACK_HTTP: - pss->our_form = 0; - - /* ie, it's our messageboard new message form */ - if (!strcmp((const char *)in, "/msg") || - !strcmp((const char *)in, "msg")) { - pss->our_form = 1; - break; - } - - goto passthru; - - case LWS_CALLBACK_HTTP_BODY: - if (!pss->our_form) - goto passthru; - - if (len < 2) - break; - if (!pss->spa) { - pss->spa = lws_spa_create(wsi, param_names, - LWS_ARRAY_SIZE(param_names), - MAX_MSG_LEN + 1024, NULL, NULL); - if (!pss->spa) - return -1; - } - - if (lws_spa_process(pss->spa, in, len)) { - lwsl_notice("spa process blew\n"); - return -1; - } - break; - - case LWS_CALLBACK_HTTP_WRITEABLE: - if (!pss->second_http_part) - goto passthru; - - s[0] = '0'; - n = lws_write(wsi, (unsigned char *)s, 1, LWS_WRITE_HTTP| - LWS_WRITE_H2_STREAM_END); - if (n != 1) - return -1; - - goto try_to_reuse; - - case LWS_CALLBACK_HTTP_BODY_COMPLETION: - if (!pss->our_form) - goto passthru; - - if (post_message(wsi, vhd, pss)) - return -1; - - p = buffer + LWS_PRE; - start = p; - end = p + sizeof(buffer) - LWS_PRE; - - if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) - return -1; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *)"text/plain", 10, &p, end)) - return -1; - if (lws_add_http_header_content_length(wsi, 1, &p, end)) - return -1; - if (lws_finalize_http_header(wsi, &p, end)) - return -1; - - n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS); - if (n != (p - start)) { - lwsl_err("_write returned %d from %ld\n", n, (long)(p - start)); - return -1; - } - pss->second_http_part = 1; - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_HTTP_BIND_PROTOCOL: - if (!pss || !vhd || pss->pss_gs) - break; - - pss->pss_gs = malloc(vhd->gsp->per_session_data_size); - if (!pss->pss_gs) - return -1; - - memset(pss->pss_gs, 0, vhd->gsp->per_session_data_size); - break; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - if (vhd->gsp->callback(wsi, reason, pss ? pss->pss_gs : NULL, in, len)) - return -1; - - if (pss && pss->spa) { - lws_spa_destroy(pss->spa); - pss->spa = NULL; - } - if (pss && pss->pss_gs) { - free(pss->pss_gs); - pss->pss_gs = NULL; - } - break; - - default: -passthru: - if (!pss || !vhd) - break; - - return vhd->gsp->callback(wsi, reason, pss->pss_gs, in, len); - } - - return 0; - - -try_to_reuse: - if (lws_http_transaction_completed(wsi)) - return -1; - - return 0; -} - -static const struct lws_protocols protocols[] = { - { - "protocol-lws-messageboard", - callback_messageboard, - sizeof(struct per_session_data__gs_mb), - 4096, - }, -}; - -LWS_VISIBLE int -init_protocol_lws_messageboard(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_messageboard(struct lws_context *context) -{ - return 0; -} diff --git a/plugins/generic-sessions/utils.c b/plugins/generic-sessions/utils.c deleted file mode 100644 index 9e603ea7..00000000 --- a/plugins/generic-sessions/utils.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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 "private-lwsgs.h" -#include - -void -sha256_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash) -{ - static const char *hex = "0123456789abcdef"; - char *p = shash->id; - int n; - - for (n = 0; n < (int)lws_genhash_size(LWS_GENHASH_TYPE_SHA256); n++) { - *p++ = hex[(hash[n] >> 4) & 0xf]; - *p++ = hex[hash[n] & 15]; - } - - *p = '\0'; -} - -int -lwsgw_check_admin(struct per_vhost_data__gs *vhd, - const char *username, const char *password) -{ - lwsgw_hash_bin hash_bin; - lwsgw_hash pw_hash; - - if (strcmp(vhd->admin_user, username)) - return 0; - - lws_SHA1((unsigned char *)password, strlen(password), hash_bin.bin); - sha256_to_lwsgw_hash(hash_bin.bin, &pw_hash); - - return !strcmp(vhd->admin_password_sha256.id, pw_hash.id); -} - -/* - * secure cookie: it can only be passed over https where it cannot be - * snooped in transit - * HttpOnly: it can only be accessed via http[s] transport, it cannot be - * gotten at by JS - */ -void -lwsgw_cookie_from_session(lwsgw_hash *sid, time_t expires, char **p, char *end) -{ - struct tm *tm = gmtime(&expires); - time_t n = lws_now_secs(); - - *p += lws_snprintf(*p, end - *p, "id=%s;Expires=", sid->id); -#ifdef WIN32 - *p += strftime(*p, end - *p, "%Y %H:%M %Z", tm); -#else - *p += strftime(*p, end - *p, "%F %H:%M %Z", tm); -#endif - *p += lws_snprintf(*p, end - *p, ";path=/"); - *p += lws_snprintf(*p, end - *p, ";Max-Age=%lu", (unsigned long)(expires - n)); -// *p += lws_snprintf(*p, end - *p, ";secure"); - *p += lws_snprintf(*p, end - *p, ";HttpOnly"); -} - -int -lwsgw_expire_old_sessions(struct per_vhost_data__gs *vhd) -{ - time_t n = lws_now_secs(); - char s[200]; - - if (n - vhd->last_session_expire < 5) - return 0; - - vhd->last_session_expire = n; - - lws_snprintf(s, sizeof(s) - 1, - "delete from sessions where " - "expire <= %lu;", (unsigned long)n); - - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to expire sessions: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - return 0; -} - -int -lwsgw_update_session(struct per_vhost_data__gs *vhd, - lwsgw_hash *hash, const char *user) -{ - time_t n = lws_now_secs(); - char s[200], esc[96], esc1[96]; - - if (user[0]) - n += vhd->timeout_absolute_secs; - else - n += vhd->timeout_anon_absolute_secs; - - lws_snprintf(s, sizeof(s) - 1, - "update sessions set expire=%lu,username='%s' where name='%s';", - (unsigned long)n, - lws_sql_purify(esc, user, sizeof(esc)), - lws_sql_purify(esc1, hash->id, sizeof(esc1))); - - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to update session: %s\n", - sqlite3_errmsg(vhd->pdb)); - return 1; - } - - puts(s); - - return 0; -} - -static int -lwsgw_session_from_cookie(const char *cookie, lwsgw_hash *sid) -{ - const char *p = cookie; - int n; - - while (*p) { - if (p[0] == 'i' && p[1] == 'd' && p[2] == '=') { - p += 3; - break; - } - p++; - } - if (!*p) { - lwsl_info("no id= in cookie\n"); - return 1; - } - - for (n = 0; n < (int)sizeof(sid->id) - 1 && *p; n++) { - /* our SID we issue only has these chars */ - if ((*p >= '0' && *p <= '9') || - (*p >= 'a' && *p <= 'f')) - sid->id[n] = *p++; - else { - lwsl_info("bad chars in cookie id %c\n", *p); - return 1; - } - } - - if (n < (int)sizeof(sid->id) - 1) { - lwsl_info("cookie id too short\n"); - return 1; - } - - sid->id[sizeof(sid->id) - 1] = '\0'; - - return 0; -} - -int -lwsgs_get_sid_from_wsi(struct lws *wsi, lwsgw_hash *sid) -{ - char cookie[1024]; - - /* fail it on no cookie */ - if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) { - lwsl_info("%s: no cookie\n", __func__); - return 1; - } - if (lws_hdr_copy(wsi, cookie, sizeof cookie, WSI_TOKEN_HTTP_COOKIE) < 0) { - lwsl_info("cookie copy failed\n"); - return 1; - } - /* extract the sid from the cookie */ - if (lwsgw_session_from_cookie(cookie, sid)) { - lwsl_info("%s: session from cookie failed\n", __func__); - return 1; - } - - return 0; -} - -struct lla { - char *username; - int len; - int results; -}; - -static int -lwsgs_lookup_callback(void *priv, int cols, char **col_val, char **col_name) -{ - struct lla *lla = (struct lla *)priv; - - //lwsl_err("%s: %d\n", __func__, cols); - - if (cols) - lla->results = 0; - if (col_val && col_val[0]) { - lws_strncpy(lla->username, col_val[0], lla->len + 1); - lwsl_info("%s: %s\n", __func__, lla->username); - } - - return 0; -} - -int -lwsgs_lookup_session(struct per_vhost_data__gs *vhd, - const lwsgw_hash *sid, char *username, int len) -{ - struct lla lla = { username, len, 1 }; - char s[150], esc[96]; - - lwsgw_expire_old_sessions(vhd); - - lws_snprintf(s, sizeof(s) - 1, - "select username from sessions where name = '%s';", - lws_sql_purify(esc, sid->id, sizeof(esc) - 1)); - - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback, &lla, NULL) != SQLITE_OK) { - lwsl_err("Unable to create user table: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - /* 0 if found */ - return lla.results; -} - -int -lwsgs_lookup_callback_user(void *priv, int cols, char **col_val, char **col_name) -{ - struct lwsgs_user *u = (struct lwsgs_user *)priv; - int n; - - for (n = 0; n < cols; n++) { - if (!strcmp(col_name[n], "username")) { - lws_strncpy(u->username, col_val[n], sizeof(u->username)); - continue; - } - if (!strcmp(col_name[n], "ip")) { - lws_strncpy(u->ip, col_val[n], sizeof(u->ip)); - continue; - } - if (!strcmp(col_name[n], "creation_time")) { - u->created = atol(col_val[n]); - continue; - } - if (!strcmp(col_name[n], "last_forgot_validated")) { - if (col_val[n]) - u->last_forgot_validated = atol(col_val[n]); - else - u->last_forgot_validated = 0; - continue; - } - if (!strcmp(col_name[n], "email")) { - lws_strncpy(u->email, col_val[n], sizeof(u->email)); - continue; - } - if (!strcmp(col_name[n], "verified")) { - u->verified = atoi(col_val[n]); - continue; - } - if (!strcmp(col_name[n], "pwhash")) { - lws_strncpy(u->pwhash.id, col_val[n], sizeof(u->pwhash.id)); - continue; - } - if (!strcmp(col_name[n], "pwsalt")) { - lws_strncpy(u->pwsalt.id, col_val[n], sizeof(u->pwsalt.id)); - continue; - } - if (!strcmp(col_name[n], "token")) { - lws_strncpy(u->token.id, col_val[n], sizeof(u->token.id)); - continue; - } - } - return 0; -} - -int -lwsgs_lookup_user(struct per_vhost_data__gs *vhd, - const char *username, struct lwsgs_user *u) -{ - char s[150], esc[96]; - - u->username[0] = '\0'; - lws_snprintf(s, sizeof(s) - 1, - "select username,creation_time,ip,email,verified,pwhash,pwsalt,last_forgot_validated " - "from users where username = '%s';", - lws_sql_purify(esc, username, sizeof(esc) - 1)); - - if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, u, NULL) != - SQLITE_OK) { - lwsl_err("Unable to lookup user: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return -1; - } - - return !u->username[0]; -} - -int -lwsgs_new_session_id(struct per_vhost_data__gs *vhd, - lwsgw_hash *sid, const char *username, int exp) -{ - unsigned char sid_rand[32]; - const char *u; - char s[300], esc[96], esc1[96]; - - if (username) - u = username; - else - u = ""; - - if (!sid) { - lwsl_err("%s: NULL sid\n", __func__); - return 1; - } - - memset(sid, 0, sizeof(*sid)); - - if (lws_get_random(vhd->context, sid_rand, sizeof(sid_rand)) != - sizeof(sid_rand)) - return 1; - - sha256_to_lwsgw_hash(sid_rand, sid); - - lws_snprintf(s, sizeof(s) - 1, - "insert into sessions(name, username, expire) " - "values ('%s', '%s', %u);", - lws_sql_purify(esc, sid->id, sizeof(esc) - 1), - lws_sql_purify(esc1, u, sizeof(esc1) - 1), exp); - - if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) { - lwsl_err("Unable to insert session: %s\n", - sqlite3_errmsg(vhd->pdb)); - - return 1; - } - - lwsl_notice("%s: created session %s\n", __func__, sid->id); - - return 0; -} - -int -lwsgs_get_auth_level(struct per_vhost_data__gs *vhd, const char *username) -{ - struct lwsgs_user u; - int n = 0; - - /* we are logged in as some kind of user */ - if (username[0]) { - /* we are logged in as admin */ - if (!strcmp(username, vhd->admin_user)) - /* automatically verified */ - n |= LWSGS_AUTH_VERIFIED | LWSGS_AUTH_ADMIN; - } - - if (!lwsgs_lookup_user(vhd, username, &u)) { - if ((u.verified & 0xff) == LWSGS_VERIFIED_ACCEPTED) - n |= LWSGS_AUTH_LOGGED_IN | LWSGS_AUTH_VERIFIED; - - if (u.last_forgot_validated > (time_t)lws_now_secs() - 300) - n |= LWSGS_AUTH_FORGOT_FLOW; - } - - return n; -} - -int -lwsgs_check_credentials(struct per_vhost_data__gs *vhd, - const char *username, const char *password) -{ - struct lws_genhash_ctx hash_ctx; - lwsgw_hash_bin hash_bin; - struct lwsgs_user u; - lwsgw_hash hash; - - if (lwsgs_lookup_user(vhd, username, &u)) - return -1; - - lwsl_info("user %s found, salt '%s'\n", username, u.pwsalt.id); - - /* sha256sum of password + salt */ - - if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256) || - lws_genhash_update(&hash_ctx, password, strlen(password)) || - lws_genhash_update(&hash_ctx, "-", 1) || - lws_genhash_update(&hash_ctx, vhd->confounder, strlen(vhd->confounder)) || - lws_genhash_update(&hash_ctx, "-", 1) || - lws_genhash_update(&hash_ctx, u.pwsalt.id, strlen(u.pwsalt.id)) || - lws_genhash_destroy(&hash_ctx, hash_bin.bin)) { - lws_genhash_destroy(&hash_ctx, NULL); - - return 1; - } - - sha256_to_lwsgw_hash(&hash_bin.bin[0], &hash); - - return !!strcmp(hash.id, u.pwhash.id); -} - -/* sets u->pwsalt and u->pwhash */ - -int -lwsgs_hash_password(struct per_vhost_data__gs *vhd, - const char *password, struct lwsgs_user *u) -{ - unsigned char sid_rand[32]; - struct lws_genhash_ctx hash_ctx; - lwsgw_hash_bin hash_bin; - - /* create a random salt as big as the hash */ - - if (lws_get_random(vhd->context, sid_rand, - sizeof(sid_rand)) != - sizeof(sid_rand)) { - lwsl_err("Problem getting random for salt\n"); - return 1; - } - sha256_to_lwsgw_hash(sid_rand, &u->pwsalt); -/* - if (lws_get_random(vhd->context, sid_rand, - sizeof(sid_rand)) != - sizeof(sid_rand)) { - lwsl_err("Problem getting random for token\n"); - return 1; - } - sha256_to_lwsgw_hash(sid_rand, &hash); -*/ - /* sha256sum of password + salt */ - - if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256) || - lws_genhash_update(&hash_ctx, password, strlen(password)) || - lws_genhash_update(&hash_ctx, "-", 1) || - lws_genhash_update(&hash_ctx, vhd->confounder, strlen(vhd->confounder)) || - lws_genhash_update(&hash_ctx, "-", 1) || - lws_genhash_update(&hash_ctx, u->pwsalt.id, strlen(u->pwsalt.id)) || - lws_genhash_destroy(&hash_ctx, hash_bin.bin)) { - lws_genhash_destroy(&hash_ctx, NULL); - - return 1; - } - - sha256_to_lwsgw_hash(&hash_bin.bin[0], &u->pwhash); - - return 0; -} diff --git a/plugins/generic-table/assets/index.html b/plugins/generic-table/assets/index.html deleted file mode 100644 index 635d02aa..00000000 --- a/plugins/generic-table/assets/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - -
- LWS Generic Table demo -
- This is a demo of lws generic table, using a protocol plugin - "protocol-lws-table-dirlisting". It shows a directory listing, - but unlike an oldstyle directory listing done on the - server side with a script, this is static html that connects - back to the server with a websocket, and gets live JSON from - that. -

- Actually the static html is extremely simple, since it uses - lwsgt, LWS Generic Table, JS include on the client-side that - handles all the table generation from a template sent in JSON - over the ws link. It means there is no custom JS required - clientside either. It's just CSS, this text and a call to - initialize lwsgt with the appropriate ws protocol. -

- There's no problem having multiple independent instances per - page... -
-

- - - - diff --git a/plugins/generic-table/assets/lwsgt.js b/plugins/generic-table/assets/lwsgt.js deleted file mode 100644 index 5e4365a2..00000000 --- a/plugins/generic-table/assets/lwsgt.js +++ /dev/null @@ -1,139 +0,0 @@ -function lwsgt_get_appropriate_ws_url() -{ - var pcol; - var u = document.URL; - - if (u.substring(0, 5) === "https") { - pcol = "wss://"; - u = u.substr(8); - } else { - pcol = "ws://"; - if (u.substring(0, 4) === "http") - u = u.substr(7); - } - - return pcol + u; -} - -function lwsgt_app_hdr(j, bc, ws) -{ - var s = "", n, m = 0; - - ws.bcq = 0; - - for (n = 0; n < j.cols.length; n++) - if (!j.cols[n].hide) - m++; - - s = "" + - ws.lwsgt_title + ""; - - if (!!bc) { - s += ""; - for (n = 0; n < bc.length; n++) { - s += " / "; - if (!bc[n].url && bc[n].url !== "") - s += " " + lws_san(bc[n].name) + " "; - else { - s += "" + - lws_san(bc[n].name) + " "; - ws.bcq++; - } - } - s += ""; - } - s += ""; - for (n = 0; n < j.cols.length; n++) - if (!j.cols[n].hide) - s = s + "" + lws_san(j.cols[n].name) + - ""; - - s += ""; - - return s; -} - -function lwsgt_click_callthru() -{ - window[this.getAttribute("h")](this.getAttribute("p"), this.getAttribute("aa"), this.getAttribute("m"), this.getAttribute("n")); - event.preventDefault(); -} - -function lwsgt_initial(title, pcol, divname, cb, gname) -{ - this.divname = divname; - - lws_gray_out(true,{"zindex":"499"}); - - this.lwsgt_ws = new WebSocket(lwsgt_get_appropriate_ws_url(), pcol); - this.lwsgt_ws.divname = divname; - this.lwsgt_ws.lwsgt_cb = cb; - this.lwsgt_ws.lwsgt_parent = gname; - this.lwsgt_ws.lwsgt_title = title; - try { - this.lwsgt_ws.onopen = function() { - lws_gray_out(false); - // document.getElementById("debug").textContent = - // "ws opened " + lwsgt_get_appropriate_ws_url(); - }; - this.lwsgt_ws.onmessage = function got_packet(msg) { - var s, m, n, j = JSON.parse(msg.data); - document.getElementById("debug").textContent = msg.data; - if (j.cols) { - this.hdr = j; - } - if (j.breadcrumbs) - this.breadcrumbs = j.breadcrumbs; - - if (j.data) { - var q = 0; - s = "" + - lwsgt_app_hdr(this.hdr, this.breadcrumbs, this); - for (m = 0; m < j.data.length; m++) { - s = s + ""; - for (n = 0; n < this.hdr.cols.length; n++) { - if (!this.hdr.cols[n].hide) { - if (!this.hdr.cols[n].align) - s = s + ""; - } - } - - s = s + ""; - } - s = s + "
"; - else - s = s + ""; - - if (this.hdr.cols[n].href && - !!j.data[m][this.hdr.cols[n].href]) { - s = s + "" + - lws_san(j.data[m][this.hdr.cols[n].name]) + - ""; - q++; - } - else - s = s + lws_san(j.data[m][this.hdr.cols[n].name]); - - s = s + "
"; - document.getElementById(this.divname).innerHTML = s; - for (n = 0; n < q; n++) - document.getElementById(this.divname + n).onclick = - lwsgt_click_callthru; - - for (n = 0; n < this.bcq; n++) - document.getElementById("bc_" + this.divname + n).onclick = - lwsgt_click_callthru; - - } - }; - this.lwsgt_ws.onclose = function(){ - lws_gray_out(true,{"zindex":"499"}); - }; - } catch(exception) { - alert("

Error" + exception); - } -} - diff --git a/plugins/generic-table/protocol_table_dirlisting.c b/plugins/generic-table/protocol_table_dirlisting.c deleted file mode 100644 index 8537b615..00000000 --- a/plugins/generic-table/protocol_table_dirlisting.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - */ - -#define LWS_DLL -#define LWS_INTERNAL -#include - -#include -#include -#include - -struct fobj { - struct fobj *next; - const char *name, *uri, *icon, *date; - time_t m; - unsigned long size; -}; - -struct per_session_data__tbl_dir { - struct fobj base; - char strings[64 * 1024]; - char reldir[256]; - char *p; - const char *dir; - -#if UV_VERSION_MAJOR > 0 - uv_fs_event_t *event_req; -#endif - struct lws *wsi; -}; - -#if UV_VERSION_MAJOR > 0 -static void -mon_cb(uv_fs_event_t *handle, const char *filename, int events, int status) -{ - struct per_session_data__tbl_dir *pss = handle->data; - - //lwsl_notice("%s\n", __func__); - - if (pss && pss->wsi) - lws_callback_on_writable(pss->wsi); -} - -static void lws_uv_close_cb(uv_handle_t *handle) -{ - free(handle); -} - -static void -lws_protocol_dir_kill_monitor(struct per_session_data__tbl_dir *pss) -{ - if (!pss->event_req) - return; - pss->wsi = NULL; - pss->event_req->data = NULL; - uv_fs_event_stop(pss->event_req); - uv_close((uv_handle_t *)pss->event_req, lws_uv_close_cb); - pss->event_req = NULL; -} -#endif - -static int -scan_dir(struct lws *wsi, struct per_session_data__tbl_dir *pss) -{ -/* uuh travis... */ -#if UV_VERSION_MAJOR > 0 - uv_loop_t *loop = lws_uv_getloop(lws_get_context(wsi), 0); - char *end = &(pss->strings[sizeof(pss->strings) - 1]); - struct fobj *prev = &pss->base; - char path[512], da[200]; - const char *icon; - uv_dirent_t dent; - struct fobj *f; - struct stat st; - struct tm *tm; - int ret = 0, n; - uv_fs_t req; - - lws_protocol_dir_kill_monitor(pss); - - lws_snprintf(path, sizeof(path) - 1, "%s/%s", pss->dir, pss->reldir); - //lwsl_notice("path = %s\n", path); - - pss->event_req = malloc(sizeof(*pss->event_req)); - if (!pss->event_req) - return 2; - - pss->wsi = wsi; - pss->event_req->data = pss; - - uv_fs_event_init(lws_uv_getloop(lws_get_context(wsi), 0), - pss->event_req); - // The recursive flag watches subdirectories too. - n = uv_fs_event_start(pss->event_req, mon_cb, path, UV_FS_EVENT_RECURSIVE); - //lwsl_notice("monitoring %s (%d)\n", path, n); - - if (!uv_fs_scandir(loop, &req, path, 0, NULL)) { - lwsl_err("Scandir on %s failed\n", path); - return 2; - } - - pss->p = pss->strings; - - while (uv_fs_scandir_next(&req, &dent) != UV_EOF) { - lws_snprintf(path, sizeof(path) - 1, "%s/%s/%s", pss->dir, pss->reldir, dent.name); - - if (stat(path, &st)) { - lwsl_info("unable to stat %s\n", path); - continue; - } - f = malloc(sizeof(*f)); - f->next = NULL; - f->name = pss->p; - n = lws_snprintf(pss->p, end - pss->p, "%s", dent.name); - pss->p += n + 1; - f->uri = NULL; - if ((S_IFMT & st.st_mode) == S_IFDIR) { - n = lws_snprintf(pss->p, end - pss->p, "=%s/%s", pss->reldir, dent.name); - f->uri = pss->p; - } - if (lws_get_mimetype(dent.name, NULL)) { - n = lws_snprintf(pss->p, end - pss->p, "./serve/%s/%s", pss->reldir, dent.name); - f->uri = pss->p; - } - if (f->uri) - pss->p += n + 1; - - if (end - pss->p < 100) { - free(f); - break; - } - - icon = " "; - if ((S_IFMT & st.st_mode) == S_IFDIR) - icon = "📂"; - - f->icon = pss->p; - n = lws_snprintf(pss->p, end - pss->p, "%s", icon); - pss->p += n + 1; - - f->date = pss->p; - tm = gmtime(&st.st_mtime); - strftime(da, sizeof(da), "%Y-%b-%d %H:%M:%S %z", tm); - n = lws_snprintf(pss->p, end - pss->p, "%s", da); - pss->p += n + 1; - - f->size = st.st_size; - f->m = st.st_mtime; - prev->next = f; - prev = f; - } - - uv_fs_req_cleanup(&req); - - return ret; -#else - return 0; -#endif -} - -static void -free_scan_dir(struct per_session_data__tbl_dir *pss) -{ - struct fobj *f = pss->base.next, *f1; - - while (f) { - f1 = f->next; - free(f); - f = f1; - } - - pss->base.next = NULL; -} - -static int -callback_lws_table_dirlisting(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct per_session_data__tbl_dir *pss = (struct per_session_data__tbl_dir *)user; - char j[LWS_PRE + 16384], *p = j + LWS_PRE, *start = p, *q, *q1, *w, - *end = j + sizeof(j) - LWS_PRE, e[384], s[384], s1[384]; - const struct lws_protocol_vhost_options *pmo; - struct fobj *f; - int n, first = 1; - - switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */ - break; - - case LWS_CALLBACK_ESTABLISHED: - lwsl_debug("LWS_CALLBACK_ESTABLISHED\n"); - /* - * send client the lwsgt table layout - */ - start = "{\"cols\":[" - " {\"name\": \"Date\"}," - " {\"name\": \"Size\", \"align\": \"right\"}," - " {\"name\": \"Icon\"}," - " {\"name\": \"Name\", \"href\": \"uri\"}," - " {\"name\": \"uri\", \"hide\": \"1\" }" - " ]" - "}"; - if (lws_write(wsi, (unsigned char *)start, strlen(start), - LWS_WRITE_TEXT) < 0) - return -1; - - /* send a view update next */ - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_RECEIVE: - if (len > sizeof(pss->reldir) - 1) - len = sizeof(pss->reldir) - 1; - if (!strstr(in, "..") && !strchr(in, '~')) - lws_strncpy(pss->reldir, in, len + 1); - else - len = 0; - pss->reldir[len] = '\0'; - if (pss->reldir[0] == '/' && !pss->reldir[1]) - pss->reldir[0] = '\0'; - lwsl_info("%s\n", pss->reldir); - lws_callback_on_writable(wsi); - break; - - case LWS_CALLBACK_SERVER_WRITEABLE: - - if (scan_dir(wsi, pss)) - return 1; - - p += lws_snprintf(p, end - p, "{\"breadcrumbs\":["); - q = pss->reldir; - - if (!q[0]) - p += lws_snprintf(p, end - p, "{\"name\":\"top\"}"); - - while (*q) { - - q1 = strchr(q, '/'); - if (!q1) { - if (first) - strcpy(s, "top1"); - else - strcpy(s, q); - s1[0] = '\0'; - q += strlen(q); - } else { - n = lws_ptr_diff(q1, q); - if (n > (int)sizeof(s) - 1) - n = sizeof(s) - 1; - if (first) { - strcpy(s1, "/"); - strcpy(s, "top"); - } else { - lws_strncpy(s, q, n + 1); - - n = lws_ptr_diff(q1, pss->reldir); - if (n > (int)sizeof(s1) - 1) - n = sizeof(s1) - 1; - lws_strncpy(s1, pss->reldir, n + 1); - } - q = q1 + 1; - } - if (!first) - p += lws_snprintf(p, end - p, ","); - else - first = 0; - - p += lws_snprintf(p, end - p, "{\"name\":\"%s\"", - lws_json_purify(e, s, sizeof(e), NULL)); - if (*q) { - w = s1; - while (w[0] == '/' && w[1] == '/') - w++; - p += lws_snprintf(p, end - p, ",\"url\":\"%s\"", - lws_json_purify(e, w, sizeof(e), NULL)); - } - p += lws_snprintf(p, end - p, "}"); - if (!q1) - break; - } - - p += lws_snprintf(p, end - p, "],\"data\":["); - - f = pss->base.next; - while (f) { - /* format in JSON */ - p += lws_snprintf(p, end - p, "{\"Icon\":\"%s\",", - lws_json_purify(e, f->icon, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"Date\":\"%s\",", - lws_json_purify(e, f->date, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"Size\":\"%ld\",", - f->size); - if (f->uri) - p += lws_snprintf(p, end - p, " \"uri\":\"%s\",", - lws_json_purify(e, f->uri, sizeof(e), NULL)); - p += lws_snprintf(p, end - p, " \"Name\":\"%s\"}", - lws_json_purify(e, f->name, sizeof(e), NULL)); - - f = f->next; - - if (f) - p += lws_snprintf(p, end - p, ","); - } - - p += lws_snprintf(p, end - p, "]}"); - - free_scan_dir(pss); - - if (lws_write(wsi, (unsigned char *)start, p - start, - LWS_WRITE_TEXT) < 0) - return -1; - - break; - - case LWS_CALLBACK_HTTP_PMO: - /* find the per-mount options we're interested in */ - lwsl_debug("LWS_CALLBACK_HTTP_PMO\n"); - pmo = (struct lws_protocol_vhost_options *)in; - while (pmo) { - if (!strcmp(pmo->name, "dir")) /* path to list files */ - pss->dir = pmo->value; - pmo = pmo->next; - } - if (!pss->dir[0]) { - lwsl_err("dirlisting: \"dir\" pmo missing\n"); - return 1; - } - break; - - case LWS_CALLBACK_HTTP_DROP_PROTOCOL: - //lwsl_notice("LWS_CALLBACK_HTTP_DROP_PROTOCOL\n"); -#if UV_VERSION_MAJOR > 0 - lws_protocol_dir_kill_monitor(pss); -#endif - break; - - default: - return 0; - } - - return 0; - -} - -static const struct lws_protocols protocols[] = { - { - "protocol-lws-table-dirlisting", - callback_lws_table_dirlisting, - sizeof(struct per_session_data__tbl_dir), - 0, - }, -}; - -LWS_VISIBLE int -init_protocol_lws_table_dirlisting(struct lws_context *context, - struct lws_plugin_capability *c) -{ - if (c->api_magic != LWS_PLUGIN_API_MAGIC) { - lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC, - c->api_magic); - return 1; - } - - c->protocols = protocols; - c->count_protocols = LWS_ARRAY_SIZE(protocols); - c->extensions = NULL; - c->count_extensions = 0; - - return 0; -} - -LWS_VISIBLE int -destroy_protocol_lws_table_dirlisting(struct lws_context *context) -{ - return 0; -} -- Gitee From 6762c7367f507dda477332eb403ed154a7848b01 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 13 Jul 2020 13:44:57 +0100 Subject: [PATCH 0216/1062] remove: old esp32 helper pieces The old esp32 -factory stuff along with the lws support doesn't have a future in its old form. It has users but the ratio of effort to contribution is really especially bad. I haven't updated it for more than a year since esp-idf changes broke the original stuff. Freertos plat is alive and well and getting a lot of new use, ESP-32 is supported both there and by modern lws_drivers pieces, including in CI on real hardware, any further effort will be invested in that direction instead of more vendor api-specific code (outside of wrapper implementation). lws_drivers wraps any SDK apis in generic lws apis such that your code just uses those, enabling it to become SDK / SoC / vendor independent. Its first implementation is on esp-idf, the low and mid-level features that were in the old -factory are already available using that and new technologies like lws_struct and Secure Streams. --- CMakeLists.txt | 1 - include/libwebsockets.h | 3 - include/libwebsockets/lws-esp32.h | 156 --- include/libwebsockets/lws-freertos.h | 4 + lib/plat/freertos/CMakeLists.txt | 3 - lib/plat/freertos/esp32/esp32-helpers.c | 1373 ----------------------- 6 files changed, 4 insertions(+), 1536 deletions(-) delete mode 100644 include/libwebsockets/lws-esp32.h delete mode 100644 lib/plat/freertos/esp32/esp32-helpers.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f5b55007..d9e4cb40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,7 +170,6 @@ option(LWS_STATIC_PIC "Build the static version of the library with position-ind # Specific platforms # option(LWS_WITH_ESP32 "Build for ESP32" OFF) -option(LWS_WITH_ESP32_HELPER "Build ESP32 helper" OFF) option(LWS_PLAT_OPTEE "Build for OPTEE" OFF) option(LWS_PLAT_FREERTOS "Build for FreeRTOS" OFF) option(LWS_PLAT_ANDROID "Android flavour of unix platform" OFF) diff --git a/include/libwebsockets.h b/include/libwebsockets.h index b015aa11..c60b87dc 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -353,9 +353,6 @@ struct lws_pollfd { #if defined(LWS_PLAT_FREERTOS) #include -#if defined(LWS_WITH_ESP32) -#include -#endif #else typedef int lws_sockfd_type; typedef int lws_filefd_type; diff --git a/include/libwebsockets/lws-esp32.h b/include/libwebsockets/lws-esp32.h deleted file mode 100644 index 5105b3b2..00000000 --- a/include/libwebsockets/lws-esp32.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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. - * - * This is only included from libwebsockets.h if LWS_WITH_ESP32 - */ - -/* ESP32 helper declarations */ - -#include -#include - -#define LWS_PLUGIN_STATIC -#define LWS_MAGIC_REBOOT_TYPE_ADS 0x50001ffc -#define LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY 0xb00bcafe -#define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY 0xfaceb00b -#define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON 0xf0cedfac -#define LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY_ERASE_OTA 0xfac0eeee - -/* user code provides these */ - -extern void -lws_esp32_identify_physical_device(void); - -/* lws-plat-esp32 provides these */ - -typedef void (*lws_cb_scan_done)(uint16_t count, wifi_ap_record_t *recs, void *arg); - -enum genled_state { - LWSESP32_GENLED__INIT, - LWSESP32_GENLED__LOST_NETWORK, - LWSESP32_GENLED__NO_NETWORK, - LWSESP32_GENLED__CONN_AP, - LWSESP32_GENLED__GOT_IP, - LWSESP32_GENLED__OK, -}; - -struct lws_group_member { - struct lws_group_member *next; - uint64_t last_seen; - char model[16]; - char role[16]; - char host[32]; - char mac[20]; - int width, height; - struct ip4_addr addr; - struct ip6_addr addrv6; - uint8_t flags; -}; - -#define LWS_SYSTEM_GROUP_MEMBER_ADD 1 -#define LWS_SYSTEM_GROUP_MEMBER_CHANGE 2 -#define LWS_SYSTEM_GROUP_MEMBER_REMOVE 3 - -#define LWS_GROUP_FLAG_SELF 1 - -struct lws_esp32 { - char sta_ip[16]; - char sta_mask[16]; - char sta_gw[16]; - char serial[16]; - char opts[16]; - char model[16]; - char group[16]; - char role[16]; - char ssid[4][64]; - char password[4][64]; - char active_ssid[64]; - char access_pw[16]; - char hostname[32]; - char mac[20]; - char le_dns[64]; - char le_email[64]; - char region; - char inet; - char conn_ap; - - enum genled_state genled; - uint64_t genled_t; - - lws_cb_scan_done scan_consumer; - void *scan_consumer_arg; - struct lws_group_member *first; - int extant_group_members; - - char acme; - char upload; - - volatile char button_is_down; -}; - -struct lws_esp32_image { - uint32_t romfs; - uint32_t romfs_len; - uint32_t json; - uint32_t json_len; -}; - -extern struct lws_esp32 lws_esp32; -struct lws_vhost; - -extern esp_err_t -lws_esp32_event_passthru(void *ctx, system_event_t *event); -extern void -lws_esp32_wlan_config(void); -extern void -lws_esp32_wlan_start_ap(void); -extern void -lws_esp32_wlan_start_station(void); -struct lws_context_creation_info; -extern void -lws_esp32_set_creation_defaults(struct lws_context_creation_info *info); -extern struct lws_context * -lws_esp32_init(struct lws_context_creation_info *, struct lws_vhost **pvh); -extern int -lws_esp32_wlan_nvs_get(int retry); -extern esp_err_t -lws_nvs_set_str(nvs_handle handle, const char* key, const char* value); -extern void -lws_esp32_restart_guided(uint32_t type); -extern const esp_partition_t * -lws_esp_ota_get_boot_partition(void); -extern int -lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i, char *json, int json_len); -extern int -lws_esp32_leds_network_indication(void); - -extern uint32_t lws_esp32_get_reboot_type(void); -extern uint16_t lws_esp32_sine_interp(int n); - -/* required in external code by esp32 plat (may just return if no leds) */ -extern void lws_esp32_leds_timer_cb(TimerHandle_t th); - - -#include "libwebsockets/lws-gpio.h" -extern const lws_gpio_ops_t lws_gpio_plat; - diff --git a/include/libwebsockets/lws-freertos.h b/include/libwebsockets/lws-freertos.h index 2dd7ff45..a7872299 100644 --- a/include/libwebsockets/lws-freertos.h +++ b/include/libwebsockets/lws-freertos.h @@ -74,6 +74,10 @@ struct pollfd { #if defined(LWS_ESP_PLATFORM) #include "lwip/sockets.h" #include "lwip/netdb.h" +#if defined(LWS_WITH_DRIVERS) +#include "libwebsockets/lws-gpio.h" +extern const lws_gpio_ops_t lws_gpio_plat; +#endif #endif #endif /* LWS_AMAZON_RTOS */ diff --git a/lib/plat/freertos/CMakeLists.txt b/lib/plat/freertos/CMakeLists.txt index 1953ac22..c0d92e94 100644 --- a/lib/plat/freertos/CMakeLists.txt +++ b/lib/plat/freertos/CMakeLists.txt @@ -46,9 +46,6 @@ if (LWS_ESP_PLATFORM AND LWS_WITH_DRIVERS) list(APPEND SOURCES plat/freertos/esp32/drivers/netdev/wifi-esp32.c) endif() endif() -if (LWS_WITH_ESP32_HELPER) - list(APPEND SOURCES plat/freertos/esp32/esp32-helpers.c) -endif() if (LWS_WITH_FILE_OPS) list(APPEND SOURCES plat/freertos/freertos-file.c) endif() diff --git a/lib/plat/freertos/esp32/esp32-helpers.c b/lib/plat/freertos/esp32/esp32-helpers.c deleted file mode 100644 index f6463540..00000000 --- a/lib/plat/freertos/esp32/esp32-helpers.c +++ /dev/null @@ -1,1373 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * 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 "private-lib-core.h" - -#include "romfs.h" -#include -#include -#include -#include -#include "soc/ledc_reg.h" -#include "driver/ledc.h" - -struct lws_esp32 lws_esp32 = { - .model = CONFIG_LWS_MODEL_NAME, - .serial = "unknown", -}; - -/* - * Group AP / Station State - */ - -enum lws_gapss { - LWS_GAPSS_INITIAL, /* just started up, init and move to - * LWS_GAPSS_SCAN */ - LWS_GAPSS_SCAN, /* - * Unconnected, scanning: AP known in one of the - * config slots -> configure it, start timeout + - * LWS_GAPSS_STAT, if no AP already up in same - * group with lower MAC, after a random period - * start up our AP (LWS_GAPSS_AP) - */ - LWS_GAPSS_AP, /* - * Trying to be the group AP... periodically do - * a scan LWS_GAPSS_AP_SCAN, faster and then - * slower - */ - LWS_GAPSS_AP_SCAN, /* - * doing a scan while trying to be the group - * AP... if we see a lower MAC being the AP for - * the same group AP, abandon being an AP and - * join that AP as a station - */ - LWS_GAPSS_STAT_GRP_AP, /* - * We have decided to join another group member - * who is being the AP, as its MAC is lower than - * ours. This is a stable state, but we still - * do periodic scans LWS_GAPSS_STAT_GRP_AP_SCAN - * and will always prefer an AP configured in a - * slot. - */ - LWS_GAPSS_STAT_GRP_AP_SCAN, - /* - * We have joined a group member who is doing - * the AP job... we want to check every now and - * then if a configured AP has appeared that we - * should better use instead. Otherwise stay in - * LWS_GAPSS_STAT_GRP_AP - */ - LWS_GAPSS_STAT, /* - * trying to connect to another non-group AP. - * If we don't get an IP within a timeout and - * retries, blacklist it and go back - */ - LWS_GAPSS_STAT_HAPPY, -}; - -static const char *gapss_str[] = { - "LWS_GAPSS_INITIAL", - "LWS_GAPSS_SCAN", - "LWS_GAPSS_AP", - "LWS_GAPSS_AP_SCAN", - "LWS_GAPSS_STAT_GRP_AP", - "LWS_GAPSS_STAT_GRP_AP_SCAN", - "LWS_GAPSS_STAT", - "LWS_GAPSS_STAT_HAPPY", -}; - -static romfs_t lws_esp32_romfs; -static TimerHandle_t leds_timer, scan_timer, debounce_timer, association_timer -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) -, mdns_timer -#endif -; -static enum lws_gapss gapss = LWS_GAPSS_INITIAL; -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) -static mdns_result_t *mdns_results_head; -#endif - -#define GPIO_SW 14 - -struct esp32_file { - const struct inode *i; -}; - -static void lws_gapss_to(enum lws_gapss to) -{ - lwsl_notice("gapss from %s to %s\n", gapss_str[gapss], gapss_str[to]); - gapss = to; -} - -uint32_t lws_esp32_get_reboot_type(void) -{ - uint32_t *p = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS, val = *p; - nvs_handle nvh; - size_t s = 0; - int n = 0; - - ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh)); - if (nvs_get_blob(nvh, "ssl-pub.pem", NULL, &s) == ESP_OK) - n = 1; - if (nvs_get_blob(nvh, "ssl-pri.pem", NULL, &s) == ESP_OK) - n |= 2; - nvs_close(nvh); - - /* - * in the case the SSL certs are not there, don't require - * the button to be down to access all features. - */ - if (n != 3) - val = LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON; - - return val; -} - -static void render_ip(char *dest, int len, uint8_t *ip) -{ - snprintf(dest, len, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); -} - -void lws_esp32_restart_guided(uint32_t type) -{ - uint32_t *p_force_factory_magic = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS; - - lwsl_notice("%s: %x\n", __func__, type); - *p_force_factory_magic = type; - - esp_restart(); -} - -/* - * esp-idf goes crazy with zero length str nvs. Use this as a workaround - * to delete the key in that case. - */ - -esp_err_t lws_nvs_set_str(nvs_handle handle, const char* key, const char* value) -{ - if (*value) - return nvs_set_str(handle, key, value); - - return nvs_erase_key(handle, key); -} - -static wifi_scan_config_t scan_config = { - .ssid = 0, - .bssid = 0, - .channel = 0, - .show_hidden = true -}; - -static char scan_ongoing = 0, scan_timer_exists = 0; -static int try_slot = -1; - -static wifi_config_t config = { - .ap = { - .channel = 6, - .authmode = WIFI_AUTH_OPEN, - .max_connection = 1, - } }, sta_config = { - .sta = { - .bssid_set = 0, - } }; - -static void lws_esp32_scan_timer_cb(TimerHandle_t th) -{ - int n; - - lwsl_notice("%s\n", __func__); - scan_ongoing = 0; - n = esp_wifi_scan_start(&scan_config, false); - if (n != ESP_OK) - lwsl_err("scan start failed %d\n", n); -} - -static void lws_esp32_assoc_timer_cb(TimerHandle_t th) -{ - int n; - - xTimerStop(association_timer, 0); - - if (gapss == LWS_GAPSS_STAT_HAPPY) { - lwsl_debug("%s: saw we were happy\n", __func__); - - return; - } - - lwsl_notice("%s: forcing rescan\n", __func__); - - lws_gapss_to(LWS_GAPSS_SCAN); - scan_ongoing = 0; - n = esp_wifi_scan_start(&scan_config, false); - if (n != ESP_OK) - lwsl_err("scan start failed %d\n", n); -} - - -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) - -void __attribute__(( weak )) -lws_group_member_event(int e, void *p) -{ -} - -void __attribute__(( weak )) -lws_get_iframe_size(int *w, int *h) -{ - *w = 320; - *h = 160; -} - -void lws_group_member_event_call(int e, void *p) -{ - lws_group_member_event(e, p); -} - -static int -get_txt_param(const mdns_result_t *mr, const char *param, char *result, int len) -{ - const char *p; - - *result = '\0'; - - p = strstr(mr->txt->key, param); - if (!p) { - *result = '\0'; - return 1; - } - - lws_strncpy(result, mr->txt->value, len); - - return 0; -} - -static void lws_esp32_mdns_timer_cb(TimerHandle_t th) -{ - uint64_t now = lws_now_usecs(); - struct lws_group_member *p, **p1; - const mdns_result_t *r = mdns_results_head; - - while (r) { - char ch = 0, group[16]; - - get_txt_param(r, "group", group, sizeof(group)); - if (strcmp(group, lws_esp32.group)) /* not our group */ { - lwsl_notice("group %s vs %s %s\n", - group, lws_esp32.group, r->txt->value); - continue; - } - - p = lws_esp32.first; - while (p) { - if (strcmp(r->hostname, p->host)) - goto next; - if (memcmp(&r->addr, &p->addr, sizeof(r->addr))) - goto next; - - p->last_seen = now; - break; -next: - p = p->next; - } - if (!p) { /* did not find */ - char temp[8]; - - p = lws_malloc(sizeof(*p), "group"); - if (!p) - continue; - lws_strncpy(p->host, r->hostname, sizeof(p->host)); - - get_txt_param(r, "model", p->model, sizeof(p->model)); - get_txt_param(r, "role", p->role, sizeof(p->role)); - get_txt_param(r, "mac", p->mac, sizeof(p->mac)); - get_txt_param(r, "width", temp, sizeof(temp)); - p->width = atoi(temp); - get_txt_param(r, "height", temp, sizeof(temp)); - p->height = atoi(temp); - - memcpy(&p->addr, &r->addr, sizeof(p->addr)); -// memcpy(&p->addrv6, &r->addrv6, sizeof(p->addrv6)); - p->last_seen = now; - p->flags = 0; - p->next = lws_esp32.first; - lws_esp32.first = p; - lws_esp32.extant_group_members++; - - lws_group_member_event_call(LWS_SYSTEM_GROUP_MEMBER_ADD, p); - } else { - if (memcmp(&p->addr, &r->addr, sizeof(p->addr))) { - memcpy(&p->addr, &r->addr, sizeof(p->addr)); - ch = 1; - } -/* if (memcmp(&p->addrv6, &r->addrv6, sizeof(p->addrv6))) { - memcpy(&p->addrv6, &r->addrv6, sizeof(p->addrv6)); - ch = 1; - } */ - if (ch) - lws_group_member_event_call(LWS_SYSTEM_GROUP_MEMBER_CHANGE, p); - } - } - - mdns_query_results_free(mdns_results_head); - - /* garbage-collect group members not seen for too long */ - p1 = &lws_esp32.first; - while (*p1) { - p = *p1; - if (!(p->flags & LWS_GROUP_FLAG_SELF) && - now - p->last_seen > 60000000) { - lws_esp32.extant_group_members--; - *p1 = p->next; - - lws_group_member_event_call(LWS_SYSTEM_GROUP_MEMBER_REMOVE, p); - lws_free(p); - continue; - } - p1 = &(*p1)->next; - } - - mdns_query_txt(lws_esp32.group, "_lwsgrmem", "_tcp", 0, - &mdns_results_head); - xTimerStart(mdns_timer, 0); -} -#endif - -void __attribute__(( weak )) -lws_esp32_button(int down) -{ -} - -void IRAM_ATTR -gpio_irq(void *arg) -{ - gpio_set_intr_type(GPIO_SW, GPIO_INTR_DISABLE); - xTimerStart(debounce_timer, 0); -} - -static void lws_esp32_debounce_timer_cb(TimerHandle_t th) -{ - if (lws_esp32.button_is_down) - gpio_set_intr_type(GPIO_SW, GPIO_INTR_POSEDGE); - else - gpio_set_intr_type(GPIO_SW, GPIO_INTR_NEGEDGE); - - lws_esp32.button_is_down = gpio_get_level(GPIO_SW); - - lws_esp32_button(lws_esp32.button_is_down); -} - - -static int -start_scan() -{ - /* if no APs configured, no point... */ - - if (!lws_esp32.ssid[0][0] && - !lws_esp32.ssid[1][0] && - !lws_esp32.ssid[2][0] && - !lws_esp32.ssid[3][0]) - return 0; - - if (scan_timer_exists && !scan_ongoing) { - // lwsl_notice("Starting scan timer...\n"); - scan_ongoing = 1; - xTimerStart(scan_timer, 0); - } - - return 0; -} - - - -static void -end_scan() -{ - wifi_ap_record_t ap_records[10]; - uint16_t count_ap_records; - int n, m; - - count_ap_records = LWS_ARRAY_SIZE(ap_records); - if (esp_wifi_scan_get_ap_records(&count_ap_records, ap_records)) { - lwsl_err("%s: failed\n", __func__); - return; - } - - if (!count_ap_records) - goto passthru; - - if (gapss != LWS_GAPSS_SCAN) { - lwsl_info("ignoring scan as gapss %s\n", gapss_str[gapss]); - goto passthru; - } - - /* no point if no APs set up */ - if (!lws_esp32.ssid[0][0] && - !lws_esp32.ssid[1][0] && - !lws_esp32.ssid[2][0] && - !lws_esp32.ssid[3][0]) - goto passthru; - - lwsl_info("checking %d scan records\n", count_ap_records); - - for (n = 0; n < 4; n++) { - - if (!lws_esp32.ssid[(n + try_slot + 1) & 3][0]) - continue; - - lwsl_debug("looking for %s\n", - lws_esp32.ssid[(n + try_slot + 1) & 3]); - - /* this ssid appears in scan results? */ - - for (m = 0; m < count_ap_records; m++) { - // lwsl_notice(" %s\n", ap_records[m].ssid); - if (!strcmp((char *)ap_records[m].ssid, - lws_esp32.ssid[(n + try_slot + 1) & 3])) - goto hit; - } - - continue; - -hit: - m = (n + try_slot + 1) & 3; - try_slot = m; - lwsl_info("Attempting connection with slot %d: %s:\n", m, - lws_esp32.ssid[m]); - /* set the ssid we last tried to connect to */ - lws_strncpy(lws_esp32.active_ssid, lws_esp32.ssid[m], - sizeof(lws_esp32.active_ssid)); - - lws_strncpy((char *)sta_config.sta.ssid, lws_esp32.ssid[m], - sizeof(sta_config.sta.ssid)); - lws_strncpy((char *)sta_config.sta.password, lws_esp32.password[m], - sizeof(sta_config.sta.password)); - - tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, - (const char *)&config.ap.ssid[7]); - lws_gapss_to(LWS_GAPSS_STAT); - xTimerStop(association_timer, 0); - xTimerStart(association_timer, 0); - - esp_wifi_set_config(WIFI_IF_STA, &sta_config); - esp_wifi_connect(); - break; - } - - if (n == 4) - start_scan(); - -passthru: - if (lws_esp32.scan_consumer) - lws_esp32.scan_consumer(count_ap_records, ap_records, - lws_esp32.scan_consumer_arg); - -} - -static void -lws_set_genled(int n) -{ - lws_esp32.genled_t = lws_now_usecs(); - lws_esp32.genled = n; -} - -int -lws_esp32_leds_network_indication(void) -{ - uint64_t us, r; - int n, fadein = 100, speed = 1199, div = 1, base = 0; - - r = lws_now_usecs(); - us = r - lws_esp32.genled_t; - - switch (lws_esp32.genled) { - case LWSESP32_GENLED__INIT: - lws_esp32.genled = LWSESP32_GENLED__LOST_NETWORK; - /* fallthru */ - case LWSESP32_GENLED__LOST_NETWORK: - fadein = us / 10000; /* 100 steps in 1s */ - if (fadein > 100) { - fadein = 100; - lws_esp32.genled = LWSESP32_GENLED__NO_NETWORK; - } - /* fallthru */ - case LWSESP32_GENLED__NO_NETWORK: - break; - case LWSESP32_GENLED__CONN_AP: - base = 4096; - speed = 933; - div = 2; - break; - case LWSESP32_GENLED__GOT_IP: - fadein = us / 10000; /* 100 steps in 1s */ - if (fadein > 100) { - fadein = 100; - lws_esp32.genled = LWSESP32_GENLED__OK; - } - fadein = 100 - fadein; /* we are fading out */ - /* fallthru */ - case LWSESP32_GENLED__OK: - if (lws_esp32.genled == LWSESP32_GENLED__OK) - return 0; - - base = 4096; - speed = 766; - div = 3; - break; - } - - n = base + (lws_esp32_sine_interp(r / speed) / div); - return (n * fadein) / 100; -} - -esp_err_t lws_esp32_event_passthru(void *ctx, system_event_t *event) -{ -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) - struct lws_group_member *mem; - int n; -#endif - nvs_handle nvh; - uint32_t use; - - switch((int)event->event_id) { - case SYSTEM_EVENT_STA_START: - //esp_wifi_connect(); -// break; - /* fallthru */ - case SYSTEM_EVENT_STA_DISCONNECTED: - lwsl_notice("SYSTEM_EVENT_STA_DISCONNECTED\n"); - if (sntp_enabled()) - sntp_stop(); - lws_esp32.conn_ap = 0; - lws_esp32.inet = 0; - lws_esp32.sta_ip[0] = '\0'; - lws_esp32.sta_mask[0] = '\0'; - lws_esp32.sta_gw[0] = '\0'; - lws_gapss_to(LWS_GAPSS_SCAN); - mdns_free(); - lws_set_genled(LWSESP32_GENLED__LOST_NETWORK); - start_scan(); - esp_wifi_connect(); - break; - - case SYSTEM_EVENT_STA_CONNECTED: - lws_esp32.conn_ap = 1; - lws_set_genled(LWSESP32_GENLED__CONN_AP); - break; - - case SYSTEM_EVENT_STA_GOT_IP: - lwsl_notice("SYSTEM_EVENT_STA_GOT_IP\n"); - - lws_esp32.inet = 1; - lws_set_genled(LWSESP32_GENLED__GOT_IP); - - render_ip(lws_esp32.sta_ip, sizeof(lws_esp32.sta_ip) - 1, - (uint8_t *)&event->event_info.got_ip.ip_info.ip); - render_ip(lws_esp32.sta_mask, sizeof(lws_esp32.sta_mask) - 1, - (uint8_t *)&event->event_info.got_ip.ip_info.netmask); - render_ip(lws_esp32.sta_gw, sizeof(lws_esp32.sta_gw) - 1, - (uint8_t *)&event->event_info.got_ip.ip_info.gw); - - if (!nvs_open("lws-station", NVS_READWRITE, &nvh)) { - char slot[8]; - - lws_snprintf(slot, sizeof(slot) - 1, "%duse", try_slot); - use = 0; - nvs_get_u32(nvh, slot, &use); - nvs_set_u32(nvh, slot, use + 1); - nvs_commit(nvh); - nvs_close(nvh); - } - - lws_gapss_to(LWS_GAPSS_STAT_HAPPY); - -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) - n = mdns_init(); - if (!n) { - static mdns_txt_item_t txta[6]; - static char wh[2][6]; - int w, h; - - mdns_hostname_set(lws_esp32.hostname); - mdns_instance_name_set(lws_esp32.group); - - lws_get_iframe_size(&w, &h); - - txta[0].key = "model"; - txta[1].key = "group"; - txta[2].key = "role"; - txta[3].key = "mac"; - txta[4].key = "width"; - txta[5].key = "height"; - - txta[0].value = lws_esp32.model; - txta[1].value = lws_esp32.group; - txta[2].value = lws_esp32.role; - txta[3].value = lws_esp32.mac; - txta[4].value = wh[0]; - txta[5].value = wh[1]; - - lws_snprintf(wh[0], 6, "%d", w); - lws_snprintf(wh[1], 6, "%d", h); - - mdns_service_add(lws_esp32.group, - "_lwsgrmem", "_tcp", 443, txta, - LWS_ARRAY_SIZE(txta)); - - mem = lws_esp32.first; - while (mem) { - if (mem->flags & 1) - break; - mem = mem->next; - } - - if (!mem) { - struct lws_group_member *mem = - lws_malloc(sizeof(*mem), "group"); - if (mem) { - mem->last_seen = ~(uint64_t)0; - strcpy(mem->model, lws_esp32.model); - strcpy(mem->role, lws_esp32.role); - strcpy(mem->host, lws_esp32.hostname); - strcpy(mem->mac, lws_esp32.mac); - mem->flags = LWS_GROUP_FLAG_SELF; - lws_get_iframe_size(&mem->width, - &mem->height); - memcpy(&mem->addr, - &event->event_info.got_ip.ip_info.ip, - sizeof(mem->addr)); - memcpy(&mem->addrv6, - &event->event_info.got_ip6.ip6_info.ip, - sizeof(mem->addrv6)); - mem->next = lws_esp32.first; - lws_esp32.first = mem; - lws_esp32.extant_group_members++; - - lws_group_member_event_call( - LWS_SYSTEM_GROUP_MEMBER_ADD, mem); - } - } else { /* update our IP */ - memcpy(&mem->addr, - &event->event_info.got_ip.ip_info.ip, - sizeof(mem->addr)); - memcpy(&mem->addrv6, - &event->event_info.got_ip6.ip6_info.ip, - sizeof(mem->addrv6)); - lws_group_member_event_call( - LWS_SYSTEM_GROUP_MEMBER_CHANGE, mem); - } - - } else - lwsl_err("unable to init mdns on STA: %d\n", n); - - mdns_query_txt(lws_esp32.group, "_lwsgrmem", "_tcp", 0, - &mdns_results_head); - xTimerStart(mdns_timer, 0); -#endif - - lwsl_notice(" --- Got IP %s\n", lws_esp32.sta_ip); - if (!sntp_enabled()) { - sntp_setoperatingmode(SNTP_OPMODE_POLL); - sntp_setservername(0, "pool.ntp.org"); - sntp_init(); - } - break; - - case SYSTEM_EVENT_SCAN_DONE: - lwsl_notice("SYSTEM_EVENT_SCAN_DONE\n"); - end_scan(); - break; - - default: - break; - } - - return ESP_OK; -} - -#if defined(LWS_WITH_FILE_OPS) -static lws_fop_fd_t IRAM_ATTR -esp32_lws_fops_open(const struct lws_plat_file_ops *fops, const char *filename, - const char *vfs_path, lws_fop_flags_t *flags) -{ - struct esp32_file *f = malloc(sizeof(*f)); - lws_fop_fd_t fop_fd; - size_t len, csum; - - lwsl_notice("%s: %s\n", __func__, filename); - - if (!f) - return NULL; - f->i = romfs_get_info(lws_esp32_romfs, filename, &len, &csum); - if (!f->i) - goto bail; - - fop_fd = malloc(sizeof(*fop_fd)); - if (!fop_fd) - goto bail; - - fop_fd->fops = fops; - fop_fd->filesystem_priv = f; - fop_fd->mod_time = csum; - *flags |= LWS_FOP_FLAG_MOD_TIME_VALID; - fop_fd->flags = *flags; - - fop_fd->len = len; - fop_fd->pos = 0; - - return fop_fd; - -bail: - free(f); - - return NULL; -} - -static int IRAM_ATTR -esp32_lws_fops_close(lws_fop_fd_t *fop_fd) -{ - free((*fop_fd)->filesystem_priv); - free(*fop_fd); - - *fop_fd = NULL; - - return 0; -} -static lws_fileofs_t IRAM_ATTR -esp32_lws_fops_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset_from_cur_pos) -{ - fop_fd->pos += offset_from_cur_pos; - - if (fop_fd->pos > fop_fd->len) - fop_fd->pos = fop_fd->len; - - return 0; -} - -static int IRAM_ATTR -esp32_lws_fops_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, uint8_t *buf, - lws_filepos_t len) -{ - struct esp32_file *f = fop_fd->filesystem_priv; -#if 0 - if ((long)buf & 3) { - lwsl_err("misaligned buf\n"); - - return -1; - } -#endif - if (fop_fd->pos >= fop_fd->len) - return 0; - - if (len > fop_fd->len - fop_fd->pos) - len = fop_fd->len - fop_fd->pos; - - spi_flash_read((uint32_t)(char *)f->i + fop_fd->pos, buf, len); - - *amount = len; - fop_fd->pos += len; - - return 0; -} - -static const struct lws_plat_file_ops fops = { - .next = &fops_zip, - .LWS_FOP_OPEN = esp32_lws_fops_open, - .LWS_FOP_CLOSE = esp32_lws_fops_close, - .LWS_FOP_READ = esp32_lws_fops_read, - .LWS_FOP_SEEK_CUR = esp32_lws_fops_seek_cur, -}; -#endif - -int -lws_esp32_wlan_nvs_get(int retry) -{ - nvs_handle nvh; - char lws_esp32_force_ap = 0, slot[12]; - size_t s; - uint8_t mac[6]; - int n; - - esp_efuse_mac_get_default(mac); - mac[5] |= 1; /* match the AP MAC */ - snprintf(lws_esp32.serial, sizeof(lws_esp32.serial) - 1, - "%02X%02X%02X", mac[3], mac[4], mac[5]); - snprintf(lws_esp32.mac, sizeof(lws_esp32.mac) - 1, - "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], - mac[4], mac[5]); - - ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh)); - - config.sta.ssid[0] = '\0'; - config.sta.password[0] = '\0'; - - for (n = 0; n < 4; n++) { - lws_snprintf(slot, sizeof(slot) - 1, "%dssid", n); - s = sizeof(lws_esp32.ssid[0]) - 1; - lws_esp32.ssid[n][0] = '\0'; - nvs_get_str(nvh, slot, lws_esp32.ssid[n], &s); - - lws_snprintf(slot, sizeof(slot) - 1, "%dpassword", n); - s = sizeof(lws_esp32.password[0]) - 1; - lws_esp32.password[n][0] = '\0'; - nvs_get_str(nvh, slot, lws_esp32.password[n], &s); - } - - s = sizeof(lws_esp32.serial) - 1; - if (nvs_get_str(nvh, "serial", lws_esp32.serial, &s) != ESP_OK) - lws_esp32_force_ap = 1; - else - snprintf((char *)config.ap.ssid, sizeof(config.ap.ssid) - 1, - "config-%s-%s", lws_esp32.model, lws_esp32.serial); - s = sizeof(lws_esp32.opts) - 1; - if (nvs_get_str(nvh, "opts", lws_esp32.opts, &s) != ESP_OK) - lws_esp32_force_ap = 1; - - lws_esp32.access_pw[0] = '\0'; - nvs_get_str(nvh, "access_pw", lws_esp32.access_pw, &s); - - lws_esp32.group[0] = '\0'; - s = sizeof(lws_esp32.group); - nvs_get_str(nvh, "group", lws_esp32.group, &s); - - lws_esp32.role[0] = '\0'; - s = sizeof(lws_esp32.role); - nvs_get_str(nvh, "role", lws_esp32.role, &s); - - /* if group and role defined: group-role */ - if (lws_esp32.group[0] && lws_esp32.role[0]) - lws_snprintf(lws_esp32.hostname, sizeof(lws_esp32.hostname) - 1, - "%s-%s", lws_esp32.group, lws_esp32.role); - else /* otherwise model-serial */ - lws_snprintf(lws_esp32.hostname, sizeof(lws_esp32.hostname) - 1, - "%s-%s", lws_esp32.model, lws_esp32.serial); - - nvs_close(nvh); - - lws_gapss_to(LWS_GAPSS_SCAN); - start_scan(); - - return lws_esp32_force_ap; -} - - -void -lws_esp32_wlan_config(void) -{ - ledc_timer_config_t ledc_timer = { - .bit_num = LEDC_TIMER_13_BIT, - .freq_hz = 5000, - .speed_mode = LEDC_HIGH_SPEED_MODE, - .timer_num = LEDC_TIMER_0 - }; - int n; - - lwsl_debug("%s\n", __func__); - - ledc_timer_config(&ledc_timer); - - lws_set_genled(LWSESP32_GENLED__INIT); - - /* user code needs to provide lws_esp32_leds_timer_cb */ - - leds_timer = xTimerCreate("lws_leds", pdMS_TO_TICKS(25), 1, NULL, - (TimerCallbackFunction_t)lws_esp32_leds_timer_cb); - scan_timer = xTimerCreate("lws_scan", pdMS_TO_TICKS(10000), 0, NULL, - (TimerCallbackFunction_t)lws_esp32_scan_timer_cb); - debounce_timer = xTimerCreate("lws_db", pdMS_TO_TICKS(100), 0, NULL, - (TimerCallbackFunction_t)lws_esp32_debounce_timer_cb); - association_timer = xTimerCreate("lws_assoc", pdMS_TO_TICKS(10000), 0, NULL, - (TimerCallbackFunction_t)lws_esp32_assoc_timer_cb); - -#if !defined(CONFIG_LWS_IS_FACTORY_APPLICATION) - mdns_timer = xTimerCreate("lws_mdns", pdMS_TO_TICKS(5000), 0, NULL, - (TimerCallbackFunction_t)lws_esp32_mdns_timer_cb); -#endif - scan_timer_exists = 1; - xTimerStart(leds_timer, 0); - - *(volatile uint32_t *)PERIPHS_IO_MUX_MTMS_U = FUNC_MTMS_GPIO14; - - gpio_output_set(0, 0, 0, (1 << GPIO_SW)); - - n = gpio_install_isr_service(0); - if (!n) { - gpio_config_t c; - - c.intr_type = GPIO_INTR_NEGEDGE; - c.mode = GPIO_MODE_INPUT; - c.pin_bit_mask = 1 << GPIO_SW; - c.pull_down_en = 0; - c.pull_up_en = 0; - gpio_config(&c); - - if (gpio_isr_handler_add(GPIO_SW, gpio_irq, NULL)) - lwsl_notice("isr handler add for 14 failed\n"); - } else - lwsl_notice("failed to install gpio isr service: %d\n", n); - - lws_esp32_wlan_nvs_get(0); - tcpip_adapter_init(); -} - -void -lws_esp32_wlan_start_ap(void) -{ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - - ESP_ERROR_CHECK( esp_wifi_init(&cfg)); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM)); - - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_APSTA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &config) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config)); - ESP_ERROR_CHECK( esp_wifi_start()); - - esp_wifi_scan_start(&scan_config, false); - - if (sta_config.sta.ssid[0]) { - tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, - (const char *)&config.ap.ssid[7]); - // esp_wifi_set_auto_connect(1); - ESP_ERROR_CHECK( esp_wifi_connect()); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config)); - ESP_ERROR_CHECK( esp_wifi_connect()); - } -} - -void -lws_esp32_wlan_start_station(void) -{ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - - ESP_ERROR_CHECK( esp_wifi_init(&cfg)); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM)); - - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config)); - - ESP_ERROR_CHECK( esp_wifi_start()); - - tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, - (const char *)&config.ap.ssid[7]); - //esp_wifi_set_auto_connect(1); - //ESP_ERROR_CHECK( esp_wifi_connect()); - - lws_esp32_scan_timer_cb(NULL); -} - -const esp_partition_t * -lws_esp_ota_get_boot_partition(void) -{ - const esp_partition_t *part = esp_ota_get_boot_partition(), - *factory_part, *ota; - esp_image_header_t eih, ota_eih; - uint32_t *p_force_factory_magic = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS; - - /* confirm what we are told is the boot part is sane */ - spi_flash_read(part->address , &eih, sizeof(eih)); - factory_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, - ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); - ota = esp_partition_find_first(ESP_PARTITION_TYPE_APP, - ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL); - spi_flash_read(ota->address , &ota_eih, sizeof(ota_eih)); - - if (eih.spi_mode == 0xff || - *p_force_factory_magic == LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY || - *p_force_factory_magic == LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON - ) { - /* - * we believed we were going to boot OTA, but we fell - * back to FACTORY in the bootloader when we saw it - * had been erased. esp_ota_get_boot_partition() still - * says the OTA partition then even if we are in the - * factory partition right now. - */ - part = factory_part; - } - -#ifdef CONFIG_LWS_IS_FACTORY_APPLICATION - else - if (ota_eih.spi_mode != 0xff && - part->address != factory_part->address) { - uint8_t buf[4096]; - uint32_t n; - /* - * we are a FACTORY image running in an OTA slot... - * it means we were just written and need to copy - * ourselves into the FACTORY slot. - */ - lwsl_notice("Copying FACTORY update into place " - "0x%x len 0x%x\n", factory_part->address, - factory_part->size); - esp_task_wdt_reset(); - if (spi_flash_erase_range(factory_part->address, - factory_part->size)) { - lwsl_err("spi: Failed to erase\n"); - goto retry; - } - - for (n = 0; n < factory_part->size; n += sizeof(buf)) { - esp_task_wdt_reset(); - spi_flash_read(part->address + n , buf, - sizeof(buf)); - if (spi_flash_write(factory_part->address + n, - buf, sizeof(buf))) { - lwsl_err("spi: Failed to write\n"); - goto retry; - } - } - - /* - * We send a message to the bootloader to erase the OTA header, we will come back up in - * factory where the user can reload the OTA image - */ - lwsl_notice(" FACTORY copy successful, rebooting\n"); - lws_esp32_restart_guided(LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY_ERASE_OTA); -retry: - esp_restart(); - } -#endif - - return part; -} - - -void -lws_esp32_set_creation_defaults(struct lws_context_creation_info *info) -{ - const esp_partition_t *part; - - memset(info, 0, sizeof(*info)); - - lws_set_log_level(63, lwsl_emit_syslog); - - part = lws_esp_ota_get_boot_partition(); - (void)part; - - info->vhost_name = "default"; - info->port = 443; - info->fd_limit_per_thread = 16; - info->max_http_header_pool = 5; - info->max_http_header_data = 1024; - info->pt_serv_buf_size = 4096; - info->keepalive_timeout = 30; - info->timeout_secs = 30; - info->simultaneous_ssl_restriction = 2; - info->options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | - LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; -} - -int -lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i, - char *json, int json_len) -{ - esp_image_segment_header_t eis; - esp_image_header_t eih; - uint32_t hdr; - - spi_flash_read(part->address , &eih, sizeof(eih)); - hdr = part->address + sizeof(eih); - - if (eih.magic != ESP_IMAGE_HEADER_MAGIC) { - lwsl_notice("%s: bad image header magic\n", __func__); - return 1; - } - - eis.data_len = 0; - while (eih.segment_count-- && eis.data_len != 0xffffffff) { - spi_flash_read(hdr, &eis, sizeof(eis)); - hdr += sizeof(eis) + eis.data_len; - } - hdr += (~hdr & 15) + 1; - - if (eih.hash_appended) - hdr += 0x20; - -// lwsl_notice("romfs estimated at 0x%x\n", hdr); - - i->romfs = hdr + 0x4; - spi_flash_read(hdr, &i->romfs_len, sizeof(i->romfs_len)); - i->json = i->romfs + i->romfs_len + 4; - spi_flash_read(i->json - 4, &i->json_len, sizeof(i->json_len)); - - if (i->json_len < json_len - 1) - json_len = i->json_len; - spi_flash_read(i->json, json, json_len); - json[json_len] = '\0'; - - return 0; -} - -static int -_rngf(void *context, unsigned char *buf, size_t len) -{ - if (lws_get_random(context, buf, len) == len) - return 0; - - return -1; -} - -int -lws_esp32_selfsigned(struct lws_vhost *vhost) -{ - mbedtls_x509write_cert crt; - char subject[200]; - mbedtls_pk_context mpk; - int buf_size = 4096, n; - uint8_t *buf = malloc(buf_size); /* malloc because given to user code */ - mbedtls_mpi mpi; - nvs_handle nvh; - size_t s; - - lwsl_notice("%s: %s\n", __func__, vhost->name); - - if (!buf) - return -1; - - if (nvs_open("lws-station", NVS_READWRITE, &nvh)) { - lwsl_notice("%s: can't open nvs\n", __func__); - free(buf); - return 1; - } - - n = 0; - if (!nvs_get_blob(nvh, vhost->tls.alloc_cert_path, NULL, &s)) - n |= 1; - if (!nvs_get_blob(nvh, vhost->tls.key_path, NULL, &s)) - n |= 2; - - nvs_close(nvh); - if (n == 3) { - lwsl_notice("%s: certs exist\n", __func__); - free(buf); - return 0; /* certs already exist */ - } - - lwsl_notice("%s: creating selfsigned initial certs\n", __func__); - - mbedtls_x509write_crt_init(&crt); - - mbedtls_pk_init(&mpk); - if (mbedtls_pk_setup(&mpk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) { - lwsl_notice("%s: pk_setup failed\n", __func__); - goto fail; - } - lwsl_notice("%s: generating 2048-bit RSA keypair... " - "this may take a minute or so...\n", __func__); - n = mbedtls_rsa_gen_key(mbedtls_pk_rsa(mpk), _rngf, vhost->context, - 2048, 65537); - if (n) { - lwsl_notice("%s: failed to generate keys\n", __func__); - goto fail1; - } - lwsl_notice("%s: keys done\n", __func__); - - /* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */ - - lws_snprintf(subject, sizeof(subject) - 1, - "C=TW,ST=New Taipei City,L=Taipei,O=warmcat,CN=%s", - lws_esp32.hostname); - - if (mbedtls_x509write_crt_set_subject_name(&crt, subject)) { - lwsl_notice("set SN failed\n"); - goto fail1; - } - mbedtls_x509write_crt_set_subject_key(&crt, &mpk); - if (mbedtls_x509write_crt_set_issuer_name(&crt, subject)) { - lwsl_notice("set IN failed\n"); - goto fail1; - } - mbedtls_x509write_crt_set_issuer_key(&crt, &mpk); - - lws_get_random(vhost->context, &n, sizeof(n)); - lws_snprintf(subject, sizeof(subject), "%d", n); - - mbedtls_mpi_init(&mpi); - mbedtls_mpi_read_string(&mpi, 10, subject); - mbedtls_x509write_crt_set_serial(&crt, &mpi); - mbedtls_mpi_free(&mpi); - - mbedtls_x509write_crt_set_validity(&crt, "20171105235959", - "20491231235959"); - - mbedtls_x509write_crt_set_key_usage(&crt, - MBEDTLS_X509_KU_DIGITAL_SIGNATURE | - MBEDTLS_X509_KU_KEY_ENCIPHERMENT); - - - mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256); - - n = mbedtls_x509write_crt_pem(&crt, buf, buf_size, _rngf, - vhost->context); - if (n < 0) { - lwsl_notice("%s: write crt der failed\n", __func__); - goto fail1; - } - - lws_plat_write_cert(vhost, 0, 0, buf, strlen((const char *)buf)); - - if (mbedtls_pk_write_key_pem(&mpk, buf, buf_size)) { - lwsl_notice("write key pem failed\n"); - goto fail1; - } - - lws_plat_write_cert(vhost, 1, 0, buf, strlen((const char *)buf)); - - mbedtls_pk_free(&mpk); - mbedtls_x509write_crt_free(&crt); - - lwsl_notice("%s: cert creation complete\n", __func__); - - return n; - -fail1: - mbedtls_pk_free(&mpk); -fail: - mbedtls_x509write_crt_free(&crt); - free(buf); - - nvs_close(nvh); - - return -1; -} - -void -lws_esp32_update_acme_info(void) -{ - int n; - - n = lws_plat_read_file("acme-email", lws_esp32.le_email, - sizeof(lws_esp32.le_email) - 1); - if (n >= 0) - lws_esp32.le_email[n] = '\0'; - - n = lws_plat_read_file("acme-cn", lws_esp32.le_dns, - sizeof(lws_esp32.le_dns) - 1); - if (n >= 0) - lws_esp32.le_dns[n] = '\0'; -} - -struct lws_context * -lws_esp32_init(struct lws_context_creation_info *info, struct lws_vhost **pvh) -{ - const esp_partition_t *part = lws_esp_ota_get_boot_partition(); - struct lws_context *context; - struct lws_esp32_image i; - struct lws_vhost *vhost; - struct lws wsi; - char buf[512]; - - context = lws_create_context(info); - if (context == NULL) { - lwsl_err("Failed to create context\n"); - return NULL; - } - - lws_esp32_get_image_info(part, &i, buf, sizeof(buf) - 1); - - lws_esp32_romfs = (romfs_t)i.romfs; - if (!romfs_mount_check(lws_esp32_romfs)) { - lwsl_err("mount error on ROMFS at %p 0x%x\n", lws_esp32_romfs, - i.romfs); - return NULL; - } - - lwsl_notice("ROMFS length %uKiB\n", i.romfs_len >> 10); - - puts(buf); - - /* set the lws vfs to use our romfs */ -#if defined(LWS_WITH_FILE_OPS) - lws_set_fops(context, &fops); -#endif - - info->options |= LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX | - LWS_SERVER_OPTION_IGNORE_MISSING_CERT; - - vhost = lws_create_vhost(context, info); - if (!vhost) { - lwsl_err("Failed to create vhost\n"); - return NULL; - } - - lws_esp32_update_acme_info(); - - lws_esp32_selfsigned(vhost); - wsi.context = vhost->context; - wsi.vhost = vhost; - - lws_tls_server_certs_load(vhost, &wsi, info->ssl_cert_filepath, - info->ssl_private_key_filepath, NULL, 0, NULL, 0); - - lws_init_vhost_client_ssl(info, vhost); - - if (pvh) - *pvh = vhost; - - if (lws_protocol_init(context)) - return NULL; - - return context; -} - -static const uint16_t sineq16[] = { - 0x0000, 0x0191, 0x031e, 0x04a4, 0x061e, 0x0789, 0x08e2, 0x0a24, - 0x0b4e, 0x0c5c, 0x0d4b, 0x0e1a, 0x0ec6, 0x0f4d, 0x0faf, 0x0fea, -}; - -static uint16_t sine_lu(int n) -{ - switch ((n >> 4) & 3) { - case 1: - return 4096 + sineq16[n & 15]; - case 2: - return 4096 + sineq16[15 - (n & 15)]; - case 3: - return 4096 - sineq16[n & 15]; - default: - return 4096 - sineq16[15 - (n & 15)]; - } -} - -/* useful for sine led fade patterns */ - -uint16_t lws_esp32_sine_interp(int n) -{ - /* - * 2: quadrant - * 4: table entry in quadrant - * 4: interp (LSB) - * - * total 10 bits / 1024 steps per cycle - * - * + 0: 0 - * + 256: 4096 - * + 512: 8192 - * + 768: 4096 - * +1023: 0 - */ - - return (sine_lu(n >> 4) * (15 - (n & 15)) + - sine_lu((n >> 4) + 1) * (n & 15)) / 15; -} -- Gitee From dfa94239833094b9b2648aa36be3146a416b25f8 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 14 Jul 2020 07:37:24 +0100 Subject: [PATCH 0217/1062] coverity: missing malloc return check This is only coming at vhost startup, for a server that's before we go busy with heap. But still, it should be checked. --- plugins/protocol_lws_server_status.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/protocol_lws_server_status.c b/plugins/protocol_lws_server_status.c index 3bb57b00..ab9a7978 100644 --- a/plugins/protocol_lws_server_status.c +++ b/plugins/protocol_lws_server_status.c @@ -152,6 +152,8 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason, v->period_s = 5; if (!strcmp(pvo->name, "filepath")) { fp = malloc(sizeof(*fp)); + if (!fp) + return -1; fp->next = NULL; lws_snprintf(&fp->filepath[0], sizeof(fp->filepath), "%s", -- Gitee From 677d79cc0866486c301221577088c69ed2ada661 Mon Sep 17 00:00:00 2001 From: Jed Lu Date: Tue, 14 Jul 2020 11:50:04 +0100 Subject: [PATCH 0218/1062] ss: rideshare: fix length can be wrong --- lib/secure-streams/protocols/ss-h1.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 0e267c88..39fe18d5 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -480,7 +480,6 @@ malformed: if (!h->rideshare) h->rideshare = h->policy; - buflen = lws_ptr_diff(end, p); #if defined(LWS_WITH_SS_RIDESHARE) if (!h->inside_msg && h->rideshare->u.http.multipart_name) lws_client_http_multipart(wsi, @@ -489,8 +488,11 @@ malformed: h->rideshare->u.http.multipart_content_type, (char **)&p, (char *)end); + buflen = lws_ptr_diff(end, p); if (h->policy->u.http.multipart_name) buflen -= 24; /* allow space for end of multipart */ +#else + buflen = lws_ptr_diff(end, p); #endif switch(h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f)) { -- Gitee From f21226ca3ec4468b92b4c35b27bd9baa61fafa0e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 14 Jul 2020 17:51:22 +0100 Subject: [PATCH 0219/1062] mqtt: remove fcntl.h These aren't needed and can make trouble in lwip case --- lib/roles/mqtt/mqtt.c | 3 --- lib/roles/mqtt/primitives.c | 2 -- 2 files changed, 5 deletions(-) diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index 6eeae7cc..0fa50919 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -42,11 +42,8 @@ */ #include "private-lib-core.h" -/* #include "lws-mqtt.h" */ - #include #include -#include #include typedef enum { diff --git a/lib/roles/mqtt/primitives.c b/lib/roles/mqtt/primitives.c index 9391e4f1..0fd8e5c9 100644 --- a/lib/roles/mqtt/primitives.c +++ b/lib/roles/mqtt/primitives.c @@ -27,11 +27,9 @@ */ #include "private-lib-core.h" -/* #include "lws-mqtt.h" */ #include #include -#include #include -- Gitee From abf9a7664fdefdd8164770b22cbb92e5063e9fef Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 14 Jul 2020 18:17:30 +0100 Subject: [PATCH 0220/1062] esp32: ctest: increase timeout for linkup and test to 60s --- minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt | 2 +- minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt index e2516648..ad6003c4 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/CMakeLists.txt @@ -30,6 +30,6 @@ if (ESP_PLATFORM) add_test(NAME boot COMMAND /usr/local/bin/sai-expect) set_tests_properties(boot PROPERTIES DEPENDS flashing - TIMEOUT 20) + TIMEOUT 60) endif() diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt b/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt index 4f8e21b9..eb0589a8 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/CMakeLists.txt @@ -28,6 +28,6 @@ if (ESP_PLATFORM) add_test(NAME boot COMMAND /usr/local/bin/sai-expect) set_tests_properties(boot PROPERTIES DEPENDS flashing - TIMEOUT 20) + TIMEOUT 60) endif() -- Gitee From 006eeaa6a06eef8c0c0fd423124bd8105338bd78 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 14 Jul 2020 19:40:11 +0100 Subject: [PATCH 0221/1062] ws: correctly handle ESTABLISHED rejecting connection https://github.com/warmcat/libwebsockets/issues/1973 --- lib/core-net/dummy-callback.c | 3 ++- lib/roles/ws/server-ws.c | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/core-net/dummy-callback.c b/lib/core-net/dummy-callback.c index c2826712..e093f999 100644 --- a/lib/core-net/dummy-callback.c +++ b/lib/core-net/dummy-callback.c @@ -122,7 +122,8 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason, if (!wsi->h1_ws_proxied || !wsi->parent) break; - lws_process_ws_upgrade2(wsi->parent); + if (lws_process_ws_upgrade2(wsi->parent)) + return -1; #if defined(LWS_WITH_HTTP2) if (wsi->parent->mux_substream) diff --git a/lib/roles/ws/server-ws.c b/lib/roles/ws/server-ws.c index 15e7d09b..ece465d2 100644 --- a/lib/roles/ws/server-ws.c +++ b/lib/roles/ws/server-ws.c @@ -375,7 +375,10 @@ lws_process_ws_upgrade2(struct lws *wsi) break; } - lws_server_init_wsi_for_ws(wsi); + if (lws_server_init_wsi_for_ws(wsi)) { + lwsl_notice("%s: user ESTABLISHED failed connection\n", __func__); + return 1; + } lwsl_parser("accepted v%02d connection\n", wsi->ws->ietf_spec_revision); #if defined(LWS_WITH_ACCESS_LOG) -- Gitee From e936c5e84d9df5a423b8b70b03bcffe39b9169dd Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 13 Jul 2020 13:21:22 +0100 Subject: [PATCH 0222/1062] changelog: prepare for v4.1 Having an -rc1 this time --- README.md | 92 +++++++++++++++++++++++++++++++++++- changelog | 86 +++++++++++++++++++++++++++++++++ doc-assets/lws-overview.png | Bin 1269733 -> 682811 bytes 3 files changed, 177 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8e1e7c47..3e433bdd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Libwebsockets -Libwebsockets is a simple-to-use, pure C library providing client and server +Libwebsockets is a simple-to-use, MIT-license, pure C library providing client and server for **http/1**, **http/2**, **websockets**, **MQTT** and other protocols in a security-minded, lightweight, configurable, scalable and flexible way. It's easy to build and cross-build via cmake and is suitable for tasks from embedded RTOS through mass @@ -16,6 +16,96 @@ various scenarios, CC0-licensed (public domain) for cut-and-paste, allow you to News ---- +## v4.1.0-rc1 is available for testing + +If you are interested in consuming released versions, please take a moment to test this +release candidate and report any bugs so that the release can have improved quality. + +See the [changelog](https://libwebsockets.org/git/libwebsockets/tree/changelog), summary + + - NEW: travis / appveyor / bintray are replaced by Sai + https://libwebsockets.org/sai/ which for lws currently does 167 builds per + git push on 16 platforms, all self-hosted. The homebrew bash scripts used + to select Minimal examples are replaced by CTest. Platforms currently + include Fedora/AMD/GCC, Windows/AMD/mingw32, Windows/AMD/mingw64, Android/ + aarch64/LLVM, esp-idf (on WROVER-KIT and HELTEC physical boards), Fedora/ + RISCV (on QEMU)/GCC, CentOS8/AMD/GCC, Gentoo/AMD/GCC, Bionic/AMD/GCC, + Linkit 7697, Focal/AMD/GCC, Windows (on QEMU)/AMD/MSVC, + Focal/aarch64-RPI4/GCC, iOS/aarch64/LLVM and OSX/AMD/LLVM. + + - NEW: The single CMakeLists.txt has been refactored and modernized into smaller + CMakeLists.txt in the subdirectory along with the code that is being managed + for build by it. Build options are still listed in the top level as before + but the new way is much more maintainable. + + - NEW: Captive Portal Detection. Lws can determine if the active default + route is able to connect to the internet, or is in a captive portal type + situation, by trying to connect to a remote server that will respond in an + unusual way, like provide a 204. + + - NEW: Secure streams: Support system trust store if it exists + Build on Windows + Support lws raw socket protocol in SS + Support Unix Domain Socket transport + + - NEW: Windows: Support Unix Domain Sockets same as other platforms + + - NEW: Windows: Build using native pthreads, async dns, ipv6 on MSVC + + - NEW: lws_struct: BLOB support + + - NEW: lws_sul: Now provides two sorted timer domains, a default one as + before, and another whose scheduled events are capable to wake the system from suspend + + - NEW: System Message Distribution: lws_smd provides a very lightweight way + to pass short messages between subsystems both in RTOS type case where the + subsystems are all on the lws event loop, and in the case participants are in + different processes, using Secure Streams proxying. Participants register a bitmap + of message classes they care about; if no particpant cares about a particular message, + it is rejected at allocation time for the sender, making it cheap to provide messages + speculatively. See lib/system/smd/README.md for full details. + + - NEW: lws_drivers: wrappers for SDK driver abstractions (or actual drivers) + See lib/drivers/README.md, example implementations + minimal-examples/embedded/esp32/esp-wrover-kit + - generic gpio + - generic LED (by name) lib/drivers/led/README.md + - generic PWM, sophisticated interpolated table + sequencers with crossfade + - generic button (by name), with debounce and press classification + emitting rich SMD click, long-click, double-click, + down, repeat, up JSON messages + lib/drivers/button/README.md + - bitbang i2c on generic gpio (hw support can use same + abstract API) + - bitbang spi on generic gpio (hw support can use same + abstract API) + - generic display object, can be wired up to controller + drivers that hook up by generic i2c or spi, + generic backlight PWM sequencing and + blanking timer support + - generic settings storage: get and set blobs by name + - generic network device: netdev abstract class with + WIFI / Ethernet implementations + using underlying SDK APIs; + generic 80211 Scan managements + and credentials handling via + lws_settings + This is the new way to provide embedded platform + functionality that was in the past done like + esp32-factory. Unlike the old way, the new way has no + native apis in it and can be built on other SDK / SoCs + the same. + + - NEW: Security-aware JWS JWT (JSON Web Tokens) apis are provided on top of the existing + JOSE / JWS apis. All the common algorithms are available along with some + high level apis like lws http cookie -> JWT struct -> lws http cookie. + + - REMOVED: esp32-helper and friends used by esp32-factory now lws_drivers + exists + + - REMOVED: generic sessions and friends now JWT is provided + ## v4.0 is released Users wanting a stable branch should follow v4.0-stable to get the most stable version diff --git a/changelog b/changelog index 8d98b9b9..c1a6516d 100644 --- a/changelog +++ b/changelog @@ -1,6 +1,92 @@ Changelog --------- +v4.1.0 +====== + + - NEW: travis / appveyor / bintray are replaced by Sai + https://libwebsockets.org/sai/ which for lws currently does 167 builds per + git push on 16 platforms, all self-hosted. The homebrew bash scripts used + to select Minimal examples are replaced by CTest. Platforms currently + include Fedora/AMD/GCC, Windows/AMD/mingw32, Windows/AMD/mingw64, Android/ + aarch64/LLVM, esp-idf (on WROVER-KIT and HELTEC physical boards), Fedora/ + RISCV (on QEMU)/GCC, CentOS8/AMD/GCC, Gentoo/AMD/GCC, Bionic/AMD/GCC, + Linkit 7697, Focal/AMD/GCC, Windows (on QEMU)/AMD/MSVC, + Focal/aarch64-RPI4/GCC, iOS/aarch64/LLVM and OSX/AMD/LLVM. + + - NEW: The single CMakeLists.txt has been refactored and modernized into smaller + CMakeLists.txt in the subdirectory along with the code that is being managed + for build by it. Build options are still listed in the top level as before + but the new way is much more maintainable. + + - NEW: Captive Portal Detection. Lws can determine if the active default + route is able to connect to the internet, or is in a captive portal type + situation, by trying to connect to a remote server that will respond in an + unusual way, like provide a 204. + + - NEW: Secure streams: Support system trust store if it exists + Build on Windows + Support lws raw socket protocol in SS + Support Unix Domain Socket transport + + - NEW: Windows: Support Unix Domain Sockets same as other platforms + + - NEW: Windows: Build using native pthreads, async dns, ipv6 on MSVC + + - NEW: lws_struct: BLOB support + + - NEW: lws_sul: Now provides two sorted timer domains, a default one as + before, and another whose scheduled events are capable to wake the system from suspend + + - NEW: System Message Distribution: lws_smd provides a very lightweight way + to pass short messages between subsystems both in RTOS type case where the + subsystems are all on the lws event loop, and in the case participants are in + different processes, using Secure Streams proxying. Participants register a bitmap + of message classes they care about; if no particpant cares about a particular message, + it is rejected at allocation time for the sender, making it cheap to provide messages + speculatively. See lib/system/smd/README.md for full details. + + - NEW: lws_drivers: wrappers for SDK driver abstractions (or actual drivers) + See lib/drivers/README.md, example implementations + minimal-examples/embedded/esp32/esp-wrover-kit + - generic gpio + - generic LED (by name) lib/drivers/led/README.md + - generic PWM, sophisticated interpolated table + sequencers with crossfade + - generic button (by name), with debounce and press classification + emitting rich SMD click, long-click, double-click, + down, repeat, up JSON messages + lib/drivers/button/README.md + - bitbang i2c on generic gpio (hw support can use same + abstract API) + - bitbang spi on generic gpio (hw support can use same + abstract API) + - generic display object, can be wired up to controller + drivers that hook up by generic i2c or spi, + generic backlight PWM sequencing and + blanking timer support + - generic settings storage: get and set blobs by name + - generic network device: netdev abstract class with + WIFI / Ethernet implementations + using underlying SDK APIs; + generic 80211 Scan managements + and credentials handling via + lws_settings + This is the new way to provide embedded platform + functionality that was in the past done like + esp32-factory. Unlike the old way, the new way has no + native apis in it and can be built on other SDK / SoCs + the same. + + - NEW: Security-aware JWS JWT (JSON Web Tokens) apis are provided on top of the existing + JOSE / JWS apis. All the common algorithms are available along with some + high level apis like lws http cookie -> JWT struct -> lws http cookie. + + - REMOVED: esp32-helper and friends used by esp32-factory now lws_drivers + exists + + - REMOVED: generic sessions and friends now JWT is provided + v4.0.0 ====== diff --git a/doc-assets/lws-overview.png b/doc-assets/lws-overview.png index 9b022c3e37f9408f221cd350befd54c7e55d13d5..af444d41718eb2c35172773cffc49d5d32ec67d6 100644 GIT binary patch literal 682811 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

kT7z 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

w8O4~*E+Z8Ed=5+dcjMgb z?>>-V@9u68j<;qxn8Nq|hEGe+m#}pPFrBm|p*PE!tqn;hqkmKelly_bpWHur1?-$) zAU-pJtp4$hM7*?J+}qHT5xJOsMWkps#c+B>;=h>$0spw4%hC8IxTZJWc%%aJitKE3 z*RL^sxQ-G=kODN%m&K8r;}Er5XUf(_EOPZ}(`;u&aD6OxQ~zsF3a@;oC$Z14(R2%m zEad@@1{3PeiR0&=d?)kCH zrs-loKSerXrM)*zzl?=JlP+Vo+^|6vvcH}3)hn_y=um^XQ+QJ`=bv|X|4N2n2!%jm z1um_zF9{P)0*kSi3o^`fB<~;4Ep6Drt6_Z~Tha|hpWf`9WKEn8DRCGkI+f3Uo!L@_JC$H?f^*A=$z2FX4(CTD$32 zt3jVe^mLEN3nnG?^*n{3a|;43QcHc5fqgdjk53V0VD#{g6Q9Ua%$B>XyyFjdQ&=da zm;0*GPUHAhK|La4QrO&*4yeM&b%jpIJ23WUE`4v(!?}_BaBad*_NmryEIY^9=+#rb zLv7{yl+{-8qjz<+QuoD07CsPj%Q#boDg~)yjb{&xmGjn3ZuED(tUqX^sF{rl)B@F* z6cVPk@as&xqD8Z_1= zPhZF;+wu%J{7Wo;+^INiU%W>TY)+$m@AN`VaxNqpA?jeK2u8q(7Dsc_+!4$3$ua|u zEKxk~>?b>lew+6#^KOWBN14=X1+W^OCJ4XBrUw8C5a)RLE=-^T|L*ZQ&SLzc?cYps zd5AL2`XczNvGfjg^#$MmP8?bK!be>?B7ECqc9yoHsufl0d#!cSL65oHWe&E z4PPO(G0hVy1tie(U+qTp|Gdu|st_NoJD_IhpcnKI?Z4@kD~X6z1Krb(MqmXtj#jWW zb4i)j>_k}|Heq53eO)IHfD7sl=sR{|Bl=%~O%4CG_Eo(X=7&$VH8|T=%=G3UYEZTM z)Y3fW%74`DxD`EWjrhu+qT+LL_5x^Ez?JB=V6Bl@A=2O+#iizHUU zHMHxttxpahaJ;RM4eP{pOvVmQ?&EL1@0WwuOfVIWYhiD)Wqc)A5;QdaS!bHE^qXzb z-0)Tcy~5dxj`nnq4u|&foiR46kGK0|=?kiI1u|_nP&tNQQTxv6C0)0`-SLV-5ftMF zY6t9)4}q^F1iG85_SAqLYZS?tXz!*N$yge7^I70!`-7@<_H=-Lm#s@=fh;zHl_gi8 zPkyo5LFVBmXx9GBD_D(1;X80o#?*xhQ3K;djsN-bK!ChNB$gXAK2y7R{q~&~xd60z zDKI%?oq~{G(Td*g)I)}Ym`#U(Vpp#D!&4=&Q`Q(qZigEV!7vX=*Ph(Vgi(6Gxg8&+ zXkH#ll2_prO5{RU4BU4tBx6~$fCLF>F#!m<0q5!vc^rG6-_A>C(GtxphPESu68lhl z6!u+y40_*+Wh88y9{Q!k;ZikIiM7Dr2Uip_4sd%MzJmjpzk(6%WTF^ff&qk_n9YNn z#^dTa#s@ChFAuEBL|L9^SnB3SODeFQIJCdtrL#N!iBWK(_5H4DxA>c3i3GCVfFjpL z6VYeh7r_>9KuLXU)h@~9k`7#n8GBy@v$g`$XpR_}K$sSez5k1FJKu#BRQ+j`QEl*N zl6vfKj=b8iJb3|+yF>B)@mT%&#STL-@;FOK^FMom> zqTRo=1?NIm7$vY_Vu;wrMR)O73>h+|gHDW`pK;r_=%}~Q{27adgX6rmSyVnzv*A-+ zqmR7(3g=FQh~=qEq+!A((bs18)||HH-*cm$q9Mcx*5KBCypmG*V{DVd*4>r;*R9{^ z=3r|w|NV2G#jK|&I?|_4l1!-Z3L%CN1)JyV8qN(y@2g#=e`zt6A)Q^PJW9);EjaAA zP$-uA)tvUqu;~v@0qJmf(*2K5`fJ0j41+S|v^0TGZix@A(G7~MkU~i)7B`pbL%us; zYDl9WjGJ{6!rhFx^Cwn)P~2H?sUW2-bHXwh!?>82RfT{5UTLjzSYYHi+{2W$kT>?# zxlZ1;&dX6W!E_qd}ob{q}th^icaFyvo>SG7oz-~}?-;<%?Qc)tvJ zfnT}nc3VNpFpK(e1bK>qoyrOUO6ae|>!b0YV{(B0J5d_c$PkATeouJdZd0_y?3z*v zpV6=MO~=!Askv`p#L+;P^5`NsJh&UAtg#hmdDZ7O$z&YtO2QIO%s0@5V!>evAjf59 zuN}j6y_~Razd$6mpHB?gRfH#@_o5WI+G78JBeFrVABCnu`vOe(Warqde@i?a#LU}B z`JD2>!EmTGGz5LFxVmr5OF~B@Ba7T8@P4ALWr4qcncCzi_*zJ5&FqqEwxjpa^76ORwqe+j z3gDY_MU4aa-GP6UyLd*S@BF5Bb&LaW#&uNT;%uFL>s$U)JQ=Qa)kW5SSsk=CaK`9x zi1ATIv!#p0sHwrftNQz#?veZp_FFMTO}!sJG$x_XkZX4iU!sM@idToeG<@GY{63VY zH%PnKZP$4;v{L*|V!@K&MIAn;OE_bvEO)1DkL3`&0?UF)MA$nKsqCi1I4`PrOH}Rt zqL|4p!(G5<`I0}~|0CtD?c>@3xlSTV{?*Iwe%C)y6o1f~cgUaSK!fiB4tBzgKK485 z%A@v>>u#f?VvDq&7^NauE3-$+5si(M!AolWC@yzF*mBM%XzyVTfEaDeL*8rqOZkfy zF+O~uByZwYsEyJKvf-$AGFxV21`!XBJ8!|MPKd^;Q@DW`y2jC6e#Ej-9elXrnkoZ? zWL-HXPDed(=Ro+us8>CizqF(yWu3-u!=yfmI=bl@K1BNn@v@G*{<{=RE^=)6CB3}m zOY2gzF=d-_#=oy>(*)bu%=<^50E-m}7%4<}kGH)EurX*$4>Zmh>oZZB4cQECDJFVg ziNyYO>##3VzI6XuQ^n?7YwR^h5&hvkZz)Z@Z}A5w2b0Yc1xs{fbaVq^k_m5FI%Oo6 zQKI&tB~U_^n!CJKs598}PU|arAaJkQ#fZ%u?Gkb3A5Iz2s0w?oRND9}sL_$`o#<@Y zvz*+;p0Hu>+Nm`cCzhtxCoay?EuM7a73^PXmH_WqI^@qz_`k7wuFiicf-jreD@=2k z74)~O*tC8SbKwOf36+0ICFPbsc^2IB_LP&gQ^JgbvRD>VY$n0F9F2Tx*40?%cc zek0wlokQh#`=J`Aaa>A21j(WEA$rI1Y|yW+k+#^i8Gd@%H^v0=9N3Y%nI{@tUEn7e z!MvDqA(uBba6!p~&a`DDC1=)ywTa&?jg8DHoAdCnnbW}s(_npg{!*@;I&sC@7&hZH zbUbkv>56DaH${wO>mZfl(l##fTinsnYVU5}xw>ev7`t!H%EOEr63&0|bp#HygJ=DW zx!~bpz#D{kuUWx5IjG}VlyE>b$1TINclZkHYQ)$$Vi+t;P8hU8%tU|M4#KeSIkOtS zm}Yui8lRrOz+tD?FjV`2pFZt{h@;ZW_Ez%n-&vh2l?eW4t-fz4IsMapv_^6P8AC=M zg~gEiafOVUhvfzASWJu7Jo>a^T-U0eLQA}HfuMXlX!%2-A)lH7OTh6Lc}Ef(lrh!j z9m^TUn7tksfy7BXp$G}m6{kYF>_yjG9Ppt*1@Y5mIk19Jt1fn7%{VGRNr6rFMb;}| zl;!m+7?Z358?21DgUF3k77Kfm`0D6)z&?|LO*iIXCvH6UUW`i3=}qRo1sc{Wy8h_P z$4|wpz58D~()OE5GNgTTs7b4BydGsh?PUuywWI8L=!dH0#?akJJBOHANOMW;aN^uZ znNsB*zvCsJC$XL*?okER@?tA}`T-24lem$Z8Sn_Hga1~^34q%^aI>g`72FVZ93rCU zKQ!CZRZkOrL-|L%v+rDP`8Z{KMcZhHYht>OnV$dnz?+pz%n$oE^*a351C#2jM>qth zL&N~OmJtUR0LN*jg-4?pPZZ=LkTQsf1Hd}2ILp4Vp zCMz*~!W}Bgr0<&57`&+Bd<0k-NN0yF)DferwGYoW&hNhPJNGF;Q!{@n#Pxu)nqf;= z8-1#H>OK_U>czIYYXmoSqay~W%pbXoVOfOh&_+Q*=ljgnq zx&bM@&au51v-Lf8nOf7uK3&k8pwN3wCQr!9aOzt5@PmD>Z6V?Wmq6*^@|lhgR`8g4 zOYIAyTRIoKat6?h@w?fEeohBlg@co)%T=`bnY#2?&Ul!gI53fT*u0GT;Yy8_S3IK6 ze#bf*Y-^YpBtl#_E0LdOCF*p{jlA=%{u<&KHZ6?HN0h6D-CBjz<$CK|T;aCos*gK z-iH!CS(f?XeeJ8bX|?~O!>gUoyrS0-9)F+ieO5LdZ(0XhS1g)Z^kq|MBDynbspy2d z-E+X8`FTibqBK>lx<#|h6e;zN_(AvXMpcDZB^H&aw?pu;`>JmbpXrl66347{vcA9B zV}A`(xm^}tcWJ!@!jjR*$pJ^b)N{ncOHD22WO=TTBwX}zlg3a*#%C6r6Um5d4ISqQ zOZE9khR+O*kcB z8Om>Qftm~GjQrSKbp~vQgO>~YHF~=d>=c8$DSfb(nQh@?RTaD@J+x@^uP85Cl&HJf z%}dTK!Q0~(o+UA@$+BdADa`c*0hJDbeYO0R3FVj~0bo1`wyDYy*(>QqUD5?TP3)>? zfFP&Nuc@!r(wjwP`vpUOLXWJKdF__&v@ESZ2NyGBng~9$OY?O|=Y8a|a{b~y@8P1=nOgJmZHV|kb}@xAgqtEhB2(+PV5yLTkFx^DT@vo$EJB=uYk?_qHiF3(Y z3f3+E56r=bpx2{Sa8+3B5RsW`!m;<0Wyy2HDCDo`0b)a1H1tkcUzVDRPL!u9$IYLQCQT_gl|zaeJ_`moYemNi-~6So4Toy5 zbu+I#IsA^NPOkYJZkj%0l&-g4@&52^&!x3Wh@NU(HZ0+gKutSqlQ1(~~&m4OaEb>zbk<4BY740N69HAWTM_C|`d%^S)gQ%P_H zbel!9Q>ZUg-tD7o#yTEe`|tB&4x(>dyAM@KO_Y4OzRY$0n&v-*nrAg|JA7NZm30Jz zQlrYitC17T=R}XAa>or`*()-8 z*mcbzu`dkEf~$2AbETSV`~_r8;JiYd@(brKdj<)s{zkb5?fb#ASGt28w3MI1b6b)R z20b@)%bA_TyC*!&N@hr-p3~x2)c2*{UQ|0hokmjnfZAeB@ z0^0{4;Vwt{@QKjF492(f5Cc~P5u+qC7rzARa}t_LiP(j|V?i_b2! z`2!Lwxm_Y3lRNACoGf>UX8f6K{BVPyuT^KI_Sf-+jmc`6psA-x_e1&>P&e`LB%E@U zPw~jFPeYGVFyupHsh|R>G_g{H^TM_k^)Y*o&K!kUXQ!V#?$NBbvUiyL+pKB{XYa1r z!4+u)<+IfQWZV+H3g#{Jt$Lhscp5W zoo}ATY$7gAFXyqXp6a_`Yk~2~PY>kw-_2n%xPjMRL002z&_tO@C(D#=|C9CIzv@8u zU@G!xLAv8ya;J@LCGEyE$9Jb0;v4s_qO~{yhP(wg|BhMiP-g&3#mbsDVc-z+W9$&& zRBv@EU*m^9LFo}&v)K9laC(T6e7Y>|r~clmn=}Gwv#IiFa$&seg}=}1GaJ7Bd;1jv zxzEzx5|7!Xu4lPQR(d_MdXJe7*W2la`DE~ahoLN!>1vpR9pZxacue2C3z!F9*>NU^5Cv;0Rx+!jI@w{g{sIjDOGN*u-G4x?fSD3F(@nP(Q z127Qj3PkXKG$kV6On$*w0bRD_0;+9OXm}p1%7G<4RnD-!l(|aSMp9OckL5WPC z!Xbyq$G}7@xHUaT4QfYaUgASzRA9zeTL-M_wkD*A%j=u6V?oaYKHp1^ZQ;7MX{HFR z6Uh0iK0dFnWErCFl???9sW<(;0UrHtj@;oBoQPP-2bV){)KV?7aAleOI1N8lmZZr`CeL=Y^CWfft5xHz zpkCuErOnpY5&5&IZ*a6x9<+;x@Cl*x?`WLB<|%mBMa!eP@+GV8Vd`l>^~81g#1!u8 zYy0w)K7IS=rG5irtOl=mtv({z5D~;xLCNw_F-mYVzq&4a; zJE7-muq*GEvm>6=R8Pxz;`Oj)WVq(^;gi|f1mKG#i7Y>&);W8kafwk3pb80 zFQH3?Zgl1|F(^HO5EyTWP6T8>E66Hp^UAI{=dowMC)3>1pfsJv0(s#<~Y-+XKn_ zJPMF>BA~%90lmJS%64_sY8;g@-!}Dk@g3eD_KOErZ@!LNC#nElA^|8uw$9rUX!c69 z%%wWdf}8&F!)oj_JtGOQUo6$=cz2?K!eRbOZ1N#^_@{$glk$(ZS?WFSiS|b+<<_<5 zhiU!EWKG#RQ_{h@2>re8&0%{2YytM)6dj{CDl+w!IfSYAF}nEqDCK(vlb;(A0ptppVZ&i1~0;B z#%~9i+mr3tmW0cuTTz1&PM!>@FJ7F)4ykV}n92+u2XMQByyuDfp)>8DpktB(ukoW5Itz<2-RsF;K6!w8i(upVXRrGM5Nt%N)`B zi&?Z0{x%|iOhk`cQ~py(va_{KSi%+`o`w?-QhYC1VzeOj?U$peYG8VuTo(dgB+uNO zsOthq5Z5o(Tn&)AkyE1lzuNxDuX!$B1ua_N-WROX;?Sr5@T>SY-Nc7?M)ltH{rDZ4 zn0&e9)3+Xa==VW0r+IOgob4P+PxIbjw7L>;HQJYMBjo z%T=c(cn0?~8~$~Z5`@!ou8Yaf%TK}aPO#!|N1KEMbnTpG7Bp~}qbQUNS2JXldIC-h z$)|7~gP-@QEK_N{XD%1e!U}MBt%Lu8M%+8c*SR-)&hzWl$2V^^ppq84hJ!W*#QL~sY@4R0+IKAkrNlH%5f9Hik_8UFi3T%lV?Jr4JnD?oN zy7XPT+4_4mAL;M!QWs;f_wRL>?-*>B6y3zpd&uk784TPvNvCe89Bx^O0Pjz_(}FA$S`QYP8D*&I$~IGU>HJMGD| zkr|I(sh?eeOk-R$9k+A(B%EM*&qNB5YGxA6HKJT;0i3sNps2>RoJfADY8lBrVc=Er z&CcsYfA2PKUw8oaPfhxMKnjldvj}lWceh_99}fOiW$H0FBHAA27AMC9whURX&v^KX zI=|XZ&H2Kl`{R0=!5z_IiM&znC&DgIF6;p6rs!qv9~$}}7T(7X?4C(eO))l4BGRXq zpU*|m!#;9-Mw@?fj={8v`&dQCu}i8e_XCe32k12mjaO~`XgskspT507*Tmib5sZBz zAD4rbAngP0sq!+-2HYS(1u=K@@J(2@6ezUAv#kbntdx**SSvM7oU@!J21SU5tf@b+=}3Gi2!UBM^#%HIj(YYV4CLtg_dF{^ z?9ZmU-xNYPp{ussIX7IQcEjSTr;^i~o4(mRGG0N#PgldTRYA8A&5WHoAL9VMpq&`> zoxC$!CL~q=e?&Z^qf_Yxyp3xZ`I!px<=esOzlAjWRs9O_ZM{^Xk5^@xr*-i7FT>lV zXjTM-(Mjd%S&&pH(xNIJ23AV!8}gj)!to3`g3A;8UG9@WeLhnFk{@ys)J zIjszmJG>Vpb1KaJ-Y}~`aakBB6a6rnzvvuuC7?TLG*xYg3f2~mJRD+pI^2l)(*4l;+erE^>+Et7@wYbRZ{BM^ z8>JGnTg5fSsbyh)pZIDv?y1L~w$4cCU#4O~o%Q;H(sxsD1|I99KWVG}-km%y9h0wf zfuJrIxfV-Q^{O}7z=RY0G#a;@Vk&h)pEbHhi*8dShF-YE&u-D*MB=AMm1<1F2`%k! z-};0HxO*KKKRTfi) zEWk=Mo++6S)XHc#^@X?j#Xo%78iv}25U1{^*zfNuaO0lx#iwG>_@jqX$cKNAGQkdi z2D2{{H1={#UFUfs^u!6xx2XLcy;penjm!n zPsS$o(hh99Tg?e?c$gGd1YDJCJY@d%(UI{R5M*6ek&w@4639~yV=as!0~Nx$ue;o` z!eC5Jze-ph2ZOLwVhWHlM=R3tB(W02pve*Yk9+A-b9V-O*(aoxuI9~f*qF1v~MP5xp)amWm8PJm6M^H5x4zq zZ{51t%ySi}8VbeiNRHY67KR>&$wTrf=h+ZqPdITU{%@~9Wl4LdliBAc9%!#<(lvQ58+bYnO7R@Mad3DgI4{gJad+8os{3e zHbx50Y8cfeMX+dsux3VC4K{!>UhQnM$-}&4*PM0sr#bIrg|(&uP4RtMRzE;kWogbg z^f+W+mLs-sHu=5H^|`DHwgGxF+DajG&I&g)N@?Wm;!$^2qVi!hJK64+xg)FQX` zT!!F=m3j9ycQ=38n@(mBi}DIrJ1*RJcU5WJ>}8dHaijQ{YrLq()pyLtGQ*}(<_G4c zX7JIRe>#ygr|hrwaFGxGe;=?w7N<^6vv1HoBc5Pk%N5n8NRHf*zzK0Jzt17B zvn_kdG=vuI8p#s+KGKZZ&h3;W8&7$rWmRrev@*9#ZW1re`cu7UHDg@-^KttMUa|u9 z7)CbMFTo{$Lpmp?=-X#RQyr=CHCcO?M_=jO4?eC*N^aV{+U;nt3}*jaubR`;rrj|Z zJIq6-E+=l*t4jA*YDe^bNxzh#r}a1~RxA=IP|zoNpXnkXk=5jH5v~#Pb%Ub1 zgR-Fw4;?yb@2ri_f2{i0Iye$m$7oMZ7Cs|@*Q8yA4B4C3)5B}5$%HOy{uwiVY&$Np zLW%OeTwZL<{(R(dq`v*E8gmN1Z^;lM*+|Nn_oKX$rQO9DK-WrP*5OM2{7#?03b*eQ z(}^^r@5_+HqArR03e%Y7TFUa}2XR1NC25}$AIN_XEw;ntvhKHJ&l;ny)&#q5gwu&_ zzIMc!ze`qqXuC!iC>-ju{v9Z!DAWRF^txh!9RE8lX5jB;-03)HJh3@n5VG| zZ8u_STrhtA;`zw}4gV+L@{XERS`_kJ5;|ECqMwz#t4sC`X$hT!vg zR|U8RSF6(GGn0Gv%XE^E5XbE2Jp;_GzN4%`Z;Rl?wJ;w_Bagn)sVq2t_3K4C2*kN7 zdi2vDhDTSHxO^It!DaFOXWxBwJ_xgLTIT+ed-*=OQGd1&Uv36kA@-&JQ6#zXfthc< z_J(7S!43=LlY?G`JqPi zm+j`NAy3p`l@#J3|Dkm8s4u<9I7f>tFJGDomeJYw29y_s4y!x_Z8O%MJ)5?f((v-w zE(W9+Gt@r+A5C8w6xI9weRf&8K|;DDq#FS#Q4mBBm6lFvX%KcnN~KduKtfQud+9Dg z8esux=~`gp+3)X}|IE()VqfgeoH^Hh)hAZ48|Qd{Q3KJ*!qEGNx!dyj{=v(>*}>TL zs;n1xG{~&q%Jlp_p$$M?HX7?viVHshlQDuR)D{0XADOo{y^BqaYd##|$?Zt*Qxn4~ z%z2GwFwn9jY_TX0xT;mz9`naRaTe_W1VBH6Cq3OfY&pJ?1-JT43&Yy39nEYrir1=ufhJ;m zoiE+Gb3!%~m-NM3UjLlQdRhXUVm4~{Gq%d}xidUZ4gGgFz}Tg4D;7gU%04itGgUmJ z*SeOC2w`E>-@TOg9%Xu>EQR`K-vY53UI!Y&5-U(Vo`^5EulG7OwepM95pv#xMx0hu z(>@z_f5!TWbawneB{_ZEdq9nh5-V7xJ&u2i=7y~b9}~)lLaB#OK|~}67j-F2lZ$fl z?x{znQ5+BiaVWl3b|KNL2pgepqR><|BTiy$+i`s?9(2_xRG-n+F6FVhwo{H8b0_1m zEN<%Y7;$7OP?p-!FsyMe>q-1Vd3%E!HczPfQDuoN{YoV7B7;a#aF;~b?B%-K!^36f z3I;TD(+~naN4sZZKL2A18`-RMErXkD#(MCiO25Xpq^#l`9Tt26U^e+*N4&yMRw~u| z!R=Lv_Xu$HsLUR7N2)`d{9qU zhCKJ1W8CasyR$fpuzy?f-pC0lV)N{;gmK&Z4#N$2NuSjVVos8!8~+gp6Vv7+S-<1o zXv)disV7QvujvxBeijupR(|oEq<-X(mdbb9{lWm$ZT*5%8$o0hAvOEt0vSPBSJi$0 z-slz$=$FxStgH%>ErFBcb0Tmhe6!*?wle9teH5}#`FTV88Q8+iXYskDVKBx(MQ+M8 z81q|j{HJ#1Fg1iILb~|uEW`~!QZ`DS+3goid)m$aW^pXg;y|(d7UTyAC;Jhw6TMj7i$*mu3Zbow*6axE0(JT~u`mE!W{9pg5OzoK@7JaYAkJ@ijK zQj#FQ@MTJs;0J%^2bXpSe{6)^z}1!}Tt1sT1I7h-g&T6LZ2Aub-DSsQ?W%)t7Cd_^ zwb_fUtuU;bAB3i*T+{$#O@*BrU-Vg^LXalyB1nD-DjtDFJvSxrVZ*1D4Av@ zTy`+cnZxbnui6df)v4?32ZfAPmzMAOUsNx3jRDxcnOrgCQ9x!nA;#43t%;#i(#B6t zfzpzSPM<&Pmb+4jlF2XQFE|~^K~OsVR}9N%J^vc+Yax4N0?o%CLDC9+H63-%_WJ&2 z&caT5u?Gy7GxLswF# zV^it0kmRd>4g|md@a9dp?;=ZdJQ=1<`L%Ve(-~A+2tWMI8giMMqtWpO#Wh3_;y?pL zo8X7&^Qib0!j$e@lU3Q;CjE^A3q?XQC-iGX_vq1)fKh*cL&-%yb4?e1Y zvx&nb0U-xYrP8!m|17%F4V%{aaQIfz8w>UTcMBdBC42sPVdBXTB*2XZ*bMtHi4q+; zBsq6tAmv6g-w2yH>WuFDY`n*V>}m|@*MYaB5GL5VQ_2N9d*dVFT0ogmHP^#H@0v_r zS-!Wb)b*sFI`>#a&j2I?qjfU z-MS0g;1zp&4Q8uP`#2<(j^ge)$Vx)T?_uDjp#p@83G$B zYNV_=NKRX0RJJ)Ed%hIn40#RvW6oQtyigthR#RbjC!gny2{N@GqXm|R{^nR{k_YF} z&WnPsDDvDmEocL)_2N+=dF(H^524MrY)yIf-ceJDKrCT#4t?^zToLru#PJ;y&mz>uG%}r>pI-3a(xf*E~Tj3)!sOB|DfB^w-u!lS?kO)>0NFhrF4TMyDEl^&X`i5bnPD$JLho6VFMBhi9f{(I-a{ZhLh{UH%L#3r$YA*EnC zOOKecw5!=L`+!^6seysQXO0v`THtUSk|OH%L?E0MtmH()VNQ~O_i9qy9&P2$ayawP zOLYFLG#u}GTe3{gG>_5eIl zwjf?^(cG1pbGc7WctyaU{>A#ER6~QfvNQ=zSiNm^=_0jrIMu_s1awp{j2NNfayHL2 zg~jy0LJXw}Eoht?P(xuUx}Ced|soit=v zRrk3=YbxoruhPV0waK@_AE2iJ<2P%oUnm}a!1}vX?6SW{A=o*NzmVy@94I^NgerQI z)g4L3N_VDn(^y_Iqg1;dXk-tEJ->DAJ-mGZzYS3=rPBqukRHPy*h91Qk1B2b{T67E zgo8vl>?bkj))R#C>jX5jXxY#BVW5BM66Rgy9KhJ z=|T<*Vb?<0XP~py0MW7o1{l68S@W~FXF+KkJIk)BMAWYg?$O6FnVxL^M8Fb6y-8_*ep;A&E>4uc zwuAj?J{)tVWQJnZJUS`EhnA?86|7_#z{=`85HlHP)heO$|E>Lo~k$f4BxKe%& z3g7#b6OTuwy7YPXhOeg2#y?seZ2H`RChrf&22W??N8M*{E78Btt9%R5GGc4mCcivfC#;T z&hzu$2D~+2=+t(i(oe)6gsceFvYDmucRU7$H}N!>G%dsax6mDXYkuZ<$0;YxP1M7|xE`IVoT5LSzAz zRHL-#fkjAvm6<34rvip~{3~Ze+2!G}1zV3H#y;R0+(owaODu%AgQT!O2N_uZdt`eK$$C&nr2Rs%}U=6Nk`UmEKwm({YuAnA)`o z{a*}jZI;rdH9?w^PWg)Gf)c#uAL<#_=K0LLDP){SqPx_r{ZE{R&>!bL$}9~E<#y3y zcRZcjZ<}R7I{^mh-CQX++Uf`aZ~OerMW<%}m=ekSTM{tFLcQ{=Mq+db(;YweqkQyR&*we>6A{6<=abYx@*G zAejuDczi08=sM@5{Ag-~M0SvQ?kbkqHpW>Irx4KEL0@qaQBa@S!5$7Za*BOL^4PMR zs7#MZfZGtBfOwQweuwwHnF%tl8i%4Qj01PR&@BD5sV!kZZ%4A)H*54lDE(dbu_zGc zp#*ElYcVP{H0=nHj(ha&_@M)C`^gp7In2P2D{pn!kM3aTI4NIonBSOt&71X}yXShz zwfqbb_PLVS#TwE%SyObCEwQ#O30~DIpl*6TU#h-j9i=_s`Ka$pHCLvFwqaAaFd69G z;-^yySroZT;}pO8D+5}z`Qviid=)UiA+mb5hm)8p&gYeyI=uF;0xi;A$l?qs4~p zamfp#TBVtrDTgR{>zU1Ucl*?Q!1qiX&npCUf6 zSm89Z&uDh>`hwqrcD&im35l(lk7{wk``#$!v&<_<+tH@)bFS2WU~FO@z?JQ#N@+nP zdY=E|Pg3s^wz#UHqo&kp_wu?;S^uW^yqpB4Z{EFFU*ukdZDQmA2&}W7=$<2H9=>02 zi95%BdsI@FNn2x#2~_!n1%LU~S>~N7S#CF)RMh5;+ z7)0CgIvm24HU6MvP4c!|uyFXe=?4w3!gpVGw;y0X7-pbzbk8J3qmnDuKbb`ex;3SV z1KX&W3q$2@X}*w%H-c}QP>6}Cs+msc$3q-P49YKebG3%FAUV|Tf+})tSr8HxsY$Cl zbH9|uM`=`FS(WAZDq5s{+MLzDSQ9#Ye+c6JUrphPiFuL|2K_~foX}QJABBRb_-rx) zLIo8-9s``5YBubYt=jF}!})lq4LKxJV&kCRI=j}kuCMb~M!qCjYjK#716uNEwETAZ z&B1;J5~mV!#eU8V-M1RxnoQ0)%^Hq9-$;TIdU)gfAyAc*zuLZB%w<}aD|@G*u2L@2 z!7nl|MDZ~)zQGD0=tn&*YC=rMs?{L_q?=d^2KD;kf*k(X`nBbKaO$+)R&G&pcZ#{sZK~$A8{I;l;A! zLjp8oN&$hAk{|rP|3*n);)pUkqCc>rRG_$C&+d0Psoh(F6mCtPC4NEEM-nq(@A&x% ziC;l$7Q9A~|rv1nY53Pv0%8Cvo#}PStbJ&5PMNx!Oh>ij4^R)0}7L9|2o` z98envXcAi$;;N&7jtY_wUvb;hI*Q|W#*0}pHJ%6eXGM%Vhnu~OYW+cD7tW0G)?(kY zg9t2cW}(&Fp|{BuCF%lEF1!Q%k-SW@Qb{9`9iUl8y|9+xf$EVtO4o&rY&@l9w_8=x z!i1@j1qspb)2im*+uL-qvY%&l^7yE9k7O0*P78=S>tB-*i;Be^F&hTW4sFNmZ~Ao4 zb=L>vqrlWu5R<>Luk+c|t+b;7K@uzpPDa(h_q#-lCQL+K1;?7vgK)&C8`(rqq^hy1 z1L1Fhva+Y;KjVwv4$n};_RB?F$5dPUqVu^ej4v{r%Tt|TiK*;pOf>8F3F$r?W6ue~ zx%YwvKZ}7^aj(#+sm-YyYfeu*W@JO<)957l?MD@^h=Fp&1Z_S zduKesA#|P)N9@Y~#DTVX2KubWFzVCVeNjn&urla*J2=WpJ?}JM@Fq zL#_}ktM2H9H+&_zOG}O-9U*22SoIM4Igv8VpuXmbz%NUoBggybSHg^e!7Yne6caqzmLJy;CK21=&xtB$#7_btDP{u zPPSXm!@3DEY%&41Xj@RGV1+&J4oV~bk>!CU`TDQ-mnD5NO(d3IUcn!J7~cJL`F_pE z8+Zv|6O&Z5G!!>w4H0>3R%TD9_$K*AhU^;iqGGyidW=@gGOfW4r*= z6u|sq+yOASPT%z1o7k#ue}iv#LdhgUm;`h{V*DJ@qi7u6vr*sqr#eSbCEkpp?GAD) zzlUKOf###fpjohz`{X*G z@s`Cmqe-Gphe`D9@<~)4OQW>tHnDN76arlz|6+e()#%blFZR{w*`tH%$VIEk5~yeBlp6c2BdM6wepnLPdM7X zXQDB6SAsqlM@x#6CJd_#{sE5=&fbXp;9M0#M&+`jxsIs%hUv#N58DSwm}P#;9-k&l zemR>}C^N6QGjS%?pTMHug?Qv^eXOd0c-3$Drr)`ibau>VtIUieI43#oIQ&j%feT0B z)Kqn-{w#x*lR&vIjuLBAujZ6d6S_|#Ox-WvEk{#8qpx59nH4v9JI>H z@i;X&_%P@-t3%{RGAGMHj%Xrlb1!i zK@zhGzF3_;^E33nx-Iz8@-wJ~kH2_z;7{Lf#qrJS*HQA@UxP#hx@4As=xD2@grqx# z6U>0y1K6|51wx>!_v@>LBT7qS8FhMhSQ$a+I7L-Gtm$lDBe&*No)ibIb3BvGZa3x+ z{XOy?r8nsBUDIqJ& zDk=b*GmrOe_>?`@=(j@roz))(EVpE*k0Fv2^faRQc>d%1J660NLHyyhs~^{zN4?0s z$Ec_@Q^6>;CtwzbElV+kBB7+$q%ff+MU<(@ z$D0`+q#AsBUJY>hm@6D2umOMXcdhfC>m1H^BDI7}PVrwyDR^9-Fm%a#bKIX38L%0h zpIOq-YC9h!{G!*Pag%NsRDn$$q`-Lzm(Ci89GuKITj5nSxc++*es8pdUu588x^Dj+ z_od4{jOYV`^Z^qO9BEdGvA-3sq5E&Ls8#@@l&LG|S@Ah`uH^P=?i6}WJgf|5We=qu z73@aSR`$JFc!sTcT)dW>3z_src`TC4nNg~tmvO7~EcEp~>=fT0zkb}`r-CzDCfVJb z{D%lW5o`V{easg}xAvM1$?$1tME|-=8DX0_EASIhppMRcyRbY4Nhj5_;T#h6oh7wk zE8Ctys zLvBDEJ8aMqpFcPp=H0+eUi=yu*&(ndrirV|MLfM>h3Uf1SRm6imc8rIvI9U5q+Uji zA?;-*!k2W?dw@zTlkzVE4M_|2DJgy!b!eMnsAH%K&wc8l={!Q|aBhKbdE93z(+Sb_ zBs?_WCt%IqyJ;XJ-X6{QDq&KN??vopw91_VL7J^{DFGS$BX&MtrGCp=p<7}dom~2} zCKRJyYo~v+^!M{#^@ET^UO8G2Th9{<{V?I!Dl_MIQFzY8EdP|0$&{zC$jL>us>o^T zG#bdSy=Qd)uKmktO>s?p@0!Ojm##vd!~;ICy2}07=nU3^P9AD14*;$Kp$auF1mMbw zkKm(jAU0}_aLV_$ngGYlC(5)4KZ9Ixx68AK`6Z>}5PFIWav-X5OPYK)l$cjk~yL5#@>$^Ca?Tw9@Sm4In+XQ9CIcD!wTVEMR@}!5_Op3(LLz#3ETzhHl})Mr z9oPB{iRKYmm3?dM_Ci;UGoa#ra~aKP5r^TS(rS;h3j45jK6fBQtVbVtQ(6w9WQ_TA zL(bSdbNPk(XQYxl+lt*2Vt^vT61ur)N#PW;_^|(T0vp# zJ8A%+dJB0IAmY3DD&nULX)CSOm=%NN?E$6l){BHe3Z{+nynCcn{@0%We!q$hUKeNS zi=ojOsQaX~EOVkYx?6IHog=`eksjx^Q5)7tAzlHOoojNNB_EM(KN0L6Fl4r@cFO$N& zYt|yiOa1fn#J=s_Fc(Tx(8dET*d1h}@OP=sRo{u@xr1#m_5n;80fXkN6d#=()L)I@ zqv*2r!Tw&mkYhrYWB1*aFVFjxS&_ARJP=ckX#@RCHO7V_X?li>(xVwaWp1XssTViM zZWqTV8;zfT)makH*DaPEksv3U7evW0wedMYtGT2o1xnV|OY&NBjuKS^_55A=Pg0%?jwO_kaWqNwG|4^QD>;f4Epnrq&a9v10^kL-6; zKjPxpK?QMk8JTBQFo4r&HX9>!u-DxQ}F;X}T`0`Kr}r$|Pk&j0?g${ zfC?axsi;)_Q%q21+yTZ0-58fx3Jy1rsF70JT5*PbAmq^d^*xvd@Q8->?K6Bd{<+mt zL#t-e>3XfAppS9>_yb zX_~Oen3v}-7xCqBreD`zq`4F z#xky&0(vjyUM^}5$y)pHSVd5urF@d)s-5M)Ukp~5M;5&?*-r(ii8Rr90W z5SzOGw2uymKmh{#nhFpR;0@m+TBHF+e;6AZn48BlaoxMEmz;}R0ih7{es0krq|}%alT3a;B+Di2hW8zA?gj?8!kRr=Pi!& z?jE_0X0~nd0tb$;A*dXr5wm9b+wbwsQ3l56)fK!M_anc{pBxuKH|$1w#kizmmf83Y zgQV!~ADr7JP@;4Lh`AdUh_zdro0)xsYMj-rUl7l8-#q_hquNFCp;~cfJq_TN%JS^ zk&>kPB;DRi*9%p4HmWajTUO|9nSTw=?jRb+=8Zl_x-%5m{d%WyKZiNU4}7eDIJSs~ zWo_3CLcntv{^71~3FMLEKeA&=KzcPpY+c1tMM*QAUqm>RZF0J^gV%1Vd39uOKlHw) zlY-^qJ_Hd4t@O!}jl7fc7LVWVM?33-kra}G`f4fso2M|vW8HCag&%;!R<|Dw@!ytB zz63`dm3uUkE_l?eliq(a;)@^6@f21(YEloslc^09Y7)QO-l4{$NVsBcO@Zb8ZA)e) z)(k83AR;?zUaE-?hk4ACuI?UvA*ynX@cAj5SAQ?k-Qj%%rTMMsX&_NbEKx%MRF5YH z0Rs_{l|Xh`y;-BP#NWfMI6I7+HTj=ACh6oqO_pkq;?j2f%MUJ;is)}hu-%n6Rns&j zn4gl;Pk25DloD&h?%=2BsFx8}O-ero|Dy)UWY31`|B#Xf5^{(JpMn7uhTp)d+kE-e z`Hvo5N6nOfy;Q1U5;$=iNez14AkQO==s00^!)G&`6NEo%3hE)^(-4Qt^A9)lR#Gn_jWck0PK8Lf%;yN|%mK{g$QqrKZGNMS`aOT___dpvr|)(Y7*tKwgB50C=fXV8gM|JMur=#3#piw6)LINkB8 z@ptUy9@?Vn_fu)D914JDp7CC$o%pE@!t-C+3hiV|D$#NiJD0`V%t&^A^P4B%uBq|w zfK~jaaxYdhcP zKYYFVePZRKqwTX+CoTKB3Ztk<<1=at!(@{cHcf157j&*46QF~YXHg(Ux|=x_1hmJh zVBhO$K5AT73-7VA=wBU68+paMYRW)V9>wdzw=YVZ$zg~Q{SyP%4BM#-Zm$7<`)eb~ z_So5rGn^v|;t~HE1~lq$G@tRRy2kZj=Ov!?+IaF6%H@uCAUWvFqR64lsso)B58YNgw13;cV=r9vRRBu;+MuIITR=}rt& zrywy<^AjX*N|P5}cu}63$cFEn6`>`!Z}(QQ$1>1z1wAKy?~@-sEXiYr*&()dM+A6k z0mMU)fqzu#*em4^>3b*)w&csL+OM-DHNHZvc#LkBctFd+l22iy`T&P4F^8+eZAB6= z(+aKE_~y|{2n_QXFn`NZQmkGb4Tj^xUia{&%3idioT=Ep_%z_~oygPJcxn8x zb5E!c@v&D5_}}Z$eCAn8H!Fe5Z1dO&8(`JzE;#w9mk;=K`q^VSDobpCCvm6Qni}&$ z9KxVj4a^ME1R*<7M=$V?x#0YiZ|}aa&kX&l#;-G7DABbn0Osh*#zhX5nqD8v*&PCt z2cw)b>lL4$w7PSBYmn$#_5A+<8*4Fz6lKrLQInf~h7jR;zuG9;53d0`w_QZNveui? z8cn2$7qCQ_e)iCWt0G(w>_DWG|E~s5Sj7e>(U;=TwF_S;`tY7u_O65!^99W^ zAJ32R=DW8XlRiCg3nmob`;A6IjDzX&k(Zq^xyomn;6PjccQ%}#A%M_J-(3xZe_{50 zK>$EKT5gB@fwuK7&R3Z}NGpfGs8*QI2_$x^L>UW)$laNA=>*Nv*ZL2abTmCTz9s%v zOdL2t{3krd$z0h5|84RGVG9Iv&#a)6rE`^=uC2V*4lPVth%$y|Mcm^N=;I0Jv8(0y zJmg!8X%Gk}P8+th%Ha9pTK=H2O2aj`;}(axTxy6iGZv5%HHyRqu$7EdfsJ?j-A-s6 z-GVsuki3-)vy`JpxB)(Jz$)kn$x*Ifkko$`a(u{56`}gqZ$!gfwPR!aXap04+xR@a zETSTcoK@8tDZiR9ztUC0>nbGa97AdEYHj0lt}K$D%!2v$byKpr1MG2GHD6&ueb0Yk zAyc4zOT(BX(yCLFv1*+lOf8>-Mva3}^9OC=VHy#Ua1oGTt^vxGhY|4<{UqS{r4)%^5LuMp66DHNQs5y9yGkIt|6v2hI+B>#RObhxX z+B?Iu_ZB82%4rw$`LZ&M2vTy!*gIe1CFuPlL>@X_KYa@uO#-&1kRJi-${0X15r`je z4N!YMokt6Be3K3i+G}7i|0q?SE7{51V!%nZKD)5iq{RPSP~G}q?hUFXim z7JTfDk+rV}*k04_pE&@p7#ESNq#C(O0;UgCc!@buhZ^D&sE9vLYyRi=;buU?K?IBa zt<;PH3dz$<odHE6M%l(O9bVCDoH7vreblccmJNMb(FCVFF#n&ww zJ=TpqV5`!UBM3p5;lSz6!(#fjDk5Njs3pFZ8VH5Fco9ta^7c*N|H|!IWKk>@Ku}V% zFnwMVppx+s?8+@RuyJF|`w&$y_vx|G3RLd?su}D)N8>p(eTA{rleJibOK!iMUJ(R* zk9)GZ>2)G5`R#*-^?-A(r%6q~udnB;IP7_z;1pJ)qOU0}@Rd1Qv@K=#2HXFrdL-?5 z->vx=_EyvyiK;xw)87FBiHdD)6TgtRdDM=hWw+SBtgpszh>}y)o?e+ZVZMAmITf`+ zZnO6+O<)x_R+NQNh*i;R!l^E0!Aa5vc~{z>$;6s0)Sp;pnQMqWx|&SSu(r+{y|Gog z0ASrau$%a~Vf)xxXZpBfrfLMN5W?E}^cMKFXMV@OoD!cww)4LEk9CcP8YX<4jT!Q= z2VC@WQ4=GLQ_dQK8X)3R%2r1`t|!ti91^+cvXeOKdE4=`n>Khyj8aj}O1>Ulp?wQtHTgQI2-uwpBs^BI zT-YZ;ggSCUOfo-N^{Ng1Qy${^r@?%z+tGL@+4Mew^y-r8@3I69W15{pe<(2?PR`#F z_;cDr^>rfjCs~5NR|=3)LE=$}mMHZA0`>^r{RVygyE=mWK7-}kjme%%MvVHr^kID~ zD{VQ1!uP*zW(b9ax~0m8SB6DFI88ED4>toPNkT2{EFh6&k0`K#mT}xHQ~1DL>#7kHJqAHpUOB5@6vE+CW;up>`kk> zE0gE++!$s-4gd*-D3v~4Fd)E%7)SursQ7>#5$fZ$y$y|VBL&R!IWZ6Pi%0Gc8!di) zlSlSzW#UyVV2?(*Ai(2%a`&%dr)jONyUb*zES+v3fA7O~hgKfoNcMP0`N-^YQHvHh zPw@-Y06S7W1u!q40!uQ+NLWiQ#Inc3eBd7F-0|qRqJXkRj(+KUh(XdkXY1h1D+wUC z!M>s1hh9bj5#ckZs%xXP6Cw*ptyAsQ!}gyYE~9lB94~ljU&|W4|GggqM1MLj3o>zl z;W})W5CCqABg;Md<#0ji&)%82&)yrVkwYO!a9j^nMYeB?4>foeC-@s{3e}Ni^YNH} zeY@sj`|)9jMiC(CF#cO3hJVkA(O37gOKEkQ_mPGI1gK3bCO~>ZRMbHMvDkDnP$Ly! zYF*nm;fmVsvxfEC3oR88wMxxxyaqxosSL@PBMm!lDWHw6EblJKcY?<+#9+&i&SQ&M&aB<94oJqn6Lv#n!w9f6_b<1o@JlFuKgvqc~(B&@Zz9k26K`-a_m9^EN-qkNVMuOTuKrIhN z4PD)T{sGI91Z_G1)rMkiXO;1gK?80A30G#_iC9VT>rG6UYO(I2`=Z+YzV13>t$XTf zp8k)pp{YRw|`^PuZlCVQkF$J;Jct^!@-Xd z)~#7>_*}OIu_B3g{vLP_TWuVLvev*Qi5qIFLtLdZvrJAF6pq$M;+0kFTGc};8!k|R znjCMRN%#F97QiS$$*tn^S4AH+l_SH@$;tdY5B?>JAw*`{+sx{}%qFW%iI4{fWtCzo zmn05t23r!=;>n^S(gu!&sfcNLy**o6O?)3KHSVJ8VX*g8ElA<%Fqmw9GMcd}pV;bl zo8z89D(F>BD#SJk0FvBLDsD8L@17H{J~%sxqV;WJ|8h-9SD6D3T1}@9=m3VL2~mM) z47#{Nao6J0=FO9Yh3yzC`>yobT}H+T3sVMDeIdCZJx=2p@~SAkib|*u(YfrX(IccZuLv z;QnCqcwN9U{c!$AK0$KEFF}@m`NN0D9$EDDKyVO%uVM*cIgE z9b!LmBL0`$8+M|BCMBEetwGGK4R(dm$TVX6i}+%ezF1f-+^Ne(#SJ&*G0chF`Oa>I z@X{8aFf||^K)T1PHVtValBQPXZ*$!@e!3vAC^%x&pX@gMyqA?hIr8pG3+}tMtVzEv zv+N)=)Z;Nf*<}sZ&m#PfY(?)#J`vl)BLXw#gSA`EK{0gDKE8MECB+K(9g%Tlj*`ND%uUbi10{1%ItuV1fv-z;QS=yy9+KF2FP~GNPc)*c)T^Hj6(g3u`E5Ko+>o5?Hg8>U=nq-3d)9>fE`Oy)-))lwO3C% z;p|Afg?+TK7=GfzeacP{_CXD%xf7m#A?p$)cYJA2kRe0*I4nGY=T7p0J=*m{gua>) z#EMC4u_2+*<;BYtudM#B!4$R9#wizpP1HC|i~4D}>bJ#a^e_o#sY27@Hz&e13fPgV zo_u_~I!@|KUg%&tNAcgtt?uQXVkvq>tu2w7MGv_9`-Q&wCrkbmiL*0_Gt6bMIV)Tj zL`6~gp_sYi3{HvSBM!fVxcZCb(XYo!WV~T0Su!G7noTOl5~*a4t_Eyb2WcrNzDsW% zg`IV_qF=(mw}*ar^~T>W)mZU9!?o|4H2iz?kDUUHKb=n&P7|xrmNtJ*`4npV;|_=M z?GYy8JCVw8)15p)U04_1A4z5F)FKw)p#=sfJ)51M<#fd@y=V*h zIfQZsFKIz)NmCD{0cz81eLTmo1DWZaZ%iuFEP4M7@%(vUUdR<2QfFqu?T5|BY3U#i z{>*f*7NsOY9IDZ z;P_>&^JNDu5J?y8c|py6h%(YVb`OOxK5$w6^>Fz1jTX=^|MOzrn=@*nU7ac zm!QtvDJG90WUqn{c!_8Rb#r`mI&r#cw1X3V=*v7PK6F%%WGUpIk4kyX7i)(-ko8)M zU*ZOZxHxxufaE414rh2s@i(CUCnxFtf|$qQ0r%R)tcEjR?K?tID`cSUiCp%bKc=sv zE%VY@4Z)Ua`afJCuwtiS$eBGiAXj4YW(cMMNJ)!tZ_CzEz3!D6I6*HazEozMWb@?xRk1G16Hpcr7yNJeimr-~U1%`fbDYV7;9>8K6N24w z0|`IMFF8~o`z~Iv^V!d%5jq`x>+ThbJyL%1(N2Cq%ATPODEt5w?Pve|c;IV9PeFh` z_4vL!b}QNc-I^gk0Su+~<-1wLt?xYPMghKm+@RCv9eipN67A!o4bjfs41}^|h&BS6 zqiz+et}fuf#)eCaryroeAg#4Hz@LX`H+mmshOiJQ?l}*G5=I+p^fm;?XA8@j5`V>f@dFudwHQ%CF8BH&suPC&viWXCQL%lPyj~ zT~%5T7UIc-81k$Lc9i4?vd?yEi4gC6RifwoPK;@FE~ZAroaFSGR@G_If^Ra)Wa;i) zS}46+BHh1#lQYGJj4wBdubvuLf3SsrtVN%VRdCK(db!H;puViS8vmzZ`M_zP_HnQB zQUBu1h@OPh7g`h^j0~lDeDsyp>sm_+u1t3luo_C+{JTc|)r;Thad-Wy7M+fL>Ak+X z>i0^$o|k%UltFZtSiyynD1#V6OH5Zo4iPflwP#V~R&BZ4h?iFCz4U6TF17C2)IZ2b zc&U`#e7BSkh=@9YCaup_ASq3Mm(WdNxZv;k$04X_0ogc*jxqmcnr1UxyzG6sc5=M* zxd<}<0l%ps0P9K&aYuPvimdpWH_r*KT1foD!v=)j-2EQku~Ue$MDvXniZ0gm_#`u! z-wynJ74bxyNh99x`9o8iK%I<&JIOVwzIxnm=0MXKA0#bUTZ((aXiCMslN#JR4nsgd z@$P%W{g$sN;kt`H9EgRlck(YC0hLwgMqjF$e^m0sN70ST!`nwIJw{5Z$XPe{gO@uuy6{k-YJW@%75n?)kmIX)W6HV zH++^VWRoRO@yU`$8R+&msG3o`_d&s+<&$}vd2R+IA%@Jji*M?Aqx*$<6hO|Hng|9cu7$%YTzZ}EY=u@O*xJE~@d{t+aGK)#tOcQ|3VzF{_nt;ob&FQMDdgd#_= z;Fka*+DoivPVf8XH|5)--Rkxh?03vZo42#;fq?#W^>Nilxe99z6SOo|cxXvS$m*3187z;ZUf6%7kf?T!q+QJywSFh3H4qRiB!V@uoYh>MB-c z)9Q-G8<>O*e0T2@T-+n51AbBRIpaG#cB$bB&2u{LgcEG@dh#}2=Gsd=?1Zs#RUc>T z#ghU&&NrO*Vq(&QGlL39fJ_4azhK<5UAHI!g6YV_$RJjO$wjAXFb!EV6N5Lmo0yfi z4JyPhpAG`vAnQI`#%B6_9-b%7;Jsx?8OD77`ci+9 zZOD}HO?<1*N!&Y_BA%*hg3`3&Q;9Ll2@p0;0+wG8==$_+gVOQ8bZn3<&{28n^1f*N(2I)ot$r(hD?nW93k?tHyIz{OY>23yQ?yUQLcdfn7I_Lbk z*ExId_lftZ%W2kJ>?(G~CVY+^G$osm)*i&r%$#+9n7S7A>(C&P;cfDJ+*o|ZD!MIcbl9T`D{jNZzU%>^Pf$6JofJJMp)~JHBt+F7T9pO% zuk{Jsdg8uBDv#XxOl9|=Nx$v(=aHlFfp4gDO&zL=uXeI7jJvB=1Y?d`ikYOTqelvk z|LiQf=uDDaM4cr>)If1Gv3043{2mXAN`B8q6H{-kKa>H`yg_1*>x0R@4L851{FdfR zo<43{?VbxNO}jMR0yGS0iQni4b^!k$x)4?<2!n4FwI%gatqWtw3P00#z!Vb@ni{&l zH~v@QlP27nnp(NFqz6-!tR#w-~OlkRL zTMrOVRu4VZ@!`$3H$j-LvECkhmp|hLa2@C$(Yn7xpUX|En&NghspCVo1eVK<7-UB2 z$3q*D0vQ4Q3V|QH^910x*a*suy}$k9V}K&eY9kKQ46lm6^;4AN8Vy<#^0)BmVm~L7 znO?WP-0Vj(VGPu4^;Bn!lS!Y^-`b{k;7|LI8<}%&O9I69B7t!$znkB#Tc}|nRh8=) z-teBed;R#ANAZ^R?$-Wk2@M%O-fMBlNA;fh+fNuTxHu$i$L`4}ggX@VsB7HIyrR$4 z(&WCg>fHRy)3%TSV#-@)H7jP-x0EMAjr@_-;Qey#jyB}#rm(0Dc{6alt!ajd%z0i@ z!3`;m2#d*N$15{(ko$*`pBh$x70S+uDp|7kePbVsQ-&d$K`>-qDKT-mch(nH1;Hi0 z<>QW{u8(FH-;2p36PU@EQ!0CUn74lbL&GKZPzaF(TRN8y*}10Onmjxzht2ITM?N_@ z+E^3XL+aVy*}P^%jL3!dpP^fMqZC#_0xk<$L&Q0b~01ZCQ#7j4G&Y1*<0lxDVFY*+*4i|w|O2iwY~}@O-kkH4gJ|3G9^1CuNJW$I{(B; zZ+i8&Px>-V6b*_gpHn;j2FX5Z^27ufFA3jW1;AR7SuEZ*yl8-m-8f??oxeDKH_d2( zbh44`Tmd{4kR4P7dYG48Aoi(%?FyXYv}xroTP|eE{LIWibHq;9JuIm=cUSL*ex?sH z&O<{kcYt7g*&Gu9@KF~83`hE;06yWQ`Hn-b(kVld*g(TXT#E&l(x}^zJne9z7Ae6 zE_)f&Zb$n?aM#mlpe2(N>X3RF*cWxRGdc0P5eorgSng@|wbuhOZ+8|*eY^kZfPR{Y z3Dr5yh?%@$N|c!|IZz@tI_)V=DHqFHXswOaoM2oXKEAlTq{ha`XswJn@cqvO8_IK@ zZ2f@>dB0@?y}?_LQNSx@#Gt4|?**~*=4_`nb4_qf9Z+%wLmfSj}eP)FNSG1#HPp2=hFrUxB+-z&w z4A%W^t@`V4t(DdX)sUTM_DGOrw?~76L>C71$4u0UPJ;oS<*l8l1lckWDgUg42B+VykDao>RdN*xn6P8+z~kn(muYReT0X= zh}GM`97!r?r?Gueky3Ajz5e%V7oyj`=!hk_ z{zGC3#C6Vgp~j};ubtKIzvT%D2DYd}@;j}GmyH`GVXO=opDFIAglWI;uq3n*?mt^q z;b08g`kZGzc?x(lO08=q5XV{NVm*9ER(~7;lKP<)gj2d(D%C9c&iF&BY7+1OrT}ZL zCZb}G#>>~1zo3QNo^@UkAgr-=8ZM|&2*nFs;$EoL3JES&k4N33c~f30!IE9gF)8T3 z_H8Iw{xuN>NsOX)y(3vyh6I6yI{dk_L1m~T=llpG&GH8HJvCI4?-nwQW~0dDW_kVN z+OXYAB=>$U$WY3i7Z-kLG>)hX!`E(iAE<&tkR>iu%42ZC%Dh0__NJzBx8b0Xi_!i( z#bfyZ!lmg1|By_}Qf7t;k{MZ4X*0!7Tt~{8qFk2X>Sqh$bm&(WBlSrjQ?1uvaWzp9 z{nEh0qVY?Py2-Mq*pU#&l9M#8up#@?k{#$aK%L}mQxdc)0Z=R6_=Zr^4$JTbi-+Qfei>VtKQl~pomGy>tOgn zFvjJx{KK7(cl+&KW)NU$xsx%HDDRV9jN=;dVS_z(*-;G~u{RaG z#Ty^4y7=+;I5VhjMeSo6`dP4W$2AX{=BtnhVQamapq?*cK=;TY4`kkZ08RBDJqFOb z{1Nht&1NutT8(Ehrnb^mSk zb1O5Eps`*ttT1FnW#(ZapZnG#hwLeP7+L&v!k=bVfQEw@H%uaN^vav;N7YIG@vys0 z6N-G;G>BDCJ73PxvCL|bSC-P#{apE3=ehEi_|z~w*0o5Y_!Z0@#PRKZ97%h)=U6$! z^{p;u{&D&?{euLx3*Rj8@q~UVC=Z}pV1t$pq*z%n&_1HY9m44Pk@Evh@yjtul9~e% zS&g4GQ7MJD8=B+olwzGxYIWnk)-L#n!M8`zhbg^NSndOr(92M-A%&l*d)q;GMz7Z#}goiMfF46{A6R-eExnaFd-aqOp!*4T&ITifw9k8~>=K z#h1h&9@+8&zoz!`YnpW>ANfLM+KWN$A_#3+Pd~bFmld>M-|y$0Tx9T{uVVFBb|*e^ zePsYDm<94vKD%3eYMKGyQ#>`xHy0a>{cu|{B#a+TsR3dC1uLI z*P0;5SA6@HYqn}NBCLMb`a=4)pvui=!XNoFJvk5;%5CBuAu4fx^X{6!;pwAd0umB}gIBW8g>D$=RzD=TGPql&@Mi;bXw_gq#quO_L0yxlpbqErqFhf;ZR)HyIZtMc`WMbtyoP|Kp7cQ7K?t9LJ z@8CB8G3oi=`<@H}jZj+-Q1L&n-}(kJCPu=yZa|dsFQwaW{yVu8licXQlHKPj8$|e% z|Ju_I*=<+-_EGvPBkwCRqVcZ7SY+S_cw|W$Tbnv~UcDC+11M`b6`NE7yEKolwqI3H z-H0(Z>Oxo;Z4&@Z0oj9A;)i^JEy7nX)9GdZNxzvD!&>ymdSCS?$TiWnZ<#3bC1dP? zJy=8tUk$Bt)%#|Ly9f(S+xYOnIb4gU(`cYe2$cWEb{P%ZXm8964~$Z1=b&T%BTBjM zl}{DFpGUriZl^a29QmtLxw4{tP<+#v=|Rzq>%N#E_^&V$h5hVSX2Xo zrd0&{v@rJCZr=VHELWZ__^6Myt_f}ZFm~WB{J%?v(xBEj!ale)W|?{=jZXn3=iL?m zcIibBobfw`$o!5F%K>EC7vrh6yU`ihUNE&(T7X&oYwOd)x#U?7fjvWP;^?E76!+&3 zbJYX8OA4Na%|}^J+8ve>uWB`(yJw64sKRtVdIca6>-SACpRvbCU3~D} zD$MLPU^v6x3kHyCi1o6-3x!qDXed~J{1ZR=w4bwL-8P?e}7M!r39E7)gfFye?09>NxYu?c}GI={G^Bh^XPxRMDJIMRtz!w5qM_r9Cf$eZ2s)8u z@BRRBwVZe-%s31nhh7%|7`?{wh=B|HE|KGSEKixNQRz!;rRDg;yoc{bkYg8Uca!>Y z^k+9eB9V~`_clq@zXXl{{zi_$?N+_N^Ys2_XwVN%DS@CanPQ`VWQRtVpBbWp3h3|@ z$06UHriurjUDG*2&(gUuhGOCbpI|AB`7)yCF`o|}jBH$;7V)z7LbqRWs1c6yU19}O z%)$8OzUAbqzv;XzeabC`o&SGBUK=Ng@g2p9L*?Kh(C}l217FON>nsM{Z7#GWgSu}w zFb=E3TX)lui5rVJ_}FuKYW2=Wam$Zs%+2*z=!@PKF9KN$NK`%O%c#F~b4XupW7XEn znSPGR}KQf+A%0j&yqXJfiks~^`r$Ns^0 zHulqDL&dpI(_CEs2XExsq+Ih?zQImB`^`$qliu7_FSXCbm~@?zRSY2-W9;8RRiiM9+*qr) zmx;p5JHWgb1=tyoWcB+ebK~KiPwTL(%XQzYB)B#BJXi zzOr`yO(^kyT7aw8>rVf?AvwjmoZyObiod5pAwLXWL3Q4yyC%o=AngDi8QjO_LH>_- zZ3~n>s9PoOM`aQDe-cEGCIX5pq?rs!0}P2b z8K(EJq7a{emE=PV+3g=##cy{{(=b0BBa_fW|54*731J!VSelR`yfCZ>yW++522Zgb z-Co1C_9jQ{uXefFRH$n7e6N16f22UK@@60bK-dJ*4{6p%ZYD(rGNngG96Q7~bbHOH z?q9dHJ5P-T+!!Vt2`SjSyG7+)ba|b(bmqZFDuIaUk1osF(X$yKJJhOD>t;qUTUphs zMkF1@CzBQ4;gwmxDzp2&#AN|VfBVu&(&r|}Xn{YS`_183`X1w2+?Oj~{K-?Ii<(yq zVvl8h*S$=td1r`1IPl}<&5fXMUcV@i3oiisJO_HyPQfNh?6UNsa$Ves8AOn}&gEApe!QC}O%* zjCO9v3rI)DzE_62_0ScV4bXWxidV0**Dx`C);(&k3nm3#kphm)fKXYBNi`m(ejLxF zBKZBlzcaMG^NljGOG=AYI@At#dQA!FvTtQaO%ATuw?qxA8(CjZsn|yL(w<<+_Ma2^ zkI^HgfsAKE7Px196L>ePhJgpdCF@nHm`xUv>-z=SMdS=`G0tpML0*2=e$xxO&@lxw zgHY;*j+3I^tnf@p!)t4L+X6mYxUR!e@eJj0J&-l~QbZQj{7^F+{9fV1&9BdX!4to? z*Zlui~-Kgmtg|HwnJ~u4>WmnU|0;CK@+i(SMJ4nC<6TYOU-}!R4Jz@;$MvkGowxSV=Zj3+5>4H^Odn2d7*H z@x|BIY|e}P47cNwg~4?!W%Vc|LiX03;ISUOgXfeeD+G#EB^5)D2nL`ieYEuIvKPT2 zp;wazHf)0)=ZvGLw>?TB2|a>W=e*)1(lyZ1tMH+CIP&0aZmfHtIEW4m{W^3O zMK;y63X?uNtzNiAS*PBAM*bN_MX0P?M`c=v|3>Mfm7)0mm5lc`8DUGyn$OC(Wo4mo zjJh0SWXtexVPeCjY9vBWzWJeog3z{c+j2(k_-euMX&W-#;9)d7x@9J{M&IB!OQP(~ z*OYj9C!1cq%M0=aj)(uSQb z94P2w=y0KnQ)KS@1TXS5L(IwdC{98HSpW3=ymhVcdS+ky`g%cZ_B-!@z6%c_eP=0W zOxiOyBdAq*gkyOP#cqvjS$?AIJpa2XL3Ydj=gG1~)Qn3FXf7|E0F<}Wh}sFri5y}C zasQW6j(MgEPFZ5BTSt>snikS;)*)CfNEW^1DJnok~igD|q0Y~j|b&cOuq#?iEpB~Fv(t;)a- zd}8tqIOUpp+2*iTa_t%Rn}L^kbm`caiNHiDTMoK%E)1U(Af66M-QtZ7kD7S|>N3G@ znlb=j$s>pke5pOLt@Lw!wtaQd`YimZeQqEsdJP!vLf13sxXB#76igDVTx<$?)BbnG zQXyOhi{L~>vvIEG9?m;hv8rf5vH6EyjB{*%*F&lrq(IbSb86eEf$B-?hr zwnq1Qw0O`n<Q+SmYAb50BibnAgWa`S%k zB*Wt`Ud9eJ5=3}6nfgTEPHzk+?8yT>-lDPMg#0Qs4Hvp>drj>*)q*zFFPV24vn)ih*Jf^qH;1O@`YavI0Q~%TL+e3u27{l5A;U@(nDsJ@I*j0)x ztqxKxKbt!ZWSkV}11901qk@ADuI&f=^2B=+bqU&?Yi(Y5c?Ykc_YSl>A>8yKDnK@T>>^YIX5rtE0R>sTOP_?@Nj1 zU$xUCo@-Ly#J7x993C^U9l@%i3}rQzAG($b{ZZuw??mEkJrlf3oXex^FRFJ0q;Ht4mMv zCRhv3N$yqzL%n6Q3&RbY>*M$dE37bWV@N>lNbQgCHXcRnGK8Th6vkzd(vto zQFnUGY3YM%jv-a)P+jpUx~g@DcUrI+CeG4XOUHm;i+ijzYEQ|F@P`ua%iA0Uvmo9F zd{=7nS&o zfjw%AqEbkifOx-2oEwwo{kwR?M4B^W%nWGjkNm+dZ@YeWJSJ@k+nU5b z#Iz8tPNfH+b+7*jDyEMA>-cjyvnVF*ah67%*8)18&{uX}nZ;Taa~xJGYMKiO~y`G%(4M3#$s#|#VdQr7<$^PP<<-~}vVV3XaaULAICXAX>#i+6B zJ0_d`3EQoFdi~FV%SZLvZ1~;iqY_C^f_r%6GkjS=j_mQYn}Rlqoq0J9^T2b0a`3zg za1*;h{mL%_*SDY2WxH%x znuB+Oo-ghe@;=c*9v>`PcnADg0i+*8%%*12wIIWk;7DcEPBm06Tre~j!`?wQ0f&V#;qio#+)Jora zM~Q8bGwU*u$ubi%J{J90jdsb{_ujOoH_6rK;}mK|xUEiSu%=McTYXJT2f9hx#%_o= zJ{VcLy=>SLR~IWe{3M1nqHM&?SL?NbY~7j? zTYh9DJ|>oF5s%CuyEZSq&MI0?(-L*w6{V1zX2*W!NhdBWbkgB#yXdZo$}2DYeT`t+ z!G}cb;SNKjqysbmd&ubl)1z8+ul?vS(|5|uRNz9v7uxNM4)$ufg zvD$*Ecq*(}pn^Y&MU^`+W8xw(QdseSOgOsa8>pHMG(M5e9m;=9)-*+86u4T`UfyIv z4<*h~@jO2{Uv@-Akv-Q+{LtM`*c`O;p@f&WK7(K>N(Vj9&y};04u)Mv#Mp zW!cjh&Tu{hH0X(f3|0E`H9pd_###0)eY0?boQc8_# zyE$KIL}$$vxQcFbrRKiX?(KQ}ZsB-sd1<9{VMRO}mOGAR{+@J?VweKUWr8c|8gG-; z3EJK4M(m4wChzQ`^HP-j*kpS1E6PKD5qlwD(OFZ++-peZ+F{^{gD>^ppFfnPxgwUWBhC@?vLQ9%eD<# zXP_2G+PGQ&umu8xR=Wz0ykX0jtBsL~;H?UJ$ULAPe`7?Q7(^&t-2$$yp5}Y$WMK?NaxQ;s*QMbL~`wKn~vFa86(y_;GyLo z5`(5;?dbN2pEwhjpYX#|=8qjE>e%8QSQEPn#Sv!69wC{qR^5WRQU!70i~$%qy!#CN zILe;{Av?`$Y1_=m;BPeVaGQ>*ef@ozp6SfOpGvd}^Xy3*D@4SqEcQzwUI7(_LuYHN zxBl+czP<4rt?u9X_Kz6Zr{?P7{38~d8{Not>eOUK^o~Ago(>tF4LY*V#lwZ6bGE~( z8>wt#@cj3lM(t?beJk`Rg|%+$(80mw{o^(cg&=}d7L}t{bsGO3-uCUnRO7gTKL=#g~@ z+)aIm4kZ9}tk2Gr>SU2f(@lF!My!>TmQxWq66M3geD&^QJq}g7Ccz(=ptXtHXo#vdXGMr=t*V*t9zyPLy{%Xu1AO7J+}#@%WhG-7E9k1@f&Js8nK15DxI=T zDA?h@h8=~)Z+oYt* znh*=H+OP;(kk~X3$YN{kOVgW_~^M~AZbv_sMbP9`26 zp8rIL2V$AF2IFs2beHz{&n6>t(7Pw7-nwY*LcV{}pzX*0;He>Or%gqBW;<@?WUQT*<-ctN6qYC!|CRONnZfqZa+-j ztm(@P>;r*8%zuyanLx{v{xc$}sIGq5n-Iw|MA+#(8Ud2ThA0i4! z9}VWVuU&pU^~H;q2H??`qLaL)nFSXRWa3j*E_9snzk2*fX86kZ%)<4d`2`fRX6;6F zY?YmerojL5PaE~3)LokT$*=c0{o5Q@)1%B8XJSjfZ=mX!4t=JV8!m9IeA35iwz9m4 z8GD|QAA;2D+7n>CP-K6Bf5W;=`R$tinY;8fH3Knu!R)333upunO!mdP-^o>e`VH6O z!z}89n;;2tJ!Xs074aUnIt8*%{J(VVR5<4*W!0jELW-W(NrZ-~DZYH)-$S9HNc}vr z_@GKeVC0?nxqOXc0kc3-bkN?rD~Xsq`ZurhxkJ#=M|8CrLvV4J8Bzd?z`%2qg*MM#*#U8Iz%ZUh0_wB0v6C1CKcDTBi4-)X4rlzL7JwV>pnSfHocMEIeLG zQ|`PsnDNPlX-g&t2-K^(jc>9+5o7r&h4ZI1{;g^$oiXU}&zv-XqLP?@R3na0WUfHt z^pONC)${mz8l;n$nXk2+1qq&0vH$M;p1oS-<`HDP`(Cl5=_`s}^FG!r&QP{H2G(W#$_05d z{VqN2)ak8R62_m*dR!-Eel%aX3K&Zrb52f6Fo6X>DRNn~Z?+HI4XhvjM5i7+Pkqtl z{LVp;Q@DzdHs!AoPJ_;@PQ-7;6ur;2v!1CAG*Q1*73INSpiz;~=>)*|#cSfUS#J^D zXmpPV-G|%imwpo~6_a=LP_wKw#GQOV@V(O%OSfYT>DsND)BYFqss98NRd`7A8>?!A zn_HtNd{>SFf#i_|rFWT@940NXS?I(CfsjgO&`)%=)2>q_FXvt7YaUVtp2<}^(tIEo zD$YyV&?VB0NH~NrXl{A#?<9ESyfyW^KOv&M3c$^F(Y-;bCmTP&*}k2$BF4nKd4 zC|Xl2`h4}}0|&tm*O2*qT4I5baMVK6FXD!tHiIr3!7xI|1oTo3MK4sL11;rqMQi{A zO|=*)$dYIN3sBPy)peTR>Ui->6KrW8!_j1LLoe%`3*Ls&TdlQ5kBDVDsr)v{`lJLQ zf?+(1*|1MX#$B!jFIoyrt7_Y8*q>SxwLe&>((-bid0r0E2TR?xkL@%^+4!^Ud@_^1tiP^H|A;-k-z8c6@`iG72 z!Fp~xz^B9STh5;-y(Z||-*zAgpSi=y>|w~~!BVz#t2VdO9=q4yB&NnyLMDTa>;F~A zY>jJYKCS(CM&vQ0CBDAH@(99Sy=Nqx_m=Uu{J1Vd3xTDrq`m54!+dy|Mot2(+kLX$ zurmF4R{L{Ne-Qb4oqp&p_0+=o4EAT_OTgzd6FQyj{*T)_@yE{J=xH}+`MzR5vK{gy zhNv`SJQ;i$LWkmvJgs1PRl=0Jk-C!n8~--bkhz8RFo>^RugGwQ<5~3#={QrH{w)0_ z8a>L?!#%2qIz{mtzal_XR_N7g8yym*8bOZjQVew{j35do77eG)GbZWI7GfWoiN3Th zSBb_x;GT~ zGwC?!O5;v;*fK~6W+*`qZ{J&Xi<*d%{m!=&Ot`gimmlw0V6Nm(6Sv#5rX6GF#TvF+=(B07>$ffXDYft3e{K}BwS(XNlInhf=Gt7UCcA}_E* z*QfO+&*y(o#?I0a<|dbcNkwEa*D{m|@?&vLE78PCqZgIS1UWy(;=T}p5`G*oR^m|k z1N7qpN=5>jEbEk&+l>q$QKGS*5T8pEpP;3mYf_+8R6c3-_|vov(mOf-Thk*KM8Y09 z`IOLYFHYL+S>)HK4COd(SI-l1UbRozJExdKW$+9vQjt;ssLYBiK-)O=1j?BTq!*hq zJY)AFiXocqmYr<$ecT$cu8egXKc8jiF%p~5&o&Bl213D@-{QQcxoCZbWR zQ6})A^QF6A!mz?692)l`4aPS#{(xB~Wi7T1&wc!Jgmu$iDwbO5iNlhIK>O;QS`~mO_*wvmKM5B=Efj|MW0eBPh-c{CA!d+Fx2V=IhsEbPI5w;f+1Nl# zT*=@F^tU0Z+YJNgk!d|5w3b9)DNteg89FpR!bAgzaE^XQ24Ez*lqdk(%+6R$bomOv z)y)mAawM>KK zz5Vy`n?ODK^R1dzZ>HNEkN5VrA^1sI40$Xn9y?I~xU*>Y-%5nIv%fIID$yocA>-ZRZLrmN5WW;sw(j>#b z{R+aTun1agXgyCcg=0@98tm6Th_xUhcgI#@GG>j~Js=D#MCGl8v1ZY`8 zqlEFH?z9ZG@b*v%wvYc>@b;lr*AM%-+NS9SLEuoI1;ldEDf(qLJnLqkq&laaJ2z7T zCzDvbj5~e*%Xhk9Sb-T@@vcmel$8baCBN{CjC?A(p&I(dS0+#jX>Wcp6?QpFiuzn> zfdRV}@%=I$S8*}-|Fi(6i+*SJ!W-RTSjbW8xC`zS6~Hys^kL}KjdZ&8-_d~NgydO= z8qgGmp7GNC6m4lh1Cb#rL8hYjkwqmXFqBz`BQ_2_!fsCVgC4_o5P4m2-w$`*;0Hb; zg9?Cwb4D{6pw@ds9#co2uMH$Kfs#DT`f)~PnlztepZ;OUbd5>GmICY?%X4-A*ml*8 zyk75r_V7JQ#bxfQF*E2}L)Fll)xkOkYi~g>#N* z3G4PVaYP#3NhK!o>$bRL_SSuSlh^4|X`S<~u^XvXx~Vk1#qy}$uou_XwdTl&5QBB= z?&0m0?FA5TSYi)^bWJL|T#bH5qIS&LW#dQH~@C2?GnttrvQi%b-Kx0Ab}W+r!-wS}FoqfqZTbwX{0kQ83?_48D)CVf}bP8P}gt^Y*hMIEQ<9}Effssa7u1K798S{7C zBLoV1YKR~jhc!y2pR-n$8Uj;o5srqirRBHL1O)IosaddDybP)xhL%fqJ4E9fET|hM zH(h){rIc%TA*_=2jh4=^lde`{T_#slcT1Ln46R^mo!Tn;q%<1T<|_7N1^HDMbjV}I zhxKRNp@-H$%lS}zk+tEMSD+qv`^RVed~T!x=g8e))xGhcEWO#e@xB90@2G0-cU#zi zXD5}dY(-15tdUg$I}xb}NYy6kRwC)J+RS!unHZA5{KTgVUYow!^Ka01$jh+5dA#`q zvp%C2^T8sszj|Fz`~3m={*&3n-C*N$QZi6duA6HyW{t!u3#is}7>F%!bqhICpNS}_L6R?vRbMyQ~*RaEy14T>Rg*WD!_d82LO$SpP zGExRJQcLYwPRU|E6gFC1>W+uw0gsxw@pm{@S;NSfyE$vtT6v0+Ou7g0YrF8v7(UjU z0Dr%&pk5yboHT3TpD3w;Te>@>2|wA}$j>;Ea8dH{phNjK+fvbGYnA2N-3-9cn;Y~;yl6@+C*;!_F((v)csnui zNxr}7w^1vmzmC)n{IQ`Z^lQjNlV}(IS@PF?C+8i*{N|}qi`CrStE;x%=Nict+gxEG z$`@UZ1f#dB*?p;-`*QR!@s>!NAI+uYUAiu!;T4@=i_G*5B?zomH|f>8tB-{foiPS+ zfoy|R>CSd1BWUtGlBO$2vB{l`s!HxDLbX?SEV<6W>UFSa@Wa|m>Ex|ua~b-_Y0CRw zYSAwu5biSTBYto%bu(HSI+?`yTsTivC7qb#y#Z}eDuPXCg#uXr$#>qKb{>d!<~mdr zv=UfW{Z%OXspAC!qS4Mqba16r!p&3Y5e+*iuamwtd2Pj)>pOVd>CEC#{QC=nRU|d4 z>W!hpeU!1X_0K!|56Yp6yjx)n*b?7*h*i8-dfECbPx#tmUeA_SXNqWw&ufVOsS;VM z_?a~#K*ITtT&dgj((=Hikf$%eB^<6S)XmL?ESh`%_%*Z#X5UbSfv99NzSsGO!cRF4BR#@NK|>x#dY4^KWeYb9P!nh@cGu=uMYZPpH-)pn287)Xl%-6 z_9Xfk5aO5Cnaq!T;fL9vq$ht2P`${|X^oc)mHMEQyg|GHH)0$Y{DgD zT?%rmC_tJv|21>O>+7ueTe!<$*KR?;2)*(N3y#pZ`tyBth#YYS)uR#ym=hC;>iU-~ z8ep3adCSYe9!r*tRhyZwV;d%mt}fiAbkU(Syf5Rg9*wBAJ(ID~Bx^tZ8z*X;^qM3Y zPy2#E`#eFFN#FDrV4;#SM5*@eoDYts&@Wp@^z0|=fjrf5Hbq#(FV#PO`QIB;RfO!A z^sz$|$3{3p3RwJo9@8$Dg0j#Pwa%n4i`O z2nl4}ecn9R^H6pV$Jp~fOuh}uMve3qJNa_m@cB&F080=HS8bag|_C4HYxFD ztt}WN#?859GA)Yl{RdO~u$xlvDitTRObVB&F?}}C7Eg^5sTOnYyiCbbfY~s!Fa3EHT)&0vsW~DNgb}MRy6;L6D>1H&3L>pR5 zl}S8vP;vWvd7nAEAsAOEilRL3RI;gx7YjPy-Xzv*TaCmTG^W_!oPX}iq_mnumJtAkB z8o50`a0DT>$k7_ToV;Y3DkPr^e837^Px&xv0pA*^^@UJEkA^$AACG78ulQw-?vXW2C%H0yCFgQy|AqwZk*%}$ z3jTTX7o8v(L$tAvUCC3uh9V^+_{f;1aRQS7aw)mitnzuQp{y&D)ptk54erV>b=O>_ zGkoQA=8i$}PD)`wK^7mOaiAnhfcRDTd)H~4-#WD?<8=~*kK9IDuzGCqx~!|I z$tG-35fU_NP``ik6-Vi=fL1UZ4H;_xPE&Qff=#X6DPONp9kvhx$#Xt2^3Lq703&x2 z-(3TG$jXzGt*&%~O$;3$ac}V|c{3a7SdCa=QL&Bp%kOd^y13e|4@%!^ z<7Ho|;6Qb!)6ITq0F8F0CY0lq(p1L^3UbRhvWLP`@fM|Z2==#3v}vz!!Vp7iGO8ph z-(q5d|8RfSuURtRa-g-)vQ}glz|l#2RB{5Mqy7zMJ}EQiTZ0*r9+nhtEJj4$Fv}X< z@O_!SQ^#!Vd!YM^2=>Og4!e{Ypu_t=)!{Ib5GpBYen9-_?kXnE~PfVI1~=E zU+~zWr;aJx5OrRlq;>?I1&cP>!^y)ZokT722~0UbD?OEJ^hNdd(V`6|ykCUMCX=m+$GOL#SLqZa|Lw`=1q~SPurvO=!k~&K1(-OH9;#3!vFGih zv=y(;S3Dr9G<9KlceqyiljNvMf#iURLUZ@yY$G zy0$jBs{KWRfhAqsnjMX1?mZf091Wl$?lIW^-Qw;e{0F^j*boszP;6dx*3gF+hwnje3-b`Nzm)Z9NF_Qqs~LQi7C7 zNr{wzG&6LEfOLm|bcetU-KDe&LrAC8P%|&jZ>|4Y@0YXY!&&p;tiAVr?fbq0(^-*B zaHp-(u@nQYv`~$7$A(n_a`c=|^8M8P>fFGa1!K7vWL7j-avU2fw6_ZK_`^x~(Er9G zwK{$qf;?0}y}M;NMuDPb7M4QkY^6QV+l@u{{E&y7aEd2$C`k2tKM~Lgije7FU{Dcd zYxIeBDe^2^8!_&Bml^ynvvIYz?Jvm*1)i_>`#A;kC-%R8PE06X2$`FR+|T-^%jlxOr~C|Ie;7>Q)6aDr@#(feS?qRbC;A^d++ z-91zzq3caLpU0TU!D)Z!8*oOr>w3u(ZMIRR4`5{EjMRUpL$ylgA%Fta5FGl?$4E0F zX0`s{2{$dhcTWAQ-f*k0q8<1-kH@j9@F6vL$Dk5s&Agn!#gy{S zRt1b=zsQWhLW{7Wb+OUPRCxFwn0cOF^M^u0xoj0IJmt#4{2#A%*w9#}{UnQ?SJr-cf%WqTGXtVf^t*=FF`{$BJ{4v0k{^XWW;Zdgd}2GvPpApT7!!3} z`#bpzznetkvvbXpRa2erX0jCb^2*w>iqhyo_lb8xnL?nXRG|FhAuJ?yJkL0gek9tE zPuj(Czpz|+NTz4nZHgMJ5BTPd1-xR9J6;?VAs+DIUf*_j$rep8IHZ( ztiL@fb2_v8V2Q^LzhSutW8K_hbDdxOeEuhz=r%%P>WMa&&iHc&p^HAQw{JO5WE~Fl zLeOlU<_wvESBkAovu|bU3L#gqI%6LDuN_sXntME&c;2hNaBkY}__ib7G5c&JT@*(1$LBaSRmf8Y3w4qrIDCnhk6DLPRq)$n_8`%W@yOV%d>1mWLkMDF z1LBzju!OnOohy?TBFLbQ$JGum}|Q1@YeFb{8P%*4f)D~(8ZLiZh=bkCI|@c z$-JO;l$p-ZQpD_U7B?M0v^@9`lFf`p%-}tGy3D~2IAQ=~?k`%y8gPA(upm}hf z&jE}kqr-sdM>$670A+XxAuFKNQ0iQY2aSm6*bz5)Xc>r_I5KGgxSv@NG*p(&E>@WT!Tayu9eouV5ZUpV|zXxHMmqK2QqOeGh|n0^0`HZ-g|br#IVReo8Al(xOYRf z7Ozh7lkZ~VFK6ECHN#;E`}gb>SBX6^&fwG7`FeS_Ykr^6r604B{u6i7{51G?)M6jL zZg{tL9w9718-`$i!OYf0a}x(nVZ*FXA?SYsrJn~eP*l^&Q|^c+?woE*8O}qA^lOS` zfqO}t~g8_#bI^hPy1nkcNfXCoY%}=muM*0$@EC6s3nMjA2vQ=WIpgm>^D5^ zCEb%g*fi$}7#kle2CN)&58fQytq(<$S+lYC)Y&AyyAg}%8EjZ>7InJC;gUH4P-jyq zK9VJh^v*fOThE@muG+u^bT8J`WeA;R&PO6;+Tl-*aYXlh--U*}3&_v8aGt*!QDO(p zU%c4&3HAyp`uKrsxwU8@LZkojQ&X(&a?)yE3XY;`DqCk0!!J2K`s#A=AEBP=aJ+QGVu9v%0?+og^NW&;aYKLIj^ED&Ri+X7n+xH*>4(ijtK*$F=`xLFEnN^&1COhcjb}QE*{K-M8xBhWI-Kcd z4N!-0`O|FP^p_eSOScfdX!eR-XL_q;v3tAYOt1X=y06zX)g>lmvoaEft@(SdS@AA0 z4mKs$Gx9>{BtRg6mQIdQQTvbApV9iRVL#lqD z@lQy8vE4Hnj=}h-n!alUpC3blrK)XzRQU!R^pkk3RtnzxHy@%N3aH-!V%5}uh4RWs zzimY!C1Nr~>rbS8duBBiV%1%Z4kb-Ttko^DgQ^Jk!)ZSHeXvRLK0Xx=bLWA>MkGrk z*_`y&RkLoKvCz9!kRMx9icRG^@`51rTr#@&ysS2$~pmRVaGP)_!Q^~24pre(ONT>Rq|v&$dy-PL+6-fyR~VrqN? zScFiq@qqjnq5IG6Ol*f}jjs?Zbx-J`8kwcdYVZZG(HRnaRquXi+AGkH{fIYBpe{@v zdhAb${o=;|MmM3<`RyZ--Y0)8lVr~Im*vcF1vWFjT?^$2EIYX%-JRZc^;Mbq{~l$S zd;0VpHJ{Sl!h$Ky()4$cHpda`IoavrxXY%mJL0216P|S>_zcb|AM&hMM5 zQc?u%*^Zc}d# z(ug8;y0&KKZ{oqagUZ^Z=5OXS016&q*Oiczy{yNH)#4e+qnDMb_{{46%1EmFEy91; z^8}WveY|Vd|iFeV({(u zZ)5Mr@U3fVot@tou||c${whr4p9(!~Y!>c^bRfv-0a98FYzn&!5dsTSLcfneV+^jj zUC5oXpTD$HfnV=&#Z&PCOBI{HAckCggw15kgzC{#QEw=I>08HFLhLik#$+~?RDcGr zW>kqL@B<%U{gXPk9Ipvx#exntW9L2uc7P;DkvNLHK!`Y%g+74%y8uP%FOfe0_Y+oO zx%CU1uJo627{atpAa2SZOAs<_(veb1fVG7`D3=T9_^zClmBsggOj22NDHWrjSTW=E zgTs5m3b`96s7^Q{!N}w`9~-U90RSs+hoV;i7)X-N%y%j`+jkQ|za7bV9N7QS&97^Q z6qrLWVN0Qz1TqyxtG7+zP1@_{yr|JGCJ4p0pK^i^I=mBIV8gZ5p_eZnpTGIjqJ~x=J+w0p>E#vk10Ps2t?QhPg!yG;!#|0Qg;tcyaioUPo1viJq>u}ly>Y* zYM+BrpJ&_mS5D2hF8YZH-+y|~^gu{bPQJ%!J4&bj_k%pBf)dOLN$o2;VkG-&^X-;t z@Z8nE`Bw7*sY{~DdSK05;l;J}m!XYcIv|h~le}>l$GMLAlb-9DZKJ8YJg3gOxdm`2 zT-H)p?-sU7;+c1fk5UB@e|kK*Y9aD0@F^T-SYB?67)C%GMr5J$kE*+v1zszK=ZT7v zK6IVBYxg9#4zKg91Mfl239i#Wha$|F3hL|>tCwtI^`Ph%&wkPlDLo!J9UML(p>j1i zv0wlP!9DiH>OVSBn}@S%@S1Wo&jSS zh6IN#QuRGZxvyvLx(${#fTdo(fY#8=ROAQ zTNQXw+i_6xq+#p|b|L9$$D#(Yv%C)fT5B^WcS{C&y$-AUWfRHt*Cl8=G78i9qGdh4 zNC;;Kl|Gq?hSxx}TwVRsG2*^HWhUeRjekvi*GONVU+4nUHAoodUDV*)=O+W0qnvOa zo}!dwo-Z)~CHh>Vl!c;Z_F4TDfYdo!6VR%72gkKK4-&_K<5*?mLKQ~91zAAU9{Ndg z0S9P0)N^bH4`Aho8f6ms9$H7Ha~;G%-o}+oR7|2ssJ#vEJy(~f@;!(;!NXUcAE!WB zvN+1!R&QLi_{EkF&{N%tTXnk!XP;Y@Y_Xb`QTKnz7_$Tui>W>wz8Skfe`H=|*xAsp zHim8Y_(Y$s(r&x=n52JnZa#-Sz5`d8Od5T$JG_+{$mU0Z?GOCfa2)%75bYxey!qFk z=7rw;CPB_2D*|Rszw!q~We1%GZYg4-e%ct?qg&@LV9UM`wp~bgjte0IeXZ(fUY}YE zejdLe_KWWBO!9$x$8doY;vs4^^_FkV`!#8ceCmwsz=V0asx+~#(&e2^{dU7dVKp88 zU99rq_U5t1;3^IByFn=ARuT#+Ri48@OJbo!uj&z zT$&wzeZEI0(usrIN1t%eTmqRaHTh(qyL}Q=WS(q47Ck0XM>-lkn-axvcUQeHWOCKt zMVtz@8z%r~C!#+V>d2gbkm1HVkroQ(q+NYt56;HJcq6N;txH*E+~h(U^(0Ryh-;Zd zks(4a5)i=DGm%qIPW5zE_r@(ZA-2@2pa;qiNJ;y*YP6p(n5Ghq!DNA83davk$}j0< zgVsBj{4F-${r0uh7xZnQAm3y<15OQkV&ZiJyrQAs0+=|`U%il)s4SfXcrM%3_U?b? zf+7Oo2Bo0Avx%}p*p)j$#2&}FX)1gzUlszH6eFfAfpM+NE{3D6%`g^P=t`q5RwBk$|>& zAFJU!mx%9IFOosE&@9n-7e3l*la>?9Jgv0b+157SQTi3|X1eqQNu z5(2>oDxdKZQfMx?{X<3}6MFB7;Lza}qn{qv_=Ztx7(5U1f+C?oZo{hfWuG~OtQq(Y z?7%M41DjKcr@F&=^aUFoO%3fwSeR5RIK572N4wo4=xF`9Bv|Cx~oyrqdpcKdAplN;Aej2>H%2`<{No4I?wqr?p zA)CkcN3CL!Q+dH=C&t%E{j`-^%-Ea2!f!EWoS^0y> z19(yZHWWrZKUD3<0)4+}%coBtrzRj9X_aWTp;&(FKHP&}%xra_LMBpV5Fsk?<~GJB zFVfH*YH*eS>}D;hbu0RO|0ntt^6Q?8++6X(4DT<2sJZdGZC1m zXyT!B!)n6;N;YvMw@f#;KNhi>KSFQO2A z$JL372Hi_{NY3u~FowckpHO?sViRUvJ70afoQK{->(e?Dc*k3OL{b0)>(fS`nyKa1 zpNQ1FZ=avt-)n(7k{3vl^Fs$~bmk|P-2Pfg)9Ktcsa@hajgUlMdl4QKtNDW#g-8Sx zN^|3X-O2y;7};U%r+HEvAC5XHmvsi|8X1Y{6MO0!m;y?ou~Hv3;bNa|-r0BBotoOA zQ;f0q(&nmw1j%iOte^n@QrKWJ%e+};7V3-lbcdtx0@os<<4&UPfFh#Pf8?ItZyi(S zd=vZVo6BwM1=V1zz!D8(;DYKk!i4~jXBnj@iu!&dn_;^1mlq4cj~?fhGWCO|4G$QI>?-;B}nav`)Nr1!C|`PAwi$w(iMW&#P zl=c=5=jQK8>>JkcBnkCoVX6FA7jEBhO>B(ak?H}RLHMW#0vh43sZ)sfNqz?EKd#e! zgit*YqdBVU~M_Vi@iCMpq;{9PH**==<5;#DBiQfbt|seSEL+3ns*a_hV7yoiR) zw+}437;{yCd2vY_mz8^Y!t@%&7^@r}l?H?hQeB|1 z%Kn8DAQt>%i;z-}VWWazx98P+&|+MG8v_=~aVc)(DEV35UE3&q}`tzyvg!2TgY=Xqb(1VlsCR3$F zq0JJ{eAi-68~0&cz91G|*!hQDRtt+EWc1-C-Ch*jbN!BK;cmYi^|liCgjbywr$}w@ z(oidjGB%`H;Z-4xA8LwDt?L`Ol;3$i3KXxe|IA!Z zE%yUYE{X`}33*}b_egstlko=oG*Z8Z52{xU;hNcpTRTIEo{Gk8QN@DZ&OA8@XaY|N zM>sf(opaO5tWz}=xAf>((wxYS9=d488DGi%Ho$86PInx9JHq!S%7y9oOY;er?9Fa_ zSj5SeJ!7jGP765~LzKhQ*H4NR<-gB6^z+nfNU_8O6vV7^;l$$WYQM(9d`z*ZD>T}H zX-VI-gFB3zXZs6~;T3#vPeDNw$<)IeE<9A zCBGpOgvr7~?TxKwY5tG!)gcb)V@eisWVt7|98E!7=;lYnm5O@myC8J`#y)u~`o;@_ z^6=~A&PGo!tlkgsQ)XY?JL~-V1z|7Z3>~$)-_Ew^I7lItUTr5*GacEX(#@p*fqUM@ zghS1kmPF7zcWkr{;Bx*Dd{Ig=#)y;Fu-?*8JlFExl?v;jOcE zhU@YW&NwsOU;ACEeZ8UaT7O4aig3y43X2}HervKnF!Wa}y}oQ@Ek96ZOvY1YOeGm* z|DF_Ft8!y85#!o;&LnV3QiHqnA;CXUCYpa@MYc5ZF{_I6jhM<1gd+2rD1ikI8IUQ3 zqn!%_&kQ!ISWiAMUTn%Qa|c75l*#O`?0vPj@wCsb#c<52sgt@C90H%yBai+SUA1C; zJzBo^`V%uv6Sx82DwZliT0!mp{uZ`aaOMhzC}JUT)I!k$BPRkv$XdGvO~mRT!s6RF zDyl*I3*v$Q?pUla^OnmFo)uxVb?Eywf9lw9AAXx_UiJNy@$PBg&6+}jCS_K zVS#LR?X!qM;cqwWRPFkP^-72Jm87?pCnfqeB#jpD>-Gx#;`ah+iOaYtpI*}sjpxSO zE9RMe54L~1G`uyp@95xc*E`PLq~%aHZBbCuozN2P+|)uBr|14vX7W6{zd)zh^W9Bk z(E&(K2^TlZ8X|Yw&*wocY7-YN4+#(^HD?7;^5_@xFxOn@L}66%n1}v7aL{_(kC2V~ zY*@s+v%kBs3wbg4&pxm3>K+&IfGJ58=&bw7FJ*BRlcIo=`=oWbV1XuMC&%0`EZx#` zaWfn1NUhSX_|$tQVI&hV!pI_}Z<1-k&gpo^Z6oG*P5K6R^7kKiyF*C_t3O$;y2ne$ zmgw3kS*ohVrb*)_gqASv+yssNmAII`*Q-zyBS+;ChB*Z!t!I&pN42sP(~^-$e| zT?`asp6~1{loEmLTLY_PvZaugM(sH7;|BFcq8TYig6YZqoSuS$^~FOMbTTTIUF(gh zR@reTLVXmfi6RZ&JCf{vsl(L+S~Tpo6NM@Hs4lW36rfE&13?PqtfyC zj=RCBv*nzA|79roV$z@2)ir9HV1ed_VJ$AkKD3(O z(E895Ab)=P+mBA{5=(3>=J`34f0gsf%ayZqjA^YRN{SRH-?E-r3J6c+|hK~b;x z==e@s+>@O+;fs|4L2Ns$5dQ5Q$Yr%n&f&w{tLsC-L&s|TyhwwbZ?M|4i_FR`& z>)T`w%<M9&PXlyWOC75+nbl!dG4j*0399Q1gzA_!TLmyK(6(pp$icUV}2P)ml8-w>cLv~RKL zy>v@g8&+O=!{;Dp<@-2S41_Bcs(A)cU{1$0C`R*G!!`^U%clJHHGw{#mM-bpgRMJh z?dNuF=o3tIu_)7%6N`67>@S~-u(SkV72wzM3pb+2Yn=Tiy3I!mQ%O^k6-vU^n>J!f zlGHRKe(E*9B+tuFqOhVSY!m)eGANFj=Zdd z#;;zR2>UN$l>Xlk#b~YFO>DR8jqYl`MU4;tAQ=Fip%m- ze$T~#u`-Bzwt#q$MgD7-%>wm;3-S=V;)$FzDJEt^L5+bS^b{YXrMr6DVyPl1Qp@{p z{{SbeoBWa_7jSNrFgyzsB>1-9N|DRM-`Tq42gt*( zU#*xe>HA)0+G@`^Dk+5Yu!Wt*2PY@6fWWwEP%=u~ZCU|L6G2&LWgwiHVh7U5EF{p6 zY0F$C&Ro?R6|Ng0BHUz-ZE1-9e9tF07z2(l1c%L7rX}$)6B@gT=cV=vgawnN{SXOq z<27-Y69|~Z#qg8QUjLvB)uk86{X~PS4EzknElAP3Y{h_%S5S&S@_4DjCNMHyZ@hIk znlWKH{aR1Y1=vCbNvRor5d=Jps6EWhbN_s;j-UCRLk7J0{^@D$n|2{nGDMpPan3X# zZe`Q(U87S!@%fEx@|V&3)s$9#7J(}1fG82|?ssH%O5tdf6ZmpGCvgl^LejGF>)w2+ z1qQ<*2}dw-#XT7NaMqm=xDLs-x&+fR1}H@Xqa&Hbd?g zIB)t z1M&!D6AA8Ar}nv&&?|fWOHu#Q+MJJ~EUTY*Ea1G}7H)9c_oB@G#^vWeJYR902AIWhYr! z`~N`;hf#(|PYDCecyvC&ue`POFy{H(d!^8VO^SA~I0-S*0;g9e<{tDd}; zc62w1?BSEl^N@1@T&Be=Xp7MU`TS@%j_fYcx_IkeRfUln$rRXjdXY%u?P+Wd4G!+L ziXN8mzf{<+j!k6x{hI_Sj9hzm* z`(!ORT-~X#N5NPc(C}sJV~%CvAbUoaokcZ=DexixURNlk7pp*y!g4e<&E$+a@7zSS zB9q=Ki6v`{NywzAe!O$lzsGA_E=Z1!!!Bf=d6n~@$nb)ar15;#@EE0p(xhv-9Hqdb z_xX#Dp4dfxK+k}6Ur~McUw%%VJZhqj1QQZ~CY0II*2Q0We+r!m2QNE!I!}fFTFI1s zJ68kQ$vV|t^3Tebx{u~+Y!s?pRSSXIG$Z9se+3NuOMGqd;u!rsKznY$yWe2_gM8}Q z2^aCdajtd9b(i$$95$}jqoBCUpOWK$eh!!b?Bh(_)LxipArOYhc1s1{rZn{(qKw2p zrIMy*?H~WT;~>wRJEv|bF0orT1aHs?er8z+LCu}5Y!DH!FpC&n@~GciaGLIZ5QQ>5 z?uC(Ad5@{L{llTFCjjhvdC)LhMwx7_b%Kjm?lWRXLmqmnfbNSM$o3r4^COV|3O})P zn>U>Mi$xocQ8Q+I+Lf%{Ec%oOB~_;# z5^zGYsgJIfSZB`MTlL@l9?`=Kk^{i8wg;NjL!+!+HTzwL`iJX%-TZ z=TDEaRz3>9>Uo3jCmyay@*;e#3n$k6-;qY>pp_^DY>}Lz zuCkGC>S%>ThdgV0T+T3%=y5iMv7g^lQ#&ICjW6n8QV<0&gZL&rNu{Ly+;oU5%%T;VS|?EAKQR^xZ|DqUHZNn?ti9d#HIsp;CMo83YuMu z?*<=mLl$h}LhLoJu2Y?BLA*TAZVwHZwAdwxP` zhf%tN2kmgYsOaBKc{Op(bVcpFH%+xGf9490A&y{L#z!Igz497S1qKCA^b;t#cayip zSxet&YvSbXbLmK`qL=D5?Q(UZaIE>o7~Rj%bL>b^Bv{x$DNF|YYbMQy(=@bd3pJSIOJ zQCg}y=9x%%_b6oPE4iCp{!&9I%SMEJZ^w3(wj639)9mr|!fw3I!!*hwY7g`fBUFZ? z8-oSJy?HEDW?SGs8)DQZRomyo)qM}AFK&f|^Xps}%(I}q1+!gaBoG%e6iScj{5P;Y4y zBMi`tlfFxJ^Pqhg<1VXQ_SKu{))CrG9NwUvE1@(p|_;D;I{-yGF}ba0{vvdee^LlgzmIM4}W++eh+Yxi{2!W z2J$0c0`-l*TjKsY9e?Qw79d{wDE;yZ;lfJz{AG_+-mk<9s29+=|Dozd9kouH;rhmE z;A1p{7w{ZIoCf+mU=N*MGsvI_Mw+qIpiOHmaPyWyx1^)6v?lw5>OQ_eD+j6+%RCp?UPmyME+_42buUuY}}{4n4bSt?2-x{L&Cs(Kjw1eyv%h_nTSX49;n~z{bkr4gA41CK9={-&k~?v zhhIaVpL?&YSCSh>$2#+yVN(F`*Y)Pu+Q8T_Q#J)OGilzvetWue^ghy_-7hkGJwlbV zcvvuk68zTo4t~;<#c&@lVqOs=G}TX^Uy7e>H>@E29nDO{Den3`g}eeFOM8$GTqWlD zTpr~!RT@Ai8;>l~s$hs`yUq6><`o+ugzp#t_+l=wp^k;y4Cwp*;xqr~|1w4DxU=n5 z5Ple&kbtGNO~x0So)*ec+y=Q78ZgvYQiBeRD{nVW3~+!e@p}}K$Oh!+Q+8ZF%J9-(IvxtWS z#~WL8n1NUx5JQI&fQQfSftG~`k3!C1ZP_9#*m5cTOfclj&i#mA4fOe9F9#eMoRL&C z^~>0uSKj+4xWJnh`t++$Yt$kaK0~Xkp^?QKc137VA>STQt|1?A$R@geo*3OA&F8&5a&ov_R52))dyE9m&R6RQz?KSMT(3ZFrL zE=LzDqZ17-V5wlsBDkyosuRLbf>31ugvjTn>fL!zICQpf7=~p?i+|Tztak&NoA{YM z#=rXgbwi8l6Qw;v9CVM5Dn3eC;4S4HUD6Lz+$m(Q4{3z@*PpLFhyiBSfA%RB z7;>(`GAvO$+03i5Zo~qS2>@WVDT}nYjmypUw!UxN7hDtrY-pCRtm3E+3BvE2tlXGy z%D{E5go;i~%L~)pBz4ugN!n)Hfbf&Fr1D%d(+kM+H#x8dnxscDy049B?wP2O{OzmO zpu>R9Dp&E3hMvBfh9!|D1CR5p;J9N=#PMSi2(=}VUvEo^=+tOiE}#(>R73}(!~ za;v({jkf5~Ww7)a`Cyb@&CZU>&gI^i*wsW<=XY2QPxaXPgY(ncG#=?5$PJExo5<;j z5jJF~MS?&S8lgV*b=-<6T~SMdiZEQSwW0NOKoX{cJlx^?2GmfAtB!^MehPOX-DQf$ z0*pD~#>N0=b3losMqkmHd0Bv?iVa!6Qm-6EXl6Kt%CBgK3eQ;(TuB9YL?MZVqnKH% z1`OXq(t)4-1*S<4aBY={qk_2?k=;HoNIy*;X3ll>p2>E2z9xhC^Oj3-+Xz0W}%u)0a<8rtNkeb?d9LO|u zD~l#FYY`s5hoG&;|G=oO1Z^~YF}5+&dXC>bnMoBdK4;A_59eO2j<+$ESnoLTl4W-)DM6;)XK*FW=&Xg1Z8&-$BPfLt)C5t# z=X{`e94yu`(&hW|2v48lqKb=41LEVI4}IDpq|L9gbo0u?4DcHt&2G$kloeU&V}*T` z`@nshnF?jzmVJk9d`>D3WLV-!7tTt+gHM>W7F7fWRnS+5i;>MbRjL-=wej;#3{f}k zpB@f99CnmY5hT;=5@H9Yi6|54YzkyoS1vc(+1lDl@91YYdS{f@+d+E@`~UhDPnI7x z?eEvKv%M0w?8EK^9d4s%_qVN`!~Xun@+{oZKNMI>DNE^9*-B$mQ&T^^DH)-1Eaf^> zThmOJHo~)b*b_C=O?Artw?{eKqyPRAva-_X_r9YC z^l6a&0^@uopUDR$v4_r4)CgRZfp6+NPuu|@MESoZ?*#H41QlQrI5Gf)bxDHp zfbPCg4+yUD*k^palmSSfzz3F{g@~bS!s~@#%Z#y6Yivb?0*)LLC;69RDL~ZKj!y=~ z0Jy#xC`Br&Vf-H#fI{>c@5MCa#lQE`vJEm!<@uB*K?k@G7UAbg%dmgjQLt;FO3Z)! z`SMG#BpZ*51$88lOotm_y1XIZ{k)z)qd!q=-Im`gT~!w%BHeWSd7qu@w~2_vd22>{ zX-@X|^9N9Wq=e{y6~Bzg!=r&g&U$T!}E>Wh*C# zx4ZTYdg<8gTgtk8_!aBjax`c&mbNDFo3C0r|0X{Uy8O|2T9W)iHfxOdODQUns#;-N zuKbQ1V@%*?%I@yrLbZu;ae|uuEZEm_*NHx9i)&#vNRYcvl!2;H+!sGooJbqh9yHTZ z&S_NbalqRQooX@E?ORK9h*3u6d*(|6+uWlKFP)H2s@z<%$*!D3U zYyg=TIS26}T|QI6M2}4d2}j|Ec6CXF{s%6N>*3sUc;nSI3fqN!i$9l%$uYoPj4jUM zaltb2%Qr&(qrZW>FvMya7!x-HqfUoK5t>wCkDZNgsb^Ft6NPF$df%4<^M7pib}?cT z;f8$|Nd~DF2{`O?0AD)4g%N+ezn3F{UsWUW@mg#sRM3sw<08Uu#HmU}GKa8GnoXMN zh}Tg$E$e-87c0EJxHMu9N&^AqR)%~VtLMki`@Rvjwl0RE`g%B?oCdxi%rTkq{DsRg z6Y(EDdY`na{IqC!(yZuG%wUjWKPBP~hAHeeGpUDVlLS1U(o(xlh=2XL+K4$ z7cG@PiQ&)-*qBG^R>m0pSMSgR*VL!BoXE-ED;*yT3L$$-!&Y9CEQX zd(+~K>WV!07q^aixV6?a9n&_5AWR=SN+f=@Ebfm7QD8ppapsg$1rQ`PJo z(afxm>TJTQh>7H4K5)yoEc1;Ekdl&G84`fyaOVZ;Y}rFw5Po_`=r_vKFTn z_{vu|TZi8l1Jo(9NW&-zb)|6Mwtwm3y{f;Y9m8m&Htwsu*yAeewK=*(qX^VBC|E4jEg@7d!4RB@sMM-tAXhA?#*=umZcfZwzMolt3(S_RKf8;daU`LyUCYV;o)-x zGc-`B&y%p%=g8RzYMqW^Y)DX=iGc@j z$lwc-uU$k2W;ik1dxgo&`i*;!m+EG!r9(k|VHr>9o3khgvB}~%9`(xHNg(BEl1M4V zL3{#Z-Wa%HdTs<8ikwj9-cIG%XCK~w2;j&2s2Mm_I2t6#DVJ*PI+NYo@yA~5!wTee zvFM~=Ij%}l!=S{hRC7_Iy_}Sg^SWT4hH3P~xG?vti6{G*!`2r2n7FXl@*g!kermZM zcfZW;>!QI9*M?3HydKA6R)X_vDkL#Uf=ZrJ=WH-Pu@v3`msUN#N?oZcok+` zJLV0bpn%b42N*7a!b9$@i2=9_SXrg%*}{Ww4XM6>=Mj+uY1`Y-!y;k;3{@Il2j~ln zA{eITM;tNUAHD?Xf(akEGWsHP%9M-#Pl6E6cyzN0@-79l7JtS?EwSeOi#+$ z{{8Q|=zqU-`sf~g1sf{bWOg||?jiCQ-5?h=Hju`%KrN>%nvo!E@`nh}_xy{g+UsBQ zKE1g@kem*SzvTMV78#S8~n+a#OrAy5V@N>-a33B0#yI+MHAy`gwXp1m9`$2RKnQ4&P60gyg&NJRY$_%z ztd;Z*3}wnG3wxOxH7S`P_cm!m7W;(%#e@P~%V$X97kgvke)1IJadV`-N=3w-Q$>m+ zedm=R;h~J~fqvo=n|hN$lcn7NpSZjTYc-qxDNR#y(lX|&RI#rNBnZfl^GAF#hn};d zB34H~Y@@z>0Rj4oiaw}B64P(a(LK?)WflQ=qda`}&4I^^O~-$3vqI4hWf}Sz<`%JO zdzhCkjQznaiYGs0{3L%awl@=Ks6T&hBp(&^uwDdeaOKFMgoct)m_mgca@2W2mLj6n z%W*v@`MTOQIve?J*SUKM@VNvjvaubl@^CN3!ACD&6~^aB-u)M=i7wI7@c@R4wN*2Dl(?l;@EB=xS*zZ@16e{ksf`%>T^J>clC6ZSa(ctH0r@uMXlMCMi{XY|0x!)O4P zX50f%g3G$yNdhX*ME!fUX$Gn9WyuLXqJ=NdSzdU5qIkBy3-7BE9EsnUWI7z`@ck^a z@8@=GGSPPDCKa^QLIG*}_PF)IUpeS()GmMs^D5yOvBz$|u9)9RiPJ?X<9=l{vv^6q z;{OL{M%Gxto?8_6W=-rw-lop_hv%D%fn$U^oCght{}o$1DN%V7cuaC?0S-iFPyGpT zTT4(7%MYUfO)XDHQ%yB&yK;M;TA?cV|_b7=CzjfvaD zOS-4WtCSKeyi>JpLnuAh$>V$~Qa74&#L*9B$0oFiwB zZJELAO)o%ebk=vOq0XCaI?W<)jnA}D29ZKn6_N^=2@j65U{ z%Jh*9LS&+(Q4vCRVrhAzxAiYdffpMEvgAWp_*cD1w6(CENDcMaT5$=hnuLkIJqCzT zTY5f!0!zCi1Wl^VVl%0P*J665Kk|SGuOuhgW{h8=$*i-C>2Opj1wB zT0LP5x3)t-OOPyn81Zv!T+!L)2>{nDt@k?2at}s#hU4L&XCfkEggR|@6+Xx;2A6$0 zQZ~9}nbmpUD>p^jQtjHel>W58gu6M@_k9xgV+SCN_Sq-a-%Bf@UOFx+`$wSy@<%}& z@0p^Iv;KX8)j?H#-`nTH zrMp2orKGzq-5?T5Hv)omO596Ge+UUFX+)$OrMnwJLP_cFyyxZnn|c2}GkfOjnKf(e zXFXx*ynqR@VdNGx3XNpx#hZ47P~ftWERTm^%_TzGBO)1%pfpI0 z?p?mcadBUF!4Z^2UoBtZyuXhUgPas3R!wuw#v3!sor~T1r<=qHtKxzMAbCZ`qaYFF>+arDO88gjdlc@d5QwjAc&Hq6-dT!el7AAFlBs2`Xqso|A z5-kt=tQr45D#6AtC^*#+`&@Lre-MNk#OD`> z6aezX^>_^;b=vZ)89Y*%{CO|SmRa>5!BxYHc?$OH`}Tyb4P_)LC+W-_+WZj)6~d9~cwGNFPy7(MrK(i(yVQW!*-86A%5V)IU&HY?^cfmd zLn64#Q!ZxD(43vb$_e8$lIQrA_$`yBSq|9x*Lnbt!$9=jdugN@Ndq3;6 z$Em8za%dT}x?g_WkQN&|cN=fix*0Q~C=d)}yg?zw1`U37x84#_`>^e9oA8HxBByWrp)C9eR8sed6oYjx0hImOXn0eNXt7577pDL zc>L?fMTV>wz=Lq-t=+Ne z^FpI8x%}HA8eWQ;27FKZ#q1&O8z$alPOIkzTP?t z5ZDeKrOIa@V|dUmO4NHsz0G=kxYEo@V?k5QU@6w`hX(Qd`z=WyA%yTu3wG`*t*iX` z<7YXNDYP8V@sP1k=7vYyb8D>@qDmZ_$L;u=ZE#pyhs8dZFb1kS{`<-Ut3?=#FeDlp zd5g@@56QC_{1g-aqR4h9?;Wa=oQxc%wF0hHc_V;I)Cl2cV8E@xoW>7tTg?bs3?>?G z2P|#*EDA?IsBBF=d>kagjuYCvNY?d`L&CAeFW`Cl*s>B?B8kx9cTQn7k&`lm-$si7 zFUYr%qw9w!lxJfW>!csEBfFZp&W7~SLR>x|_yQbDuGTF{Y~E1u+q>X8u>o$zFPm?W zxf}MoRu3E26naO&G`WsaT=$cYSI3hxjr2{v>N>tEKCQ^ggEJ~urFU-4en)W4knT)= zz3ufQTI$mzv#it0%ZXJpoR`X+Moh*}!(#U}5Xk!=m9_(Cf7pIKosWhyA)b&ivA@6D zpWJbD5fS;J>EfzEhAe@gLgseNuw_&KLdjpvh71|ISo0N`KnjkzQga-4u-~XSo>*`n zcdT^Y{-T=c2fRAI&k0pbuQY7G)Ux3%PE9@~w=b{rj2F_%x~}c^wFrt-~9x z#bY?}0X-F-#i!oUm<)#~vO%o4rNH9V=cGk*QLK7yGb%@kVsk!Hp>V*^Yj4+$=Duu4 zVm97@;7P2aEln#(&VxcEC(iS!rzZm$zi-{eQSw&C)jyc5emu5a^T`kzHcY?Su;jmTaUI~wy6(ExifEkZmvurN|8~EG z{oeSVPh#|vfE^5B1Dx<+qo64I;CNaH|jprB+^&D1G-m`4wy?k|! zWF8RUIf31|ZS2z@N?wK0>o4y+3J)Fl}c_eoc~T{97p6lvS@|p*}hgGZ(e~EqCo3 zh9VnuPP9%td0hq^4ZJ|Mm>($J%zpT&9Q0Navil(l0a=;UqWZ62XKP}fN*k$sGB86G z*iUjtal=f=uo{%DmbHJf*c*9YLQz3?Vr*Q{YFh7;t>56j{lSdrJkBGcl`_Or7m_Hg zazBGj!oWR?Cykz(+CXpExLILhzI-uB&R_`{bp8R$^Wy|8jXvk_6x~IZ0>&Xl7K0#9 z8n#Y|vytos#DLxMc8K1@*kmD)Dru=8%9%qv3GHl(AI;e-w|6Jd^L=_zQD`u5(R9O7q)GM4S^Q>R2$!w4~g z|2!4~fZ3FH%aA-ir=8|{5?ln#YC|%%g|qiQ4&vzE6d|onXG>_RtR#5j34pb6~;#a6O!s5-)!4@_JaVwH#O2`?A(*Iz>&d zgjcMhw)P+GVZb|AlWVU&?+NK|pR4?ZjC>tqYZzC(ufskXu z!yW*}2YzT^bmp^ckH2VCd1nvwAOcy*L$h2*jp1{s=+6{#xIdrY(IQ!Q*!?tz z>uTTtc^xg(`?(*aK3_>Ct-`jO2k?>SkzDv!nDHs;E3=5Z7>|R)Jvj?k`iMJ>yrAy* z&sT+2P7G03Cf>mt)Ra$q6Hg}Ot75RaHY)-O+DDI={TZr(0G)gZ~K+8N&n?56`#&Ls2E6 zI|9IE(Mkh3Apm?D;(Nc!Hwn=f5w^Qt_=Pt6OKD=G*$((WPPDksJSFXs4H3wddY}8O zoBM6~?+*HxIihGIPd2;nOb<#<{W(rO|E)XWrd<21ca@Etx&t>SB}vE){N)3&8;ZlV zMeqmCgqd#qOMHTL9zrjB^9#vmPdW5S9^iSxu@kIM)Y|d#xwE#DfppN(#v^R(U# z*ZsXXs?wL(hFz>SeU<`8;O~&v^g&d|EuagxrVgmdP`?{Fa5MveQpn>lCoIK_)vlDzZ)CW~I z@~V>3@(`Ou@$$T@BhfYv4P4V=JR4_BE-TSzyh$*`M2ZtUoKtpnY-26(J5HZfmg>O_ z56*C%|9p(c$U&zMG0BxpHx|K*EhA^<8OSsf51!Gr{#HQq_zSDZy3h%`mE5QGsr8BN z#?>)|8aXT-{n>FIdF`{af7D&q0n#q|91lBF^H%jP+l>eYnHxVkN8j6&Z=WuPfIHL6 z{SwP=dmfr)rQMb*fRF1^{NJ8GJBLRK5?}Dy??t}5N)brt++7E)Og{v{2rue>AQ$WE z;THEN(q)jmpouHNMP=kGb|SK|d)~6oQS)@tH@tsxgiGXGhgad*?^y?U+NbLO=h7tC$)x9j z8()(*9aemG)tV={^&AVOtg#Zp?G3{-fuW;(OV0t&5OVDNOjYdn^h%vz%v7vev8!<%NtGcRjTxy0{)Is;w=>Ft1(=&=!(ukAy zWaIzEjKv0a=-6=7S6Asdf?G~#n@$k1@7dZWr)zpuGTVZ_a|UDWT4LI7@i~B-kg&n( zv1t1*WB(CotYf*!ofM~}4qsCMfgOhN9l|y-PLR#eo#~}*TBX0bSDr|cmpz3JCN;8f z^t=S?;&4dpzq`+kYXweRoWsV3B;5a>3lL@#wFzFwJFRXk#%s8)Vg+1Qq}*6ISkRR6 zPtb9l%Dhl|gclGHnCi!B1bjGwM=qTVi2hn#?6NXtWIbw`7{CBlXG%7*c-s*4B@w3+ zv1XboATA*4Mft{pi8-N+ z1}@%yoH4=oOf%^pLAIDXSof@T`I9a}?h%GE1+$UmU(>;v^wf~LqJU`>!@SbR{$q$T zJAfnM5%&}pvBSsuVS((a5OD1(oEP4?=g>uW??SIKM`_jCU6wH=?lXNJyMUz)BUox@3&Vq?aQOzVRL^1 zUYS@#?%h4>9kC|VHN0z|vwUwENATX#2*NhFeO)mPqo&>^(1QrP0z>KbMQ9wD{6S70 z9dRYHwvhhV_bPZk8l4;?uMw2{{e^TYHTRxzKFhJl|4@($fI6se2iUiHjP7pm(8~H5#ejIP7vdoaCY%Nyusibzi?R)2{e3X18=rP(od%7radS zma)9N+fNTd^DpPa7L};!?W~|Lh|Zpa4cP8JPI+5hB6LfEzW6`qvN4^NoF#g1Onu*Z zUtW}j>uZIE^E1APsujiyYhiHmcXg`BU?E$0Q=Pqg=H$70JyTni|nfn*VN=yoXX-`;V7}pc6gKd+= zoAAqAg$j7C3n29?(r;GGl1e&nlP(LR!9$+23qPtn4(0=pIah99dS&1^;_h_ZmY5#B z(3s<4?I-Ul2he=eLkZom&&utkSsB29UsR=2$8I3~?R%C_#LG<{F&;Xpd-aansVshO z393fCdz7`hfZ2I?f}&C}H`hpF`aS8mKO@>4UXQGivcr(S7ur%ym;O@1%Lzs~kxh4W zI~iWib`n*6 z?34jC>-g|bC@fH@TCcUckdTP=)~NWqDYcQWJZ2tSR1K+hRW5%_FQ-1|c<~0@b%p%M zvY7nGGHJFF_uxy1coT9*AF~ptd-gJR`D!O!KQt*tp790)TL}a-9!1ef1@m;qRBk&x zo+IT6G7io9vxg9pxaRd(yQ$vt(iV)i#F*IxMCO)@iA~ALZy>V5l1|&-VuGGd@K6F- zLexV*zT@2Jp;#J8s>!HTizxmu_zFdV%~=ZBAHA=w^h%XB6PaT>AI?5nfA-Zc^B^|V zZ@_dn@=;u(uiz&N9FXI5v6wj%*2ZJUXJA8rP_a7j>w-bV4!fHQ3WmSFJ^0f|*3tw; zd#!;072m(mmbrewMHru-(DO<0CC;B-Vj&A-wW8IzvzMdha%8-&E|^l)!`_?unD}Vk zXDq`DA2lTq6+m7->IuC7N_~}8x<-+jp^dW3PzRMZddg>+FkLRDZJ~%P*lSkCZ0n1M zBvBd0yU$CnJvQ~R1DjE69R(8K425&r@QYXc>|gTuhO@{}Oxk3+Kq5=eV=QfUtGW<{fbiE_OL+?P2pjOk>&j?c%9?j zk1=j6v^||*kTRd6!NSSTjqOM<`xDNj560ytQjtdeP9l7Ir{t?(%TZauilagp-gj>DlZLPAcu%?4eg}=W zC8!Hf5W46Gp|)(O3^Tl$D63*dPb|{{fen6DCQS$>N(7*<4_!J|Hv4lhsIf)?XiK>0 z0or^368gS=2lP9rAwC{_g5zJK{Kj3K3i|z_&pNv$fa}PnU-#ukxkHC!N7Sr=YoC^A zc4SyiBn-UUo~(E0s=U8|=Yz z=nD^UT8iJ!M}PA&D}-Xa1zR%4zsBOl9=wZkYWc@t`m`>HGX}{!qz{`efcxMo^+QvF z|3MEm<;D3zcddJKzijO!NUgCRtA}lW?TkGZMqM#ux>&Io{I_37BF@Nyhpk7~j^Hdh zK&>Uv#M+EP{zvf;tNIs?i40-z&V$};Gp(-Na0gjL_24C^d5Ma`0i{m(^>>P?$K`$| z3SX}*n%uawn6#vjeSQHp`C4ulDoCl&vMqLj>iA`uV-?2@{hAo2?D?pXL$(ANkQYR6 zGFOiOOe5?vd0Y&KiLgMT+UfaEd^&Eirg_O5f(p*9^){~0>q(z|*NekwPjoqEXXhDT zlZS1vyCt4i{nt3s9%6-8sFnAS`wN{tZ9f-pV8M=d=)TH9H_AX8xZ#zMuf$T)IXwlf zUq1axVFo})gJ{|k|3+34GVEEl7tQg@;M6INm-eUqqw)^l*-P7o^%y}2;dMw+D9Ltx zu88VSlvANDUnAy!BW3~D?@OJ&|9KYs1BY?pNef^A9S7zHH}jMVH}5}?(@QSSy)w4( zW<7K%i#~Kb_AL>{^|z}O8AT60gG*lB*%jdna1dqxNTNziW}5)_zlJTr+`rkpgeCrW z6zNkRiuh+Bycd^TDP8!pU{{?n8=a9|14{s~-EvR#^ive^l`E_#P^V_&VB!*=j)c4y zQqvXpHpVstxN&+x2Hf9-YHATlFh@y&nXdNBZwJ7C><208wc}N3#8>Qnhq;!qeeq8T zQINbE{S98e#=zbAL2WTW+b~3F_y4&4y#>Qy$Dg>y4nNUx_zrj?IM=*+$kUFTNZ8QB znW#;uAhYjs*4~)W7_Jc&j;oS6L6tfiW;4B9eMbWzPPdRS&?IocfjeD*+Vwum)%wL5 z_b^M;qBs3OyBBdvJj!iM_YRyNrv%+RN3T;fQWT{T*~pI)3N2#h6JuC&3}IwkWrxhC zM*T>`BJ_k>bGl)wLPEo>Aa5ZN-nh+`VMcZKHh)|F6LmG2Cdn`e8qI0~uC>dN9e<=- zuAEKw-6!^j1Z%Edys?Vie``V1=dl_ebq5=7g=glq!dnh()1DaR|JBIDHR>h!6eQ?7 zR0x6#DDHGoXIpphz!|GuaMf7vUXL+~6_EmYKc{dE01(_t{pc5*etHr9AfHhmoCggV z^3-_F7}Z1IvY3p`z(WAtNYABKEdEQ^TZXgTZCo#zcJ!wKknD#wa~4CiI9c5*iZbf! z#;QhsqEDxk)BF_w6na!~@q4D8@vAWMu$nTiVM0ow*_P|7P)x?PI!H2tG4yT306K?F z;+b$neS(#RLhLEffCYf!HVFVS*2b9-AVzuqCFwG^z4lazdWatKFfS@v=)a{2yxws< z-`mC>fAN9NE;Th#*Q&V#mMr<9yc6#3CE;^I|L5+-xqV?{EAGU>V&qZ0Hp{!RRWY6v z1618 zoz@~n!1Ym!>-h4*`I>?(;{X;wDgn8R-2Z}Hi-@)r>-ecGYoHWX*VHE1==MR%$l}YD znIq%+U?~vcTrX~dGL`9I+PFFWQs%1H7aX6rTtR0PLl6I$i#>WR$GJ{8=!*i#>K(Fd z&-NV$>e(6fr0VKu>G&kzZBKvqOhB8oB-Z3UKjIaMh+?6Buljv?g|`b`;2_S%R>O&H zAU`yiJX>&x*Z?h#Kk-R{01*DToy7=9VKF3?j(GU1tBNkB^T1oKLzt_J;4{7U!DLOGq=F(KgOQ!(k^(gPlyAcKxO=@fhd^+)O#UdNS4l7uiu zhT?FhkbJ}u??-5o9kghgxScmq6Gv=X0!pLO?Tuz#sYRqCFOLb)$)g7x2gr!)-j4S! zFL>q^l@o>XI6FzYt&K>UcRj-VY)#I~&EP(JCX>%X!6z;VKTau_aXwUn+`i7u`vmVh zLl)-R5S{RbGm)gU8ptYNR6S$5Br3TogPjL79oQZFur*`E`Hoy`ZLj+_3xoQ_%bUEB zk}d~!pgfSyWDP4N?naG?MLMDm!y(UlSRmER19-?D{({xqP9`X5ZmbGj?I`=|ezfNJ zf?l4eLv>q^mxkyjVMJ`}`Bve9aKQtGpo&vUiL}0-%)4lv7ihy&Q5+cB3RE=3wO)pt zD0<&8A4axLDuB9%Dba%8_lg{fXac(Bc>Chgw!^+&BAdmDKOQP?4 z<#lXdG}r%m^TuH!qcJtc1NFYXpGX^{+}Y*$K!>MSV!g27s%%g}yK*gEf4Cg|dA_30 z($!)LHOt||0$M<}Fu(J(psTZ9B%OVevT<$FSlCpD@h@7vxe}ELrAzrS=n$hAS&lC| z*hf2tYp-FCrKGB9KzJ*Nv}V=ZA z3O=d%)w*+X&);=;zliIRbfZT2-3LmUze2qoo5+7$yLVeiCRh)ppzkRfmN=+%u65K7 zPaSf~RY!ymV1LQFA{aC*ZF2;>t0B&nmlo=iMMIPl&7NliOjE>_?(uF>A)e@^V!%?j z1u>qyI>OULuJZ@#8Lb;HS|sa%2sUo7n9zTW4sPM0xK?33d}6p?6z0V!HzvhY9F4>^ zwNyMc0xpqX&h|vjrK^Mbts8t>E5XcRLoh*UxZ{5g5eWEl$NXh3k?$UtbzI2|8nNRh zCqzgq%r<6m@b|c!6Ml~|XNUv#cgN&ZG2j1$Jr4PLJplHQt24Z*pY%>Hx?fCBa`hW4 zr3UUMNCzn%Pyw4;7Z7(d6mA!4dcxaD8EHL@V)Vqvjp<=>$&9)F{960SCFAN9Us~ks zy}40BS3{OZ>_Eyl^1jj948GrzPD0ZkWtF5tzWUJ!CbKPm?DbL@n02FU=weVug@lJe zpk8>-wy9)KL^@%Z49ZV`naHmwu3{joV#6LcrwScQ;`<)T7%mpc0o4_UlKb0VJ;j3P z_+a=`0f90e3879B+U+;QJL3c%GkXR*r+lFOp8W@h?8TT}9CDOu$m1RihBhK}URn6H z6syGigLvp#Tw^kS{Mq++ni;|v40%;EBq9heiuUbG(_Kk)6hgGe{$!y^aU(QZUG1(C3jiqlnos&GnHtBK8q`V1L&o#pA@(uE($lzJcC4 zz;gs&kNIf*oUV|I)6ce>ig0>G!b?>)^)R`bHeWskz3n2nrx=8k zL$ZNtA!KjZXXSN~b38VLNxMVeL1FoGSUAlzNTNagNhsK_m z@DdB%>p*IjtE|AiEMLGyIaHosvWRxqPVw$XV#r(yQh>ztEkZMQ4UKhekeb#k;6pJA zS~}iyoMJTSL6GPRO9cZbx7z}zaVICK-7B4HFDxP|MJT%ma$y;&=rh_*`{d%s!dKfi zr~jc9K(#ZcbBUAIyP_{PbwNd_@{7?CFd$M2E<9oZUCUllDMz$?0aGAx{CfEGKOKB{ zxLI=9sH3WyqbG#j&VqbI?Gyu`k#hR6^$&3K$CzHymh4wcI`M<}-P;wV*H_%doz~-r z{_upV_b@!m&6`58L6?D`p%!OF;J0bR&pnA$(D#4FX~ zATdN%)@pE$`S&U4o~I&C3gBaOb^Bpv?{-$8DK5;pT6Gfb`@UmxKvw zFYf&g^VJ&$*Vi%jzwRp3sv#YTL)_Hvr$sDYpjQwA9!k2m$0M%D(KLd=t!CfskT7Vb=dsfal?nK_yFHd#Nz$j=Dzv} z*9awlilVcVbSFbfThQr`_ss{bKANtj%4S-mate`-98Z_}5!j}Q6O*OErqT6~j76+7 z{6<*Ji_6FBBKR%m*Ayt}v}Dzz?;`pU{rfyY$fWp~w1w!@pCrUOvzPR$FzKS}9PQ4_ zTne?@=PBmE1@gNU*nog6WE_89DT=v{AP|rETT(a=T)XAefn6Qe&!W_D zQfj$*xZN=OHA`=F>H~G{_b--6ZTwHaJXXE$?ED@*@bKnYssnEZMEf|-#!$?zz{ihN zkXUV$lz1jgPDq)V9ghn08H7IX*tz*kq^sj`jUb1T$V-JohXl8Pl~~S`FX~JdC?Z|| zn%Z=ObV9%plZ|eS&uF*6-zS7~m3}u@(QuHCnt4JHT%I~EZ%5>c#*-r6Z+a|cWlA_kYPY(`95Z;C(yo+CS&7_(8s%e~ml9d18#X%`5Rpgf# zM>AMqN`Qv3E!nwr`-goif-MoX7t3gM>4!^ybA5nMJ9WI>U$zrwJ5LNhQUF`0s582y z6kQgYiav_1~(EwhgPySUL*U9Em12Xw-*lXB6%#vix z8D5559{&E5BhFn>zVR~0iRPBzZ`-R=(Z+`Kda z(GGqY;@@BZTNfo!?DP+HxHlBNsg~TVr1bG=zkD?_PTl*A9FH#WDpz9KKmQ%fnyV?2 zF-$0(n!`$ZM~jD*$@Wg!I-M%k1|744l}KNy8xsxBE$8urxa@#;{+m zoq;oqDY4D|3)KNLa*7zcaG0+X(#t*bHl3GA1?NHVKbu=L3Wb?Ni^02&*6^;Job0;= z!AXGt5w@lYD8NGE-g-4Ulc;Mu&tkcEAnuU;_PLOHueIUnq-%}+jPk+X6Y@`|V&Ahe zJ1G^^{L#8ui+6t4-QQqD<3=V`qYf4|}BGJ*Nb5NN+CI&Kqc2TyvcSw7#{Q>zJXkZ{POqs~4K}^C50wp{Qi-zqsGY(<)R@sKKP%VUYM#D<&<5ak;L23L|Kjt16F75!Drbd2yx2#=sd{;VN2Ff!94Ku<= z<|`Q@K6?++N9MPgRKcy&!jzGO3I*QNsUybv1N%@cyCMJ8Vb;H{~0o#ku4-}}-5V|6h z-f+p@?0e_qA3;wQIZV}3yP`1M#-w{CVpBw!amR{%i8LNb&&8ZSc<`HuR`VmF zqKN=`o<#u#W$=W}6#lC$WTTW1;QaVk5#>HYWpW_Vd~e$;`NyXx_W_1H{}0r0iL?-6 zYP$ZAFOnX6_7e#5Nq(o@TCasUVJFLs(u2(L{-Qa@-49Q&w6Xv>s%)aJ_4QZ0okOWO zJ)R%9U2f3KuOVV#>dC0c)F&T1t=vz`_s3Mz{)aO%1U(FQQA6`dvnzVv*YGm-Wr z07I(!z#|D{>I0r}^^PhwUgN4a8Oe*m)ipUv>jt zSR8oUBD1Yz{eVrG1W%p0HLiaCy$r2=?Nt?PqM(7-$8L7?-ecC=G+u)_TOhmr=0=oVu9R zh&|QzTUj8xQ|umpmfO;fFaD*g!kof&epnQbQj&7ybFUYb%CkJ6kUNfo`wYcJnrUdy zz2%6K_&C0NnxN&e!Imd`_vty!0t<-3u|6K-&#kjZ*OX}XX1<{SwR!LR{)BPc-G5oi z%F5cW)K6a$vT|~A(zTtBPy9VkN?4xVUwJp%LHXET{Nlxn9R70I#+R3;&!3Y5@aG<_ zMaYrVHl@F9PWLAVE!tfV^yP{w`4X~LTOhA=yh^(t-iH=~_4xqNjUliVO*C*Vz)!fT zZRDZj)IU7@BbsRs`n4e^WcV)CuM^I{1=pziv*}p@R_@T)8ZnFjdY3*+6Q``v@#I@oj?`&x+|R*r>E!I(xU-OrkJty3iXKLu z!WrZl=i#c6UXz8w)!D4==&QIX?F*Ec!4JFoURSQFYy|3n*WIzhjc-%!e=Ru>$5biTuQlmMD-%1Y7 zwTEM$o2Vz&l5S~6um1O?Cw+>tKMl1oQKhrDaz9SDr`H;5yfr_nk^uv z-rSq#r3{`icyM_P{97rJY>9(HGCgQeYkOaLCT{5N_`YsQtDnInzUG#o*?oqKX7O9P z)Q68;h*N&(W_LysU-Waa^30<~#udx3t~#k0H6o5$DaUpiDZUw{^r21-SsRY}ta&)c zI`;$JP>q7sSf+P=S>*?C9vvNh;wp`+I5a3IXg>IECRft?_^%mw@~bM?3Z9P(OgZ#E zbuQo=k5D3+*xyqS3#}8Yra1i`oT^4{pJCmonT#VLh=jFhWUCC+q+ut*ghJu2@`8HgnV#zS)GrC2YGifLjjzROQlLHT(aT8IE?XU$FP&8jOolM0?_!jfc$weEh z{qEj1+3@F@kmB4OM)Wgcke2KO=1w(p*&(}IY~PAu@$<2T&nqi={Z<&Bxf(s-sSGl^ za;-bYHNMNEUmu(A+U6a9jY3E$24B<{&Q>*Qx%(-=7i%dGDN13|)m7J_#O4@~(QG8{ zWcd2YlxZ}5u_0(B*^^@Y9fsbsH&83Jeqpv~KyOEd=DuUYjl1nV7TQS7QD&Mv`0b+( zBHxqY<5AaBoyHf`br75z7Z|n#Va9$<{YnO8U6a-3kyHF9h&jY=7ZN@V)C!OSK+49y zRZhrYG8sb!rfP?)K^jFG%C6Q}9n8PlX`-ZCnSn2;-|@3j+_VO%y#$A@$ab)@XCBKz zweK#%nq$bv?iv%7NL8KneP0+eN+@MIUbklo5s+Pt--Pp$>}6=wMe|3z9h|X@V(4zR zhHLZ3C8cdkmYd`^U(-IJj$#@RhyC%2J^!EpqRKy&vBFw%G9OdlopadYfu zJjkN!dW^J^`apph2;4Mx&Vh^Y*y6SXw79KwEJqRiI3(ep{ChaLV*GKSsI&g7WAk0w zgeCQ=A=viG=20|g`X17FNl&@-#ACKM4U;Y`>|wJPiG|rv5dh;)#jZfhjDKT~U+ue$ zT=N6O?nkAS9hHq)%1I?KA{oN5SkdxG)z!V~wO$PDYGk=xvL46Q9_^E4S%XLH-J#3%_nwg#Oj%IIX ze(gd7&F8@seWPJu%kRVyV2a70$DRcp&=UeRMhl%5gitfDld2QFeWOWbTvXWzb!)5>B&Z(Nx=P{>GIcGDaPd z+^%Da-U>FSu~F%`SRWzg=+h2?!kd4`zxpv2*CNl}oFn+`C*$ zr?urGk6Ln}sTh^T6=JH#z)8+>5bkiGe$MkR3UV7WaIyV3jSetpDY&ljaXmg?Rl$H| z%5yrUvVme^@qU?V2ER?0Nd2n4{VAZU0VaJvrx3QrfO8B%! zsK<^uonZ72VVKl!DijUOq~qKujTsQd+u4z5C10Zd#w!@!_HOKIM5U$X+sz$#y`eV0 z43E7T!$AC@7R|GpqalR+N`CgrUl(Ez;7B(v5&L2uOFw%>46y*YzLmIoPw$)_T^n?n+%4 z;8u+ECRy7_CcO_}A;H`hsNW({*hHHR}0U z{NX|L>NDA&>W8Iwev==+{rfQlzIa3v$c}!BVrFE^ToF(nO1F7g$h?PDW{6UzrOiPk zD%X2E5n^fF8G34i5;(j|Ly~Ee`$<(9m0W!|SQf_gd5K!xvExr&01BNr zn8=?x-e#@lt(y!#)>q<8Ek0Do=z*^8k;NgBF(P_KDqlgdk6+QRiA%eH^dW2@T_9(r z@RJU-$xL1)_G*Nvgj)0^(5(_|m8$}v8Q@?*bvD;jl~q%-ao3P6z0@h7*eqNg zqg6~IhcuC-TFMiHPdH{-il$?vyJ(q~H`9inM6r38`#6{xu`Q*u z#0%(ae0tpbpd71kMzY~w+>_YE3%onXTIYuoBHYm zM#|9WnQulMB|AGSkib1__*SI9#v%kMN6bT$>WR1eK2jIH2Zn8YUzg-Ef<1K1mGjBU zA?kXmB>>I?gukjA*ostzIqXKG_ij|K%5?9ow%S$y28TBUB#NR-51Hw$B2LUSM|n?V zXSC{jf_3;)$SX`B26?CUSrupXG06No>bX-WN&fRV?){q4S+7wr-uB-7#J=o2HY_>y zX5-ozPUyQ_@;5|c+j<=BdHn4qKBYgF9J@k*$10k*Gd_@s22Z5+00!Oo00Ns4l;9W} zz0rm_6ZI`@*a^J(2c5?9p%V)sp37&kM#`4X01%~1F+HPJ-fY!@Ff=b8tPFRko)Z0+ zym&)5jD8CY`a63XGSAnL;gp8>tw|v>p}LV zDf|U;#FbYBSl@bw_6m^;D$jdQt{`v#0ngbzTN_**)HhsS`IJvkQ@`A^n%unwhpP`s!=udC>#DoSvEg?mNx7m9zt!=dSf^YesLGCXpa@Rmhnjz~e zADx*L#o;9ebUQK&D?Q6WhvS7cc|y*R*e+ zKL1IB&A(aLhVjY9{8y!MhDa?NK1~0#t#AP2i{-R0?L%A#R`q45RU=7?DIEbj83yX~ z1f34+TKgoQuwqh12^3J@r^k?B^ry!V%<^kf2y*xuu*=wwK-5xIGH113hBD`A-T2~F z>nVKt7hqC7nEzqz_gn{X!ns|5YTjK2pCxs>ixmWL=+tN7Z+rF1r75 zjY-^A2UYZpisQIeHilVWpOE9%7l;a$#>n+f@J%LBvtL52^xkDKcE$BTZ;0zG=8=V0 z4cj-J$<0#3pV+M+_E!)V0*D@LXjQ=(pWT%jC{T+ukhhiC${e3i=miR+JvKIioDXt4 z=;U@E3zZ6dy?pk}@Wby@&!CIix^h7pM-jg96ln6MfUU+_$Qsv_b`8aPn*;bp{i|Zk zTOW{d9>~F?-RwhyZHc7YL1PEFN%+JqHQs9wSgoKVEZohEv2iFuh zX_`VMJV|NL2DXTysDg2)!sXdPV0^v29eC(y)oW)fEELnGnfm-3;MqvnkI#+m$U=PY z$sT#uedIvRJNj(3+1a)LmUG(u0o#kWk0i3O;m`;HGX{V_B@OdBk(EBfISNdE&-Dcj-Yf=*{zR7Ef!m_hFKVQoo{4gvyf`t` zpo~kPU(nP@($ZFYfdw-QA)nT=)9lqCf;eVL+HhLNJa&GA2O?|GIB!lA0shC12_@w@;qkng zcxT6aELlHq+K2gjX1bkSYFXCJo^vOxcT3=)-rglR%$^(iXJ{sL`5-9Fp{BH#f}7ao z$>I0$#)q`5{1~APKauS6DZp{beGTCRWAF(9_MN^b4g3pxs=L(Hwch?#YjgGwXSa$B zqo9&!yT8X4+Fsp_Rlxxeh}N2%lwhE6y12ZW`?G`W{hZDs>l2K!xuKbTzldlU0FL&+ zjpo0?1;u!FJ2d)e9ApDFZ3Wi}J1s2H2u)mqW+b5h6_PlYBUM`9;3hLN)wb(CR|Nam z_|yi*!N%%A!o^ChOtQorIYTDJuM?{-P^un@wjW}zgxT4EP^OH-*#4OhILe;e|9&Hq z=%e)jrN*A^5l9B5gajziuI3v}x-f2SzP?&!c&&#;q0w6xEy%6;B2!7vl#^cTg<7d~ zY&4E>CKfYsKLN+==eoezPs<YiR{F`?jNRp^yoQF@1`yHxK>NaoTu>0KG?&9`#l#h{@6*v z{tlC@75sW-yqdQZv7g4?Pw3jRh*GP;*qJg@;r5(-U1Kspg~o4b(gT|iT0L1<7||_x z1x{M^nIg|)V8jO2L+9Lyb;@t4dZ>q&bBsmH0yO?d9ocnCfp@J5+^53ZR(Q@^U{51P z;Zf+_x6-H2&ryK|4R~T4ab@3Y{~pwaQC@Z4xKJ^42g}KB2omotG;dZ((e?I(B*R6% z!+{jx5Ybk7y1G6&M{1Q`-Z=`zfB+ol0C466$T|e?PeNa+5>i-w3F7XDpkLr^W+CaD zI*-XARJS2359vhmDhxnrfxzah&x+?jh7TdeA4{|w+zAn>h2PMN!u$pXf-4QiK9|2m;_TR(%No4Mk}(w3qwpfKWmte?NsjTvTkJS zo^rWx9xBY9_x>*BB@qSFf20lf@+X7w^myE?4B=Z*?QWA-qNR`q6iK=;kOTOYWH$GV z`q2377Ysq$)px9%KVFlH+m1+UxmQHtpr+=Eq84kC)6f6rXHbTa?>z8yCsRC^CzHMZ zcp%$27Mk+yY9@U5wUco>&bzEG?7oJ}qRk$ch3aR4)|}#jly63i%S&;}<+%|E<2aeJ z$vo^bXW8<}4jTZ4D??#uUFJ{ssoypAr13qMi|brH9Hn1AAYjt|Aqoso&`|z7)ux&& z{eIOzTWYc>NO-QBsJHSb@kK(G&1q$MvEMq9(im5RswXuB9I!DhY~JI`%bMYM<-pI# zog;#MLrO}|XsFCJ{YI4LZS*n!>w{+_wGfmFVL8Z#m~Uvm_)GkTYOlwUdK9=a0)dBI zE0Rj@w=hG$8z1@AE7H z84@Fl-&;-|d((EcPi3F<6MpF*Z}v@=XXvHqztq6|s`+A5aXWyJi(dEpNuRQ2)%i!W z<%>RS*0)zMLM6p7i?d~2On>S;m?v)G|MCdg-!mn_(IGQ|=BUW}G02%a?S_dQ>{4}d zPZA0!2c4fsCa?hd93lE`)RY_6qT|-EUBoXgg;C)iYhDgW$f;ZXH)9D)ApOdD#f-$6 z+s)90jn7GVJxn{@f!7fux~TJAAyU2h50KAb$`R`M33=Ana{23ep+%WT-SV0iAASvM z_7~H%<}2%rC5#8@LA%E$=y#xA7|b(cMJ~nP>5>#Pp`jBLkFhr{rv0{?TwX9t<{%x6 z`BFqAftHIe|8D$p*C?FXK+5vm-_QRx@6_EYa4V=5kf$dYraF??%O%7{xjq5-rKOL5 zjyw#(lg(hF=Wt9sNRMjU6UG8H7giI83d{&WEx5y&+!#Zw7uMjefbag&klYov^uu?v zi_@C5`-wcBz~h?azt8|Ezz6hx72CE*WygbF$pp$2M(AVey*h#m#6r>Cj(Rrf6V6Q0 zD|`LW*s0FTy8t9=4S{R?Qfm_;6?t@P;%5PVbYLm@u+R=k5pkMzpb1D5DGC=cQ2yJ* z(VKmP61WE2GKE(J@B zg)_^NZ^A6CROb-vQUb@MBROea=YE~G+#|#=AEX4H%+WTE_tIVMNvHn@0pn3Ue@ow9 zK2v|lBELH`|8ew~FM>&pVf@AGF$LCV7>R&?jWyV1t5iAhwew)F?DrTZW0BhP!${*4 z*TUzHxhTDwvYP3H#(HX8KMQq{;)(=)!7N0Q)aRMtr=lVdU&Vy#vFS0}^=amb$(~yV zZde6v8ioBmfSK}jV$3#p2A)ukx8KqMzyLbF^*Lt(83j%`C+UsmL${4fwU!Kcl zCYIuG1W)@Ist@BH^^xPlrGZm9*4f&T4U@+Qh4I za`nmEaeVY8r7vxMC)M=5xiHu$_QiL=;3uj^&k^vQDLCXwwthNX%qIp>Jc8#Z}EdaJX0(WW~OrpWXD#1s$)@zDHWG+hXLvO z{_&Efo47|UilAdhX)3D=|U<1 zfdWBWuL%+*W1n}JyO~msWLkl}#7jYxqSEE+7Xu6bCJwrz8UO0YG6Y}{8Ml>JR)sK| zujz}l!UxK`+UBJ?zklG;=z07-BF61>*cM^RFdSEw- z^CNcNSb$UZLeQc`{&KN2Eqz-zka)oW)NyllrFcP&j!7Vh7$1B{!2I0r-@b<8Vz6v) z1<-kq@w)S6&&6=ycQ|zIeXV^U#*Qi8>{{4fl2m1TwKG=^Z@91by z>~HbCm%;#5+dD+dSg2(jdbD!F$rR^v3j2R902-F{Uj#GFIJo{tfYTo2HJ$r(tlPJq zF=T@27u;{l(T@*47S}TXDt1Cc{8BJF04>c6XUKq{zu$>FBE$8rPml-WEhB|Bdz=&d zM;CT3%z|n|MH54GAKRn!#hVRS(*VeP<)*es*7h%)EcXxAz5 zxl|N3dA`Jb#L}48pP|QmHex?$!2Cu#;=lDUY+~+xzYDtZBRSPuWIbeh%$?cgz&`Ly zE7)!bTHb{wE>HIPI_~LC5SD{k$x&9HuD6eqeB_zK3VN9l{#rJTv z?X%CNbN5{uMuoFWzlo7m)JHC>zIC3Qus*Q5GHTg)UP9qIEzZsDW1z5|KSCe08fmk+ zu{K9BFpvFjGxehxVGHvzo32V_F@t+Wm4c%cU5u>&zl{^;mqbs&M8*06=K}e06Aj6r z<~VAHUQBk-XO-zlVbOcO1>IY6F!j}rgfQ9tof~C)M2GBSe(T@dBM@-ZTs`>iZWRJ! zkQ#b^k-!HjL@!M5j~CG;ZGs8e-2WZwMphJ~&-nRuqlbn=$nnM5ofMy>1ANQT{|b!V zt(`FGGwFi^M5A8(Gp%D8d#Q43L+|*UhR=hS14US%9T4ZI3Lx(jNq>lv&CABDB zzobOt{&p?|;fL=QCIX|FlIBQBGmPE_nves3+3g#7qVe?c{fUtgY}{ zME@qTFGY)Hp^ru#YvLzpnVxg)Z{Rl0gjSZwt1GDnRVIykBWKv7RdL~_DRf?!D53GH%h|^Pc2wO(1EdgUCFdEI|9m$ z4cRB;ehjV2uMJx*{?^tXH~2=aC@37#C*_qAk}QHE6@X>aY=Q4Vv(e)&@jfNll-8oZ zm*XK(G?U3ck^4ha#!@4|qYr^kn{+^v9>!XZXpz^$i1WDz3lYUd!?q**<<)^>LBl&V zzulH+j0#HU-J$$f2NzPB?&ew93VE^nKRWW)01sPJhyICB}fJ?#&IFr*`r; z)^^sw+&?~feiAfW>aR~Hfjb9RWCd>z4LdLY6pQNJyvV%X>9x(PNRNZSGnah$@6wx$ zSoPyjZrzs>`%c|a6d1Jf1c*t0{GcBcIBOC@Sd&G3H@oySewy8_`055%lJq|tJerd6 zQQGYJj2=aIAMoC%KjUhdkO_}$VqtFn^_$38eqk5n0*zuy2ASBf`YyFEnNeq7VdA+> z0B1yd_(`sknn&q2Eb_s8J%_!9Ki{GMlTp!eUJN71)h z{?rBZnoeBol`IetetRBJAAWRrjHTQQ|IC$Svk9&)Q*F;yXQdbG1a*79Xb7~6wKiXs z6`7&a9hvNtWoK8@ufvE>XJ#SgVC7Lm#bfCuLBt6o-O}tIxws{Dy|yIF)6Fi(o~5a$ zk=Zlk+|8G~3rvU73~*AC6qQLkXP{`0P?UzjPYAL@`GCkFY(%X$@rf6s)XgC^gi^w& zFP<5}t{%OHv4-k&gZRiehnzjWKtd1Mj8+*f=0%t>z##25Xwc{QaP3Nj?1FmW=&N{K@tz8hrc$X*2QVqJ-~9MO*4F zC}s-!GnevyLNa5fuQBZFXSmbnC^ZFRvS(@qF9x?#u;EgRSY@RgQ!+ndrPd zqdhWm5~Q~(>Qov(X6w0h^^me-O0OK=F7FI7Swh?6A*uG*so4U!oOV9M)GzL*I46(o z!V>YH$@jSpav;XKVwRmxI@G~DK5|Xg1mxjQA>z9R@JJ^M3o<9W_Lzq=IAZh?5saL` zhdJ0_#h&U|&vW$-W5i-;&nsx-K|&nXdKzz^9>vbD`M^n8bYT>(`Cu}{ zuKu$u81ygCo3rYW?d`gA`3m+??pstQLZva9f^Q@-=-zMSwgEV)pWlD;!2uLDsndDh zfnM)7;ky5)1O2JlZICM&N|kU?N(wJ)|^^eikE5$J;e|2E8o zR%#I5JkoeBX9bqUg+0XtpWi(7q@cq5cpyTV<^W(^|4*IdQ>OadMg5U1LMrX!gx-C( zDML(YJTqV$0mtN0#4;*a{kp|4tbKGje4u8_9k`q8jDgy(!LEp9kHLWJykriP8OGQ% zShJR3!Tg9Fv6(RVgYLYR{i`#M`v3y^zn11{9-SJGr3I3BB&n= zoktxjWinV48ptV+@mcmbZb(-bVIN8&uS@~T;8xMkI;CUpJ++$l1LPs|S@SQ*^MpA9 zAAT`>Z}XGh+{nPlX*PZp4)v|>CTMDHEAA1MTy8w|v@qNA{NtJ2)$pzU@t>8s_e0fM zS|-Lw(~wwGb4m1w+Srr}fBJ9ar^n)V8=>x#BkSG=V~E(V{>7XP#4^cTP+kgk^UtiT z>+%@DFDxwmZys1;0gi#}Oxy6|FgO-_J!)~Pn|f+e3Uh#LEE$>{LTXbi|I>DXoKX>$ ziK4O;%w@fTje0b}*-;VqE&PE^s4`9~}>R~Dp$FWAHoA4{?b zd2-Wk!_o?KE%krR&YkzI%E&}ZUVV=?1hIY`j~b?G?*F1<-ge{XZ6$9$)e1v5Z;(r^ zhne+{plzm1VWKkDEa64y6B^NL+a9zn0&0`7Tq|Kc1xIp-OW55{XvgNp(c=^k+e;qX z<|Db@5~P;`I%LB{pUm|4Mjf8_x8nOU) z>Qmy{Ewb+Nar_!}k}PZUVUBPVLAT$uDbpLRp6*kl~rirU5XEUXD3he&~# z%VpE_#oq;c=M2VW&Snd-bvwCNggmtXXkW69?y1@RLTm5OX8sYSPS-USN@R19V{0vb zE$l#`*jGFtVm{%~X{HTI(o?7-3Hwju3pnf~W)Ylg^F44@zO-OST- zuh|wI=2JUS?!n6~Z=1rs@>PTgM}hOb(rCAe4rNg%4r}sD0T73I)7h;WB#XG9S6|9_ zu&=5A^Hv}|RLW-r^?v3nJnHb$6yt4#KuikZ;QU?}K2tq|+p4o;p}1e)k~30o?HU}_ z_by<^A5R76F8r3MC=Xloncti;7;h%qHg`{jq)!EXU z-QCzSFL+G2(8f=>zECsFGE=a#KTI(^GQ5J6)7K@T`R z>*Y}{>l#%$Udd0)6~&8SW74P3YRgam*6T1Xi(lN7{qlX&U_xNMYNM{#qLJ>dCH>~0f&x95!Eq?6?*2*jIz<19IP?{Y!k|DNV=>?0rr_YA@sZ(m?)ztBw1CHu${W zH601;Gq6y#;_=k$;|@;*5ox^yvaG`Acw}V4%0cql+PelD_k&rq0Y_ewq|x6)Zh}RO zO&D-keVs;cmT^&h-=}NySyN2XX#a7E)MGD!ys}mTv6zfTT>JBy>|8LjDFCpfol^m; zi-(3H`5Yz&xD?R~uA2>~2!2M7LpdWNfe!AifxmE_pD<(u?GCURIc+ijCYP#>GE9vM zd5M$xtI#W{8-}8A1G*lxQNu)7`OTuiHJ0SNi^h9lQO&<@iL_+W!YoYFo|L)=7nGj-pWcK|>tHk?c&?fEQ?#LRr4rg!4?(b_;ctR`86)2gE z+YRO-@qylbg7pdP1og@Z(VU+RLb;U743%`c(F`z&IDTQqmzLNt%{aaDu)TWX7-G`= zNwj~z?UPb@k;b8orLAC5=e~L~#5GT9Z!F${D=BAMn}~DHfM$I2qwdhP(C?11?u_18 zIu9Pj*?*ruzegAarmu~gk{}D;AHdsg`g!O9CRRkpvtC9ee>?f{Y~WUvE=E`z0?1JG zAA zAb@{*?c-uzIFaU54?%WKvHK;7xhM1^qKV+wZ@o2Km@n=uTX;pw?grlWoAOP1V-MDy$^PeE(xg26^u4Ygz8dMu#)9dz1Q z2=sUeJW_SgtWa$ZvHM_Jw73VYKImE@?@^+uK6(wwoJGAw@w!v(`S^IK5(>-jP8yr+ zBnt>X^Edar>;M3ZFvO+Iwd*X%qx1O_@C5HIfdD*^_Dht7V6-!7)B#)(r^1Gl}i`4U8*L+y`U z=nhPa8~4zQ+()&Nh6X{IX*Vp0HsC<_ZI1S}L?Li*#SYIIhIf8) zh0^g5Jb5@3AaTge3BEa&gJIRfYfwO+y`PRyGbToNa5HTt#1L*0kE=3um4jEH#0+l0BFnjp^FTx2AV{{G2$q|9xhNCO;;;*+m-Jp z;V+FYwaa#t*TAeKL5tbmr=s}vsLktatrGirVe!R73;dxweBm`6EiB!7vSS`W&NFH- zhtvF(8<|B}*26mjn+o%sJk|#F_Mjyvv`5sUA3yk3xd+vO#{(kUZ7GtJuT~z~T!y=AV>C;Dea+g?gV=?F4 zP`*#qX?RFSS3vokdH~zkFnof3&V&Yz&F+ZAdsJ0>f}vNAzO1oh~H7lC4FRzE57<|{N49a!BnzdBr-G#01 zeXW|Ps_g$1ms_QG%l=84_IL{2kJHen-e# zdhr_FmF4V=Z+eZh)8vx3;|3J29_YxP*CTAxuvOL+k}qpyoljlonVBHKAN~xdpEY$) z))D6uiV3|5*;dXv*}!H_D=2dSAY&(kqdt5}L4G{9?ja-6vQxpISONHg{ze>L=lLI% z>h5z!k`JSOq^KeveTII>wfdmPJO!7d!k~RN!h9B)CVozPcuK0OjoO#JJ$_XjbD;Ft z!Rc-fItM;ur*t^~N@<$3Ny=~ zmNtM&{iCLBU%Lgln}R4#nhlVU0#P8Z_Vw4!=w!7HK!oU6ebRT_vT>e;0n}-~_1%+F__DVkW-7x@( zS#E3HMG&t5@tF|n4eD(ah*ziy1P4^Ln4Au4brQ|iKM@$#I5}E1zVXqN37MU`WI5-$%#F(n4uBtlq5T{i1%cUdqq5mxO zVGRDqAxu;Qm<@DFiRKZ{f=unP>~TUIU~s$J#VGiO2I$_b370CDPH5^&OFOpP(WTGL z6>-W6HLXcn92{5N&11?;j1byGA}@?1S^_b76#}TOL`JUje|7*lTe+jirg(N2?^Avz zg_5@uwxQ!VLh2&)TO02;;$db5BF@DRLi2hxQ^_z#`69(@D-C|Zr-tTAK*7(H!q)LQ z%*#u_h!ihh6=XCn47`p=!TE%t8WO|rsDm0i48R=Ldr+Uh8vXb@lziP;xp z&V;^XjgVd&Ju8j{Orp-IGKno(?i~>(gv^he0J64ay5jD=nlK)qv#8~LMycdHycOv&wENx^p;m}QvQtOa#$l~1^g4SEee{lz~H_- zv?UT9g`c-k3&eG11)_g3wgV+@BdJVd6w#M5B?qfrJ&^58EuCLU5z4Gudg@&96rjzR zO4D_o>t2;qR~F(WnEo55zgKPMb0{`8#fbUB=LM3xex%fUMIikJNp~fqvK$1P*#09* zZY<`NKS=Rn0emoa{(h8UmctG9Z?Ryg5f95b-W3VLXPDF|3s?4h{mVFn${%))j<+f2 zfkPYt4(XU79}srGIndF-?Pc+RIvQHV!4SwA3@_ za0f@_MV}1cyS{pvT3v+vpP$=2gmttkans1n4X0M-&JFFjeii-^xgH12*1BMhfQ!3! ztSqcuhITxAG5)WfME`)|^xS)rt?$Wry>2nRJ-?QXd~tVf6Vo;@??b2G%a69+L_{!D zkTCJ2(P!aVG?pUUg`!xN-#1^IaD0PpJhfWZ+Nz8Ov(x7UeZ= zfMa&)4-(OLAw;#bf8ys8CRHj*kleEfQ($LSp~NRLL*B`~FS?%|@{8&bX}{4^;ZMO$ zchr6q3R|xArEeKv+jQa4L5<{FhuCt__E!tmcd0ZK2_JXFK7`eiy&4&@b?)eb#APWCjrGa3Eoh!s|#mlyZP$2 zL6ME{3-40(sowa7rd#+8n*UVp#) zyUS9;!o!KZBYxvJx{47~bos}9l3s|CaZrhnDJpo1qPQ_9IC#occIMZ~tI|58#mXPN!HbsGOoY7G93vyf`(3hz$ei5ntr?C5w} zz{UMo-Jo$VFsRRE#QU(2z$bf4kfNHmZdM!IS@?5BRnUXB^*eocOzoel|`1wHzPm=4T4t>w<{iCF4Rq)r?KUeG}-0Bm9n%ydxpQ@|Eyg~ z;ewguP~9r)UwAX%4kpm&-sC&-ScD#K2>Znu9)9I$wTr_WK(DnBHbsHF9X(md&J6Kn zjw`SdVZ2~|*^dGjb(Hs#N8N)EAW34j&Q}8kzfkBo=t~M25Kc1mAVFuilF4I_a25lL zc$Q}evw3{5TYlF{JUEFFGwX{l4vn8gwCum{A`+4uQ)B6$bLlX4y4JFy1G;-9<6$zV(N^rqQZyQcsUhP zNEyyk`B&f3Y;IMTL?eg#0C0*8m;T(4@~?@ORD7)jg=E{OexBRKYIgbpORZ~}q329` zU4ykDi(zt;xC{~zkK>=13~A&Rh))J{v|Qid)G-?-`S60-{AKS{ac=G+(q08gUWJQq zl>kaaLw6^A7hxfre4Hu;6%?kN@6U(%haXdQke@?BWrfG59-EW8ySdEprkrWLz3c}K zv#@>0?BC~aZwWLqGbm2vwpHY<#nOO-CAZlFi~GR;*!BA}Fccp(hw6>LjgHdC5s1*J z;82UyEbT8!f~>?pVD^&Ob&F||_0s5Jy+Oa%On{Zns&|G5qE8xoB9MM%R22<~53J%TIx6 z1${ajD0Rr6Ju)(nR_%c@cHd3Yw8G;$w6X5em4ykA{+|ml`P)fkqNR`{3hX0PI#|YdwRdMy8O*BWa>v9#y?`gy*B{yqvczH$gY4b_N#079?t#4kayAq_Nxt zy8MW^NI}1T8xVgn3H=vZBt}8+b8Rxf=(F8sffqNhB9sOoS`ihtHK&yXvMtN$uX)nb z3~f$?E50dqZcqZ$Mbki^S~gb-Zy=gL>$SuqWB61#ZQK25RM_r>`|FbDQ{UAyvU-RV z4SxGgU_Box*F|Y@X}4iDj}7t zYpzVx24Ph}x%lgvi_UYaG5b&qV$+gVW1EUNQDjyo_0bgxRr+o z{6SxX52&b;G&eK58JY?^Ez4gG+*S=?eQo$P5)~<2LD*xr0y+RG1c_gnWO>AP?E?2y zjdR*?Ih4ACg%&qCOjU($Qf_D#f@yvIRvA7w;&x3pTntAa+=64C82Z3Z$h4ItUn^I> z5l3%~09z0Q4>8txI(vXACK@#bi@=#^5ay^n4)_z?&^fP!uiK!3^_o9L2uDbyhT1l2YsS9xt4~Z`S2} z>zZn~7$-;wIP}r!ICwnb-WYZY!Jp?8iz)86#~!|6Q=+SC)}ivsHnvXPZ*V_{jFbY92$_zV7M~Auz0`yJU56;09dm(w?tO5_lVrM>#L@yaXeGiqkKlhMIFuD2{#WgrHhv3X5Q#apa(EL;~VQWTTe(fx7Dxi6MeIK(T9&E?n39$ zpP&`HC&}ujcbcvot2e!i=lgVLszzWbZ=xz1?k_q8l6H3E?n^grI`#li@y(_89o-TD z?9+-zz}vx!5dt6OVnyf{tsXeIoh>ne`-d}dY|{Gn{Z0rBv+xsED6GA6uZ`Rzc4;)pU<@})UXH}9r_NI@@=0x2@ZGDCIJL+EbsNqst(4#5 zgwE#e6ltq0?BBgPUiw~JFLq}yH~gUeWkKjUv|C-|7_-8(Xvlv)GP#f2XrYR5;HD-{ z*i%YNa7JQKisf1ms=@G9>?HFd%@C zcniNyY`%+uW<>W!}Ii5PM<`F zh%!oB&m)%-0`WO%t8}GC24tUSzJ=7nhdacsZ*MDg<)G&5divSzw_iQzn6o%7O6-1P z+SH5p+$?}i+Wn4_ZUzPh67(y5Kc?^abj+XXv0smV6brxJngahLYlJy@2S>5nC6IMF zGr=BiGm$sp=>AXYz_~W+ZIDnbT)E#`XJlKQv^o&!LXM4!4d%F!Im!v&%UO8~wVQ!I z-!54EA-d2hQ%PpWvii=6C2r75QE))il`7ua=lx;Y@A~$=KnufXWEgIN`|QKS?xnui zvZSvXN6G?<_;_p&|7WBZhjJ!CP!qHWlG$pqlrf}&+#b{$Q-A`0_b;${hooqWCM2(M zdFvMkzZ;J#+;!z6fm^N#?-(m8YY6RBg)s}^x`$8%|v52c(6_u?M?9OYv; z97%0X;B^jhZURJ7sOmX$!qrW@YjZ;()SqC#7l$9#2t}nI8%yEkiz32PJlKyE6#s>9f-KghfD~<1YdpTOZOgo` zz2hW(J>MH2{{?-CdG~bp5=-FS`Ps#TK)^`Dcyp9g^Gl6>`8`Y=zks3|d)ks3#eKk8j_ zsx6)kicgqtSB?5`vCk(-rODaM z{XuTzQl-S=3QB0MM=8roRjX=^Uc1# zF9OIveM+@UROeR%S$KQe_Qzvk8@2_8eP@;II5|3D0g=9+vrkBNhaW7IW_^`G#QQi- zZCqebWT_X{CCxBeS(Oa0kl#K9Glj$Tev(sYK6P$=<|0sUht@Yy#+F%tS{Ubi6fP8* z)LA~9b4Cw}8_{gQNDiX+aCd6$GLW#d@amYgi?ep@%}^kENf+=^G}tgNh@ z6r2p6_^-e{Mp)xu`R=ZAHq@>0+a9HYX60Apgt0puu}Oma4j%(oh0h z7`>boCid!jqhaJH90|3~P!>w}IsAH~2ri`z2hkH9Z4`5kK9MSe2vdIh;{5!?f7t+} zKnNs*(e(*TSpesq`?TovU={S<*l}#b=+GB4J-(*BrFO;81uHI8dSb+xUnrNeZ^e4a zhlw&b!cX|v@}&xR&0sBz^mCl(+eNIn&sf@X&sfzc_{a5X;n3(e!WLDy1!^?BS}Jqr zXKR(D0i5M?hEj?y6dg+sKGD2znO+G8=-n729MuqmW063y^1J@3aq^f7LXV z<8AvC(neGWADNg|={LwW04gpP3cO>+pdu4hikh~4L>+AQ?|Z>$hq_3xMjCriF*`?u zxhawWS;X=J$li{-d`&A7Y{U;yrsMzpY#Y`ke)%-ylj>T=6%+qHL9b`BA}svxFLHkG zpM$f)Lv{C2bfQ(rcK>$0xw~L!#}7-oGq*#ISP=L{Qq1_^?e^e}T*plK;AbH)Lnw^C z8Fs+Ip7>H=9W2B*+;)`;UO-KPJ@`h|2JVW|l{=9?bk{~$o_pkk48_l|R2vf33sm8y9U#tEn^cuV>>?WvtqUry2^?1;4uY!4y=gT*VN=Z-WT z^jGZL7uKa>EIzFKIvzE4Q65tZ?K}2t5dMrXPjnMrf0p@I2LR|~5QaIA4F~QVZeUO_ zGQ5npU};?MCle+b6OSzRMM+phluxq$mdPuNf0nYEyRzjth{hDzX}_zMhYSE}Z-0*0 z!=Y^*x6+q~{a4{F<@P6tlCQ@Gq~m$_GLn_a4HMs&3J{_Y1ese}93m0W|BV;cyh-hE z+e}o4ydVK{^s&*WVC*My@g6WgW_hSs$}*t#k(hONzkN^#HP3Sv2z{+ANx`#Ybk7le z$NTuZy!-Ov_I47V=#|cAz1Q>I^7M5>C;qr)a|e3j)DpTHFIKyu^BuDHeLWrj`q1Ga zx?8C#0wV6`gaFS{a?6J7`!JaI{|bJX^{MSECv-#o`RtEu-MT+N6u3|2PbZ6LleK)oVq>5(D&scIki$qKK(6{aS(h?0Ii@J3}Go=_zep1-uIR#;UB(FyJXu>a`&L zb6P2EcZ zpk2fo$$CMSu2^q_^wKLK}g84iH#`mXp zeFkp#uKw_2IQ@HfI&(aE^V|9!WI)YgC@&xGyGn7mQ2nb2KXllM$(I=okvLHmS>B5B zO)dm_beVG2a+)RKdW@b}OYRgwI3BdZUkcNVGEL~XDFNg+q@K_519%I@szUPN8 z6`u7YW*^zm2W{h-U^HN}kL|S272RrNNqKIr^{7zlymv7_Lep=1wsGTqKD5TOv<~y) z!fq4%>1=o_ew-3>xahH(`u;$0umd^qJU{nN9vibc|N~S1^bSkK4_phnU zr<8lw)|7dc)pPEC(_khy3(ZwnWtpJCVW;i7&{@DmVtrHBu4fK3p1tw)d9$xwezeX0 z=EjkY)=Q}~a7Gi+@i}LdZ7*4&bbtwMBB21&ROI5BBy_0eo1RxyNpnCu8#dfI|A#;P z`L|N3R3?I{>NT{Zwc@YuYzl9 zJvc{UwsM#SY*q+ZT90TniCqI>Jp1DF`0cJI(Yvbw>BeTHOIsi->miFm6ZkYvL+QVn zi2l1yGWrhybJq;F4Gj$mPavp7bOEo;$1HRmAcN{EgpTgsFv?5a1;Ia&L|L&L3J20c zASDDmYL@yh^Qiv{6VP&|T>#YA5*oWnAmn9|8mY0A<;|3$3e=u(h z&Vbe#S7gDx>hodVm4;Nq$k8L{cz#pPcKcZC&s>L!MMfQ!V^2PTsF{~;XCEy3&_@6O zdNPSk|NI4v9y^9$bq!YD{7F==T!q=^Ux;)hir0VqqbZF)>kI+df&GyFASmxfR$N|= z^RIjtwm<(YMhAMKD2nmmX9j7E!8X4W9xLb6v#T6#1}=B@=BI0#3C5=m{sEwM%^IVe z7l8f~9T@KInH2onSCFK?4EVQ}g@iW|LBdxu&SC0SRn(N1qkCW=^N{1FFkr9N4tQgb ziivEp;cdeiV5WmPa+Tj8@IO&A=f2I~NL3@|HyXc@P1|!>xBvG4zJs8@7y$6qdu~HC z9-dO)md&o2i_d((C>z+(dmMND;%g4hA>d$Jwt`x7ee1Y>JZ>*i>Eua2<1z=D(q@N- z)~aL@bl`QcC987293F7Hd{-=POgysdi1GAhk{FYWF(HTqBPp5WBoq=FNn$FK?d?Oo z4UJXp!6IKHB&0qPp)5lywR)QYB&__C&v zL`_*r_qYTxo{i>Pze!1waWEPu2x#_6%+Pw5PAmXs$o4ZZ!x3NwRLJ5&0hu3??e`=B zsLZ2O`Od2^^(?ApOg#ytd)kc!m6qjW`d|)Ch69kCz$63Xj6QYV>)ZcyaQ0ab?Obri zwabsT<@8{d1mv6%$*jIXzL{Wu{I)58`HTstU9wSriw%&oX^Qr>uYI@W``^FsZXrZ5 z0C+r}j%CXh-TR{-efM`~oN>|b(rLZ!Q=j_cMNdEdo8Mde+;PX3PrUHL%Xhr|^0s?o zvDmry-~Vv&Cq8oBXnc}T>L`p#Wsa6d0C=<8Up@)wEt?rT1^WL~qW_j1+XuGg58yqI zqo!;-zOl}OBgI}kOo4JtSP62YC% z!F_Bul%BTiHChQ9{Xfr~qW_i^jQ-m#FZy4oFa0z{{{g@ofan_N8yQVYXgXz7^o7tN zbOA<2G+);Rx_U;(f&c7Z^B*KC%DiR@fXq|@pp0N(Ry>0iAIdo%1K=yKKv}c#c5v*e zCoy{L7#NJSf*0@DfJ498Xf(DCG6{3R4*mfELPFW|I+!+2TND1GBCI|CZJ6D%08$Wi ztFi};Pis6?@DDKPX4ystBOO3>xwHFD0sNO%SEHtJE&u}%9N6~Clq3I^kra;LUv<0T z^#|-b&OG?H{;zBBh=e1~^Lad|4u$fL%TeWOgrE80;tUV~(+%l!NOQiW?K>-Y+c*i) zzlqENNKbiJ+jnrGN&g3I4gdyRb^iNt-fBZQ^YP~%#`9KcK;HE}zHj3%XB-=D{vNy@ zA0$a^xceWFOeY-1%urgCo%4JFLIAk)v;T)XZ@X`@lXB?0;4lm9Isy2%Y-9-NI5w`C z(i|#QSJqdPghvv2q$H2j$wLwzDakD)xkXBPgdmqlO1IFY>*&F*&AKFrwB!&vEAnZg zsj@B6Q1aM7D%F;y8=fZXABp3c?MLNEq*GfwC!9EY(O`7d{NY4>c}(|tb(w+W`9E}X z9RqClUjwkqOd*Fnod8?gY_$h7jnJg}NeL#UbR<9!00|+3?xylLDfkBfczN|gVt(I5 zZRS-CMHkl&9oXMn-uha1bwTWEH$y)O00bl~3X?H!3IHjktpuRWgw;~ZOe$9#+SyIF zb`=gkh)KKvE+8C<@E`v0r(d`R+ge`L`RJo9Cow&8mA00QT)YcuoH9 zH~rnmwpqjc@sA%|HLm|C#uWj`+8{6hR99F3)d~Z=6+{PHnC*ONw;~eg)5H7lM9Ui*rV%$eVIO~PSQT5WJ2poD9u7NJ&I*o*# z$L$30foYch%dp}T)~_~1Tc{3#%r6q%^Mlsbrv<^I74Qpt2K z__qOfOQFBA+-Kza3quG{N|`AGC`E3Lzp7+40Gb;lRxgmKDVJc})B~{P{YwJU8W2kY zV^Lsm6zCl?90LO*z(@p$CV+U-Xr~M0zF&wWmaRP-&8;mc2^i@C0UzL20k_+OS&ehC zdfmCW=!*ANv@X8j%GhY*H-3JX_S<{DJ@)lq-xt23?T8-Ar~ccc|4!6@JKf2O{*$Gy zh+GYT390`8D4+Uos&?7){-xlG)QAg>l&*QL?-Qz0mh+_(Vc_X4kf}7LYIVLk6uF8f zZ#YF$6a}jm&CfVeX2uw7m_EDKLVwH#Po@C=nSJ|2;NRX~aS;0Q#n8@N4Ov~885eSv z#>2kccXNi?HAa<2B0|rOZF${f_n&+5B`9ua0011^_$#Ew#&X9Gz+IgE-cq9@x!sVF zUa<8){~fRY z%wN40s>eN};6ML706Cg3i7+9PZc;FrcEe3SYe88vua8(SH2LegEvx zZ(;Bc7-a+3ELsl$c;xB(uzmk#hanpOKi_mT0Kop^ujjOT=lLJNxhpTmnM=-_=%gI_ zE;!5ryG{Z8n?~)&fYI?RZ_nFWYI%7uD0Sv0!8}5cM+oxhI(dW+x2{`G0Ok_9bocg* z4Ms-dhYZ~xfJwo8uC$yL8qk*3{Aq}bXGdd+p{b;9Ps<{SG+y4*Nv|9@tW^YulB?$p z#m-&YA6ec!oTw{LXkHJbg52K+=PdJ_w_lqK z5{xm*2|!C7BgvheGcgCJ&$wEm+G?a)Yt6qxH$e4=*Y1CXz}UT8maNGKeRl7Ll!9?r zVHUu+bwU~wZ;R<0-{d6GAlpHmS}LkS`EMke%^BdztOIVnp-s52s~3I4 zy@K()Ex*}T@0JAKg8U2TpsH*Urbbf;c;8wHB{z8hJl7B8$ zX0{diByPUe2s=qh=out*^%FY#fX;rPvk&MQGD?x#O%jmOjDJpMJaYwVY8y~D{~RQe z0%QgvRc<%|{9YiH1`-K?NI^wa4a!25n7?SLCpG3L z*7X+$_F7Lp;$Q`+|GCkBTi*Y4sQ*-;vgiF1Q-sEq?pY0Iru~6&-sO?4dywer zcb+H*3#tLs`)5v|j{#WL+Kk}D0fg!I%f>BCoB}Wf@Sh#A!}h$xtcs*EbQu~u5!#Mog-{kaRS$tr?$nEDG z)hk!w(8fn|+A$(@y|iWAe&gX>{#fl>0E~@7IeG+Q-hAYnzqlCnjdS32dvJK)>qtf; zV5$Oc?n{gpjI>V``~!fVN}>DsQOs&F#<1{=GZ7mb!Ej%%)39?6QZu^|q3Rj{M(WdH zbIu(OV}5i7Q&MC#093ad3(hzT^)2%=W1q8l3A9uaZF_gycgs1zbiu!qo&*u#jzu8- zCD0xG0HLBHq|#}`Y*io>rlOk9MvrzJg2(_djLc+bW+Xq`RnktuPPgcv-8y=Y;f8;` z3Jd2h%k2A=Pkb9CLBltC$336JSTxVsGYR;wtDKEnKWv0Jx(7P&Uk}_~@c16L7aza+ zRscry|AkkxB7_yC)%g5%h6X_-R^UzlG>QIA+?+s%_JFNg2dG&+0OsP{_pSwv(Vy%% zNK#74x#SX3>Ldjh5|T?PnAC+7OmLY_LmoQR_0sCKEiJkxI2fd=fO%9+RuqTH?>!jn z9qvsXA8PQWruxwDk_tPL3W$fmPmqIMR)9u z1qr4wB4W<5(4pk317+S-^)5bn>AdM$PfrhOYHAAHOQ&ugR=YgP)a^tfCtOaJQmB-; zYVnb-$96SuKdZ5`Eq8Be)(&*;TS()*Ofq8J(0`tC*qA|MgxpF2iel(FC~%JL3kNYk zOZ|WR2gCO4KD69iq_2GCmhS^FJOgIC&wu`w6L;Qu_l{UBw&uq_zW-gf-S(Ng0mA?M z&yOlLz3{>vR?k;mb;+w!JF~*}SC#?rmIL5#!X}~rpNjb3p&eicjzL{@7+>%x_!qnZ z*NjVr_soU3u_lDo_xu50-~AE}uqcKbS0PnB3&NkL4KR`TpOZ~g`VS}^{dXc=JC^=C z$>_fafJX)0^d<4VpWgNGk=~xpZ(VZPyIfKT#7T!o(T!4mx={_FvwIW`wSEKiOB?l{ zvJ8NlO1~NHHy8j$ls{WKP?{zGh=d{f2g8xD@3=H_=a__|NX)91Xs7~U^EC?z^bBSl z0$u&Ui2{xR%ZLC)^T zRD>pPI1O{6^G}@rZv*%C?RnroM+?A?u~_aga`v$~4yZT?efbiwSPV+r39#NiJIr$g z{|vy9-~SF(OP2wR;oJ>(pzpPv7}&EL`+xaxrv3bPT?1dpAVTeZ@B!$_q;1^Uj#o>wqsfI(A@b!GES#Dd5p!5NcpN)0#0BCR`7=xo(2ke(`{5FaM217dR%0%CBtj&#Y~f&F-TQmP?(@lFs1vwBQg|>iT=omMCWjcyFW48%UFdw;4kHVuZJnz8T}Cm z@q~_{aDoQM!ZaEVOU`1VESMH+TaxL9sz`cvWn8NXrL+>SCS0nZoFcf4fs-M13>eq4 z1m#>qR#`v-2MWbdDwQp{zWYmGx~*U|rl=@5K38s>wV|b@#n$K% zOfSLujkh;#Zp&LXb)yZ=kDlku+t>xRb^G$3EsOK^X|ruVv;*w$vv98&zz^LD{sC`r z%1CJtwJYZ0+}HQvct}$vWiNCDyqC7 zZ&QDdcEL-38h+2KFGm-jIFj}Tf^4Ls%9|h~KENEQ{|4@1;5>)=4~9(ip8%$CWJ~@j zik0`z0R;q7q$apXlOhFIg@mH(aCfvWxly{*oI13m>FC+`XNbfks+BgI8<>j{_f!g9 zPR&Y+0$9=7a>~&MyPayezrsR)PV1~U>O74B2k@UW7PkjfRS8sAfe8T?vw06~{a8!k z6YUs1ehkG8v*9ZXAy``nmp_1GPyGRaAriR$OJ9cKawF2!iS0kQD`)@AlG%5>w-<9S zxfF~s6xG$CW7D&?w)x=SX-C` zU(A-qVc*dSU^;+*fI;Xw`rF!2TwV@;Q4ttpC@wEYU2_X&FIWh-$BW+fwwx{+=FLMx z>p}p4mP+E)O@D&4K=CBtp8;rIu@a1PBx5mj?B9z;>(*nz8S63{1iF^S!5yz)-%Fd3 zN+fdjEp#3Zr#U_FZ*39+-0Ox;;~%4pG5Eb+gyZp?^(u2ig$oH8$z|3s(;>ifIvF?Q znF9agKAt4_&)>JJzXJoqJy^4NJ-luoE?j#VmbadPo%>%xBpz|x*WUBHFS-sNx%{Tg z=VkL&W8UmV*mLw%L}Fu^@73*c;|n)@6Ysg`Isiate>=YPgPV~yH2^MKe=R<7&25=} zj&~i#lsl%e&T>xh9d4x?xtGk0Q!vyYjVobl24V5j&q21#V(trN1k z0*nz!0%xEs*v)+&B}HGX%(J*cVV(l@r>1XypC8BCj^q9Z??+W-B~~n3aZ3Fu@cI*U zd@leal>q?2jFNqf5x1Wk5fl@!TkDME2jhH+7&uqRsIi!Jl5l`P9E_X&GoIb1auRyZ zd=tQ+fKzrn63iwfC^-z;hBPh&ZuZN;h)ZrR1JWo*XzU{;RBo^e6aa#Adgh5urN@qS zyp0I%v(H}j(4099DJiYTp3%?Z#q-AGI|$RiuC9~v6Dkcj*MsIs!+CkGF1 z{dZMW$pw|H$dSwCBBX&d(r~-o#<){J5`fq1B_NK0I1mT~%ySwAP?~*Heq}#~ zdcUq0b^r(+%t}7;z;FOqZ8krF#*PEEKfd(xcQ^R`eh8sKN*$?`4qeyqp=%Z+=u@*A z0FWTFydPjh_J8u=P8@3=gp>lIVw3hSbOTUl$^sht0nxa?(3p`j@cv6Au2?U@W+*AJ zBq&hYbOlD`LNF3YYlbr;9v6rubVTC<(U^{KL?9f~F%}jW3F}Cw^$hDl2ul+|WW*7T z_1R@z*AWee5si!?7Kwl{F%&FOcF$Yv{nNRZl)dg^j4TI0PV`@79XfXEzdicTh%!t8 zEBepCxzxaQT~|b!DI}RHG_D+<(|lz-6ncC9JPbVj5+eJ@3p*9EkUNBVMe}Ch8!$}a z3f8Y$g1`(?|7Q;T=Ye~3AA27s1^x?+fyZLtZ5=>wpAl6m1gIGhYHmTObpetiBL-EU z0nL|QhSi_G1pu()2Y2DvGf%;`SLQtJaCO}m{~2{>tpfl&`-OkR$RVqieLhUcLp#U^ zcm>9q`N)9sa%hW}!pWqR7&vhPx~8GG>jb*mj>5$`6wbgE4lA!V+v(K7zkQK0hT5iP zG%a3&l8VaAc^=xa14mxlX`f=8bM<>r90~ypIJj*qj_rOu|1kEM$QuR2rPtp8t|%Dm z?}yMel-JG5v>7w7Y%qQhL)RMg|&Zu&2rv+`m9 zKr9i(f8BpOe)-IOIRdHnuB*%Iu<_2#2>OfBH`I*-ZLj0})$agcunC@d`7!J|v<(%d z)wpc^wWzOZ%=CT3hAVKe-KYi-Dz3oBJ2#`Ws2rXB?U+^7h(B-pJ#PEX^>93J{^?J4 zx_Q6X!W~Uvo>diW)!Be2mys?bDLr=YD+iGlaYbQCt{}lxmf$K+xLk-UZX{i9o^ZQ( zQuXlU+OwL^4OJB{QB_VZw<29C2U9qyDxfMVS-*V2IHl4mkEPu_5?6Urcd>X{;mNeh z(>h~Pa&Qn7MZ)7I>30hm@aYurYBJyzGT_mr$1NmRh&Tgr4sd3IQOYLkXXc0qf;b|H zGFM-?&KHS>+~HJ-TN7R`bcIWBC`>1XYtrwDY5~ufR$kPTtSIhF`n^Ib9K<9+GV3}t z@V*HyjcA56Ag?4MrZ8zJ-;?BAF-49z5rG&(W}iy$s>&Mw1=D&6A3Ssr|9kKMV*kMd zXqqz@pS|U?Xlc$82{c{9&z&c3{Hx|rKRHFAy;M} zP2mzy40Q*M$g6rR^;$}+iv07FTZ%vMo|_(*QhL^{TYbkf&ph-fpc;LVDglt&?UMEN zOTRfdICQl&Uw)r&$C+oX{>~Fm{BpA~UqpaM8h=54zfU4c6h)MR!GLkhF``i-DlIi? zNev7TRaRC?00guVFvnarbtD0s1LVzTZ!rM=+Ks?AIIMooytPh;{@-TX{@kyjtV!U1 z+zLK0LnA$D^LpT0*oZY-Ud7?a7$S)TQbi%?ROFohZ_)pCGy3kc(eI}k{m-ZWPdWPU z&2F=z|JF9ULOozm(}itYKKKWK+4C^w4Mu*(sF<1swA&G`+LUX;u;wHlCg%azR5iU7X;`~(-XDuPDoNsJvsh6m)B2<-0 z)K?NhB@(f?L^73S5~!*Qug{NQaWPyjuRoQ-oX+FPw{7{;$opS@A$;+kSEKX$`_teG zONK(O1UQGZF+Lc;i1YE_9{@Pdq5c!VrKT%FWk8&q9oFamT57K=K9e+D2qGJ=uAhY{&Kk=fpI#g!;)Y6but z`t3%<`}-#Z{{S$0>?oQqy8?_cs2(@EUw&yu!GF$tB@$p>A7pU61S(?;UcVpla2Ua& zVz}IHj0_DJxwe4uUD=oyCj3!TUK zW9QGnG{C?4Sz!cSaXX5xdt5F^DUnR)3WIui0GdcaM=EX`o zk;Iw#Bs62knd`)MoeoE9Jo`G=l)ZZFysE=JD?|OGje*g4l{b+tcBM7HstKQ>3$LOH zznap6u4ppk8Hv^TyN2f%AMIUM+A&z;kEImm^+a^e2?}Gjr>}8tQW|Lm#&g7=!!s~Q z33I-(KcdVKsoaB9YpBRu=I2x7>i^=AhjHDNE;hP+3udU;gTss3@<%+SO~P(se;&%uOkD9?MCiGuRLWFjKYPdWGScEE~o-!8m_x zK2}rnN_+KMpG)gl-8ekR!02FqDA*P8`)Z34Ne)hCY6daJ$&hAX5C9k%jvYG#0RR-1 z)d8?G0CWJ5Mq5S6)e2Byw9^5AGqUOxs$3y%UNo9&r354Z5aMUx)?yiyxm(P;G8A=0p-X| z|1^7pNtetK{!;+xWTq@C3P^%!X61p5>c2)@5-C!GC&B$gjdQLi7(+N3!=biL9Bw~>j=nw&42~l0paQ9=9OdODm{nDc z*2V_3HqAkGWhfW?8@-Nq4wy@)2L7`*xp5AGU=VWIBCw`8U`LOE^$)<(P|631_Av|} zIDokq8>-@~|NhfB{M(J_e&rP;M@F1q;299@>A}FB-Kbi&9M!8c;6*A z;G#3HL{oh$7z2)+IDn^K+K7jqx);e*HudA;Gq1v>XBh;?A8ou7@43i``e#G{9l$^5 z3O3yIJuGcmjg8OVkFVbQ*#h%X;KZjgJrjLL;ZdOTIMC3PvsG;_FLp1lt4#0i>9h0z z2uv`7WFVn45{yBpU~*(Ak{lX{9;&J-UI>ku7*T*hA)QI4GER&$fJs1tDT*M4F%TGB z#E7Z7af0UK-1yZI7!(kbFth^9jYfHSA_>OqbV9}eN$4AE@a{XYwtP5NebSUPNh*&d z8vF;l8vF;l�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

!U5;5MsV>`Fr{zo2L`WRh_sH&ljL%HZ97jp51 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

lNT>_pl$5W{330gNb649{>~Gm#b~p|m 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%0Ar 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%0DlINbj+aSYc_b_g?|e_%F@)(q~d|dLishDO^7? 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

S>hbTJgiYxR z(9Z$yb}2ybc=#M<=nOZ~-M-|x@w;*KhiCiGgcSvIF2)-n6h`k-fVDR>2FK0-24WN6I}F@ z;^U6`DE$6fn77Ci0F@Q6a&^x!?VWxfKzS+r{-@--&++36{I-GOmWODQlI9>{eOU!< z=~A=~a1q@Ae<&otyI~C2n*=a6af%QV`Lcg9-UtvN)0+fH5)p=>?M(u_v{%D(uP5r* znG0)Xs@RpRoRN9Esiw0v&=83L0*Db5k^oW)*RGvRX)S^vaMrpmv%frS>0J_#Cjq20 zjv#Q-I#K8uAgyuMIFt&UlTPG`fJEY)MMTmQ1x_lVJS89jA|-8XtaK6=MZ(ztk#xpV zhzJ=4RyZf(*dUA}Qp(BD+9Z}Lw9Yx{Y$UuHpm5GgDGbIL5ld^NGtyvkNz-u4m*Cc~ z>;AAQlA$mDpzp>3vD5${?6t*nsi~;u%70$hXUx(29YJ&J2A-b#T#xOeD?E3&v7>cZ z;2&V$?R~|`yyXj6zj1w$A%4rAGk0U!xG6a2xbXH%yTCs{Tc(Y>p1+T89QkGT+P3@C zbA0t!q>xOg8PE5R`!=sHoy${mpG8W=CuV(&sbi<`<--w_L`-9X8&WDKCZi_ zX!gfXVfM#Q0pQN(?%|@pUj}&9!t9TKi6izrjPi6D0Ii*E+&kw1u72=(5}mN~7CZ8# zLry};fNLJUfj5@T%RL*v>JM+fH|L-7KV*|Ef4uikoN-LIxNz#2DNG&Htxl+}sHR~< zFJ12cIsW&vZ+PI}1`(N2lZY$E^;_c)-a{q(%rcw#*W1R$&LV`f;E)BtzgzBag+zPc zk4B<}lZlihLW)EP5~V~IDH0{g63AFc5eLe}DiB#IMWOZqYPl(8h&}tEqw0N zU-Ai?!j^x9j{jf#HP`+1cg$P!Hh*%C@kTT2;8MIJ%`%z@BNVe&wm2JlOFuvc_$|u!zFm%um8x&^hNsdBM$URaKRP=7D=R{+GskO#lcy0dU}O4{UAqCV%4! zNaczOFLyurWH|6Zc=JuT^G;Z{Y^0XkBPQW9^)>j;ZtZLy0ib}-GX&TFZ+_Fu`!Bv2 ze*J4`YlDp&eH+9vW4sdLsH5P^U-pKHciaI#`Vsu?Z?JU0T=uXc1$+drf>?)t{=-*6 z2ps*GwB@5v1yC$Dr7J-1NSe43uWSIpyvcj=iG9A@Z4x^T++ZX?KE_POy|t1bkSmRl zlBWQMO9Bkl51^(LGj=rbpB~}XOSk0sKo#%7x^M|R`V8E8m9ObP^#@+EU#J2ojH*h= zefKk}5?*+v=l+Jqz8wRCz?TL5>lwK07yVoy;E_3)1?Ka4~|C78~vUYRw^4Eovu+ zbIqglD{t)E_5_jWK>|QeUjUl}`*{)oqp>P*7B?g{fRMP@dILpejmwh&);i$?B2xaw zF*a7JoEjkMj3p>1gp{dNU~H#$ab#WOl$D{iT39FI(8hswVJxi*tTlSiBUe zv>dVh&WN^+xMfRl%{>9%aKQi2!BXE%kG}dOkG}e3pD|O%P2qCPzdU>^ z>o+!1Sz5u#hn@()v-4gU+DQsx*R6H};OV)~^$Y$HaOiFa0`OMdVwS93*5`UGS?#|- zYb!?+1_6oIOsMJZoO;JIcXRQbf9x_dyzj+_x%1qcNJlC5*={f1UbB=tpS_1EV17nw@6&gi~v08%jtjO3L}{fuEtWw3730yNLNK z7ch3zSf-7g!gtc&VD=xrjVidEiJLg|)yKHTXl6ObxW@Gy4s=Pg3hVxRM=|gZ{nz~$Yx!3Q z{(HCl8%X*;Qm+4n+5bHFpEC#b&_n#tTKD}i) z??LbpM|dFo*T2G1pVzIo z`hM)c`3+2*=sgk6Jky&YUVO194HhgIQ33$G3Su&_oNg7wu*v}7{VxT0_`B@p90%nd zc9v9ed?EPH$6zEtUIp;n_c_37zMkK%O1Q2%!8M17fk=Q7ydOZG1ZXDb96JaJkS@WE zn?(HFQ!HDsf+u&}f-6(C471}G5jg3jMF=aL zwo+m;0vkDLjdDg=p|!Lrp`CF;8Y?hDI*o7|^aK!NLhx_3LAo=4}2f`2c3r6?JqZIXKm z0x1-rnNZ`I_jSz;TzdDFJvtd|XxqS&wM*Gy+IC%QxZ|0-8CzA`MF5<2?YT4*wjKmN zfA9(HG-C%^JKOlt_2=>0k~dINaq3}T;ERWx#1VTQ#*L5PO5OU^TyoFl{O&8~v+d-q zIehnz^59Ee2DsGDMnHQ~?kC`{Cjj?f*>w z`kQ2+O+S-jq59(>E_x;B%WudA&ez7?EBO6x&CMhK~0?sLFN zsRbfIx`bTTUnmhvNmdDwphT>s$jX3NDiH@t#G!BVmnh|8r9={jB2mieAX2eXQp=P} zeAZuSnQ|r)(zw9dbl^-r>#wZyF8@+6Xp2AV!Fb_S7>?N=3=RB;k>~>Y)(V&Kp9%hp z)%_QO|CgR%%*&5)UYKUV?4NOINv>Vsv0r52YcKHeNB_Ykam>e@qw<~A{Q0u8xa4a; z;(x=k?s3t0 z&0V*({muPf1ODN?HvtrQ@ZWEHtbyYB=i!!Hy!*W|@aa#(1gr{S{8 z;EgvtFdpHxPr(xarFa0psf?MxD+*=}WpG84P12<{N*oR32^MO zaMxX%xVrvhG%yVqizh@j=Nc4^pY`(w`^+G3yaR{vA*wT+nE$_&T>8=9^7e4nSQsy! z#fOqMZYD>jNyRM(eUBFgIShcZb$!>I|DqYp6tKD$GrF4gi~hlt*|@J8?i+8xQ*(N@ z_?vx_cl=+Rdo3-mgB5k~))F}DeAsbY*ggkA_udu8j)wCuhjr`Wf3JjTlVGQ9yXSj* z1)TA7c;-bo|E&Jk`tS>wCthZK5U@I3#_FoEG}l&>4GVezXDPUm$lXAw0Wt>pF?qM) zkuV072AAXp7a9W^n>b}~o|H&>%+Zk~NQILMm*i@Xloc+O7AEoSk#i&f7^__>moYLH zrvVbp?$1@9SqT2~5yfJsSr63zJAvrqJ1?y_ z4OF?CL+~Vkl{f-JbmmL~Gb$7rsa;3%{K|&b%bs19eR64&%j*7#$cifDhjvBmwhv<5#BPu@5D*&- z{EGn|4kE#JIIg<)&wS;g@9^Xs&tjcpQtbpvQzbNPSkL#b`U$JvS=}}3P(bOV(cRLx zmI(5*Ot5ifU$;a9=d@wjr9m2m^E_`0A5`9GEdF(zNcUN z_^G6$Gzd8P;Lif^kLUkMQ(O0qTvIO7AB7PWCFS&q50vTOrYlZ*&ONf=zrXX^Fhxi0 z3|gk{PG;1k0l|N=c)e@8>^a?b%}cSaYx4$w3XK#7-`39{rAA7PAV!f0DYHTmi-4?< zGNUA&DiEDY`5*t;AUgsjI%Oz3f{>0dlpSFp{bxrcI%HroVT#TmlG&idWy2I%l~x%Q zsce{bagYuZRj!gSEp)nK0aCZ(6_qTTU&j;5T>`uIOyz zyO*8EO>>^~6_mZfKe>%lw?!DZ_dHXmcdqA!McJLWK*a58u>4L0n%x2j`!Q&!iEj~&$Ed! z7GI)WO1A=FQ$hjiZBGIt)a4<{9_`{AeH#832;`+s;(ICwu_7O?dU zxZ^&!`EK7DaKAm^*FWeU8w7Ci&*0n(;gFMHyRG1N=l1O7`^!JT#BuPq%e|psvFOag zxBi!nN>LxASyoxi>e1t9OO3*$(pa4!OyHl>d!+<`zT?0HehDs#ks%OAy_5hl%&jM( zPzliCO#+<)5?>17pGR7lY(}fR62Mr5CjkPo#tCC_qne|NR3n=nIfn0@%QLzkBvs6`%rPjdrp}np_)Xpd40OXPvOJpjDtnOk8Iw zwp+=x@vU-lDyAZgUAb^hWJ8fj6q&{fxprx-UGwHt>N_$pH_J*r{W?U5%ElT~TzdF{AvO zxxT5vXZnTcA^_Gltt)y=S<2T`wsf>~Ewi%BcL2!5S+YsC#}n9j#*S2#R${E-pL6c- zF_&|WIg9?yG5dUisbjj=d+9%~V%E$(sI45$i3c3Zi;G@imo0W86KDAAlRfRN8r!s~z-wdU>-PKN}hV03ZNK zL_t)`JiN#xZ#P+laCm2bCxp-X_cHi1NQ`jO2!Y1S{SzUC7WrC#>E-@P;Z6ROi-nRo z*}sfs;NnQBtWv~MxA{!iVK zcqrh%G{F@T9`M1a``;Ale;)j=x(hjH4i{M4oe2AH4P(p!Z@;}X)7aQ}TO7w|onVY{ z>2%7ZW<)lsu68XgMpRW*42)sCq1b;F_=oq00NAX&{5|*h-z6n*;)x#gA8-K7n+Mlk z>$e|v7~FjGNG!EaROEirY(4=nU=R1<#OTq!_P@3k_TJl<1LQ*~m@onAdh3ohJthOS zKqV02pUbez0O0*A1rU&bx4W%R;Vtm*?~;CwEk**o`fX+>F&9FsnqBnfN+2{54{HAW23R#Q0Awaux@)n%DR zskKOYkpKYNBDzR`e5rs28;KqyfVEDzT)jWwNdRyJ$|;RJ>?OD3%r)#ks$J}yPRKc@ z6@KT5g5Qo0FBF*PMQd}~&0kStU%qeKbb`@RnnVaImD5tAjdt1!B5Q>)LTG87*3xNfMC7c{P6%y{2!(aV z#YShISsrKqy}Bi}_tffWugR4nDozBDO2hPR5L32*b!%{S%OTr+n>QTrKdk77Sm?-h z^46-weGuqS!9PH3x`9A-`6${u+bM=9$5ne*{zPjUH#QZWd*)=7! zq@=q;IwS{vfPi#22!f~}-8Gbilt_1X3|&*-{4c(Xc`xSvoU_+n&tBWss2|Zw={LG% zO$I;3e_DzVeJQSJ?J(Qr@_ZP>$VsQ{H0Pkz`H?hb;4gQ9<-zuEcGI<^C@|SV6sa@; zLh6XpB)|HGlG*w4@D$dP#*3DYeM~|fZ=z<$rli1V$EIA9rRl)fsPWkZgIRCD33Zkk z$r7^ktNYmWl(Z_EGgxhpw9;@}u#5E4`P0+HzseqWHX;^Gxsx?xdut>3$G}cUcL)f_ z<3n*Etf&wVafcm^#Q%cphOiEcK{n(ZM^a0d%z^_ckguh_1$BWlrw!4xZ%WshZ0r702H|ZW& z#@l(gjAV6`Q!O140CJNP8x#z5b%>SUVMpeg3hr!K{ev%(UdV{JJ2HB9M$B%{sto7xw;qQ#?-%8`|(R~#jT8(w^8Q=@by>P z3N@uEQ*)MrIZtzT%v5KeBkAnZP==VK^Y2eCVCuI&q&bYR*%HB3MgY<(=3(8aZ!f-^ zzx;qM{Nfe<4FPjM{i_E4u*=j)^3%?yCx#7MFVFCusq&F;3SNHm)IlLEJyy`lw6oqj zUO;yPY_fJem@u+M8?(6S`il|vurU;V_XICb1Gt}pumV~@C}xPApPYCJ5!-U zzJO-|sEAvBR1&dy{dgW0_Mn*mPN?MTgUo+Z9vp2_!K#~Yx5oh}x768RIcoYM6d!?A z0_{OZq8Il*pigIL?tC_rsAjkQiuitY@t3>M@}QyZL*tj3#W;U7P>ozW&>6&i{Q{)# z7B{~5M8l*E?44qeCwWbb$JzW&kULg0<~l!u(~&mjNeevsLg8byEE_5LXV!N*ah&9u zoXOb5DZr|PtaMK2aycpvOWm*F+8VGQa|I|DX_bL2TY$!uHUGmko;c$Jd4NA4a5ctJ zj;w28yHYV&hh{?-J=R4!R(OQL5x^$pmn52d?CP_3ZhK zw}U@|ew+;PUWVw{FHXbLN_C3m)}UfkOSfJXCx}o@_&gRJubds z79sISj10I^x7XTT_2L6{_eO*t4kzD7#2VM(g^LWjU9Ngs@vS!8I2g< zLtbu>0Dz^(uVAYVX=2B$UY7)AbOkgQI=;MXBSBcnvdY^SQa%X-4miDM> zale@0w~#S12=3X^K<^WORX;KR%^ts~Bl~jfq(5%8waR`F_wg>eRMQu-*CQ5yGzf$C zNf3=gn0v1EA}&aJl@ZTkE8}fjpAid&tuGg4Y7c`8ulQR1|KnBx0+Na&H$t$?tiv;m zr#p-AcqNkkG-fS-#ys#?6~)2-@O@N`t%?8l=6kK*U8#Ii|<{f5VcHz z3KJ^+ofe0&;`fIXaT`LCNDT52)OgDPD-(|50JgarFs7^?MHW~vqP7>7zx}YgykzQz zT0HmTB~R<86hXLL>qJ-Mew56D*bg$Cfjd+#M#aJa4SGlwh|>pSpsbkH`DOf&a)J>D zT$8@XG2A<&*)Rp8gNJTrNaQM=ujlMu7RCb~_$BGL`w!=*0IrXZ2V<)mN3o{lY2$)A zwON*cLSo-1Uc-i#sH_F5|7wQ*#Pq#(tsyg0|7x$e7c*3mBn{9}G*igX-mgrSDkvTJiI=HePN&uyc)`z6<5bPN2jWP47_ z>iebHb};0Cr*t~*o7Z%%Y=j`nIUM;fJMkGGGWzImuBPljCJ8K8xyNA~?=?gD^p)itYaPnoSPtJCKo18( z9qyxQrhMUG&jZy`aZ)z&I-WvJ%~0L8EZDySv%MG{7 zRzhJ9p}V^rMdJ&LyV3Hm>~H!6zo0sFe-EaCI1Wa&8=LH`Jzs()7Kv>#`#=~zQjJ@( zZ1u69zJ&`fly(d|wCfF@7w`VJGQk(gzuKSc^~ff9@od{0 zHs^e7$GiDq7L2kmHVKcBg}Th82qANtLC5Y9^)5m+wJjwZOLOzWh`n@<9Zb9pPucC5 zuY)TqB=&{LnyF2--@bi2>c^u0xOL!O5H28={008OGCLcN1BMG3+s=aKAD>j#&H^oiEhGv;}_{tc$=L&xHoY>&l*MvZ|Qi z5N|ah3*BRu$RR46eNpfLD!?zA><5BImS!H->15lfI@%;y|ncOa&t=Aloc zKvDYi-eFY+u`>k3zNpRnCL?@W`6 zg`?YTd6Efxrgn`Mg$}w69?c}~db1t?m)F3x^v$mgLQal`1BK*oyGs7Od|AN@l?1g0ARXd5s**5`6>`sEwLb-}Z(#04)k^%xN& zduw8N?~PPfub>L@e7b2aTCbvpbeJujlq+yb?+qi~HL zQu`XqZzhg{8X`w=lNuBx<&Rj+aG4KdT3@kPq+okbVY2`iOXl;jC>@1T`3SzQvl~}B zYyTu6Ki*-Z1X8_SK{`l$DWhMQf4Twk5?W#DhM$h4(5$`$<>sJ3alW z7H6yB|FZE+!3_yl^Y$GV{e>UhE}CjQO!Cb$Z4UN+<+p`Jq;ksMr0b$>sCnBKa}W(1 zrz#&{aJd&Q+?g8mO7)oyO47XQygy8cp??w8@%HeJS9dZr=LQ)_T!yP&rO(JnUJ>uB z5j&imY`Kht)k(K)&|Q9tYI3^h4>WK>;f@0`i(eZiH&LsozEjh}2)Dh2i_VZ~{Ybe# zY4S#x=x;(se*!lXr?U)6jFUNdc_My=#Q3p#_3R3!^2~%dCbDf#>Dt5+>D*>Ln=|oG zb-~=RUK|VSyD(Mc_|HQ*6f&?;n#iJd%K9Ua(LW)J`Q^1QNclZZ20xn}XYBiQErtDN zd_!6;Tcsoajcse?sh5VQUU3C?3~JY<)ej79x~xP^GLW2@V&@{ zQBGk>vmw=Y#-b2Kh*=RI6hU^f6;%;4m8t z`9!6&jtu35PcOoeP+pDImG*@H_U4gsdN0Dz9$APM=jVS@THcO)dh1>=pI-U- zb95xfd>~_kuKW`N3HY9D9i#8yJCg|K3vNuR*BY$@-{WVsbD&X;?U^GG=nF~}$2Ci< z{*{!MKO3n7{RLFT#yPHv89Eg-E^vl#qAeqaKU+M#(%eKvsq4b}eiudaCG#uPuZg!} z2v(A|JG}mdCihUIDt_O63Hin#B!RfawoF-NiV7)Qf)P-6`#pp|v28DZWPs;EQ(Z1>_(H4YZ% zmij3(l&{^Yr1mS8ptycP% zs)(7%a{6$H+lP)GpZ3*ZuxkRhgQd^6h}ob2;bg}m?kl5eU+c3`^;L>5Uy4|iW|*!8Fl0@ zr05Pq*m-Y?0i9$3`0r3$MBK-X{+HBfv$8Zwto!z3?^6apDYnxk5G?1uU!E}FPWo^` zD{=Yo7V+X3r8QV8h~t$;X&-ZWi4}e;bSUAF0IBgfNq$(+s!?kyGozS6by}3ScHFEl zq9>mgWBChS#NNz~A4BouUG=DGWsIJ}t9*K~Q@#rCGEr8H5J$MJ_ZavSkF{G-`)RQ| zsH&NU@QZ=3DfGyD<6sVI&Rt}L-u5J|-~=Fjl0dM2AX1(9lJMR8-x6dh`P~jR>}2H)TKn*z>q=58&BuD}Z%19{(7JHMTU& zv^h_Qrhe$+DT+}CTP3deteL>B>->(Nf^dS!ld-(qI>$M-i;rKW>L>N8_9y^>^PMU|tFG(@P z$Xr?F0+ZnAsf(aY2FXFMND^mp(bYd4%f0(QW8I5Lv%ROLC}+Qp41ADvI;}`Jtv}0O zonzN8I&6&SQ1Bg$urBZQp|dkk|6i{iZCG2ytBdr*LgRImaR>68Vdj2B=u7$V;@>MXWvpv50Vf0FI3o^RI;cXH=W<8I8yb-l5#0C=kp3X9S5k5~T z%QvTOTJu%<;$D&ZhcQ09^?!c<V?_|9OaaBgK z=1Dpai8(QmdT$XNQ*w&ZwGrgZk{C>@a?9%*=zhre*+#w>hrOv;pPvt2l$0Wwr+dZY zaw&Qg4vD5Znj^%WE$;09{BumIqt^`h{raSEvEi8x*>YO6TMkAI-GHCD1B)7@LC7Co z{l=)_g}84}Pjg-HlT>Oq%w(~M^e0pRF!3um%s4LcnI3v=2@q**yQd=j`*%kZv-9L8 z5qR871NI+1Ojo#mT&sG5`UUx|MW{BdXMGTJn;v{ROq8yS(Ef#J?P>M(p9y#f+Ssv= z!$Dx>e>kFkW-k0R<65q(7NujH@vA^if8n8%3~#l7t)%InQ>kT{WnAD?bi|>2Z@s@J zoCmmDj1bUK%fv#c*;b^P?Fk_)`>g#tVBDNN+oiqB$XC#6#c&& zmMc`nGV7)POJ^mHYLX{%V|M;8ODH{USb5>+OkL?#eYh!Jf8G`c3bVi zeYi(>h?`|(`8gtzMb}}y7V3RwDJpncD7&4njfvzJo(0O3L$Aftg1PMsvux@DzZ;o_Pps}qp#MiHV}sqU_9*Ld&#vIuo1+=} zJwDT&uA*?*ZtwilelC>Pg-{x!>jKxSSNy1Q87nW915G08OcK(a8Fp&EdGZl{w>a5x z7{U3@t#i~AAg1^Czb7!yhC8q?D#&tkjc6bfpeuu8?zJx36n?+F{$>VSg&T3>?WYzA z3-ZfBNUOa_-q=D8GTbljHjala52DDSE%0e=3GLHtX}6%=o!cgLpGSzYCL(zJzf$6a zhek3R8t*RaDF{7`BEZa#dSk8LWJtj`=-nUk($4QRk9B|sPx0~#=3Xbeh-AJ5Iqdhj z3*Hv0q{u|RY_&flH(e5po76Tave;W24UJugr5~)4%WIk>{@5j4B3n3J>Mtg#+&>C0 z4jK73-wv^mgQ8D2=)}HB)yT8f8(X^~4GukdDXg{e-;`lzp|X*9WGM&Q{db$4KO!Q+ z9R58&Z&(2znHiBzWBRD*2@+J+<(H3zeW)trXqoAYCIKS}sz0Dcj>}D~{!bf76|1SG z(1{Ag@Mj+2Zw@A5oGBn{ufeS!PLN8l8T@<4h{n&GB83B3w?s`$m}H7kn{WS%%+@hU zz^gg91uJjXt~1KKosd0`SI#Eh1>b#oUWNo5JDZokRfK2mYuO`1k5VrB20Peen;Z%^5l)!^%@%V$)aDGflWz&{nX^ib)el znSFIIq~jyACp+N>-$cYarHWTVHH@0aV;Um}(9z0;wMt%QR&9$2vn!yC~jh%atZ}4ElMvm<#s#@x=wLPUABVG4q3{xLCP_G!Mmt)+EP6CDY!yr> z_y~rCv`SxVb{jF*&jwXA)f92Bn2C>wa~<@I5@Z_{)lYMnVns(I-6ID2U(RvJPLrbS z`Vz5ZRupJFON&GroFe+2k-5EEe`oq3S2$g0_O~u#2UMw)2a`8jp_}2-X`p-4QcK;+ z?*8YX-d!Qc!}_6l-Qps2Z)dGzBM&yp(q%NZmDy5R>Am7w!aAzz*TiQ#r7D8Q0RPSb zcq!I5-89a-u_uk){U0NPbLlxwGy`%;cEeZG`jrd@kP#sBqGk}BBym}J{CrYfchQad zHcg4A(^O#2?$K7?`j7fZS zk0G#0qkk?szNpfLGfUwydRpq>%NzV<`_w1V$%o!U>W*be0v$hn(V{?!*(7K;$>WjxOcf$H#TuptiKAJqn%GuHQ7 z1v;~P>JFOR{PIWr?uaERoO%Ot(jdP5oZ?wwsg+?)ceCU2^Xrk<$*UG5fM`uL^cI}6 z6QVQ&Ec|iW`bZ3v370`cbI*!aG2r-u1uZgbp0`kFOCyPt6~~q;#1!o75*=^1`x+-c zS@fBk6|E+KdG|w`1#9u+30*%Y$}*Z(t;~K~#e+SCu>6Zi9Oh&rkk{zoeH+;Xq;+K? zO<(H!G@zcv#-D>>Z|53DG2_~d9osa_<=X6TX6|1R+d7Q7(mu*ANTS24lmE_zT3pj5 zhJPVJ?xO;uT-Uq(c);qMrv$`2ZA_};P4Ug=Expq;Z=x910b z!X19~LIFjlfMl%9Zn;X4=N{iuiU)2R4C=);%v!#8y|t0oI{I_@zzVpY-6scHq5Taf zIfNN2d@#~3t?X%jd@Jbl$v^Ahe;ncOAb100C-m1-)?nB@a%QpA#wZ2QaWPXU=D!&I zgO}mA@k=BLG*b6cov8+BG%IBOpSf&5@yavA#0s}^YZNrc8VcD zstBaJCv{R6#S`kk*R;?})G;Rb;Q1keQh4d{w?tug&&C!kyfD*byUBJ6r$*7F;_?9q zWMLZ?cP;9}W*6~!{r@b$anennHC_~PIp7hCIbGoqAMBry#wwWBkmf=i@4*<8lOA8m ztd}B&jVf!>U$gmd?IRNO8>`l=#S2BBnxcG;`>3;VdHTE?5iZfq9U-^!tjJhiq+{~f zJwPSlF8FfOdSUZt#0i`ib@m zX49iLo)2^fmBRPF4r;$X+4TLsaOTP*R2m)=x*&SBtQ(e4`HmKL__Z=!cf?dCe3qeo zzerPzu5%UMQ<#EeXzm0Z1;RmhGQEH^(NWIMon?#9?sq3^QsRkuE$(p0iCdn``Z&}& zd|viN>TjosOR9?6spuO6-SdlD=z=){Df@&|6k0pt^}D>RKUWO>tRYSod0O{C$5Cla z54#9jcQU-A5 zkvAXEZW`_udNun-WDYiCkk5-w#e)5^50k+NxC)3Xa^STgnw&L>joANgnLrrtx#Ymz zV`=#~7s?--6_ zwMjmCXytw}t~x3LeESCM&zN*P*N4QZw5)Yp!5d9e@C7Egmqjy|mwsCu%AEG9nYqdJ| zqh}mVBo_m4w9a17Kw{H0fkvF5O^}Z9nn1Be9(7-$rAcj!gf8Xy-~=-#TNz^@Cpj}LQON*R)P-Hr5Y5`g-V z$t{`)hEOkhc6FmlBxtHbRIn+hcH<$oXIb7cQyDYXhnkqq+leZ-bUaD0R_J0UDZU-m z9j6OY`HlI2sfz%~wjcCuU$q_+CHiF9&CWuS;8_;6}Z|}~k*7?y+jAH73 z)?n!$oH+XNoOAQIXrv{bTas?2hPXw7dlv4{xxVP6Dss#;nJUYSm=&hj#O@d#qZd)jTQ+f)>+p2)sK#90wyLAX0}sMF9gh?PtT|9iVj$BHR6E zEYltz0?mUrJ1FUQPj`5io85L(wZBUQ7>v9fLfDeNK<=h1+I!@^y9aluOW&nX?-e(V zu2!9!3H*((@0h+WWJs7VWWc#ypkZWC>jQnyX0R(KQM*IP$6yl}gPi*f@t9f;$;tqn zN~D)T%pGErMm4;4u?}X&+UE#EHZLmJyb;@U(f-edQNdD4=U8raULCx{%r3B>sY^Cg zl|j3aYNbeJtlJg;;P3kQbE@4f7EV1@uHa*>aCeVoj;k==>MX5D_-3^z#BchziQa8J zh&cmknGa9KM5q?P<$=gwI>@v>P<()&j3psz4dcOPs>ma9!&xlgOR6Z)!)lze7W}!Y z#9zYv+hn=e{&M%p%J`FO60J=-+ql=k;i`!DMlj^SY>67?jCnt*p%GkMh4yj!^TN$i z_ANM+uMi z>+9bAn3r48nGz1gN}q&fU#C*z@W1Emb7_!d?c-tP@~)x6a7XWW-kn&w29zeI`vrO! z*78p8TBr0z#-S~&kI<<70~tQe;K`1{-CvE+C1M;wS@0xvZAX52HWs6CeOOvkCNoVy zEE|mFPTSbbvUv2m6Qp)O53ZGnqt@#j(_YA1d_tDskQae2|)3{;fEB&=`23(3wjshs<&%;~fn9v@f1vM9ifai5L}Z zD*4yn#wyUji0@HzrA)O>Y9q)BII|$B7gdY2J%|LbeOISn70#qeW5u|8qX<{M)yv}X<%Zk=m{^hJ^{#D%c4QhWW;6LTJGu>(W2LyxxNzBY-nDl3y54n_5 zuGyihr01a?;5CNFhqiq_#5PX!W}v}%w9E|?*-x|U1_$=LkUrJ|%D3Ds`pG$m6ncrZ z8J(CePE(8a{!{x*X+KW3kqH0w>7XYoX|pYm@d#b$MMIDXgmZ=Th;OCJmJ|a{7WFJ$Xa^sT zv+wmCf7fcw-~4-yusq=vL7$fjnJR$5wHQ;6M-ESWI3gB1_WS;KGMvZEYBkFu^5mR| z4!?}9Z%yEg>da1KZVL)ONZ9rqt~GPj9xjKzLq4YHr#0|g7Bn#rPvAml0W<}NTXKXs z-y$Qq4LWc!MJ_e+WEw^zN6RdY-@peCC_itfbcXG!c8Sc(^xhx+;QnfN z1G%u|53meRpeQTC{DVFVV+oQ1U6f+wWVVrzb%c@g%5{KOf~2()d$yZRsT zQKZ|0O3A9!ZOv2nRmJQwaO?^>ci7NTmrJ=BBAq+*-{3@EN5tDrScL;}{0nI1OAWdYFC zpd{&p5NX?F4M+cgI|gJPY`FKn#X&7%h*&)~?6}hVX7X|!!p?TxFv8w})CCoIk5Tpl z_`+S8(HPTTdL{`Q-CWCDDYb8Zl8)dMQm3lvx@s!UTKgrW1dwW=FS+;CQt@u(D66a!5L4C(%jYc8--Y9%nnFE}x`%>hj>%E26;sT9{j{Xai zRpAt5SE?^ZUqQ~3=r4H+vsIygPK_`FgTX5o%h#xQfhQffajaXHN zh)g`=NeM{%-u57KrG2hn9srE4uI@g`mBw$X@?b+N@aszxw=wu<%p}&NiR@ z_&qEhJDfL6`;%ROQATsAnU}pm;J#<`XIQuUyA%dUH$&a%?*XjChlsH8%<(oO3C+8K zA~D(kEuMmkMgZ#z10KT@C*Ff^!IrcFE=dP9M5S>@W0SEqG88-2YMcvp6kng1<5T+^ zsopdVG!DFJV%)GBwPQ-aj-M$^XrmHJ%rF&Z_!=xkyOl6wzhgJ_q->deEs!YD#B$i2 z5JZZ+s3BlpFSMOCs{rS&qk5(k2%54ddiPGBs6(+WP*(UzNziR(-m-Y{?n{|ZzVFL} zzT~1zaqfAj=%;E4D{q)z@It1J%G!pzX&%Qmu*nI))XP_su3%-DNR*wYtpFX=!uOeFtDS~c) ze*Qr^p2!-X%2qQ+idtZ}(&+WepxV7ep#8)dqpD;B6g_}@Q2VxwSctT_grBR9)<%R{<(`fPOF|> zU4O(qG_3dg&DlW&vq!D}wX9!`_mfQA^0%%&+GUH$a2DHwfYUad*QPR;sm* zyn?2j)64dEBBe7Bbv=X~`{NF6YXhZGgTs%&YXq#vd6fP^ zH(0R~iJq|*E_{hnbybOH0d<9EdQ_|eN;GN+OmtS=NNFPgS;ZoF5hv0>H&!=8nAF)g@7Jg#1-+!RBKHaT00rp2rhc%GuxJutE zNunps)7Ss|WVBMR9~-jhKY$_?j5kN_KNOmR!_ljsTZMY4971}gZpmr#I>UGju$xU! zuK(^?C2GVLV8hMI7oBgj{`eb999q6I`Df))liTY@w3 zl^Ky?SU5zqDr);^FPT!=P1C>bPc#+`(HazJM834s+(`^r7 z|4I=`m`Ff=f@F~86C0$|z*5=^>|x)*Lva`Ku8Nn7t05zwow?7~c_%vm3zv-9gmU7V zvak{m?U0t~MXq@n69w_r{AemS>pb=VS1gk}*V+vu6|* z{u3~k`LqRUd-)IW&m7v>v6E9hye2x_r|Z?8RJwjSE>N{9vos#N`E=QS zcsrUCAl2x&{@vzj28it1=nd)zO=xh=ZVE(~hjX31IBIi~hff7GM9da2*IcOUAaHI) z%^ywOTdf0O+HwhYue5l+P$;oszfxiqZTP|!`ek=Lx-!5MLt#{YGZL7^h;e6Gh<#V#khF_rls(AXUj0W`_JQ8~$N+ z?N6PPjMOEU@lY^Fg#G-JF>GWTQfpTKcl6o0XQmXkePH{FBI=EJcv4B%;I_zUED9* zCou9abfN(UD(y-$zW3biq59x7@#<{<1L6AQD*Y?ld-gvkyQO28p|e*Y!2sk}Ekdb~ z0OaIRFK)-Vh>r7rTcDub`&EN~cd#3S@|idD8?ui!otBdYn1v#h5^yt~blmfE*N!?q z$NR~D&t^PmFkf+=(t!6|l#vw|h$B^l>i$hQZveAPG6Pa9pBVLz>xOb7$u_?}PETSU zCav5vr5E#dw-cva)9^*zd(2A{Zh*~ebcFxbNc~~UXd2Z|EC#Jlq_R)yZlYI3hpc~* zSyg@R)_9cGQpbJ~*zHkSPrYRgYttnSiV7NXQ|PtdIHO7&{QX(k&uW_V&66K`2wOe1 zEdie00s^kq$ma?|1CAbqyBfx@;6G`<2N~ZkV*7MJ>L*;lCvLQe8whPFp>M-mIf-{$ zkGHl}KHJ-TPA1uNACTH3;cb4UCT?BE`2#{z2);nK_QzaDhjC<~Xq*J)Uw|v4Qw`FX9|{G$NZ*ad_PR8_?p8{F(U>_Vs$w zmlv86P@i49;rjW2c zR)?C?p}gsAyekJ8$8g!+aI6lf|sA+6l?P!-yg4>Vzolu&N~}|bb_@Z8GoLy z<+cykmV;nPaWAGb)vDx80*7yN*J0iHJhARhk>BRTPiahK zrT~1kxD% ziQXTd&0|TW)d$e}zvBwOI8vkX-V7(bUyT+yBm{ynE|>#;m}?Kb)vjv;o00eJ$^)?9 zF{%Fm<4gH9lJ=fC{@56LGp5t(p?&~jfG)l32{m7x`gOxjWwaHjKQ`c{UI{3SeEukT z&MZh07|L*2mzn2m681RwgGO$)qsc;tjYxDot97!pbg84mZ#K^F{%mNX=ORF|Fd~WA zoH~S|7X5uj81a4gkFDB)w1$gMsV{K68Afkqw;@mLkk-*BVQj7_td?S9=?4RgMUg+f zvcb|`oVfZ08jt5!)>8L(I&df3QDo-rc;e36-JxgNNZUcIKgTf9licF}zD zjF)>4^60lUpyv(By4Lz_CoCW|W}mT)_me4)VvKKmlHWI#^pu z**lns!S4q1I0(DJ5aUKb&8a^uDJQmUf8q^KVY;d91`&heEyZt|9Ccwznte2iuY=wc zzj4Gw+rDPe$<+1uKNg7;FZUJ>wKBoO|2C1Y_mZ~;RRu^U)6l%prGgDUV)Vr%#I9o? z?JpX+v!tRrM$nO61))pZ94Y`UY?vrwt@uGahb!jZmF#@>^~yI}&j&F!Zsy;gc?7_I z;S&%G20Q5_%;#ic9vFT(*Nhf=vPeXR+aaFfe{Q5_29e}D%|uK=B^Fwr4afP!-D1D* z$+SGvU_H8TC-mnwZ=dlo`3Z;}Msu5fVQtuB%X7Om#kX?!K4oq9=JU2MDAKa!UUHZ8 zp;$B^{I1C4-<@c2(;iQCYDuTOk;m{!FX!~*KXhyVyLLc4VG;jsv1m!xi>Ri< znllio+=tIdgAbpH|pyxrnd%8~JRQr1@{&W#gb0m^^P8-WzQo2-nVT*xrydDzqX?LM!FVShj zy(XoJ^7>@4bh@q(qfhN})9v};bh^o5U%Fe2VXuPfSiiE$aQlR^yQq#fK;eYZkfCaQ z^FjhKICO$w@VX=q>{f-v67UC`l+Km2=F3V)w)urCt)-yTQ@aJk zx?^PD^pf*>yZJd2I|&UW%*%+&GuH zUIwO5SQl^YW#l@dg;Ef#pe2Doa^H21k4AcjyTWw=wqMW9!n43s)=F`7v@p0Q0?s!Ma(Bsti%?4;tZu$&l zGDabPi66q<@Qi2V?m)?`a@DW;M9q=fX&3-T-Qw?N>XB4hb4+jV22;+>a;Cu*=R%fm zr31VDLd%sfrcT!$TfEP*+^cw9PJOKGsN;!U*?_d~@+1=3gA-*V$+`L`^7H3TPgwbc z?RX7IiPH){(j{ZZ=a4H;yt)Q4lsh)mPblaEVq8q|9h?>}F^TvnG9?%@!hl2^PM&Jy zY282!!^5EWe^e*j$6uD3&$#ZkkkPUz$c3~q^_b5>dN;OLk%X`|59lTy;wvBVN|k=I zHe0hUixUgPyXz%4^HWcuUBt-qyR{~P;V_TCd_>xB@76pP?yD#w(jAT{%^TtJ8Hpg< za{1r5dbmn>ReL+alnn~SdtCZkZ;aI=H#M0t41bLZ{^Cx4g{0Vm2wH#CP08E}PnuG{ z+^_jUMtUilTuWwuz$$VIqZ4q$r=aPRZSnjt3OA1oB7HQ#$T(wQWd=ReO4g<+ZOsVP zo&V$B47sFaqK4B&><>r31iKAV4!u_9SoI1U+c9PcJuXOfX!+Qe1DB8qoh-bEM>PH3 zoXP!Q5po0(1#ixOAeQUVhCJSN5rz$J;e%PSGqPVD{&l&bTz}Vt6!!u{G%NePJ$h<_ zA|6^nqqC zQ)OP~#!buCtZ!0b^q~lK!&$I20D1X12N$(pjvY-F-KlN=&v+;gKO0%F!>Jo(?y0Uc zRFLkOn3*bz4gy@TZWq0+xBwX4cdtQl7*boX0QmELglR>WV9f5o#>`st+=!y+SzX;P zNM$|^1fZwqcpzVh<1T+K`G_rl;}`3gl8Au6ycRoiLVy{L1&)+g#!d1oO6wvrw9`e7 z{1m@2|J?z+%vU=Qqzoq;J5@AF{^t}gH>ke7ui);hHA7FK)U;Ma=74thTjV41j6M$f z$qd%1q=@5tnA#(->JI0%FH^l0xgWuB1&YPR8>2)i`;k+E5rA6wpVAr!N6 zj{L?U=hrb#TF5Hb@t% z1o4V){-56|FCOE{tG28`9od^?zo*vG%u^@%a|RTzW)rK%hQX&)~SwpeNvvgW%1gg4|5c^*_$hvi=fXvjl?ZD z{=l9HVmF~c#K7b5-bEiTFNE~w+YXxw1F;t|gf$x-pu-x1PjLGDxj%sW1y*ghE_~p} z{#ktRhe|~!WB-uVp;5qLy{k}zs}Ncm)t9y^d0c-*WT1nvV(thrEETji^IlqF3p8-} zmiiK0O=bVZk^J-h53+O17!AsXIguIaxM>5zJ?_>aSjrs}*xA0>tbz0>H%ANPZYit2 z!=N3{EU5)&PF{&n{7=&q7O93t<{8%nCM(wu(qNjxC7vv90?u0$@9VG;1J$2Pt1}4a zA4Q{NV;_1kA4x4Z@oGK#L-Cw=ccOzScVBjZ@DJhze&%skaf4m2bCd0_Rb$EmJ!-bJ=Sk*gAnIMP^TK|$GQJPLpFc(ccwrQ1&J2Yyqp@HCqG5cq2Xa6 z-k9w-n0~olGWGD5sxZep+DafzC)$k>(){(V+vRbsT)K|%ej~`awHK}6hO3`0k1aVBf zudZx`fSzZUexY$te@(kf{)~`?G9XWHKZTrRSgQ$g^2cVm! zCu`PEe+=EPOOg3W09p7ktEM;-wtkKNJ+l!Wgbrd7SMqd#h;QI=-hin;5~mIz%ey2U zk?t*qsyDj~gR*eau=}Rthx0bwk6bM4ketjvOcyNc3=f@9q>0ZqH0>d|5n;GhFx=v= zZQnsXt|Ik`2mPg&=?10A+u^S(JBRh2IhUKd5kivlhiEnEf@$QkRoxddz1p3w?>KKd zcT2}V)2EqljB4I|fMM@$4SSl0$1avYgLzjDKfY)aOZf z60LY>%*A0N1JF9fauV)yWKqBgqq`!0Ue}QeHp%I!F{#dy`sn>j=b1bvB7@F`rQB=o zr)arieH4WqyR+J#3>=a1S;WMTuyGt+Od@P)OfSS!j?(w`b zzcW-TvO5g1$ZQB~=+!2i0D_o_@hgAtXB235foarRuTIUZtiK&|RD3qYl^0wOws4RC z?>}-h&d+KG#d-g+yuueBGmm!}t8}x7eW&Cz6-7Fj@S8c_;Qs*0KsLXJc(8zgnC20e zDWP#}v&dQ3w?BJUzwW-)>2VAnrS0d^cTfAw(&n})SzSaB5eiEvMpZ0xVnUP<0;rf1 zXD(CosyH*E!$izfG^#U1#G-n08lz^IibO@CiJEg3omg-p5z(kBQBz%WP&A@3ifGVA zzjJY#wmC^zQcXXoL?;$RG>SBUm1q!=h>C#)6^UVcy$CC}R;xEW)SutAzFKS^2%;jc ztK!fJLQ2up-?M8vHhTfKU|($JTxgpDS(eCvunQ}eN7?az_lN}hw+&i;$A(zD`hn2@le_c$ z*0n{kzBgKo0TmOGbnS^mNm=~Z0Pzte0ewdyXn{(OqY#l?oa8iX_m#RPxBj|1YT~r! zozz@L)v4CJ)0+2MlT2#POVwx8oO4xIvYPj<=1SC@lUnAfd2h8+$>pv@Ju7Lwlu11+ zxw>YW`;vt$qsS_*$lA5gk_4x&kSs=DB33dDzMMtpo%v`n5>jiz3@cPjoSGMn%J8he zcalv03QOQ0&?qLUqKZxXcib?2U3FmFlJ?85dF4Kr6C<%S^bGUx@zd|y|EBKQ*CDxGtJa=0ZAGi(Kd213 z{Kv?1KD*}crfex*1h8ds`QitUYr8i?qnhB_Ftwa|h`Z(V-wOWo!QLQ67!KwgR&P-0 zBf-D(n2xBb-&^1x;FsUvp!@D(>Vb!_Osj!(f1A|XfB6gi>%R__8tmopB#g72l=*MA z1bj@AoR3#bn9zO{LP=f#^MR)TpK1KPN72~{Km1`brug9xVf*&s+Ydc7)yB`6lceyw zhybi2f&c4C?e6X)wTGy)cR;U_lBSD*_X6kcg*kVM#f#yCAB2~@B)Mh2?QN-!XE$Rz z3HV=6!r6B+7&Np@kv&$ku^Tbw_DHE-vQgVl)?XbGezPP*=q0iQW$pf|C#>nG;nvo|E}gXml4Yygi1%_cPFvbzH5cT zIAM7ptnP`${hMR`-c2#A?@dzvWDa3M>Hspdypz1&fGA3&QPIU z|3*toKj$QlW$@Qp=Rc<0pP^d+cunsaEqu;`Nd0N_c#*syfzZ?=3*jLcNF|LOJf z&wluT&Yo7uKY7lq2WlNBeS6)TI=2>Q1Cp2Jj$gcQ@vHKZD_{@J{@8V!KktUX?`YtE zr}29U{D1G$oVH;N7sZ$`tSS%9oX3T)e-D?#km=vmKVaUif8@)d;JC)BqP>fc{>vx$ zT)P_rUy}j&>{T~?@ zUI_1d-{_BL*R(vAo!YYgaCTM#w5kALY$d=I! z>E<$qjQ;vviMK6zJ8$3Th4juGF-I4$9i*cR23k}A0M$(hox@cCuxlkiS1B!zR051t z0l@f502lX62{1>goH~VXI-!|~jy-|5{HlkaxDi?Y*==NhGlO3)?x6dDtt^ivWTHxd zs15Z%b6sOUjVaqdni2qDJT-u}jB8Z`j3l2jg~E`g62LLO5&%*XmjHQ8N&p~bu0!hY z2M}T)3lS?h5o;&`VoWzLCsrW%5JXBXYJg}~5=SkVd){qrZ}heo+5ZoH2>$Q~c=+Mu zD*BFhz}x0#eQ|$h(*=^fOWfvMIlnFnH>@Wir0cp5; zJBq{NTQ7brQq~q7oDh zstq-O5Y%Zc)3ilt1flYkHvB8{HvsszKLs+#2%Y-4}De$R$#?S_X2>UV9b zTX%oN1nnxTxQWUG8sQvPZpS*OVKe3s=PoABU5rheg>`gc*-v2Z$Eoh$REXscV#hS{uGtjR7gC$OFSR-Ql24sW=$KBdbYi}=`{3UoZ0NQ8 zwso<3)rv6qvwQN|pVt)ms_qa6>cNC&mfz5HZ6OkI8c6E{LQtVVDMYj>+0R9-z)7yE zjUQ_2Bo{Ar73%7wCQj`uUd6ZYwD?~)0!%^EORySQgxo1&s@!U>RF~W@2r-U zq?$Rcmr7bMm89-UQe;Vb@L#JDtAi5)|1Mx^J4^l{f&V-tZ-pJ}_5l2U>*G9c<0E{< zj2SyFZ)4g(FK6BGd*&@Tgljsd60#gS^k{kyK8hdQbqno9&M|nJGfp4xn2-{IOP9iJwU4JX)q7{Y5m6;!n{A|afPIa1 z1w(lCuPP>$ao7tHNJQWU(r4i#41ESC71O7u)_2!kmoD<2p5zv}iyo1I1pXf&Wx4NQ zIQZY&fVUuBWDf%$B3*2IB~CpxeOO-oYB=G9


BVI;NtYLWutK~l-WV-EhCAu{@h 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
vT5JOE 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

Z5upyVQ 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

Fau<4@XHPMV{Jo-RiOZGy3E4 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%0DnpO}4@-lWByeIHG@UN| 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 z z)fyV;*f5%_`*W3GnAtqzeuMT2-KKJ*{zX@R<@{tJR^cxN|01J3^5wp7+IZ~ek*DgO zFq5u%B-ljZ1Es-+;l!nTWK4xkJa?I^`JhHWNufp-zO0xTb2F|9Qhgc*(|*bh)5rpdMzgo2dxKI!DPm_QjROE)c*IicIQTa(@h(0SuDARm_*TaaS$e(;Q=VU|?qf67z~hf=!Ge=XR)u#79c}3k zqREydZs|t&^HE9Z=S^=&W@|l)l$aD6LE^e!kFh{~q1>!m7fZ+ZN_79ygkBNDGvho{sE&M3NKP-Uk_mO0a^lA{t60-j{Ks$ToSWFh)&IIkqq2c45YW zI5csFKeQy|03httX&cZWk>ltDvQY+(Peii~Xq$7ApT<%c#fzOVm@)2$T~m}EsFHT+ zMIOM0BHVFZz-V8w^k(JVA@{QPVl}_m)&38`|2)i>af0Ee3_Re@*Qp0CdtUjKk(w9J zagX=3aV}{8L_}-FE`7$6DuIMNKU7wI@JSy|^z zrxbJG2bl)$j1xTS_b7szTe4F#(Wry;qRSOQ%u%#I(GqU2PyWT=nV;#*xpxEk2_G{u z)K4bMDzrWfbaTlVA4@-B{k7Ngyg7y;&1xxh&t7Bq0st4YKP3W#@!r-DYCnj3eE^!S zUGKXq0n;9o(JB0roCTIgT5p8EBZ<)1u9^$>_l1?(X-&egp!d*2!Mjtor|H#eQ z-}_aN>2y0XKEI1vx!i2yYq(gJY|$)&TG72XfpDnw4mC~`SRni!1Cb#E#n>VM02`V6 z=cN4CnTm`GbRtjuCgD$8f5Fm2_5$?ucKH0Chqingylz%r668em;pbpElOh18U`qJ- zYdARS?^ELNfj;*f#FVs%51qh7ICxMGN-dX|kAFrpCWx9(3AO{2svrxOfnPQ8R}}0gOnhD1bz`z*;pc>sdLIAGGE+>ffRob{`zt*XBdQkfQR8{<)|XeP$OoogqYNgA&?%8!iv>IJe8#+N4( zGQwu8^k2(vF9+o9?dM`YCKvV-fZcA)eMW65|I+MFz!+C;Uz=XRqjx0Hj^7#ty%^jU zhkCm1j2HP5w-X)d?*HV@f|j%J1Hr6Vh8B9!a}t}Z0O;%@a0IER8I;Uhhgd#RxRIn_gGqs+GmO;% zlAB-EH@6IN3|`~c*;Qd`uZEz_WX*p(fP<6ntnSp*r+6Uj#8Of*t)UTta=NhK6FMgP z%>D@f3mY~hk5+2&x_pGd9h>HK5QI&5HXomFzq`jNrGPCI59p`d;*K+Zi8YeY>&O}Q zGJATQ3j}10q#k1`B6HY;9~GEq?S5*YpjqR0n5i_%aN%P~%#v^=kG< z9|a}tklWQ74+KZZ*bwnw$_NL5Yd=IkdfFT9t|_~cLh#oP{LmoR1&M!9MO(X+*j;Lf zufC$Y$FD_PqGCl|e|)EaPK%-`<^VTH#Pq0cx+#;B0qWIKBF13BVUa|o#kmsJNJ5XArS6{K*8}&BQK!Y$+3Pp?p=u$V|sTeJtre_7jYMGl+qRUl)rrRYG z(O(dViFAn%aBAuzAwr0VhCSuPLOiJr+F-^I`q9U1F)VTMP?_q_6GWes4`RjpxSu(y zi|rf;8nZ=6BxSGx`>UuDpnDzh0C)xom4Y06IJGh%%;%|TDm7hWBoXZb+N7CC9D=>b z?{h|GuH28RlLv&i?IfoKi za@9J^Y-<>*2dKBi(F$2n{Q}qZrC?}|hI2s#@gs)hEvcs3GK-A2nh&ovR<7ib&JQyYaTw*1VHiA=oOrXzkVGFMefen=QlEV zNTQU9?Ks+4x%PWd8&p3SpibMU-iLZmuDc$HibgjAlPN2sLagsdFNd1WnlD~%KKM1& zICu9jR@t;+cNss0P6Wubw?1$F@_W17fILC^lw3dYCupL<17dVl(BRn@ddD>a!};jK z&H4zw2C63|UwkVf^YL-r5Vyd9nKb+_v<6U2hP9P)#-|09X~i~<#4Tco_|0A{@gT;9O{W2b}CRqgK!VO62|&0=zAQcMgc!w>>Z$f45NJLd9#zqOdlTZB*E#?%AKb?+X#U8C*K zC*(OKCH8#!Ax(a_UX%39zhRq40<|zL#D)S>JbZACh*k_GHSbw6>s-fwBXiDUUeM%K zspuZ^%VY}z>>2|1o%ka<{Wye_%BRboHAUon8>O(24<0oIFO;`(;KKvuFz3ql9XWY( zR~=qc*E7qz6SWHZX^goUA(Rz<_g>Efp4A3pw7t(&v&29*;+r8V*G0cI`SEyMZ10)d*^ly-7v=7gifcGCVK(JlL#! z%`}zEt88v$TJcVXouS%h$)T50C7EvmXI_WI6)xd|+Tx^6BQgaumY6__-#9CVW@OKR zdM}f|_(JIZN&UmA*(3H3e^*+-A@dOkgd6wo>`ci>$DP$mybsazByGK7c-Zb}>~}B5 z1YSRmGnR>IsB8_LZ!MPBNWZ_~rGExY3E$&%$xjegV>c-qpw+=W3h(T8(JoE>-SXU+^R){)z-Ijf9_$8kdu)&1r%rP05EAQ?mjTbNz-S<|TR< z4txFAlh9|o^qxlE+L6Ei%q#EqT&~)ww%P|52hs8Y0~XE z49qRhBjbKS$tkGE%w~T?RbF#u-xImz6Zv+HrlULi{rq~%6L)VR0O_0))40h!$rbg+ zH)4)?KEF_V-?#ng=(zcuy>5EGyz0RF=iT&I>-dx3NX$^1S>$Qfdm{qIh->=nyqgxn zO;&^HXm5wUPJYr^za&1R;+Mtwpid0hE%LoLv@NimAn3p+E?8~+#urxpmBPH%8QvF~m{x>K;ss%C#-vDEh{x}Z3hQpp)Q|L;7g&WLy*e?*~D zk6atrG@Q3Y$%A+}ipyL^&6{zJALwu_BnQYzI}}uI*($ZE0qsnwE_CskO=VyZeIdtI zu2{0~w-tRI%<=ObyaJ#xMhM@I$O#HPJTTS?K1a$qKEVN&JC5vy+7DKB_4Qq$P!`lc zcEZ4G#tP;&%atIAhQ5X`QO=$3t>>pZO4&UTTj&19sMJ_+=j`ODg4LB0iCv7!_4+u% z;oI}Uu~zG0wu;lYuBI5@UVXoTtg6$(j3c}gGo}56?3m0CJ9|DWi2v*zY|7F->t8aS zSi$gOX<(B5KjcZi`Fki|-ko*0jFweZt?n&Vz)^w`8C@hxz8TOnm$Ng2I?CENnj?Sd zvb+n#|2a!b-B@{Z6L3trv6$FqLxS+Tj-+1S<0 zzH}l@rU*TaWncY^>4!BfSB2eDR=|$6j&MU~>wnkX+a4u}gD&$y=$`1iV}MPY2=Zdo zsYm;UilPY%W){WYW^840Ub@j0xKbApWPm?MPAOXKiCU^CU%Seh0~3Ujt`jY%sFOnZ zL?yZ}&sHfbc#HL>8S8@AR=uIg@Rq^^+D3Oy<(2j8i`m?LtfyWV8O^(ip$aJ?bO4=M z^Yv)4gEH)zOn%JV1{3d1?Y|?`i_#_2+}C3WsQ`D8@>W)$zG)k}UE?#Q!RPp9!eLn~j8pt+jim)#bR;Tsc{b+Idv#~@5d;+V zf#ZQN@n93BRIFbM)I8aC^;D6Ix(g!BfjM<7uEuKDFrU%pm0i6tu(fYX*Vi5>k*hs7 zWvJtybUJMTfcC2Q&mav3Q>uG7F$*O?r0R2em<-WH1iK9Eq8)ztMmE$FZ}zoInd?@y zK%p^hM%0_5<6`sRiRVRi=cOv{@Y~70nIelJ%YsA>;=`552`6&YRWFb-zn_8U96>CW zrE2xSB2(rDrwO8dW5iMw407tn14DN=Gjw+& z4U$Sp3eqLrNOyyDBS=Z7ba%JX-6`F9=KIfouJ+wL&z_5SueIK)ByKTYE)laM;W*IV zYC{EO>5?hcFt zMa{e*yzp!I49Op9p9C6((O|469(-*5L~BHW%4|Uc&g~9pFGtiAg%V&?qJe(k zJy}F>Q2aK6$z^oJ!E&d>HgFj*>lXBDa6t@6>Lrgc)aLbaA_n>(Goh-A^zLikrB_(`3_) zotWU6DdC}LJ+>3R+K^IFyA?RgPcy~{x=94jQ{CyX$K)2B_p%+Gi0?07xr)k}oRoNO zGC3;VQ<%8zg()w6)J)b)G_`XRMRMLO3s#%apisO|Alog2kp0kOOg}Ds3BDe>z;iB; zRnnC6M07UG5M(UWqbQbmhLB1#qDyZ5h3pIipRqn+5Pb@ikogPofFS*(KSBpl!hVX@ zu4#to;Mb59Zv09qw{?S&01$=a9};3JvUBpMwEqYhtIwGSY_Jg)K|qUsWsCM_LMI0M z6rvZuxZTJepHY4bV+4+U@w^UxIKFND9N;~oWS9<@1J%km{;gWFP#_>B7E`qLIzkZv|tvN$gd28I)8XsaMc&?*ZGw{~_ zlzMZ1Ic$;7F$nG89q@z{Fox-dBGz`|bwBvY-88ma(+}usRO-$|GPHU5tOubr2mCYp z464$DthWb{T_zuowm#KN;)~TnR8=}3V7@>0rVES+D<}EiijWmKSDty^{Si1<-ro+5 zxw(MQgP-q5?Ky0x-+dzr#sSvC9h<0fpa6)|Jv?4QXfpA=bucKQ>8N5Qmfqat$Y*}@ zFx0i_`i1|ztjYFat|crd#E*XTJnh9(mihbRvBuII>xw=m9;1K9AB*{yn(_iP=P@p- zq>cyJU$;EhZCE@Jnp)>l1A5{ivr_k}4#Mpqv7XmRfAA==h6v+}*e_zb0ozdj%f^Dc zC;qkx4mJi1UjTq7l%xCGHnLq3q~aQY+Q2fy`jn-%zj8GDR!qJFUE$wuG8*k@{QSIh z$Q9dg$cq~OGGX{Sz;d5U=|rNF`o_URh1Nu~h)`@sDG~jqeuKTJq*aQkU5csJrWTG`f8S; z@qa|hb@_7k>^ze1^~8el#-Mp;d9N0VughQNx{6u7wSQU&MNB2h1ct@`<_RmeO+(U2 zf5z9;)Y=q{ZHrUpaf@J;GNBzH+13jDAyDrYMYb&ktob?qY+NK)&K|GN6X2vyKqW>T7a{1SQsvx2#+YCQ2s+255ltY zGD)%qK8a=An3^*H143R0|C9^D$|qAz@`#bN%=?*yCLSI@{m8jbW|oX!Tyl&$K=hwG zL)i0){M%^`=JxiTSl_^&8xOzxPwriK6uhgBo9~u(cD+X$q>w`C-p8B!L3Dnj>367r zrB~@v4RX>PLE?10ZU`mZ2A-Lp+087fUruJex(T(AfhTeaJgWGYqUyc5E>XA@>Y|fz zH!@KP#_TvyYLbh5LK$B3hy`+qx}-c!(j?h30VwMUzNFRfaqAGSbm{6$k-^2%IU}ssMHfBe17+yCH^gYM%srvb!$*E=H&gslC1Nw^78 zZh|*VZ^r4oi6~W8)=B;?Nx@vMvAo_oyG2|jOy_Y!jO5lH$Zhnmi*)krJ3hhGi}|I3_ zS)+Botdi>$J%8yvL#0rQov}uaXtLn)LbZ`p!sU*wUCEXeD)4}!1)aV=-3&IBKsd?) zpwIytJcN|^{UogXon{`*9@sppegYL7MmRzJk!s% z|I-3A;s4?a)r#OanSSSJ>_P@z@Jf1>{5u(9{@^0(QLx}ZS7+Z$HN6(!_X5-296*xh zh6Spw!xQ*a{K~|BYnM=LuyK^>!UrTS^(b)vdVIdHJ~`i6^53QI)2;YtByu}8+FMv) zu$#KGNh?hMF7!sD_j8s;Cq<*)Gu(4mu~?-DE_ddUqmQ$QUE3|1_hjArlM2tr1(-qZ zU-|7bjAR!@R~P%}WkFX5;xE|llFsYv9GA7f9dyGt4iaqU#O#&^eLtkgo^K$;HsqSgb5Gy%K zvA2fDd_Mr4$u;=w@;G*>=bbRZh=^VB=Vo%%K^voGa@{@~5m5je5D zGp#d*3Z`LXA$|oss+3DPJXkR0vr1nZkbnfNsQCc?`|@^WqDh0zu!NCv-?|GTD;^gX z?7I%kmX$=S+FLyBU9Q?fyumS5ZBh8{qTd_(M_ctNKSRl#>EmnDcOoTgFld<;Ki0^W z>3U*;F2rN=SGY33J{2Ol-(6R$|n0tR+x2q`C{I zTWEs>T9v_q`A?k#wH6|i&K=~;Nt;bxiuO!ahZA~8 z06n$fo2_+=O{n}`%G^d8baqu}>E(;jMw^3gF>Q%2xU%`quAcmz)d_~EdD}9OkhC68bKV2|6Lw^V$-$)-_Jta*r39ja_=W9f z0+VDa9XpP#A3vv{wK{jdAC#Ssk;Gcniq4?=7)?`y6$pYrIqERNmvaVrI|HvD!E)@Y zCigEzS-*QrQgb?9V(kS?W-yhCl`6+uBv^J+zrPJW?dMZQ_dix^VAda)xF?Rg0^jC^31HcOI8gYiykm$S87n!}HdwvTwW0Mnf%R|X**qFm>U!@d z2u_@@>Zt(q2BvrniS+B|1z%;gx!e%Ry3;0F$GyACE+5B#qf~EhguX8Hchq2LHl#5W#Zk0+N3_k!&<|ZsK0d-pM#c7>dCn82jJF!u(PiZ3gt~#$UGgdqQy^Nz25i4W{(%! zKT7+Ws#Ot|olE-?>Mq+r8_$N`#|~(&gnGVl51p#Y|MZQ=r1EbjqwOt)UFcTP)DIQq z_2G&PSDD2Y$27eZkN%j9!DWG67_MW!YwI5piH-gt&dj6Gwis;%09G}L(#Jo4DB^sc?)txb zeduobH$WBdz>9<&IPKcxfu%;lAX$Kd2T_1gkd#NJy*b`=f}&MHtvaOymNwb_D5ltQPyvJ0f^_*UZ^!SHRv}ttd_R_g4IyoJhm8xy_bK;xmryg zU%p~k$-0Z3QD3>MtVH#U&)43?lD>C^ZaDE8*P{my4ijgCX z>lKrE!kr{Hthf6qg*D|;LsFt;#G>*nu?+9)ZkX}+Bq*aZ6M-t9`eR3~1g{(*5srH$V%%RUVWY^RJ!x_$6-}G66=-Y4hO{3@E_4(ch9jKpTJ${9z&W`7 z`+Wa*G*gc{ULZ&}A_P(^b>RSy8dz=*&L|Yx`@jq4cs$$xCwQIPKVVhLGEJxa!~2o9 zp0?tOx(pZVB8_!WD7;%+GEnk{DspA zg75O-H2p{Imx^w%?)@zs`6fee%A5xS+LOSRh_d9%1wnX%8O^@Iw3ZMp+TN9jDT zDGdFpNG{sa0_V4i7w5`%?>#83L>jT*c409=$I(q2L?;-1iKo`!E@t3!@<=GgD&+xi zZbxcYQrzP{rd=3@d)9__2gq@U?k+2Z)I!6$$|$dUd+~{qa1+aNgn9yUMUGSLjoTNpuaOm(ItD&>HY)>yDFSSJ zcJ0)+VppXs*0os*eIaGCrTk7}TSt|n4#w7S6Sb+dqvu1ugU0K)lf5rSVji`^2>{)M zcyHaRBiH^=3-HyxztO%KmY?;3V{MD|v*S5j_)sYfQoMXE6M`>Z=_!=Pyw3>%oA-#- zRuJ16U#OpE_Xnh)3}lP(#kaXwvuXZ2OUh>S=hZQRw=%dEdb|I1L}r)b3NIGTeagchU3*?O*3z;W#rvJ!UPfWkt ziFZGpSaVaCcv^QVliy?b%WL`YdlBe+czj)4s!w#VBl zxP7X`Cv0;EqGZ{DOO)vMe<_guQZDL%DNT{)cvH08_>j0w%#vVmHyf~bVzea=0`h1; z^fEp;OyWE=;^*2#qpSok%0ZZNqpjdI>i%U*1pEPgXtiz+r~CAfR>;M4aq%Fd3#xD;gy6A<|o)L%L9 z#Ws0P15@O|`ITxzR*SrJ&%Cbl8b|GF9mZp|?Jmi2ppk-OK*W5%oui-yEZ@|?N&u_N zLTe`ZFsAXfNg<((rny7;dxC?Hfw|-i9B+7)+=3Mrt$bgJgu0ehTo;a_91PVDR5dwt z*n?qD^8hGabHXS1R6V2@cPbfoln`^6-g|nFZ&BO7cAUfa@%6%h;CZtg|D(xC#AY5P z5+F@EBzyDcNLYhw%%S+3)X89gS)WOsiNZRFMKf+e1*1=CTEgEIB@+#EC1s`@lb8v$=~9K&B@5z(9r~ z{0kYAa5HV5dcVay@B3va!jZ~87f(k1cy;EFh-9(0+vI(ATv4Px(7@5^`v3s zpvm+Bxx=b3_2&84fPM|O4uctIjtHg%B|#us6#-Yz=L#QW(-Jr|{IZ8o3&a_Xu> zM4;zPQ|>t}iI;e}4KL??eq|MQ%d2E*Fph;YY_`HBud z(KG|C*({v@$`Nqz>-#&zC>i@8``?Cv1`i9jKTmRZr-QxxhVwDUwY8$^u3~zxz03}$eI>-X29)Rfv{YzULY)*fBk++7;fd|yr z92LNwPT1K2WvVv>1fhx9KJWH<1|Lib=^c+8hj*&J^qZD!8(I(Qw9>PS$O1ZRqd3JL z!^h7rUR=CQ+V@6Q9D=O$DRV#8Qw85ZyIQ{Qqp)Z4r4L=hgj|))@4gU0J=k{=0C5x} zyt%GE4EAi;ECJMfz4@(tB`&ZO({dKE@k*L%Sw*^>x*|(^HY}HWNW-TX@WuM066(!i z;z3L6c-f7&Eu3?d-z%?Ko>BeJoevFsL%l2D`f%%`hmD=F_JTBe=8eV*W;>jK@~p3z zo6xYP{;EGg=7Ps~)5uXiO%XS{1rZl9ND>_~;ddVFi`L}9JwTEe43Fa|gg94d4<(`oyFLF@&qF^3PC zf^brynA5fqKk;B)5#cEhNz94lsFG(ibzoSgr=&ums{TMUe27{Q)^A~zkT@!T$EIPB z!sy5b4bFo0dbrkpoByKL3kI|3(}zxLn7`kTJ=SDz_h($;u&w?2QG}Q4j%@E$|1yET zji%CQ!lHyu1%IKWx8erz-U4ZLS10X$0 zPzJ^W5p7(|NZ6Ey%RQ0dnpwJxe!OcZ0vBtIJnl?3AM2Uprpu~L$P~?-E5*!R-EkoP zKE=bh7xNRnLCnC}m*Ak_pfDI9STx4^yy~hm#2)VR%k*C0KR1pgzc==*i=e1D(nm85 z_wuTfBbTmQAtH9i&~lyTUv$qK(|)FJdPUUq9D{FY;FDVRTW7K#vJ$}=$)gTu?~67s z=id@l>q)*Ih0ABWcZV1AwDPGhX$FJaLNhd?F5YPm=5)Y0T*woeZ;-_Ocrwyji8x?; zGMvp0+lET6WpAArIh|hhgk1)~4lXMZrH9N)FO;;}&eS$vtFwgRsus>l=;yRTV28HF zWwg%o%l`Q#ZzAq1DK#|(fPXcFX|s9%QeZXY6x=Ld7-tmJ1p)I(G}oEiu6j?L4=?0{ z$U%Lm&~S$A(Fm_~_QR+B!-&Y=iP1hwv%1P$uNV5mOWfwouFA_k)_z|PfMHkQ&>H9!Ji6_@mt&- zWm8T22!PYIlk6~hsQ^dN9c`PUQ#nXq{tud`a&e*?l7BfqHOk~QpXd=$Zm;|Ex|)72 zJbH#&B_M8*E%#R?-nKhYxO5M?m$}ZFl=95sDn3m-$5rpdSewE5b{sJ{-N6M;eeAY7 zjzQk|xxkjwXODl%{#@KYDU_@LpJKo~O0qso)7kPSO!XVcHW>|WC0XsW2o6HklaYS- zb<7t{K!s?72KT^bvSa6rdn`n^g&69z_oKT2XlA^BljZQWw~Q(>{L8&+cb~o(8C9uR z{lw2TKm=a4FA#7VOs~@z7iUaX?9(euDx=Z6OfU0JIrm9cL9x@6Yf=85B)9V^h~d5D zue9T$^n4m*MtKIzm12qTu5j#6jC%~RlDtUJ``rf)In^ng(S}woED!*7Z^Y4R&IQV` zA;CkZCS=(h!Rzc0?#7nm6Of{rZk=RO#W9iZJu@?A^KB(2`}3!!;d2RSS`4eA6PusH z4;$PE2GF9CM(j41mYewG6OUB@6$Or@uD>zZH1Xay{qaA^ zBn^m0DG=ctcre`?`NKc=?}`X>9GsJLit8XWvX;uFW-M3;MvJ}j-OJCQVwH$=u zuc_2lX%ktuzsr)&Wn{M7@EE>Z8ZPW{(Ii# zpA%@oV2JEtOi^;~r95a9#7IlJOH5T6x<8wK5nuJl=O#t9sYPaTPo+htRuVe$q}piM zjbP|SFcfF}4)6%t&LdI&eq-*J<%H5v!TU-Gh<{^S48QYv%IS~l115jx7AHSBR2_USQ!QSVJujQV&a<(fiyWZl!hD{Ve&WwL`k z6rjDm>Eytt`sZh`7n%RcqSyfa3ytsBD4cfP^HKIT!lD$7hFJXQ;A@R*A2zthE8hFU zximOHdXJ|F?&S7N_dM3X2mB}NT0_t8Oo)K=^{z~yB^SH1`aKu7zw)XB@99(b`)?Mk z&afjsVx|3amoMMW>9WR1aat4h=-zWnZ9Y`6|ujb=BS|!2D4VMS`yFVczQMU-%hy)8H-CxuZ_^q zNc%{lm><|pXP=DJRG)nj`D8xe(gj}~bx$KTw8a?lPzuD_VbCL^PV)YuV9!r}jue1ID6c12QY!fcjy%mpPLYfwty+rNe1aTR9v;rE zcCe308D>szH9b5n8UxV}#o3H%xf395eNb^^4i;hQ5y~L?$U2_ZI8X6yRKi|L*Ne1H z&HT6V_OX$O*n$LVCJby$IAZwlqoEnMq|LAJnWeN!X7mblBvl2tjNCd&QBuesF@H#o zEY;V_A+;YkCAYa2zD<)=b1~8&ojrER{wkUCCmkQV8+4um=Xl!!KHHuykvpo^dmZsv z`ZgujVLFe6mBwMIy|$3T502U1g&WotIG<~(c%MEyN?Ioy!U=uglj{ny2r^y7guQhA zUKpA(K`Oml@3IJiP^y2Yv5rgZn-Qc1ptfpIUKQz|_Q3-rkp1nG){gp-1S zTMED9OOrjH?ce#NTI1Y|Jj~Jtr^fj9Hw8(pn0F!Hp~IkG;067AZKBU^+`NI`%Q;)iE9&-5 zlkHnolxM9N8`A?ClbN6TJDue09W_R>q~Q&>H0!AM+-|+9S|a*iB9Bgjrf%=s@2R;l z>fX1<>UF9vixm2 zp=s;1rmmFZ*%)X%iH!oc!Mzc}P>~jm_i^S3fOkbfFF*#$(vQ@vAZq@K!Nzp#*B50P z$I+x8=P%n6TsgA!C$Z8oGg^g!DNR9@CX3Yex?f;eI(pEBFw46ONwVn$s9>><;IQmK zVA`{prLR79t1f$7fOxl4th9vKFRPWmQuJO#TNT;&d9&!-erf8(m+DPa>7kBYL$dnG zw=}eZ_)xHT^YyICW>{vg$_C;rN`E8Qb9e)52pGTuv1GN)N-=RetBN`|BPi6Re4Wj$ zy@~#M-h%L78(&kOxQI|JnRS(Jq%{3#9-1cm(AVz|?Hs+XMc>x5<2!Lo3*FS5SXPxn7B9|Hy1;9Ym|PSnKX5 zuXj*7AQ`VF$tx%6NOe6rPkD3yU-t1=Lv)*Obg__ei1JTI8ARzBIP6@?^uBv? zI{)ChQq=(mDF7k?WIZQW$H6hAMU#qekqPI$k|8kt1gLCM!bdNWHiJZDCa$xBGsP%p z7lKk6J|Yary(2{A5Z}zgevBQW%6AT4q^Dc%Lp$4}>WNOS7Rh{U7r{B!uc*$zE+md8 zp*yB#a@;+cQT=9>_7MT0>1TBD;>pwZR+pd7AASqk1$OZ<2e0%F(%Ae$ie3*3fq+`W zWkK4wZiw+b%iH#a)qqhzwExsxci(MqZdf?$pJ?8y${uHBb{RkAssQqaPvZoh)ff`7 z4KDp2K5sREIA}~f?5Tph0i8XlVs5aVTW7hEGt@`wOpjsH`$nP zgeKQ0DY`;B$W42lrgXBRBS6N^4rFB|+57wum;Y}2vpV|e`1N6HwqKT({V5er0EB@G zL=!^Q9SKUp8dAiGq-9oC6ZcO^zyrZ&4=SLPh=2B?V5FOw2_pFLneM%Q+}utg!G{cy zYI-@;SRQO`E>8K1A!>qzI*>Ss&VUO~JR=Q0O^zG*Cdvs5f2bP&f$@DupCsN;kaRAE zDlq~)Z~#h9My*)5d4J1{*DgV+x;8M22(Wf3mwW6d$_yDnZZ#Zgdpowv+q^HSr`B=&gW80t{6(J=uH06y{+i|)84=sN6@4-H zQu@6w9XZDsjv&L|GA1a!XVfyo>$5wQ-5vE9ZKGV|W#4wSX<)#NuU&e-j;);Gxyc*Kr&u4V_(Zo>#qgE5aNbq=Ifz_i%q)M;+GG35W=#VyN8FHMyjEk z!@lCLOV(m_A1X)G^%74!?*Af3tvwpn)yd=4Dmdxmw%4wszLC-l7yx;Bx=OiTl|Qa8 z2PYLPU#$^*#JPw&!4aWbm-@hP8>8Z{tz{k_f)UcI4Fy!~^u7Dr5={qZ3LA#eUSG@W(Xo zGP&(?aeJll&F8q(gb0txvUJ8{4=)9fZzMPD z$Dj?>*L}nb5AN*7A3xM{e71Q@^+p&b^$oSwCiY+ennMw?uFrTXy*!W)(pE1*AYoN7 z5XOtUA~^4#pF7z!)zkfW0USiAEs(^YnO)+t_R2ANBrFUvzYzMVvW?I$d@iO3lW?Cb z#00VBf*SDsgxYalA+})wl)}b&7F6W{G`Ioi&1eTlRmP2&Z|nrInb8}ko%uHn#}{P~ zj%*s~1MoXy`s~Ybq@kK~I4HvVFTX}l_^k$3?Qucv)=_iWv3~AKeaf+-q<7yUw#4ju z<2y)@q3_1;OBhzJ^F62KvL?}CuEt`U{k`jPFxb%*X5+20i_$t}n{+H(SKCZ1VDR(u z#pJ|=wvaj5ocWBL&65AHwbs_q7=ZD9=dQ{bmQ8ezV;1$Yx8)2*LEc5vjcy`?28)9l|ZgK{}$bmZ5{0@V@GoPeWEILd9{s z#-z>wj^-%}$Kd;F8X8l9DsO${3T;ciYAM}+4)C3=d%YX2Pa>T=LZ}sIlawH@BA1ReEt{ntuTLfC&|E1-Y*x z4kVDCmhOZD+m}lfAi*1MaL^&g9>U7_+3O!FDRQ^Qw$jRi8pd7x%`5HemN|L+H>dN0 z+#1Y$A-)B!eQZg}1qOet<4=J@!tye;I#kY7fe_+}L8?I5CQ8Y9Ps}gY)S=6_S|t$M zkRAlK)+>JV{pruSsz`*j@4KeZXcBO^_rJ?HTL%RYZ|-XY@(39V)cxk)$28a1CdAq_ z42_=n2Ggij`noW64HAF&J-BgnWk_z+T<)gUoJ17Gj}~;7f7GRqEsT*6Y8}IJprj72 z*lZ1=h$g-lO$}0m5pq*PQ+%|Vs#5z9A{`YTt)rK#?@?lv zSiCe#iX@iz;*m&CU2{yPk~j9X!it0YD#4Y#>`DJKRr1L10&x^g=>j=PY*q0S2`Fv zs#`KpKma7LTL?wMP+S5}8Vxa!0Z@mPlz|O|s1PB^cud*|eOr3G?z=!#di@uakF)CW z6QIn4>Om!OtyM+W&x9{C*WsBsyW7FZEBBL=XBUU|2tcVsTpK*;CJ{A~1l{*cA-6%s z-;;RRD=>iR2d>Z{$j(ejBQ}yGNWal{w;z-JVYzpi3d9HxAqHwef#vJ_6YZDVn2+e( z$!2gGC~7bKvA(a?`#cr*N-VmTI8(>Je$00`4m67e+jzUH>N>=J=yaGX7<7Ln1@2** zNB|fnsW=4yRE!?T!xz+QJQDB?2?tRefRkW?iPHd-( ztmmG~VP3};fpI!21Bq(ELk+3$%@8;+%m_wqSoO zBXWNwsuhpaf!x`>3t{o;>$dle;#rOYY@bka>ff`_ympbaa+_EzzoB03Z~r{bW-&Xy zsLAVj4*M?^Y@BH-N)e*u&EAnX8K$PWG8KO1`wI91eZ5d*^8?g0(&mS8~tK#(MFiA^LO=x10i3b!S_TmSTlkyc74&8E3}bm#OE; z5Ce|)hydleWGTEKDL;NAnKw%|>9Tp{>X%#D_6~5(jFu}jLGga}L7?3pRrGAFb61?~ z`j#5CgDn{fp;Nu>l?Y;b!j57CERTpCDdQU(3a$uIzcimWgHg|U4K1O6!Q}OGC%kXD z%E~LlRc`xKD`Je6{Rv!4+h602o3h6 z$H2nhcV`nXoB0Ub=kkJnLqg*_QPLQZARttfIvic0fw2W)vm?%%jI5x5wS9ew`Sw^z zGbdNxivN#oKBk+p<6ok?R*-N+JIB8rm^BvV8! zt_Rk}4H*j-KlKJifM64dAf}&P2vhw*8oASuwWGnHWA-8$49CG{P0J(4Z-O^Mju&yQ zLqkbh?OPvv`tfu!t@W+03$WY$(*@^b%#6nTV{0un0UK43=odU(%($pqwitr%47W<) zs^f1HSv;F?=`?(``}2Qd4QH&+4rV0Ku^2W%1z)jMRJtj{(r$6QgA+HLn1qcPG_(ub zR`-ol|8oN#6F68DVu-g>ot2g9rca3xT^$lbHewk-{GdnCtmhx_3UhsTEx{b3#}_q6 z?#=Vv*XP4ze*94q-yeoOVV$$PD_4K8l#Lp>ue4$!y4*x2s-Thgi;0Vc=aswYoj}EE zZ8`*&@~3uf0u3BaIS4B*>?aRtUm{+$;jTx4oE)tlUpR!8R@*-*70ctc{x*#VyXM@; zSEg1%dIsw(auL#DTpM-jxCkl40#%QGEzaWHf=Vl~IMr1^5_(^Lx*@3veYfu(P=O3# zg5M7LADzhUUC(g2t}Y4hgib;84f;q_3b)<#UgcK)5VYJPa(%J|Dvewqqq%m)RCb}4-DG7uZxN`?hHFBlRy^;7T!ZRasA9JGcGJ+3bb$MzizgwLK`s$G3+j^65`A{pXff2em|`>Sy#mnPhp?0+y1`%Tih!8A7C219Wwz<=;eCFL6>eiW{Z(39nUY6e0!pC zbc^fdS8b7zyq|CL5V*ZlHu9w{4x zv%JIgvx6f1%!k-u6m5e>cWk`kes3{#Lss>W8CYmTz6`OLu3lav0#F9_J73uLs=Q%x zCd@7_%Ap&&vaYQojikAs^&a z@i?04D6pJcmPmHnlyN!F)i&Xxs{z5!fZn$6Wdm{i97NAkHjQ5X;oL*zuwn|oMg6fu z!Lu|~Cqz27JC)G$0u-~bdN3sl6SO?YkqXB~3>Z8LqkfBmm`4=Fn#~8(-x4W!kGeAa z&Q@v;4todQfh9e6mpn6O|M%p%t1zo;YjWO850;OYrlyS#j-?TP`b0HM;Vp+W4w<{P zSiQ5OCJADdtc6%ocF~MkQ;8#4qADc;TzHT$z~jgJ@6LNU6O>UbwOKKyhw~h<6(BJu zpXiU1d*iIS);J|!Z3oaLv6kK~PtPr4z?hIwgiydUGON;_%p3gKZ_) zxbvqvIDEKMbcSkgs8MxF24L!3E7=of6C~3fvA3@{{`8qe3Vf3aDaTAzm7rbjs`SaV znH?2<^t1^L(cO0{v%BSxwYRX9-+ZGz58_R=K@=J&;P6RRk~_rk*ZoEa#W9LcSSUIq zd*4DA!Idk4I3_MiZo6G(;YhMDsLsymbhj=Q^@6@jlH~IgA3{#>`Ii5{!F_ujE~lbOY1iyoXo^*VzwN?X{-9?} z!Xpb_gnWpkLF`HNFt$8Qx2-n~s#aD&(bP{v-}@ zug8b<6_53{GaV9+WvF#K+P^Mj^kw~eYCoW>8;W2TSO&KY^S3vF5NGofM-|z@gIMlQ z)&-}Ba;aSLHGuY zb%=d{B9|N;F*M}7mH`$L>W+pYo|c|z1^rouwOTV&=;p_3?T?IGD_tjoS`fN`Auhww z5ORVEV8JSLnqc^M=%ChYPg1b*A-kz&yr`1cD{d})KoAT2GD_344Hkw+^u8G^KAhG? z6zixa91wkCI8`ceSj>5HMCW)u!PL4nPHk3xyMDbt5a;*Z+G7$~aX1mYzg|0I>k$2V zz-b!=3_)hJpu#;d0cz0+d9oyk*@+*~PIaEPI8mo=;zgztb!3bCKQW zh6E7z27qxwwuQ+$V_|n-w*P(|v|2Aa zo>n)PnZzBPy6O6}@skg=ttC(YUbWfyhUrG%HU@yY5vCbPrh*Z8oN*ZM<#eVttpleX z(Gf}O`!=HDcI&q`6Lsq5B#E@C;FEZ&lCg$RLRc)~W_3(m2#6;j6^L=$HZ@5znt@=U zN$ocm;D<$cLD)b#d0aLqAkNCJ=U#rhT;7B7skb|5iarP{zK`okcWBK)9L^uwIvC#s z>tAevWVjg=L=(dI3-QTs6gC`bSe=ACe?FvEi*2;mKRWzPcEJGV8-z%mns-QBdj}1&`rJPipEh85HV+Oze>x!Saf?=gMMazI!5D||>7TWK$-Fqp zkKL$GW=3B?`YqZ7iP#kuU+@gB=9Sh$S+t=LQaMk^63=^&rx7WLk7kWCyRW$}E|sBc^Ku03OyyUiiA&=~Tq}@w#XvDM@zZ*3pjDnp z380Xmg243mDJbO1LBhuounU9(OOw#Iu)n7N1Oo9EZLsbOXo(M*H{&arA_@U2I8Ys1 zN?*d1E_xt9AOqb$f$%^qct};|u2`y{Q)lIM!6E&r+v%*G?ln^pUf{}o&mp2n)=5WJLbXO#?{{Rvh>#_Q&UC74v1!eK`-004o53Ur?Pl-TsGA_PC+> zU&Je~h%LLfQ3WC1d;}aM)9vB5se`fTOZVUNhP(-Fdxcw;*Ojp_f|bL_M}Mxbkrk{V zyh$ur08wJCHN&z$-W+Kwx^urG0Q#`0tm7HY z8j(=GC(l*s9SG4*KWe?TSs~&HLlg}xc!YM{BxJS-*6qH3Rs;{;ITL%At9_Xq6hR~p zNW>6A({-Yq9Dm-hY4f}Ce8zG^7mV+!ID23aZC!si^)%uvr~kmZ@{89^o@e8c{jCnb z@&C4cC2QZakj!ozCW6`Je03}NMoR0mo1y0if2;dI=DR&2Z`d0Uwte1w)+O`P?f#;w z(`ac)i_`Tdc>902`l_%f`mpZ-mae56mTpNABzEaek(LGt>F%YwLr?^1rAtC;X%LVU zNof%2Zus_jzw14D=V<0+PxhL7{`W7#d5jVp#Hf#K=LB+e!fg;-G3H#p6y`r;}l77RkdPR;Tot@u9`Qu8wAm z3Xzq+snGodgq*(Wt?&~s*0XUU?<)IIB``RF@#gNzZ>-Dtobw9^y0oFE?FjvlZtv0hEbZW z$1L;Nv}Y80ZJcu|!9uD7-(OdpoQD%yoJCz=1RL1%I2~QJk|uE|JbSMw#Q>SkAAp%b zb-@rVBo3znnQY7qgks#BvMVb44##X7;5+@J+QE-zsB_}zY_SZ2CDBE1-ur!yiaJgF z#Z-g(?QdrPZO(7Kv`x4Y2ctnKM~V&yDvdpl<~DX^@fpSm$1w{hD)$;TtAt*fQUm-F ziOA^;M_^?)UUE?u2SC)Zt+upTVp%I+U=cB+N+QYZa^&pWg7n>l$+3QOxImAU0Y^r( zIPdx~7%oB&I^sw^$>rYc)8{{}e%TywT`MOB-3*>4^Z9xnSiD!fgPPwavL8TqqjuDL zt3c9$MTo`Or9bV{mCMkbyV$U=m$i&an?_~CpjZGb)NKg`>%t)=(h!1tTaHi&i&D+< z`ILOJ#6vRs3I`{TxoIpK@T*cH3Q(1@@LVW?zRs)4nb-6vQD`vtq3#;wSl%`v_<|3I=cId~ zfq|t(+zb@3twI|Lgyw~F-(NwXkTN@WF%MnPw>{@5zWM9i!tqALWcKq~DvJGJN{##V zl@u?axBw-3(_M58j^=v5?86*H2pjx~==*ItU`Yx7Oq_VV>hy3O(Ad?DoQH15cKeeJ z*dgfr1VGI3Xyd%-{gEoy$BLSm(I@6lqP1nX&EK!423D2DL6lU62Gb$Ne0O z^v4$&zaLJuvm5-y9!K95Cn=c^S4ti~j+@2(LgHfZR3WLS?i+*Jb+L5&HNO_0d)+`9 zpvo*Uc}MUX*uSj>`vxa>oTOgmh5afCdgDibX?Dd`Z6R_BV>vb|M+y14RqFyaCj|Uw zC1~A8a}4$ukO~}xwJQr#%2r}pr+ccp?ESULQaPFJcR|LJ(*$(Uor#STU8ESO6Y~#U zNPn(ZMeQIAdO2!SoAT{$^M|Zb`@%w07p*&9u$VpdRCSFB83NgAr9d6rvY!mnQV@E4 zwT20RB~XAag0PyaqS5$B5`-W_qcqx>;W5t}d2(*~^U*e&vqmKg9;`Ek#^%lxuQrVE+ISLfY(d+4bqmAQa^ z0YdADH|rY+k!5lKgSn@&1nN;W!zP7AI}(<7=O)+cz@NVN8u^b$qh;I>#Yl}v98K6Fq~z@!(H zr`kjU&U6;>se&;{XFm@S{$QNWAGN{nQLoqyBe~0Q?VDK&6tpPCth;#-z{e?k#6z(= zGjzk^0wOvY@x197d3xACB+^B{Y4<4e`1nv@7;XStd|+a?K_@-Rw{5>YRrU3sWIFfu zk*!Kp1^!nH;MkM{Q6L_X2HPnhC*j92=Ao_0wh~Mu$4w70Va?+SiB1!?`dLZ>Wcu*H zWaoxY>2Qen{g?Vw3BuSn-jOf7RFM)@xHXPzp`O^C^yoT;1+^(Zp^Jbb8^XK)(RBg9j803J&J6q6W za6TV%xXz~QZ8!|9UC&P=18(A9cyNB@R^ksCQpzrL+&;7!U-r5k*~{|oFnoZi6j6h) zKfL{+zvBJ0D{Z+?#i0k%VrqW8BVjQ0^>a8YhY+C&bJ>Q@C0?jlIH^Ycg-L+?itr|* z)6nZ}MxOHqb^l#1RvVk*0^@|Sf*Q;*K(gGTfaUBuF0nx-5R+1x+>L@Ilrn*W+J_2; zONs>o>)n5toaKQurR&_0t=eAz7B!XnXi(6@7d%*Y^E>I+K)vl4wHiMl=Q55;CDDYI zLKIhknj(6Ql7W_ztaNYSn5!1iw)3+eGcTB0GBMFt^<|kM$C2UC_2Ko8N6{Ndg8!+M$&@HgS4#j1z1LQ>#z4|X(_Uz{02&Ze>psdt z8+=t^K>k~k6dvd)e7W~0q7YY{)9ox;vuE(xEjEV9JQAH#DQd>`yxGmZotnNDYS3O_ z>iI#{aMJ0~l}O<*_DETNa-*L#D8GvmsE5TP{)pOc^@C?~$>ETU!h9|6{jsX8TK$=k zxD|nv{}M$l%YG#TjKuYzS>Pzs=9rS z=DT#y&ExyXc~8{u*tFn+=z5jt+jBNiBupKS$F}XBO|>cTp6aWLM-8cr<<|L|ldYoU zL1vf@P)`@E8%q?%@PhLpPv0R*`Cqb{+Z zpccKRN_ky1zmZ05`bha8LZDKAi1&Ly7wgR^Iuaa4{-YSZeDebVLs@*C%Ps*g_i=l} z8LFSXr#(vzW2oO0OD^akWcMSxxP$PzU2;J#WIlPL)HY%a9R&QHYK$yeFrQd+BmH zm$j;Bc&0=`j;f+!H{PHH`dcLIA7*-9A$7hh1u`-C5l6$FIn}}0b4inG@=on2P(ZcVRkxMq@oY-xmk1jhZ z3Qr-~?CsbudAq1Xgmh})`;lS@TX*^L` z58UVGLN9Vr{6qDz#9el<*H;t7L>73r?D1!b)fSrS+Ilr=qTl6&(ppbj3!@pK`|jrS z`<@nHrqT^X5F20=1ED%Yw)I+}3NAi`x~7czBi$}+o};wij})C&j(#u(hUx~a5zaN? zK%?fY<<=C1+p$SfvR@FAzK=5D#W=P18mwopb3emqnuqAPBIHzXKysuh)~v;NNU{Jd z2u?#wD=sl-jTnZcrU`>M$Jtq7ae+8r!lb`rPJt(S-o8;L#)Ta4%T;wk7J{Fb+l0SU z$8x_&r^s)YlDv3uHrBc9^1U_IxT)kjlh^kw0dJ0v=liWrRR_iCk`m+xZ`GX*{OM3A zjrd~(wjSK|xZHoo;324-1MJ_F;DxoIfg8>$8I@-6r3*VvYA8V1Vf*WM^zE1J!I@iY z*P$)m->yUPlyOD~=yx!6sNKNU)42@l3xW^D`F1M%h9<^U%9j#>|03jFf+jMBW5Y;& zgcW3PDzcEhcfL9XHPMXzRRC!2yCEd~uG(3XAYuLuL;#H#Adz*1VJUn9K;VQYQlQ6t zr3MAQ>3;n1-wg9`k3hki=o{N(Bn%_vXolG60{+O53mTf`i7k zM9YmX73U=!m-1h36Ws>S;6l0NpI>WxJ#zt&vn}TLXU!OA)lmBTY_&Wxqqe_`!sT!w` zBE-kCcWKBW8GE~miCfJP@EQjyhkZY!%;*rwfSuiCLl6wZE+_%3g^2?4YtaM-wUJ0P zi>b!Y8VyO9mFCcxe*Csa^hSK&)xG1m$Y-A0;G*qg^Rs)7SSM_xyU9+LxpbOxKa_JW z-=}BsLU>ergI~M(vpjoqZ*px9cui6J+Zvy3+U)Tu3h^!;b->-^>~ga5a)RN!$mpQ% zer9emdg7Ttl?C<7j>+S%*YBu`sf%v9#eVjQjjG=-6#L1S$p)3u#Ou9s^fFBVdls-C|CT>fY5A;K$fPl^Np41zEp^ z@U*zX`jTj7y>LzBBJt7+L$HLDdveK$u}*cfIfQ!7F%6n5Bzb?VML**yCQ>5@3BMc^ zF+c37Qz{M2?!ynLHGs=7JiTJK-%D?L4L1oHM^36 zObpBf2m?|uD6{o^>cJk=3P?*4rok3xTDoq(^}DWN!cwr~+G$#^HIW@Y;7Y^rbIB{2 zD&AL(U+EKrRcNJr7}|rjtBvAWxG%k6Ql$5g)ri@QRe0d1w`PvlFCm)TTipHFbhTw@ zr(rNZl~fA5w3p^zPZvf!R(EqRUnjMRCkaE?h(9rh)m$303a0~Y)!lN_j?<;oM}2>zhtHs9_g;)oZ0`HJKQyV1YjlK zI80hT9F>99ULJnfcLmxch1C7t(6=OI?_Fd;7HCI(g=K6#*J zLF#D07aPbHfTnjZ0|Tg9v7n?j)1{rx8Vfk1`>(TJ}T3)NiIqF($n~0-DDgvSQb6|l=ib__ zk6j3M@9bFSkBi3_lN-lhg}S0Q*feE6w~#DizURX0Ok z5eNieq{Y9!-D?I(78sgwB9(N$qJ1=8PtJl~owbDAuj3SmH3K1Hhvl_=l*a`**vf?U z1lK5}{{~b{Q5f$h@X9feKq_wdKyUKjyIj(q#5W))6DaEWmzks9OSasV=pPM3doYe# z{$p9JS{6NwU=SV-Dx)Y?d){o*NyW}lu)pohm+(EqTWvI|%C=q8cP&mtp4B)vG_jxO z-k*>~%{tK`A||5PMvL7HV(dk=#u0h`g0^40J^x{_tpC=2EGla1*XH8m3V4O$qV=ol zS9JB1g{M&;9$&tq;3w%<@PXD=r&a>L#TDHayh zK_ulP_F?2To#$L4Rm*U-5R5(oAbT{9KRq1S!IjZg<`InlS6baq9|4w231{5ACkmH zA-dQ6jfFEuvAewzTRpE05^$W)PDo^L~ zI%78xf#R_#0KAU_0@l{o&SV6{R z&hXo+dzc5)#LEJ-%S^q_*-gwi$r7Z6x5kv{X1G2Ehs1u2Qhr>e)LczldWv}}Mi3#E;B@H7j)~Jw8ng2vsx%bZZ zAnR|_*0P6YXUN5!cR5I!KHy-&-nib1Ai-JnCP?$!?Oty{PXX*dJTG>;bn_7R@=ooQ z>Rz<);sajEJ(n!lV~wWaXmY^D3lm9>K=iOdv4;k)v4}Z6#n>ljCxbtHSb&~q`9GbK$1A~lS%kt;l z{4a{pmVnWdbp1f~SzBfbG~o{@E#Gi|)gm-~I-!|9^^30|O3z-I{6U2nqrU_C33Caq zKVLdzS}`qKExy-Eemp#N3qbNp^fv%GxmrrI0xzQf>0)YoBbukLF89E#w{G!^b$^i^$i3p^pr?sPJ^qSndSY@$O`NDkLx6scsm{#V*Q zlg{c|Nt}}vA0Nq{|IVzUfX>+U{fs?jn?0+u<+EJONQ6&j55>{fiNkj0R3lFkXY+x! zH&jH<_6*StE@t5rCi5ezut6RKx-`57famwUr5{@5LgacDvF|xP3lF(@fBdTCcx_gX z_5|jGWoW7S$dDf;Mx&qoE+NaCR=}A!tNonE*>d2Sx0K_+K@4-q6LDT_(?{Eo*$)py z=#a@TgV%u^Q~Eof;6j+Uqi*4;zmyYmA_#*{rh44mQb*wK^mZd`L)=|q@j_^#f1Ibr z4q8_C8CJ_nr$jDMnanJ+9~D&1exX5C_yDxU%htgO@0CQ+7t6_4Vce3AR^N{U+cVVG zCbj8&?H==dt$zpAa#pW1)bw>%nDyKk(J)W~kWgMs`q-k&xtbL1+HWN_O&IsC8(oIT zYJhuF%>4OEw}gNd(DywO)80s=LPZ}{@G;|1{2eRi+YH-xVDLT*F$IG(@6`ZuTMxq; z?`?1}UthjC^k^6rfB&;JXEU7PeDIB+%8(~%urH8uu14-Qj9)wpXApX$uU zvjr4Gzf>!R-{l!6sb5K;W`3R2@)wn^eq*eUnM*1q(W{6DP|e^;)wCsj`7G=j7Z> z%=RpKV}e6y%9M35q8k-e3y!W`bgE;|^McW0D2Ajd4vrtdA$9%jkb!g-O)(mW{PIzfrO5U3J_vb{G&0jl#~PKG(T7L$zgKTCz|bYz=HWU)BYPY z{`iK@(5V3qUrwV&cF<1y>>>=_dea}arI)yG2qK7vxtaLepf5FKqu;ek>X?ZBp+>b9 z(iH}}t?4b<#Gj{JoR#p0%Q*_xDx{!`lFs8})WO}wd$fB!SAk z`4*!*P~%I9g`aePbripXr#?rfjAgfT%BN2kUTLpe@4HNWF~+NmW#vL4I1mFOZAh_} zj63WzoCQ7YbHrdMm^6h&KCSV8gdjeqAdE?@vheoxX055JrpxV^5XGZT-S6!mtmw-D8Z9@4;Xc<7 zmW;Sg@16eyjGE<(U!20&2juT^eq9c+GUNu$J8{GsZPm(f@<1XiP~h4J8{*#c_Ln=w zN9wrA*k2%4{j`sV^4ZRm1qj{Iqqmiu{s!-RJvdZuz1$7f%szji)%(i%eSYJ#n@;%I zK1uWztB%2k)_~!uMNQ+*wa76SHfV~2(`=_lf2{O$Mtq@7-_6z-&5@Yj538eR{#uRD z(jZ-&z076jCC=ZMmsbuhGmkv?H+c2qf&ZQt3ndE|zc-QG&6A`^EGC@|Nn^a#YKOtY zNM~CTp)}JG0=V5@cQ1d0p>)e2Bo00US?2t8aF1O9cYPHDY#tGJeYiQZ271=9u&OQc znKS#f94fAP7LS3_unG$CXi6BBUXRM$OADHn(p43aw*!{gJhj$_(x|vd(+EP@9L3zj z)XH|3r4|*DE}Mlw%{~JHDY1D7ysj)+Y7q%?x=7goO9F^IZB%*Mj15g#j-^%yC`-kd zK#YziCa#8}Oe@xb$UTH!2pAzcIwbAZvi=bpj3x+J^$eOMsE%1*nUYNE1s5KV(a5$+ zEYhdWE&O4aydGp3TltN{t{6u~beKj=Cvty~80L#n!8Sr|sPhPY$cRt3yknBlU90mNe5Z?9Ll*)}47cd~v&qqpoygouZX@}w>M4Wo^kKJfb+Dt zUd4Tz$Eq84saLwqX_IXFr>hjUM@=|`U)I`NFeWs2((mgEW(HVI!C{2zlTc`eWj9VA zPmK1^t(FQnBh3(+YV^WmC)xVr2XF4>_YVKrpI5TZ#(m> zEG7Q-zx}LAZ%n2GnfxGAUqm&GBwNUA-QM7Y4rJLjCOJr3ISNT=l0&3HNE!+p7RkVW zgiBAm9i95cy@4BphP2A@E|y1D{xe33(l)=v4}Z~cueV_Yd-kYIN@=dA#v&KJL#jCq z-dG}VccF9FLynB9KqNMb(FV5>V!**dz`~E`JS?=iOf-z#TA=uw>MX@qyNy_8d+ba&+`}~mL1yAMTOqVpcLA@NP70AlYdmE z$i2CZ->TKvLWG4CBxK$2=JZA)OY%ZEOX8k?YB!XBFWjOXs{1)*Z1Z!bf-S^J5=Poi zT41GTX_tdfNriL;2`VckrY)`wf(O2OK0EWt#R$242b(F#?S>mQdAEK)>t_YgDajzx zP&o|*IKXMB(#X*YiNtddP>LS>;eoN+x1gHBgzt^9+r!MuV*j-}gP&MOCM^qy$iQ&- z?bAusBMX#XhhW)9`0El7x6^|+o5&be4o+JV{hv8mG@!NUScDF1Bed~c}vih#xqVMVOqF!QteF8?_^`|9A) zvhqI=VGkTYsCgE-dF=^^iWmqDV6!Pk!OEVu+PL`7%z=3)b!UtXr|e2@r1RkidJ;+p z41k`co+>f`3mAyPM^KI-M9+eMahbbg!6;!cIWoEN$2O~&_jQYClrQgrf8&p$)bNZJ zHOE}%cvB4iPkJ0LC=8lxZEa(Tv(3o_H z0;s?Wly30dZcj*K+Z`B|@H$J4n%s|~W7*6yMr2J_d76HzNRKo3?HySt z!?QivP;|$X)OOT5+o|smKXkI8KTSVRXiC+grgwj?uODKQ_dg^Wge*P``RKo9rD^?A z3rI#FWzF+1I4}95K1>d)+bJ?{Uh*WD3;ZoeGSp5GKXhTc)}~f*tlT~5<$kkl&{~4| zLo(}~tWv18F|!UGuToP9YzkL>6dk+x1NG$8LfGsjxo>cf3_dPSWn;$2ZzyyaS`mow zLU>>SWu~rj67CxQs?dT>5d?htz+6F1KG}Pk!2E z?T%9d$yF+8nc{E|lct!nO62efDP1WkTOKGQgV2cj!!r0d&6692a~MBlH-YyzOZ^}76_TWdjC8`hMP^=1m^`{FcO4esjC&X2S3L;y(`(F zKT#Q9dbKCEEd!D~S~^(}`XjhKOD6NN(~41vCBB#(OE9Rc6|?c1cOafz!Dpy^r-LzF z*qlG!GY4Tx5Tm{n=+${44_Ms5(=-U}&F|&2A+L}WdIJJofYMk17xaZLY?GO7r^M<1 z8#LT7pE!9Y9G3sGYrOm%bn&ZTR^vHVz4O|IkkF^2ju`oWt15S3im-+&^;Va)=nwAW z0}jYqK8W!Mm<|{y{@jc%d+uKkV{^Xg@5`lb04La2N<^{Ha{-~?N*=&sn1>n3!SKjr zJJw4Y7y*TV5*lnYGme%NuEd#b_}2mrtQ4is4ulSpALwC1{18`|Xpm93fK134kTRJ4 zmlx^9u(Z5;b3+4mJ1)wi6eov5dWZ|3-X67WuzdaTE&nRF{BYR9<7a3hB8}w>oTb|} zAQp)JUo8N-wEUK3Rs~ZGc0aN__JYJ?-TgIK7XioN_>84w6ifWxCUopw_WUxoc-!>y z>z(!$hB6H=FQ3b^^Tdp&gTKpxDnNXsTgz`+QGW|qMSLtSJRED?F8t4(_agOvWG67AMnxz;nk%3a8%n3;^LnrV++h)5 zOay>FXn8M6Iq6CCsPi?}16EcFs7!BLIO@(OFT~Uatx$z4-2D9(_7!K?T`96$AuiYS~f6QOj3VD_H&^wT@Jo7gFTP;GR*6C-0nY@=9pPBoY>e3qt^|`$ZRvi*E2u7z2 zQ;R%azBW&(7UNfEAG}JC{$4g0YN^QSt;G3N!dpU933`lv;?CpM2ca{HF)#z8a~S@^ zEsSK@qM;gJ-_Tl3c}m;F)iL*`KS8g{gBbDm*M*Gug|$0&>$~L5cCK^j<_MD&`!GoD zZu32(dHQ`}q%?(M)iQ^v;mDSB8w<*VI8UCSz?m3#_(ZSIe+vG29{ufFxr?gRg{N3`| zLw?H}t*s*D)g%Cz%Wp{Wr9{m6==@74sD-W<65pW#A}#|_tsW=0vV{F@)t%INI@g7J z>*-h#&w>~zy1KiQoo|D8U)re420!45KsPt;i!{172NZJGijVzXB%T>5t_>*)YjmF2 zM?h2Dru4rJm;e+eNxbQ$8=u|M-TLP9N5i>kP+nexzKDBVTbHA}N0`*a>^}>%GDYjG z4|3c(@i_!KE|^#yZpEr(As7O1aSK%EOWQHL>neI}J zIs@kt94@rHlXGIkyUAg_HRWL`5!oY&sZ`%*AOG$07pTuy|D!BhXsw$alDy-oPnN>C zEZ0QUHu`=VfsQ$BwZjKWnZkSj&6_N};Z68==iZ{PO4;>jGGvdU7ao1w>^h2-blb6}y8%V4E-qifI5 zeiB2tFbhmUlxV?)&!+<}?|!Jq4=jazB{iLr-2>o_LM^w&RQe(J+4fzAR816u`wi4! zIqXsntTYD)CrR_&f_w*OXDKljPtp)`oY_nna9{mCmH(WK#10UO0%W|!Jqpk$kQrucfCn_G0MoJUE@M$XUX-N{!02xyK{;c|G{l&?oVU4D# zMb*j8?dz1MJ9OH`g`~tWtBK}Q3kd>9(2!g9(;rQXMOUi)r+pkX(-RJjS5j=lq^5ad z49y*PGL=o5{2&7J>mTf{3gg~^nBC~IT#3*;FGeXT8$D~zW%SSU5*8L43k>F$9?2UY zqv^w+UT)#N3;w2J_Il$Eh13*6fO*HP4-&k;RiSNLlfR#E*8CKnoPWu7oa}A zhXDmC>7&6D_>qVQcLCd zCxclhu6~}kT&aUKP&&+6x(TarUA&z>-AAdN-|-WnKnuq#^^h|x6%DuaKG6j$cxdXD z*2=rOo9V}`IjX&_j#w5Pq-em&E$*nv1X8xo_#3TMyt;UIhw%11Lo9AOCr@&!ZaR4f)vNYjjonP>b$=Xc|$g;x# zF&?8aMnEFf+vO$1N8=?tSk7_loPfEdaH1okwI!!F_&6n1o|b))4h z%k-c{5EDxg$%K08790;e9)}->fBeXQU?4TMi7tl+o_~pbGhw);i-CnkmUnT;u)G>NpY<| zL96rOq4L{5ec(^qzJ8EzXE&OfZ2{e5laD%_#~*r+pq{l4$Byro)BJ2j-bg(C8P+F% zPYA$-Cd416CLdmP9>bmZ&Jl^YhYkN3*cfYtfCY$A;I{tv4%DUwh^)?FbH)^e z4iPpFIt0C20Tow)sX_@gzQi1xf9{u#Ah%8Dx`w%Tbs$6o6&H)88sNuFGa#6|Lctv6 z$)OWvB{tZH2aV65&_?y*tzb6vy5=mGv(&l+CKw3LmR#8a5P8b_JCS%{gi_gPyAYM@ zOFBqBe!?hZA_WqPetfvv0&H(1$pv_87lWOZZKDtx-O}`Q_)jC2TD?ku{FyZ+UrM=D z{L?e-!IGKIx#>R)%5Iv)%QVI(-$#L9%+LSHlmlmp?*}#W`jTb~A2qXMT0`a&D1MA} zkY5gdkNEx#&LHwf1jA*2IcX2PimJ2z^VOf|tM&&Hj!9L+$G64gU8Nb5vlE23f2mq} zM%H_gnw0~yPK*#bf{ioW@qyi-#bZg*?SJ#i8&|5yJ*+M_fXFvFZ<7-$+6FI@YFm-P z^_G?={3FC20Tktd{2stT0Yh8@ALCTa`T7|D&P>a*H?DFy32Aw&# zCz8JbmNr{Idg+F5{$8utaFs#?hz=;n$Lz|2@RAD@`WqBk`EV9V5B_(G$><2)ca1)_ zto=wdeR+f<^vw5^?C-o}%s0s(U;6+;@11sH{^HgKvZ@X7Nu&;42SZQ;)KVSZ^wZlj z;SeS(OYH{*BdALkpL%ljhc06zG|0bNy*(%;Egjzz35r^kM*yKHSTaSIz%fTki;RV# zr#MJa3517l{u|h69c;J}mfgIZm#R>s1_Wpo%^y)d*&X4H{*0gFCjSD#I@9$4zDGzg z&5khZ{PquZ-JIL6ckWIG^I)S;{W!vPex1Y9&?}+s$mvo2^aYht<=prbvx!Gfn?VWo}u9ZRezRUHU+GC&6Y`q_&nUR3$m7{C5y zGkKK{_iU?FkK-VynAfYtlOvws{mnCp+Vtrz(Q&S~@Q0&>j2*8-3(f?C6jp zZ~gU~H##ZfeNxJ6s+Re&x^^jth;)_=*E!}_)y1+Z@Srpq)%QV)lxE0uGjul*GYNnO!QLX$4% zm#_JYDOkJlJ%Il1mx~!EGzFq2mEXyWRN_SiFplUuZYXN>$c6hFWvZNO}zb;wY%*AdD78+nEKCyULNBNro<`>>?)6}^R4mn``-rXDi&ZyZ$VR|f6p=jMLBsHGF^XIJ zhXX4#{?(Ho#iREx3Ri2-!PfWdc{v^@4079Lzph+o%v=x*&Ua)z>`rNjWQPqi>DzM3 zdk&$kIpi+q?cKXPAKyIZ#5m!#Iqds&!Oh|10joRNft@ba-AMt-Dsso6K`jUQP@&G# zw{z^mn%t!;ix%YKhnXDT!AoBrk{>>Gux=re*JHvMfMdO~jh!@{2Ut_BPh-$SIT}>g z?^qVMv;fYaC1Y1>&Zz9i6Ub4}n3{1M#8|nRNx)Lms3?f({^Fcx>sqES;gMt9xN2I$TW#{C5Ke1b(VzmO4oTLAhs(Q<|} z{+aR@qhROf)l_8SJiluj%|%1rlAA{jKd2_w*1Hw(4+}dbjdf1pX92RzgVKTei(@Hd_MP| zPO_*e`baJK7*YBQjfM1M5Tr_FQLe^5h<$uRHLW+TPdMbyR64uH$7^iP3GkCx>}N9V zl|-X~CXvf=>#cfsNEbNG}dk?u%+kX0a6o2`#X5c@>NnXdm4-gmQx(RJ; zOz^)7#nmtnoeD@}YrO zwK^e;q3`<&mG7Y}$)TYqvD+aP0MU9iemz|?BsMlYSm0CDz(+MxZ`18lW=nEP+iwcd z=BzB{xU^PJ>rq*+jnpwnrHuDQiah3VtyN4IxdK9q`J<`Zg1>(**c-SiduV!vqH(S} zBf$DW*K6b+EZh+1qO7QdC*+4njg#b1((2`VyT!qr)>3B|ApgiJ@cz;JUVKmrC?4=- zZHJa88V4MYUfcW9VU42zly_cEhzCWV)o+07-t!c3k&OTVBwQMN7+pumh8KVSx>d^mJe+bA69u75*ux1rJC?EKHId=f@NFGZwM022FJ{1Be8HkF)D9 z%$`U!Vw)uQm?XX(Kle=s8=wITgN4ygVa7F2oZI9`>B5(+2b9gw1b3pr$K&;9f66mD zRpO8tmvMti?Hp>vy7HXJb*!s{`mKHBuySHid6TWDm2=_9`7djyHPV)q%7Fr9fmk63H`H}-f@l^4a4nvgjLANN2Px8# zq+2dvB8D~$f9Mb=fzCFf7Z81 zeiUt!&R*D1hr$F%G}SDIQ84&Y)8zXTwfUS!E8m&0h4a!ht(K7SS&rO}%}LgBr&Qy- zqyQN_5rV|H2->B3sO0J`t&1BgR}@JNYESk3Y-29avHhFh5&b|T?U7QUo%uG;iVPQW+pCen6ii2W`i^HwlTzw|W(->ND%hUY7r zxn(VDRdziBu@uI3wmVW`q`?O>KH%umspaWX{P?}u z6UN8iHG}}+#z8?w)amoNW>bcjX4RwyoOWB$13Rtn$W4Eu2^AImKcdbmsO>h|`oV(+ zcSvw;f#RCrQi?kiw-#%0*W#|l3KVzu7K%f0DehJ%?ganxerL{{o6J9%TqGCIo@cMU z_WHfg|Dfzw7WaMKitNU8ooZ9#n(@mQ#guP`;>@(y)b>3++WwAiIOse_xg^Mk-9fm4p8HKgI{DX(-k)4Jkfv538b!~I!@#yHx|jn z`4G0FT#EHg<7L&YVFkI3m{I36>9{NGs(^ zL6Xc@#}lHsURdOM_pCYMGYIv3EPy>r4tGY{G@Vd-tjq%V!&3Df>{su@1t)$5Y*yj6 zkv)Z-{Fso3iJ4EG-8a>E{iW%*XaRJ+4z#lCzO0qHO?fAJ`YLSyvsnkMoJR)1xUG!V zx7AFSu0MRaA$o7}6u5CC*tYYhn3r4zF3Tk=uXLzHaLWX)CyS6;!!BG9>R=4pM?(h0 z5#8ddL>)LF0`rvG_+!*f`1tw%4zf63PUE&}E6x@6YC?QJ;N(Kb%8&<1hll(2WS@J9TOjT1&qozH71;Nk$5e6inz! zMwFZkyWIYDi5u_iItwEIkif^uxkyz*ipnrx(#vk{_RZ;9l=SO++%%S0{Z|j$yZl0A zf!ICOMI)aM(4alJN^hbqV3YMv?-(F?K;RLv0 zM&Ew#a51CY$lErKE7QRVsO5PO_4D%vhG|!P{*1;aq_WUL@2>dP+6{R;PQvc^{B~*- zf7^b<73_}w;I|+HUHe7wBy@M_mg(Y^dEc&+h!`s{5Y@TnQiu9Y&+kNUzaw}@@H*Kaaoyk(1ayn*} z3TjHgR60&wOMAKnHijUrykc{vCE;|{I-ICQZU{PWI1DMW%Tl~D+a_=)c7p9YOLIy>yY*4|rPE~Gzz4i8VxsK*` z-CgwgYUHr)=1$wxYNryXxA!r`n%j=GIWGcDioB9s$<7kp1tFf_VHwXcVp~Q{3UqW{ zBPJ|fZY24JZ}=M@ZtJTK0nmf)w>PM8_4irnSeOp>JP#7iFTT`kQ6y1Zy-Euqw8~YpGm#088^r1*B__0 z1J5klYbfATTn{ldM~V+clT1(NlhnhPsen!MmZ0(`BV%_PnZ{LzGTOz_e)|>7=EENZ z5lQ`})3{qj^Nl9@D=j>ucwk_j*z$Hb7y{FpV1MM4k&Mgx#xL7q8Q0prnb5qx^*zcz zn(h8;X`VViBm(yDE|ynTa5S}byF>&3OJ90Fwu;#L`Aj4rBG&nKD0NBhv}x6wR>~e= zRN^d}#c)P5c~i750#3ONp_?-l6?i`SQ>L2TJe(FA@K|W`<=4}o*~7qxudWj>2AE$a zMfawsmOhBS;#7JK)BRsBfN6)-$^e&>EOtU4GFzMh?o^N^se(oyMLtU%jGZE1o?#rn z15-ZwPjl|8G{e^qYFIQ*sho&GvHDXzWmuTWDpw!3weJX&GEsSR;Rj#(0g8Ni^t~`x zltZ^n@TLw%Uk3t|(cM@h5{vvV7~QGQt+N>!{V9kst*HlNP>=!{9owA*9i!|-sgL3t z;=0m9*^DGqHxj*&Cyw_v{uaH1pXrXvTQJ>(`#o*pMNA;z&Fh||DoKPMC}CE04P;P@ z0an1upEwt;7n+lZn>vnrR2bU!r7{UZbYTSz0$}X1S?lL$Uktvs;gq^i|M}V(Un7Ed z0*YESA}xr1@a+At;6A)4H2XOgNsw1$z9Vqme;Zo}snq0txE>m2ct1Q)(S2JWxFZC_9=xvH2TSI3eBFnGJjeZmtM^R1_D|CX2b?n=>Oq^##(r4ZMh$ z3Ar6#N`7vv1u9~=$HHyzkk+DXS_lL825P9AYx-O4!Ww#7S~_$>Bq+`dgHxso_q6UP zdL?(HzhMKP6wH`bT|nW)I(%ZFKcd^c z4($8~D2e8)wNGmx75|%FD*GVq>h#tv@%7*v9Tb3qtE=k$!tT_wd%UQ~Ec9tc7wM1L z$QQ)0bo}%UOFa&da1gmn2g^=@Gas zB7oZ(Wo?=U{0v~fc^QPBweD?dj_UQqWGHQZ>6Y|8-COS;7Hs-zF3LN6bvu4pciH=O zlkeY#$J9j_v(Zf~bSHP;35dw27<1~q{M6}+)fw=c>TKubCkh!ER9KCALM)1pcL@Mf zN?|lG1Q^|8`gY&Oj_SRodi^pg_{rk+-?Hcsyq;>1aZG~-E}S0_IJNMrm)qI?$YEM{ zR<5cOjOGwNb-Rrqm==yOzyL!zPHy4j{)`A~AYx zS}s34o_XGvi(w=DZp4*4+YLMW&x_jBZWOu!_`*Hl!Fu(j-JlC3gxBm`U1i%YmPOf) z7`K@P>~@1($fXgiggnwSY1EDI8cCzDJ2R#lPWYz0<3QD-Ft38-&e*tL!Z0R^zg~k2 zIM|mCy~$m0Tpyl>a00Bw>XoF!$@SXMscL@VwmEdn3Q#;F78aREfL(fvaUnad)S(&a zad@p_Tjk9!&FY^&=l@UB_4P{L>Q;yPN26?EN#6+;`m5Kk=IJ%m%&L0<{>1L`3r;KK z*`2OPYweyA%uP*{Q2dF(xNF1no)A^@r{s#-h7vNRjL^sop2=U>S@RA(nW+^B$ydNr z_?PWZ+f0NFAQHGh8yIo#6Oktdz~wK3#ls9Olu(>3PzuCsYh z554##?k059Bb;$wsiT|?^2X~2Q*;8fu0iqE-6fNa(30Gs3(m9eIEM_T9y0o1uV0`M zEHhgHNaX3BAM|Io%@VThw~a1`>eIQ}BbMg!8tW-aSm=*JO<5L2ugQ9ckA{L_Tp?;7 za7zmYDJNXoJ`cMU`M5(Kx;iG8+eiMeA8;|fzbykeej1OX5RbCVzhlf$-r#hDH}3Xhf_oVz8;{qH9v+iBap`M1RpBji`FdlpKK} z*>fJ9PKo9Z>0VKKgypa4ByJABXF-2bYh2$Fcr{iqE@FD}8M{2OhaHh-M)C(_|BWD_ zCu*Rp@iGo+R~C2Z^yN4OBi@TsHznK_eZ#R`JbCGQzl0!L#ochN{yt)F4G1u_G5XWy z_|HMG-hSxqUi}jH=dr?N$-)r?LaMzZPx4N|;; z6T}*HgECCr9pi8d88+mJxp@XM?=H=PK-m5ZnRIZvLL{gV$RFPR=g5dH?WuaX?(=V? zm(&kV(B_poxe&k5`Bevd8XBxMB< z0293lGAi@pjRw+vHBJ53R<<^}7~~5aw6OZT?l?ob$)O0{ik3VMLs7&UI~4+u2?X>5 z^*I1A`vn@g9PCN_@9`K!R1^59Fh$cY$DQV2P1NBKI{Uu`Ra`)Zt7HBw%8YKD=erH( z6-ofO(+Pk($BxRY$H6*=w9H`Y2mhOk_586Yb}zhU!v|}zo3rs$nhop^(M|tIV4K5@ zJguwk#~Z|BKEcVMLFm#n|J!34T{*o)a}VMT_Mh z4mop#dd1!TNh%1(P9D{#_Gx@d)rh+pI`>tnt9f7LHtZQ%i_#xAcLZlY#m*OV-@w%0 z!j|G}#7MksD)1v^`nyknU${U`!`%s)4Tkh5>GeYpo!AW{5E;OxI~^SQR)t2?zXt`yGOV~Aj=T*yp zjh*93aX0-af*xkXZ+*M|b(#s{drdZ=lPZWK{5m|-h~QP*wT>ZSA-CE3vI7@ziP7?J zoR2dRFFAPfjB9ywFgA*EGN76`_Lsb&8hwx*{Ddc(0?aQf?5==H@WGZGdAmS~rn1gr zFfFdGxpkv1xXSO19y8)z!9ZPu`e320-tp2w<#&5LP!(|6zbgNe$6uHl?`AMc{+z;E z8IY%e+v<8lKe~Df7`1oo^--Yz^G{bo<)JtJ(>w-V-ybDEM`P^IV^*z7Y(Mb;g&~F# z*W$h+1}u?J1T22L?V&o-N-TR9$MI!{l$fvAdkbtQP+R zJ2*0+uMS#^4QudnrcXr=xRZwu-+kRYx>3I~i8jAMI6O(7USaqXH$aU){NteFzw>8o zj2}NGTOU{kcVGt$9}Or*_}@gB1 zs3}?0%abpVJ+<&TiY)c#DM;6yiv1#E=DRB*7fZoXC&~`j9NRCtR1sQBe?o+djCH2{ z#;2sgkRMGCzU4Fwo>$HdE>5{aBR>Ko`WGFG*^83853>eG2jD<5KsJtPo)h3O$0T~} zP>}BH82!r^?(hrsV4wyt0Y3spjo!t|E#6{9a1;J5A0OQ|qLII3sBtDUVT{rn4P~GF z+radEj8yv+4!NdCgxqQieYyFko&1~x)#;s*Rt_iGts!*(>d+(@0_Km? ze1CmFR;~2blpF_MVG?}1&#*DvPG=UuMq{z!LF-B$>-bSqhY(w&KgtM!28^N^JNlUW zzAClC&)Ioc!Tdum4b6RU*LjM2D6{?sb`nF`cP25?9P9lR)#gQe1W#S7Sb|1}$w+@Tbo-qBe#M>&&Q<^j&ZB z*}O+r8fS4isozXgSM-BWBd$>*d1Y%5ZkuWU(XBg{91~v?%2;z!1*4coVjXD`4LzKa zK)OF`ZZ4jm!Gp+1fz38h9|}DOBtSxXf?c*BiGuRb{LY%z#04*lnD4D3Q)H=~0w-Wm~C#l29llk4*OzJmH+V6rrT1eZ7J-B=Zwf~*mp-dK4z zn7vLZYF=2|8XLwLM)yqwQ8hN`;!7biP)xKXR8RnHb&r2s&VoK%UQ~QMI@Kcl3EFroxDkht zR+E9tnrx4MrE|Gb=AxqOh(0--Y1n%bKszo4$=znjKErQbwGsw?qJG?d%I%gnT*}+- zicj_U&NiVKaV5(0%XgmMFSWe;Pi3Axd0|aC8Z?UG_ie$nr{a^$p!mVN*7v}ph&emQ z-s{r`v2hAPo?KI~Nu(^Jy0gIA}X^qd6t!W=JwQocreJkjfv4@yVUi=tD{z~+e3)Eq*LW_ z_oNC0Ez=o5af?a*CSv!@xZycQpf$4U$i$gc(`mbs2vJVOLU z1-CIs%%Yc8Lu+d|1&x;OJ1C;ewmWH32?gnGh&|GtxC|r)NyM(!S~+v=OMkd)*JoK% zg&doN^iJWkb?#j{pU`7y7d*6J?H$fYBYMVL~IHP9jFiA zjuln$CpWYNSD}DkY@*jC9vW#_eMgdG@XTGGVZVReZ6MtsFs-YEQ3;Ck^do2E+`j#u z_muap52bJ9?o1p!ic^H+i43Sp{?@KMz|mY@Rc;Gvdt+V;1Gybg&8H-*4Z!D zsA^GNwi7|$33oYS?{!Qa-bOaTCkccsS*V-F;gOz06gIGXf{_EwY5?9JeoF`?CKxj$8*qt;o>A(G@3?iRh!w%_a#sYDjjFSNLPx&9%lYeX)ZH!ePR zcfs$JemRtgh?sH?7#&=*j93%b^9GyXVi&qRelBCu4Demp!L;$CUhzeyqlHhli!k?p zvaxZ4o8V(k1f^2xNNe)vDP9{xKB77e%S~_is>%hVUJJ0CdRI2ug0U^ZfH(Pdg0;}{ z$nW(~+D;PZYOh6PKsZeZSmxFV)%J+^>=>ohd4-Ys?H4!1+~ot8ScvHJp=%6A;IS<9 zK-43URc(x+XLvp*kT*`ENln(thUcLm7_kB6dnxC;8{T4i;^EjMZ~bbhCTRkiF`+IW zAOpRj;q=gGr2yzz++QF-;$wE7X#yMZ_3px2HalEMncgBj-y5u4Ku-rvYT8!PCzng- z;VX{62&Z+Y{?jrQO-SN-v=9uPbRIGk3zjWW0EAIsG(Fx$;!4(NX%g7f0{6#Zfq%CH zK)0e?aUKe&;fRUxW6l$HK+)s+)7<=vu>Nqu>@L2$knFL2gchAo--!n`#$d$XlC}Nj z>}2E)JuwNCf3I)W{QRsRVxc1r4@YChr;#2NK}7-A-k>|#=7%Gwwa>HQh!LchpDI>Y zMOGS&kA!PUXIJP++cnu8&-ze6dxm1Fj`_%X^8i5XTD{o_4@OK|&=HbobG!)45= zsG;?kc(up$PJ>$2ItEHde05h^)@jhV&P(H74)6iJQM5{^>sx3q4-JtvLt$Lo@){Wf zsrIXVExlx=n_Uye9Z<+uH%9vrCdT9jZYGPbRkT0iliC$C^^^nZI&^ZBi=q;}-ksVH zE~jyJ8Iq3mUa8YS00wMVj*DSmY2OFUs)~glXSF9Z6)$E^tuM#BRm_=>guOzCU@DK| zo|!3+yxNwI5c?4f3u1}j&Y@irW4G6*3kJ~PGgr$X45g8qR-^eMHi}f%TpuyX=~1yr z&6rVA($W6ZD=WYBC+Wfxz&OgoXnO&yxSt5bb*XmuKc~oSmlBu`Xg_*u{L@(()YKR&KI--JcyY4xHojH~L|;$Zuiy zrU?yc%-y;IaXP;@UEvy>O?bw>7rQE?9fsc?M5apz*cpuG0;a-_^Uynq| ztRF15vg^OIzzIz1+OT(^b-Q_XiCe5e2u)NzS;T1#KGzIW$3c-L)Tvs6l*wQtZ_%=# ztYd)?57D-hnlYcV$rcswn(W|xlD^-ZaS>ccc05z{OWepy%=Q2Ac`+JYyC-z~Ar@;# zSBr_E^ z)maZ4t+?IWVCND$?bkT22`nKMdi1xnZ7RjIy-c(=72!gkFSO~l8Di$MgD1q!LiLb$S=yhQf*powkO}e6=b(vf2oD5?2^Tq>O*|A%II7;4@19=iO3MTN*XlZJj(? z2?k5?{rqYB?}zi)*vRl$rDQ9$3NP8`G1Qd1zm2^*8fq-X8d^VVZok}opt5bu%R5ZmrkQ@Xe?%3Q2{m)>ou z&kXFwOlT5rNis|$K;XEP$Adme&;g~0j|4FX&VmI}I?cH`;pP|426jK;qnDodi7W|= z!lpar_}qfXM6L*kYMnXku#5HE*?`b45c?1P*)#3&*ru@CE6qv24uw}nsC~?7(e2FiduJ4v zWd&vWt8LCjI?9ZaOE&a$sBdLE=?MXf*3)?`~q%7jv0NkzR<4K+>f5Ww^hn6P8P0wnaX1oppmPru>^M6w59no2C283vL#%R8r_8Ynry`Vs9HnCR-r|q>eg=72-HC3ikM8?JUSqs>YWLc8 z79?qD*_`M*e|}?2tgimL|M~9yA$p-wC%^%g%^HWvBzcCky`Vwa333khoAUPs?X;dd zq=1qV1&pP#n#0!`#C)bN?J`y<02_i6@bvXJcg!{$yJy>3BS9KvzFF4f=JJE>P9}eN zFQetL0yg5B$Dj`bJE?n4>^bt-fk805pJ_u@urhRBYmSQ>;G(2jd)-B-KTDuN>p{p< zUYZ>F-lC(X04dA^T-vr8(_(w{?;Vjmjf-u8t%R~dB0c?U|G9F{-5JRY^yJDdbXlNz zRj_;W=l;^MD`}}(jdDOgt8q>K_q>YC9~xNGYcIn)_o%Wll#I2$eb&`9gJxWj*NKzp z-0PtqYy36Ji1(b)S;~ID@UyuyVVdFQp}sjnnrZ8h-;F& zeV=GL&#SN9vX!4u0k%??dQ$N-j;=;h3|HJ>rJw* zsl`gC^HKamjr2%rZl8akS%4*BSN!Zmx8H`lQ4Rm!>)Wkm6JM}|&8`02(C^d!n}5-t zNY!b-(DlGh-5Z$^p}uE3&e<3)9kaJL4dXlE159WL5*Kc>q=igvEs3H zJH2o}TX)CX;*^{Y);{ikmzcTC>;koTpB2Cdq5lQvb6&ys1yEvd-0;$GQ6G{Ergig& z3K&tL3BO2xqislLkuHK-X-rHwsa_|^tZLI(Fp3P_E&Hrs>H@BV!2gD_5p!PG=kME_ zNKngbMAWYu54>AqC>X5X;Nr>oFdbVk$E9}>iJ0&FCy+c})A%sKr#71{^m~1&E16AG zSWwO^OpgAQN`T};vzVwb|2+rG_#J2TY@$PxGE>qt(asn?9POVh7*~8W0U@N^Iaf-A zG6JjWkp5pUK(Gf*EBQ#VvW$qH>O;%*Mv;83+WD9S!oHIQ?#MzdTvaA|ZZblo^bB>=fS>)oJC z&v))_WgGwSz!h@HS8uLsS4h%u$o6IwpQKjWx0M~S3r_N5iR%K*EQ#(xnxjlSZIaP1 zRZw16X++B9DiE{B%f+=w57>WXMSNc1Ln$pWM2Wso@omY|9~pH}r)M1*f68p*Yx2 zDJ0+KJ3BOCKf5QCny&GE6BrokNBnG_CPv3G@H)qDr45l5e)O5G61^*ShcMqkqm924 zv8B1}p7r}%%gNB-Yt|Eb6|4%s*#Hj@3GcsVGtYDWl7mr~El1O{yJQt+L4EzSh?l;r z@fpMT+?Nm{>v-Y2pDFet2FYF=ml3vRPn*_3T11q_PZo3b%8pWa-yNKBa{qam{h^Cb zeLS)%`lj6v%LC0%Pa9q09?cn08Tp=fW?3Ggzz_zC*e7*WoY{x%MM<&{zBs%Bcpxj7|uMh)bobe1zAtYz%|2=qY|1G}Gg@;@(% z8w`Aqe@e7>Hz*J9jKR9nqwDU3n9!soy#fP08>1mZ^#Ly$|1qLg467?XPmHYXuJ&40 zq3LD&{mDKkj^qTFUY$n(jJm@d^@nTiYvw1}5QsJxJSfjm_)OZ)<e?#7rn&3>j zoGuXT{|4TTcnk@x!G(XsmE zJV}(#-_TA0$KA7*qpbc33(2VVq;nplNEmk`PQLE@f%-xn$))c%K0i9B9u*{VY!BGn zvz1EnOX>Sh-qNxdEbX@oc@8uF^jRdN7IAoE#P;1cbd0OIHZY|zz|&jk3I_M+gj}Oy8ixdr>OtzPTzojCti#cC zr4-p0nwgQvI^XFq(B84cjLnSQ-SV80^$=JCy9Ulz3WvzQx5y>1@V+#fIoKOCAO&=8 zT8qKweQFz8pcB)kXhr<^+@gGjfgvbrGNFLTW(n|cxDJ+D*t`6cu$z#8Ad2=HzMoyU zA&Y^mfJw16$?~?F<*s`0j{~xh@@0jVdoDA?YEQGf7TjCMR?mRDP+6~tuDndUSiQ)q zHm!D)W3>ULZTD9C_D0(_5yVsGr*$wIg0~r0tYhu0_n#|YXQw`l>KaXbj!eb{agg_Z z81$+u{fI~}uwzER;Xm4zIdh6LDZ%iW)p&q}{PMTr%tC~_u!J+S48%xvhL%4BGHf%o zxU^R9xtZiL^X`>A@zr}gR5M(fC%1?;S0!{wEV~T;#zvJt#H+|OO1u>PPzLQ%{=^zs zXV_f@taBo?hF{?Wb5*48JL2OS(`Pq$kc?!4@3kjBBdV|3y@U+5M%h3wp8m~v%TI%% zTDf(V8%T&Vc&PZt8x!I6*L2Ztz9fW6 z@0zfZobyDs4K@+#7EOB4*A$vo&vwyj%zem?JJ^iZV%J_JS9E=ym%pX$;xbda-dg?Y zwa|W^pWq-5PxidUi?ccxAgS-U6a&y!GJIP~dn0cVDggb7TILfFJx-N7Fz1%o-tr7Q zS%r4*J4wX73cAI(aT@UPI30*55L0-?{pFAM`nFyO1fb0N zy!Ijykt=hkgBwVU5KYBNz^hF}CfGOD^6~xhTpg4FoE|?-yrFA9JFs=T|Eg%VZqtCf zG012_BpD~I#TN~oMhtj^p4jHq)zkL{^% zGYew*7IMr3__}MM!-^)0CD4zFol3~CsF83)q86hcS_(47l!YQP%-Eq5EX^bSl|L9< z981KT#sM&GyCH)Xb&L>mx3|g>?QbS)#(q_C(?}~a;)f&UZTzjt(w-4FUe9W-6L}-; zEg=*DRe&|)UIa1B(9FNeD;|SAje=0!ID)|Huo6x<5==);_S)_FuQ28#J}EWZ`NL2M z7z=+ixN^}8=-&mP%dzh6#5drmbJ*IE?MN=p?w6S@TjZI1SirgxgUhfkUPNIay;8xp z{z1g^dQWPf62WmYm&w2PMeIMP5)XD!X}LS?ejj0C;IMispZGD5G7}L9*5-Rf$ydz6 z?yqm1-TH)T=?hkMScUYp=aQvN3HZrY{bKnJyzjk6SPKj$ZgRk1yKb zt1C28Wok}!vvyTfjko=~o5F7iu-~|$hHP@^30H32s|#126S1gdhkADfs$YYFz&7e0aiERAuz_Vu29KT+a*P9q$|nK1TkKwSDY ziI5_K!dXe2rnO;NGd@#OE zconT=hIFo4$sawv4dS0>(9o;?HUdac8Jt)jHeFo6gdAtoGqP2NF>9{v1SMP6W*T&T z?!=09*m$B+aiEyLX=j-JH`kjIhK(PR{+_MLtFre@zR1-T_GC%Nil5F4VgmF{yEV;G zBKP43qop^Y8zoVihC!Hta|T)0J#$E1oTL3g5CJkgdh%Z1Wi%obYojWD@;)gbY0s1# zlw$$ZjX!EFX=cr)S8uw@24suTq2`43R6_KC)g4~QY51!&5CXlR(-IJJbq zOzEk}5T=sgi@dk!jBh_!wvZ>${2om>dKeu?M0bs$>i&2TZGlnj?iRAof7ZHYvz&W=4If`tG|Y1%VN+A6X`Zg!OccM`1HxgjN;?(6=9Y z7SgN?oAC}i`3u_GE7ojYJS)m8epL8)%Q3ti@P_4_l;0kRtd)C9T>FAC_!~vo%I@Li zz9cpUY zxWroDcC;zfUfD`E&7$lP&KDTcI zI<@sm107e}Q>{kQm}<@#UrJwICxv&KhzTSw{~!ycQN5C<1!R1<8a!qp2sHXLCdx7h z=epE6!_HkEodNi?(4UHj2Q<>@avJrxL05(c3LisVT0iapO(30>UbIkno5%Uh`oo}B zeWKO*I%=Tr#u%sXm46O;%--ekg!s_4;^GI{0GvO}66-&3PivrkCG1xI{Kl3(_i%Xb z3wG{@8y}W|gkNyhugBhTF9iq4a$>m;CO6oR;q%Y*;q_cBE8awYE&ktBQ%8Q5{X<8U z5o-KM<8&AQYp+@JCN_c-@Bs}f1y*zpP?o=E7rZZsywc_cyrKD5@pC_ZF{$&TjuZ14 zLk;bYyrpO4)$9kjS^ag+wCx#&`dxBzZF6TKSN&yu9{fD|aat!9p90$VG-(K>So2!h#Mz#vR+69f!P&O6bpqJ;B<2KI~($aCsn@hxwucv!Tw@T&X*WPa75=%;>N=(0 z)2aMtb{%G{#026&pSX>9uXhrl5lS%r-EwR9Ps$8xN?#%c`xdhWohAqaIvs%*+2Qls zWO^d=U?q##Qtz|kq=WOH56EwnvrAVC)fj?kqTU5XYopn%Ty_E<+)uU>f6$swxcsP7 zDH-lgWX>zdyp$%etIO~O&lyA@MT9UfTFr{ljWd;|jL@musvA+2nv0p4Y9sv;>TvnU zEOD!Ywj`Vu@_L56=uNE4OjUMlTfsM_J8Xk^2lUlZOL@LB-YkoeP%y>i*H^tJO~uEt z6^Tpx;i^yq@pikf^xti$_wjiW_db-;e?Mou`l9Bmd5-(tlahj{m%xO6-PYEZON#Hx zFEXYkvAe+-@*Q>Vo;?j_zoE!T{}H*avl&AY;9GZaXWk%jRt8a6TODzw8=AJVdCwPM zyZ=?Y5P+V%TBr$2V29}HQjk(bDlftCsNd^}2sz6QCf0RtEm%5n>z`mPxz+%p z_G0B_U-XI?gbYqj*Z6rR8|?Bc^e|B(&;0n#Dk&{yd80f_6NTh8kCsQ`#Jv(r*gNz> zA^Nq9zXd9PT`BU{%Y59jrlbQ3EWJ!7uRm9Hgg3`}THKA_A%0tud?5wuIqwLEo3MPQ zWI|@M0W6__BOu_D<#nzvlBPoLxiX*oi2nM4x9&v;4S-NO^rGSd`XC=;KVM?xlb*%u$^Owzo^wKj z#b`Ipph8GzgV`3+gZVHZ0zH#J7~kt$4A@x=`bSRkewUF8Kt#7~CNCoz#Ia*5FMR6* zahPY0O?L$nWTT>_9G*iM)`$x`SW?Sn$N!Ct?~99!0Rx1-@dC&+<%MpeLh_cTzKi_T z2;f7;Z%;Y-2f)`R{|JDbtXpp!%>W8R$970hWzD#5_CbNyVGmlu;LWaV$+au4ht`*N zWz{j<*K_(a%F6fJh6DOTZB3*h3-;G;{Z9 z=q-Gf^HhFC1NRX?HpWBf*{#bgAMg+{J3l{F`!1@b}|@MbWXIF z?E=9YIXFv!;5ko?bq{x(23+WHVsTQn*I9vfC&(5LYL8Yhmws=#m)P`tqiwe)GBxAl zH4`+e&nGgTf*NGg$@_d40)7{! zZD>u2H#e|5P3gY_s;=&Mygn9+u_5!{(HU;CNVcL~Ys-4)1ImM~|7_#bb4SlP6~))! zoLqgsQ|a=c=OPJ~oEqe%9pLTj(Js7$nQv_FhX#@>Q-9n1sis|FkTp?NHF_gV)t_ZvA$~-qwEX z$3_fW%DSK`WYC*Lh(H|r6wZP|mwb~7KP6)jWWyKN%odYFUHhK>2J`9_=6<@U-{}R-;k=oWg@B1<^KS_?+pFHGAc$X8F zb54KVxaDL1&XhrY!W)e!N{@<|u}6z8!qXN)_$>;*?{YKSWv-*Tq~-;eUqp?CAh@;0 zF>iZUCE(%NrQL(Zc#dC8La%-<>-XZHKdAk;aVb6`?r{^Rem8n1^Ph^e8k-U1RZpFc z;8_?pxpWXbywU$?g)&g`xmjr0Y zcbHQ|0OzUc+gmQSsoXyZ3}{1UETNIW2x?7GikX;=_!0 zchDC$vZM8W60;#Oo|xM!mzQvffvWf7vu6`~hWA*-;HS^@g*Dd5(4>3b#Li5`wRoae zes1NA;<*BkKpwcHwD|h%jJIIgV9l~5+|Xc*AtxPg%kST6|8oHM+9BJSQZ}=wb;Q#7=G8l9qdn%Tt4e? zVu-xwRgV1P{guuiITbwSFz|;j;g|M(8rnR4YF~%4`3?%OpnPbwflHZg0#UzE@-yXp zlvTn$YrQ4$cO5<7H%#+jnOriU^>+A{f1DlCG>88*Rj6`U_s;3r*27*Cls~I4&>&&F zf5yNwGb85~v*{dDl0719OR*o47)ckgrD?MFw8j3LMhh3Ik1Rbr$E+sMkqN>+WN3~qJMM57%< zk&H4{6Y*K~I%Rh!9DjW6?UkVtmHf8*%n_(AuYTBx~Hvnt~^1s{qg zvWsnfO{1H=@ylNeahlZ92J$5h`9ib_g9*);&(MCYr}lq%!-!#eO>7IAq(TiqAE>bk zTNIrwu)u)23_h7W-e9X^anxB9eBQm=rNk2sn)s*!4$4 zuVVahBbzsT+{>!_v=bPj;44rFkkNAZLm6n=O*ByqV3Y*a9cdSqcb-!>0!S=48$qxx zSEOfV(r2(Pd9E!Lr@p*72Zj zw4Zmy51tUVmOK2v@d1$yEn?%nfvB<)mx~YZZ`NlP?NeY`Fk4*vZY~_6d$Rs}Py2o5 ztM$Eb-50{s_Iq!+`ZE-201~`A_G$e{|^{mE!v0MqT| z?8TG#!v{x{h)fQ%(*5&&96FedK7$^rI3?mP~f+OMQ{~iByu_AB3t4eP>#6QpE ze45qqtU9jEoB7zh7zXw?YN2=peC57K2?n1BZ-;;fN|{igF=~-N&!yxi#$9xN338Ht z6+|52SV#Xjzx7|(RgKBPCw&>+wRsjuBR}cdnTN?A@;l{4nH+{A*#@Io+e}m(;OeZT z`YuyU)Z(rQ1sHhTzWb*4VSX08)0G)IAr(}T&-cyQ^%@V~7p>FlbALL$x_1<4?qC>f zby|MyjvGHIUJ{QsGQr47Y7R|Ap+mWB*YlWyaLnBZV{%%YiBAX@^Zh;!3L!P$vTR}Y zJJ;_kblN7|11OHzCBcn8`73y+Hwq=Fk6qIJ-p=#E7K&R_;ABg_N1qL3PsGYcj}>P! z58W(au=hQ~%<;G96~NJ~P5gT|sk|14>S>#FC6-uPulJ^wF|~6VamocS6sWHg<-CNT z(rwiJwM8NU-e_hg<@Cj4Ur(18o>*}FA(O)Ux~drz!WSii0gd9#Y#37qoOU`kQLl^J zzLgvl+)>Z2d44P(l`*eWgDiZavmS>nyB)d6gR~sIuRh1-|33gZLB_sG5kfIiF(RSy z2t^2uXCmWi=ozixd7&5$eNRGTB=n3##yALquTfwmRD<=6M1CLUV65CXeX2T} zre$05pBY^^XVY+B_juUTS+Sjk&=w17eb3@~G1iX#)p-!4-FzU^k-{=i*|PVs-+Oe^ z?a$5>f}Ch6tZWoWt2#k|&J=)5I|_tqWJjLOR0^v;3gp6-ADB0{XU&y?Upn7d#2RsO zRPj3l&PgmPB5DQ*8va!uLS@B&-Hr(0Z4$al}d$t0748wG5~~vmYE&^ zsm=^d0Enu_Z;j6wfB?#Y1DpmR$7j=zf&Lk{-; z`pyrs8Q{PFHgkS*H(y3s2!xB5^5NIKo&DwUCXV81Mt?9$n(g<>*R%Dp2f2Ot5Z3~o z*0OB#qg-`hFW+8wQT2K~k%1G7S5RKQj;}p_7iUKitAWC?5#DhB57~Cf)of}QU<^N? z(Gi|F-`kD;2!K-7iQU9`pBMdMO^)KJHG>}jXk*TlD0BeAaO%Mi zW2*`ujqt+*#8}is6*X3n$f{9D;fIaXsHzD=V~8Seq^Eai=Q*oC92E+Sn+~kbjz01v z`)|1iqLZ6ce4seM>aMdnqf(+{vcik|_UzQO7YqCVSbNE(th`_YiiH-!Okrs?Akg( zN0(3EoTAHnfnbb5F>!7XlR^pyL!4+<5(VONg*Z?llDv~Ch>0PHdj}IM?r}T;B}r0s zXReG(%HZneVb@Hh|s_+jq8`ECyE*^iAPCu3zZ;3I({HU=J=g&OW} z0!nP;{%Mqe5YW1)kE|?~P?fk+RVrbGjjB-}$&lwPE8us`01C`vfp&f6g>HjaXnj(( z1`M+?f3#C6f5EK6kGASa%dc&%n!)d%3H)&0=7?zbE~KM`>FI5+T3@NtTQPTTwE4hc zDxuXx-6+<^6D(NcdPpIsx*#%(hzM3K1`%uG`@wiTMg(hB#8V*>cT=W_8pI{|HN;d_ zB~lU3%>l+pdY)NCL{-E{6%9QJ&5Ik2-fQ4tCarTlW%YR*bGgx1g zOnVy7b~XDkAs6vxPv*Dmu1FwAl3S@}WwsfdTTexJZiok0001BWNklM@G-?J~&+TE75Rht-)GJ_kfYa=U0DU;JzD?n*EcOQf)lF zB>OS>5^v$mN(HaKd+_|jhxY$qtbC+ma_(uZBE~@S>XA=v&KEU^(e&}BvA%Wn0Sa1e z2f#GhGn%R6`(Vpc*Rd9n08HIuLKGohrcME<7pt`%Qjo?&y-Zv)$ATk?khaW z+%vfI#aeJtASCxC8mSe}xVwxhXp{6@jv^H?NuILmv1S}(ar0Gt9#+rX_w$72$Pczj+ROQ<3IgtjP8aTZpaz) zi^op>Me7u^Pkf@iTfiUIT@L@aNx6+JZYi7TlHA_rZRkv*KaR9nXIotEL+5es=n-xp z;}f@*OF#Xm46WV3&CAcJy`T+e+Q0k_l)L9}R|(pw!9#^FMFqrdH7(NHbtK2p(|OSmT?Xl@g99(WiapOg$v5}y<#i}?R2ka2 zmDlfhid!zcg2P$(kw{!Eo=ddhGQM^H?aT>7E(E-ZF|K{!HYP5+n)_-xjW6P@qCc{4 z=FhhD6#$70RMxrMB>F=$W0{WhRq`9^mnYMI+tOD>YVYzg?X-&is0Rbd@0j(xA9b^1 zV@kZ(e#VlX?~mwuPRzXRY8Q&3+>4aK?H5}cV2`Dm$78NBV=KMFEzd^fg_E$Nu3YbS zTY2q>=+?6eojZZ5S1C4=0S{UD0m=Sw>srAN7YR|@ZUR4i+JqmF-c&sw@FOjs3qQ09 zKMX|H0Vi8A#)j&t#i*);p)uIV93B{2wr9oJA6CzAh{VYqV-#`VmU}t!z~k){KVjD8 zb#YGbN|rG|@7N@sJ-Hy}wB=iSJ~(My)bQohhaa6?-CXk8*JU2iK#bwYf&FaR_*iWl z&6{a9xVjPKuWvr?h6d6v%{If7{p5XX(RZt{Wk=ClDzaw55OX?8Y~Qt)-8=VSqli*x zCt`%K5;1aQlX@H{D}QBAIoECg|I1(KH!BWtNt8t2ch`97V4(|hD=?|g5+ zKwHN%AO=dkUgCq9e%C)k@B`WzTTX!)ZMXKulNO&T{76g{yKgTVhIoU6Z4E#=3q|jo z`SYS}M~>*|WauD>;2fAnM6ARN)s0R>RMkxzs$vjvkzOilJT=7U4~Q61wIH5~hKMx| zeIyQO>L3VW1u-!Mal|AKf@J1HG2$HF?Lv^Vman{g!GZ^gF+qG2=ou!t644(V~Cxl&gvhH zjn+bodP^XP8Zy~w;^j@I{cKyFMUva@R&_kD5r8DivzD8!uUrc*z&+cQlMl(569`gh z4nd+2N!lvLZTQwLZw5j90M;-0(89Bpzw?cAyU)1JNU)HUN)m@KfEY<1@=^ej;>F~+ zaP=Yt&!Aap&1L`uVmOfikj!!mcw#gQK(Yr)0zh1%b27(R=15EAK{EhEi8HEY0EjjL zAWme|sPQCbx)ML}=K+u?9+k-jASh@CfGD*9#28Pl+FAf&6UsM30Agzah!^-t&XgE{ zL~+hF@Vu!3NUhZY5Jx@meNV$Mss$hu#16660Hh2QS^*G%B9uyfIx#U30}yBnfE=m= zAh&OYWy@-Q(P;p3+G?yF0CGdlUD}m7fSLM<-?%6@^run`vnzFIE+ z&R1ABKE^jMf33S_@5pI;&80-|eGmWs`A^enBVGoWu)@!U6Oj3Q{uBO8P3>R`y<_mGo8C ziJT{WrDh80s~q@oJknRqqD-1eUu6LhI3STsh~9LfKWzR)n)F-WPtsRzQ|{?(>T~o2 zz>nJ_d(mw+`t6@$e|L*UZ`-N%4I6Fr&IdHS_Hi36oAfzw27W4g7osM6(botml*L|5 z>5lCt8XvLt!t9fuLSdhVuimERaE+EWW*?qC0MCu3oc;ZZ%h@pl_@RQ>Ec~zt#x##c zO5jJ_ULO32_p`Xq?ZXcMj3@2F4}*v1zz+=(jbiwrNX4p&LgR@>X3v5}=N(+K?0tx7 zOISM^pJ30w-OkvSo$VAqAr_bdOFNfvc4-L%V-*VJJgR%zP6cbv2Pch-8ooRq@T1yj z&ai4bZQ?sT|B6>IXWqP;&> zwr?J0->wOI`U`Y+1=R=;$wX#I^0u-`JeMGebI>^=Qwc3xM2Jg*uBm4y0Vqk%ktE_n z1((Z1Yg`>M4AB^Tglv3p6L)<3PIhm1KqrMA$-hiu^CaJt0Z6|-r;%&7hwV>zu4npg4X9}>u#s_LuUtm zxP`~R&FZR5b33={XZFW7I|q~=Jp!Z0Fhld2zviB8rs(Gh(5~Ma= z2oeN=w|ec`H~07TU7PqTGv3X{ZBnyr`VgeHDXD=V3RpGr=(fw|KD_1C^T*3QCs*#O z4HGGt$ez)0@K}FweBwwLCHMCdJMoiWm`pRt@2xtjYamGV?fh&X$<~p~nIA8!+qjebLk3EwILE4Q1X$3)&7k5fZ403uino=y*d#Bd`6K=9%+DFBJTG7A6%s=k7H z0Fv?!KRyTY0SL4QK%m5N1CXs-sR1A&+>rAtUrcryfMl#)`Kuq+-NwC;qd)%U1_~d% zmUn;P<2;-!+XnJSuVCP>ew}xH{6;=`$BoP@cJnv?Hp*Xr^RKvja-8dck}9hox`!)% zdN1F&?ww2w=d`~J=;?*GzMCI>;qN&TR(LJda-#!_c>Sku=U-qNiO-?!=#L`@F*kgO zUp%yrJ?k!F9N@f{Fe)DZ`t0LeWGzd9j^U%c>8C&D(U)DrmL&S4yRO|UU(bX0-OkR5 zabAZ5ITt-}E6Z12!1ud5v8|#%PMY*ph6241q^}|mX%}Ri>Ulp@^P@jzCF!{bQD(jh za1UA8zLVv7<4QgoF)|7Mm!j~aJ5+xwgeBBn7ZkcDVbzYvUiWZRxpV}(<4oi2%Suvd zgxIpn?cw`A=b6&uqoN!4Y4}pDJw#+g?S&id#L^XB@xGFnFq`)y3qKO+D>GC0QK?F2 zS&QI%O^-*(fgjf0>(-PP)f7-Pvpo2r(mwnUYa|l&6{H@1L~2A;J+%&gXlRVJk=e6k z#T7>uE_$cL=~bq(%Hd&lf9)2^2adE;eAdk%%r7nAoSu~oMg_V?$1vLPOnBN(5u4iK z*jP$(znpsTqob>vIrHW*HZq*9=^dEMhAUoK<5Uu0`%_P{b>rjJB~sJcl!IGy$)zk` zx1Qx|*U{PC&5`{F2rG^6N;V&N<4;Jw%w)SZ-D55KZZ)>4`VleA>*-?s!g&N@cy8|j z4({0>gOCnHgvw-vkt5@5e|m)dd&cOS+d)UCj}a3;^e0Y;WaG!VLC8LwClB3{f)L_* zPUk(&DjetgaF6mP{p-f+B({=h4^<%wBQ`$t6nA{{$LxG|7hxF1ksg}K_mPpZN+hl_ zxjSm2LDV)xcU0F^WwL4|uWSlC>LExNTI#1!;|X(?7x03q4ygQnHvN^2h1xovld_&r z>@_X>X+5?X{Lbl4J5A=4 zlhQIu{L*tX2;x+-W(Gkz`#L*UuU-Fv&W_TCbhA|_(OH8al6CYpG$kN{T48ju*T3t@ zYZvW4yrO5?C)mj}0nhaKW0Ple9v&XG6+5Y@h(Yi?#dyS69LPvlN%Ho64g{%>)yeL^ zR#I31orTT|f>PK0`wnhB(o71ga5AN^!m5LKswfa^s<0%nb|8pnPfQdDRHHzkDuuOS z)%%y9yZjw*?&?^0t?~RJF(w8Kir7R(6L9Avv5+1~4xSnSqH#Qhq2?Y$RWY7>Tuk6Y z0{}^)Q`NzX1b}GTms>9hyvQDlbpXWOl1u?WlKwLHMWzh^;($&&5g=6nf}#4tNCtp7 zxDnU!jAC7kt(rJuLoG(LK%;taw+%pIEkgr%p05^rTmYm@)a2zx2S7Z}(E9l_B*chD+0OTkT%SlcFK;(uSUi1&#rvXUDW-5PmWlotFO7zFC zUCS>`j`5kl|5JLec?Y-j55TAX6P>qzjcKSg=RCF&c>nLS?W_OD z_eV!~J| z&dHR%O6rDocBQYTo%aK3X2lbc_ak>qCn@Q9=wrTE4nJ`WuBMGSC4!;7YOmgCD=SKY zw`rdE$7|TEM z>qdr#-Xv{a6DIc@WcSx^B|J7hb>S0W{e^y3^{i%YaV|y-k?#|E9=?r`(-7p8vnda% z91o)8ere($l$L8-cip1FoMAPNPT>5@U(We2zk<077BGD9Ad}-`T=c5f&@*RFO^qlF zx#xS|CM=hk3H<2j?&gx$ybdu2BSQbsJXWk*&)CQa!-o!5tF>&j@h7}c;74|w84(ut z_ON!r5CA*&?T+)@MG0p8fRX?*kwwY9#da+JUVE6683=SdnZzAQH z5o6AtJERpG+MP#7Q_ppLa*McJdNBk+#0nU(neZ-6LcZe25K$3~1uIeuL0klgc*%=h zNkrQ0LXdfj=Pz2h;+&5JfnSrutpQ}T0YTim)b+)(p#iNS2pD!AT+wy+Q`amSo9t_2 zhn$*bOdy!W9S4qznXHUPg5tS6(|9IMJE+Ng5KCbthf)TB0JNVEgogd2;PrOQJ#W|H z-9LyXMsii6j#mmRSw15vthy+WW_4VS$eBrDHH!i%0Oc7(fz(T3B~c)kUGR~WtCwB> zj_%F{R~h3ECFRwsbH+n008y&@TLfR+(?}M8h)5a&lmL)q6I-ol6Iw=s~XT z>ftYc>woYCc>WTf*E@S>EAjcsl)joO??Fk;0Lsq z^!&@^@B_o}#wq))vob7wHVUuZ9fgO_i3-o8@FUIP;T-#eo_}nW6mNcp%9&+!X||0B z<~(D|uN_yrd9jrCB+KjJ2gJ`N_3*>@r_T8?1Nc#PPp>uB7W_~Zwbf(EEw6(g*>xHC z0bm^bFyP=vB#6~o_+cw*Ld9rkOr)W=^XxTm92*$8DtAyhHu}sC_I%@q*mCZ(*9kRW ze3o`CWog$^d{g^0V?B?_Vv)%AG1g+NHfiOwJ)bt^gp}h!l-w_;Cj96f7+}LIu0%xW z?(1X4+I7sCw}1spmo?Pd{K!w(_3Sgu1bzUV|MFMRKQz>^wKhHYKq{%#eBAjz;e`V~ z$lWHsF`Uug%i8(#K;XH3`#H4l0OiRt#bSvl3JEI_!$-$VHEu;}4i5ylGM}64bs1G2G{;0Q7zeo3?=}BL;EZSB( zbw}4U`Zj@3=r%uF@M8x3v^O?s`L(T8Gx+_p2|sdIRVvusyOI7mNXOJ_o+2XNl7YDx zQM>){2qIuf^k~EdhCt#n7U%Vkor>|~pb~p?ljS0K5gLhzBoKre2;#D)&n^TxbLrBx zix(~apz%#l!|$x$SalGjc9r|)+>Lb*q&|wF83a*}XZEh`dwAQc=0(<@T9@n;HxVHS zh6;y9I)c%OqoE?=8CA~%<7t}RupW4{n-7H4A)Ib#@}fY*n4ZN$%NIPg>!G_(gcMdb z3S=fySf^w{^cGPdPzzIDa_$F~Z&>;Ew|A5VuQFl=5^1WcNeVz9jz~zqRRM@AnS4$n zsgiR?QaP*y9H>Yw07<5xYD*~qsYZ7sQKzH;#LYsIp76~8NSeDOGp1ym4FDvn_8m_~ zv;rXR0CVkS0f@8!AgYiBAj!)pemwsq03-n#Qv(o(by@)sLk-_xRscvjO4lXjPAC8& zh-I%@0T8AHAjj$e$f0@wQfH?D$Y}tQ+H592f1yNw0DS&0c&=RLI-sD+`c3!p9<^Ku z;CX!MAD-qT-Tkn#uHG;II!7PAm9IRvlb55M0rVa_%=O>=JMO*yqil!jE8qX}w-i70 z7XI_rXL$6yE1A6dm)UmTcliFXqg)I0sB-4^XSw?6NBPc6f37x)WG2xcU-&dbkKN0+ zRGAAzJ$?M)$NrLEU-J?s!NHHT{QzG6R&KxdI~*%dawQ;@NnY`z?=bL^S8`jStzXdeA>q7$FbRQf9W8%{OptLf(bm^JCESx zIP!ixgf8D~^^d5Fb|}D8UC3QUk5Y(8P2mU0V4J`X6~tKAZvsE! zjvCz-rx5(`^5KVQh-fT(6~hnF&=?J^|J<5&Z=dMxyCQc`IX3e6GwlD~UFbi83_Rw4oj*fBQ@KKH)I7nr(j9>5xD8U1sls~AL^4;;~0&o0hY9yHgR78}jBipE8)rx0~ zT5)n&;@K2}SXJ>6jS>hVw1gnwqDw@kh9CtWR<2p|nxT0^Zx@k35`Sji_R8C6Q$Uca z12qqVeg3hrzQWOChe8B=4+0PML@}Nw!~@7| z!?yE*#2?c=;kI-AdEIRHe_G;y~y0U$!0lsv8@aa%wPAF2Q(xd%ytJQ4t+Sul~*j{%4w zmfZ4UsVsE~&Y=!~*lPN9B$Z|Z5j;&EZCe8n6aS7xK-7)DIRJ4HQ9>R7Ny^j%5SObY z5|Q{pHU=OGfW;=`tOX#JYEF<^0Ad;dh%rWELX<9V8-PTybXyJpv0n0Y@3}rQ)(n8S z9O!QOlmKKrgrEZW1VGT)sa4slDgY@{Nc~W40gzFkD<6Oi3=Fh2JApe2nXGe*A6#@wolnf66bt-_AS6$N1EcJUc$dRe%>(xbUuZPxeK3mA_*`v zz8`BQ3+MVBkB(^c^g#_T)!I#HhBdnQ$!L7>S%r@KyH%o^q~{sjdrBEOY0z~a;5b``*d;Yf^XJ^BgCJsVrxwduJxy3UrwOF717!-=E zzUU$frTQyiW37$%-^>1;J7)wx04{pftLdo&D^VD7-}k>un7q|6)n=&Mz|FR4leLXa z0^*1YB zV`hF&uj%hBg_{o?29?+mD2R%x5fLlc*t-`y37uolx#m2CNFBgXQ88+;SP?6Nkp>8Y zMeu|?2qMO~m&B)lAnF%__2;jDM|XG6l^NeVZ9$M)4}8ORt?sk-lcK8%k8HhS?lXHf z%$d;v`~t8-q01Yu^cN0~910P^xocS~001BWNkl2ZdU8UNTP(S!NFy|)3P7rbtMyGH ztwjtTO&mUfV2o?c0W8r3S!4kSkOGjD@74hj5mRL^X&agO&dW+*xqFN(08s;~E^$&l z07-sR6@a*Qi0`$U0+4izy8A3Y1|YNqAd!Ht2>@{iMEuVr03=L5w*(+G2OwksNWIkn zkT^ej6rYUlSd0Nk=vN&T^#CLcW5J$ z`PvV@%mTG+0Q|}%Z~pXurDxOKJn&baWX++2{1Z?LihTK=lgYMyxV0Uj6~<{F?FMV#}{-Mni1v)sSsF*>(A$=`)#Ua@%-`tob}adMGvH~QmL zO?*CE(pQmp>PlbbK?yG|SD*L8nig_YCoAtqUD9)}4rV3oPX#}c=#S9H+#A~8*LW8S zj9npxU%S-vHv^c=YnUBA;VSW;I^P8Uwp;AzD7v-|U|^wVi>Cc64Fx+@Y0=qPi>fBzF0xXzZf3rJh?0YN90XM-qIWg&$E^3oEkl!w0OHCHN5$ z-?KFyq6z!}sLAV*fghB$rsj;`hjs8nLSrUtCqwBU@~!yNh#%1~@b}&hW$}<%tQ79yr9r=opB>FZhfcnPk($ zJF#KJ{4;v-JTG-rh!yv;wdjQ%NH*U`ebk3@l;r3A=$hxzIpk04^lDkO zt#+jL(=;dQQlE!3iB@Snw%M3NrmB>`@c6e`U6pBW=T`m9{@7+xX`0>Vtgr_TKqbTs z4z{Y9ni=ZqG4p!5!Y2X4lMhVd~QdlP{A$q$}AoWsMogLkB@dY1RzwYcey{n^R;8o(8-s-U}sU%ghpYi~R z#D5V1TdhM{CvHn}0ED=Iq9&6P#;v!J70)wT?K8mu)v>6x=@@LR*H=AG9K2`?fIu9D zQVT%Ri75V@1t35bfT*OwAXxwsr$eF{0Pzq=~R4Q&r^*V2vY)(xJWJlp$b4I!mNA2rz7w+jHyTk2!aYR|EL2X zWeSr8C_=eBIV}Lv)6=6c%xM79zP;de9go+JC;B7LW+H!edz)=PHG|vMRxl>9i+j1Y zT;>nsuNFX+WqY@9+dJp+k}2!|9MLUhe!WoQlkp;{O!AxG{x-XJ?&L0%euSed&gH+? z*M0ZLIDFmv_yy1B+W?+n<7L;eIXC))=FuO?=O5j~8N^dWP~_oO7)~??+ye@?6Ww`%%+=i=^jS z^DvGYG=B6??vXZK3;DIz$@62`uzJ6perC=4j+) zKA<^T79MbZp=ZbS9YY`K67Syn^*s_i)*X4}Y|``ePrL9V9`CHc4`__%rWSsfZ1Q%$ z7Jk&!IZpU7Rx0#tUw!Uxgr(A|h5_Z6Emzoc(`_8vw6&e$vt}KB2kUy*vAk>fw4y#* zS>$<)b#*e**TZD-1)GcWl(#7-&m7ODMDz7|-3jjDY0JjP z`Q8`)H+!~iYgUwwt}ZTo<(0hVt#50{57J_AhzRGt^s{qRFA#-0BYa-FWy za&2Q1Ew)KRsV3`BB>YIMr=!Rl&RxxwE0+<(bMUdF!))91G|xP`iNpI2Ql1QX@Q!Es z>fhbP)+hJ5MCY+AgxL6bI&m&&)hCep22|L;^AO+v>W{hk#ydH%=a9>}5m}-HU_@1D zK@`;_CAX2HQA89)X+5`0u~CxCqngtrO69FIjuMH8B1@FC5k=T2#M-EuOC(AXqt}5B zRVT?-XF;c-YyJxhe)uJW3EDY!>sL;54w+Wz<7jCH9lhw`M~l+Y_N|1E{uH#mNKo&r zxkH7wu3wMwijh^{ssvG_K}9vtNCH*yZKOeDHPA?XYsHTud~4OOgtkB^zO6*Q4aKWi z^|9)ORy|u$4=Y|JQjbWzu%gCVHMXKA6bz9VRYX-K3=tcJP76!iJsm(fGDfY6Dzf6N z74Pr^-{q;K8r_vW)g|XAr!qKcp~Nw&>H1_lXXlMXcBgg|CsMPpZSUHir*~i6TsZz` z%=&wV{K;@l&z3!1#pm{Q6!sk{_~R3S2_qvKds?fmWzhKfA=!j3mrPxwRq3(XD_oAV z$rx|Z%g_J$4>TKJ7&&E&#PXiKTUqj~-|zxt6W>6+MH$~jvpTu5+-+JVK(a54*4Sv{ zq5;2Ku6+4#UHrPs|L|jT`;YWGGeNMD}KKKVb zcHyO5V~msW%3601pL+X8*xYO^$;G_g#ODAvf1aiP^xwE-&vQ-v>kXE?Q{52#ku1;L zl(Y*cT19{4S^dpe%jl0Lb*ED&u~yL^x#edo??)4B1zl!4??TS-@(3B(V9T?zcS6|C3-}F}IE?n4ZZ~&Zf*4fONH?Lv& zQx82zST3K2AI-XvYCr21%;TLGpUbj=stnH9$T7A&@f6QKwu#YWBOE?B%D2Dx0N?u3 zeT*ELaBpEJl376Ni;AVNP}slc2)F#}oqYGpcd+NV1DV9+q%u~KwL}_|lo*Dny5%;` z;gLvHMNu5NkpK*}L@5+W;6@Bh60nl4tLFYlbBd^~iTd?)m0 z#^w#25e!eP=-jfmtFY@(M{sx~@FpgWsYFI>MtU{P2U7POQNOh^dFkscf4llY$E#lQ zlDE9J)fk(-s2DYor_QsWO$d^0tA#pfja4d0nDfGCxz6v=Mm8UyQD?cEZeDTWhcCS1 zC4cnszOF^TqSjlOS1)^9&*Uhc_QSsbp)@&*u~fWWhW2z4RYf{H?veN=K(=^g13D3Q|$V+kMomkz2Thp|KMY6`qqv7>(Rq3 zQp*Yv_I390+kf{XzEod!f2J$4^m*0O)`GA8n*uafAGW{J<+k-ln` z_&f_gPDJAKlPP_b=KX-08SsUW_hTkW&!L+4Ba8(&3o4Tvv2O=Ffyy;r;cs2RTKHit zl7$}tri_RR7X)384WmyU(C{*?9fH3{E0-75+_TUGDGW7M1!E}N#1|o~lg>v*vD=0< zT=J&k;2-yiKMADp1FA{Sj~9NVyE^_odGN!dDvdU6_>q)v1AZiVY_jmfRxql@XyhKK zQ~1%@IknvdAPA8Hs-j)fzm?Ec!Vln)+hr}(T`$?ITM?k|r#TwP`qfV1)Z`dyEHu^f)7jMo|)JDvgtlCrQhl zd=)l{z^DR}Y+es1Sw%HRNWI)uT2C{;L~F_=pA(s@6nr$XD9#;HZ{3T0I{Lk~PqFsT z`}PXV#8)148vIh@tygPj`Sd$FRr7u{pTnkTwCOq8eiKvn`h4g8n4+YPjiHAQV&>1U z)z@j(Y|A6qFWEilfo(kh2o(1x(y$^WcAXk{$p3r|8l`} zBe?usY1BhT_6e#dwPe4ipEb$-BXMpIr$CkL<2WfvMgj}Ks^W{NihH3V>90mwD$WU# zt@RH!T>b9^h`DV>H9RPLX zh^!SOCRL`=RDCLW{56`~gBUT@(6YFU!LgBa42hN&1{KA_Q;p}zWItt7ts7$?PDGzd zU}cYsSQ^V(@I(Pm(@tFjQ%hiB@O`5;mceq#&W)?%d8zv+{z}y$R8BuvC9vFjFGm8) z_kC^1`;j?g10c*42rAX{pa4(^VhJoLP?f-fBE{J0Rx0%?6BDTf764;o(50lvaCjJc zGZI)E_rp-W+u*bWR-@XCr$@p<0z>~>BgIHvIiO15s~Ap?2HLQE$zI(Az)HWn|vBQt7ojo|f zqTXI^-@Jt_2VL%1Rb~Iq-HaX`=8UtJQz#X<`{u`a`jO|j;@S-?S~7&Ha`ey`kKezU zXP?+X6h}`a`8QM*OB~S=M}UwfI8Tz7S7C@H3onu~Wb$}eNE4n@g(=Chs9MiXnd_t0 zRLRZzQS38x&TU`%s{Ql6y#h13sWIdxYH!)r&k+1*uTD;ZrswGF*{KFU60=8-5I%4( z!G$j&^$xW#GqZt`K3iECxeRrH4S9$jHo-;GIZqe>atKKE67fZ6-je7ydHej$Jd=LzAfqbF)3nT<= zAiysH0!avgKnMYXjcEphZHjRN7c9$FvMkB!U90W8x6C>3_s7iKJ9qBPy>nM9S(fzv zEbpC})25#}&v~9_*MUKuFf}Jk#iq&JB3KDav2f3YcbHi-kth#BJ5pFW^gOsj-KD{L z&tScRp#!$2OkD7hy?Zu%u(x|})kJe!fszuObC(kU@*~(!B|%W-s_i1kFzd|3NCGMc zl6LKM#UcnMUM$-|cKwP>s`CmVj1EJPV;A8KxeI`` zCZcNTCm%8ZNyIwjo~acAfC|Z@v}fQGNH3XTQ)PM$*kF>rs@m@-@F}>8k;~R__1>f%z<9#z9@uwc(`xwTI`QFkp^J7<)3;M`g6IVE&w1Q z&@!eCvrbunm1mxd^RKvO%IdSPc+;dQt3H2d|J2|8>qnD+`oc%>Z(sc+-gWnPFn_Sm zJr^NV)mrS2igYKXuVMoz!91^)??=@7DDb13k$lWn|DYJ1UBJ73qVjhYHG89awAL<` zyna0J1AqfQxb4s$_~9$RpqZA-)Rwbk`u~Z5WMu(7^Jm4Lw@WzESA}5Pyt1T$dfcG(|(@FR}z2NP2o_2C-3hGk*y@|9KVd%L=@bJNCG5B#VT zM-=?1*P=S$hZkwf#1#wX;?ntZko0*u4Gj!p)AQ@lbKnqIYwX|CgP(o-K|FNN)A-}B zpT{r0`!F`WxC6@efD6yhgB?J^cDy+puMeL@l_ziI$yI3uZEM%(gI&K6?Rs~VSszM! zOb-RkPCna{!g9SqlvXat;`>(zz_mksKZHeSnrLE_ESDM{NsqoCYloQ@2);T-`^i0e zrsty%ejLkfYdA&){D@Hv0X#5(;-4M|56A24h_+NFdEN4*Xi8;Rv%$=!R%~j`rna@o z3`5y4HM6O0n2NQbZ89|2fMx>)Hf&9XF4~3-l3Zj%DHh6RLo8^f)D`o_73*;_VhgHV4t<+u$&HW_5OwWP=xq_RECDqz=pl2wsZ|lOvO5o$8ltm zDat12q;?!gTRRV?&91(L9L@<*R7C#KXOCe}C507ukU1Ds{0m%=oVsk$Ww(r^?e!)i z9|}NfM^F0$JG2}9LYFg5&yXIR}TfAWl`*pT4v)5 zBi3(?`J9{{Bi*NNK=KD)#(n?wSxkA)-{WC3BG1YuT-|d3zhaHEn6W_FIInL%Zo2bx zu*?J=TX2^1JeuRCzvb`nr~mqAyj0BN4FC+*IQ8BiVo81&_pG?6{4BcnzhK^QJ|6%2 zKf!7pgJE2+bs(-2hRvlCgf$jcol{oxgY!U!+1TMGB14W zH`x8UEAdPq1<*5( zHeEcnb5a!$MMSU?Nwkb$sJ^YQ*=Wj`S6akh+hO??)IY;(xAb4U#U8`AO)- z`uaW_O(MQml5JgNNFaoT~o;Hwn;v}n+q4i*A*LL zy`Wi|54OS_@V8TFCJ+1wdVaV+OZ8|~E-wgvh+_!+VBfQ-A@D;B!MYOs=xZJ`e&6gl z?`I)f5hI3o?Z@7qJpi3QIx3~jW((#wpMs2WWV}8OCzK(PPbQ#+aHO$LGD1S*SO!1B z$I?e1{Ag-z#i{3=U!@(fbMr=QdExoe@?c*dwyu8>ecgvJrgJ>ZL;}w|{2=-cG@Vsc zTW!;Z0|b`@cM`N{aVr#ef)>}{P@J~71b25UP^86*OAE!_rNxVD@fO!V?^^$NwD-|I z$jZz!&pk8uMT_Iy-%eV|6Zq$6g|j2w4Hw3}qXD%LFi^(^%a9m3a>j~)kj~34G>e=m zipm?m3irvkn$8?8@>{rFvbMeWa9x}@p2)R72p2JT~ykSX0R%*fF0OFGNVZ#y9 zocPZzCVcAuhA9~VNy8=mU(sYsbfjMp$GpkdEh#rt`OFAmsR7<3R2P5HA(X>XvLO6a zQj6D{vp6kbv-b7(VGFRu0mG2Dq_)Sp7Ew<^hMV+EtF1aWVy>qZDjr?=McgQKsERw> zrbrv7vh;((X4UNKyC=5Ui9pvGCo_4s6Er{qEZtlwZsjvCVc|k*MrgxadOoUDPkNSz zyBq_L&kHo2l*qq0AIPx#Y#b^^u4$xG9WhSG4Acitu%T%@Fos%NeU%Y?8sbLJWm?vP z?yn>n@I5N`87zJF5kJ5yJ|mlG4&RtvXmOaWm&H z3PMQJwKLUY&h)UnlA+-njMd5SUOQw4?V6d4A@GvBLO85-wc9Y4)cH8Ir^=%~PdH@VP~y?n1wqM-uM zw?_PoTek9~O+>#!o>-yJwgZcvCy_7Qy7(^nzoT_~(QfEeYGv3s+YpHX_pax; z#`>T5vreRey{DKZmEw$JS)Z*a*z?;mgUnkJfHXix4ya zC$Sr8hUjNE^70zY=ZE2IJ$~tsUax>3BAJ3^1ef7?-!T>;mq@<#=zahjyR+^pj4bu@ zcvlK(rTYe{{%54fHO@iKDRH{1%;YWhzgd9BZ|la1PpyyHHU419$ECH6(~}29lZTbi z^s95^w~k)%D--D7Rp`+mIh2J|V_3dTI(R?h(?bt#OCb!S{Gs|IF=?2ZYKtwTaiUi-_orN~qS}cQE>yMlra%;VIkFFi*D=**4Snj8rF5J&z7UH_o zt|`#Tp}v`U!&Bo!2P6F8MMJHnWU%k(&;w_|=hE=}@St@qEvGBV{twu!7;h!-RBi0_ zfxuk(G6t7G>Zj6ow@XTJ@V%L1{H2D3S$alx-C_Fp&2j#7Y!m2-uC1k=$mj!Ket%WJ zYDF{c!Z%_}&*Qkolhk#^YN{VY1}t9COS9X1~-Ys%{LkdzpdMREmgkscFzNCfzSL#y}*VdlH4(C z9!FV@ETg(%p=_hnasg_iWCt-PLS)?%69a2b$FmAqK+nM8e9aQ2SxEECE@YwC=YG8? zv=ctAGYoY9h`$=xQ27gD8*}1Zvtof`6Cxs2+tsi<>Cn>TUjJ?zBbdkM0ngFZt7pjv z>Oi}%M)fHAh9pL3hLL^LOe@+@^VJbk#bj`9?1mk^=FqUmr=|}NRYMU%YAO>S7n96_~~MFuA&ngI6Pp`h%9px=Myu&rfH&hcK>q z-(EsICtP>(8@v43A;XYH=hc#<#stPiKlbfr?C6sS8N=6W#hD&cHyir&9zWL~bY82T zR?Jh=?*PvzcCZgawP%ag7^fLTUcCVWbv=JRXlzYiPjo%NZ#6z_Y+%1}CnWUra}X8} ze(_Rm3oWzktZu`?9|Hg*UVGk`{N&2C3W=A)RjKz*J|C{x+R`Ih`#>%q#4T|jeRwvm z7!+MK_;fbd(t%j~X7L~jV47*|v@CY?H{%F7N~}FwfRu{6e1@9u`)XB=yyzs^fT(<( zCJTcmft5bdGcKGj%sIG~zv>j1TN{R%I>pvSkT;)Rg_fBtU zRv+#m7QQ;mpGsNm?B!5dYa&h+qYivXZV2`7MmmpSqf6fL zu=W@Dcd`bT_lA%Czi(G;=tdbwuF(J<_PMXY%b9eDd=!Q+Lws_> z{BYlsU|~`%K1eP{Ik1LNFxZjj#AwF9J-u9;r9I9%(x*Ru(X_n%(fMqPl4E zt1xNb{2Ax!_dl=!?X8)WN?Gj}8+w*9mJUy|LO@JLbjL0Wo-Kc^6~$+|Q+NLm$Ohw4 z(_2^S`RHhVTfOSFzni!eN4ORat=v{N%L{ii-zzBZ%{caIjL>`W#EU4s&!Y!FQS;-h zE5@THs-E=*y&j`mPB_%(?7z6Gm+=VnrdSqoky-1etDU2u8ndVkTClMZDU7t7yje+Y zsV_3n%}&eg#!saE#6Bk~6&2C^jWgfokVxc{6FF<0E_!a*H}NVhvd(e>h1OH#1!E|V z-%`~)p5=y6QbUO?1zyJ97BUFDA#~r0-@SinW{AJi8L6*jlc9C>7*+6MfEdaiZ7SzJ zp1O`DSytg;lrp?+ocXed_aJW0ny;Z;Ah&ABdM-lS`fVvp&)WW2$woSLBN(bYc-)X1y*ufo*FR>p@9)bn_crs-rc>0l z_;^L@_B2OUmh*YOV-nSC@(k;RG=dN;*J~R}7U9)4njT9f{SaqL{*FJyKMDLHdI70} zX+7FR0z_<_JJfAasA@61O!a(L8p`?a?y58Mf7~1wjFt>`pl|!1)=Kq@O+%iVas)*i zsVw!HFwgS8@SafD4U5HoEdQq8SHitSzIpfNjtEUSs&DWWeMc~&nhI@BuUYcS+3!a7ag1yoP164Wr-L8}yg(S@osfKU8skA( zPJR@OE>(IOXqI$x5P0?B|M2%BcB$y7S2aUML#-REFndwQYJf?~wTt(q3*!uf<|1ESQj1E z?OQNVP%3FEbdNg`oBP!4gF)c;!FRCZJox+T(zw@{Z{~vOX7{Q2N{;KLXbxnA{mE?s z4HY+;3Tqk-TO%K*G}hL^Y{2Egz-sez`K>YXmX z6kkd@PA^LqsI;_e5&g>6`xB-Z1g#LF$3)SBMrrSCsR7dN)yRF8?GeDbuc54c0ooCS zIyASRlOCh&4NSR{YF|;uwa)Hs)=9Ce&PtFCO*44)#WI#>@pw!q20b#puu9uJyYH*1 ziyD1ueZ9R9M+W!{AKO|L2>JJJk%{wUDb$?DiU9!LC>?G%i$L>pQ*Z&VF-PB<)w=&` zmRc;k8Pay)=b~}8! zul-M0Xi@{8cmYg=#DHP^^w||p;wOzYdVjj~$M8Jx0xGmru*{ERFs}dp`7XA#GHt{r zDC|c$HHwt@Ritp({Q~XgC^Aoh-bOq`gQRbg(}s4DH96o#oM;<&H7nS zu5&Jgu9NL#EJw{MZf7 zBj%`i#{%TK5|QWd=EdmOFH6lQ!!IgOlCst@0aYCr9WDEOu*zuI$6wViz$VY1e$hD`8TT_#JdS5-^t|y9iMu#xEJ9(q-8^S8=ws z`Vg{oZG8;Jp#NnSxHspbzm*=BQ0E=@c>(KB`C4-lF!|cSs{d#8w`nx}!^N4Yh*y*I z3OUTcxc*W4f%w?;Jj{Q$5BZbrg>CO1nHDlaoER3Ew3vvR)0~KhKP5S-hQ=gWr^1)P zI$=;_mM^T)={%**2vR)l2x%26YuxS;9%a=eqO#e?S)x2^Z63q6k3c61I6Xc-Af!7s z-pp=&@)A>R z*RetVe-%L(^VCE~*9HXs94O5@5xFj# zVY4~A6B36Zu=*VtA_jT6F}L=eCMb(-gx^CW1|EYchFBDKUryI{z_~~R&_GGHVGasT zO(V$0kt!F*A3W@FpNDgGh2(!Pg<_=c?QNu~xtLDzguP!<>LcI?%~J6Z7)mqZ;RW&w zbV12NvYO!bQV5DMf>rD;0VV$AEerarCNeM>2IMkv#YHTlz=2|9lzk!SsT*KfPI^J0 zL6<`+nBe1|59~BSc(!EPnS>fhb0=9GJr!vg9^7uCF%>lM7-|SgHv*#pjxhXwfYL3) zgO*YRpjQ^N;gcQF&Q{^WZ8f8msSSezssLF$f(ATzwN{qBW7>RORV2{tZ2V!2P}+NZ z+X!p4u_TP;kqGNy9uq>TWq8IIq8lU2nHnCt7}h-oA9U_jbELpq#%So~$rtFiBpid! z3Ycg~ry}`x*0vh38pA@9eA_>59pqhy+9lg|*0XIWl8MEQ z0^r|0UWtqRK==+tN~H>W)bE~q`fn-)YJA!oM-%=2A3X#M*~c#GTh7Jla(^pwe=F8LTkojZ=c=6&(? zg812;aWpLBiZ@+~?brJiVt_zy`G z^fw#7v@jnEF}f2^GOpM#ZO2;Kgl^6+?utVa*1y-PyZaW$~Spbwo zst%%OXuuLKVtuacMBLqpumg#$$jAtHw@I@L$e##PR?EU5tp0Y>zZdYyn%>kJZMwtW z&Fz7e!yKD~|u-6;iMkEnD`acp>0&$q107S|zWxkbD-nSp8j>@`fc@soiGLvXP~J z?B#Okur+#WHh$?4T(3;enl)FARmdRK!cl00Pnsn4A`7}S37lp+W{6eTsTFcw3GA%C zNYXn2{smleyd-8C0flAPTAYr|{h@i$3z;2A%={gSy(Oj5BeGyeiPl?I>nx2|VIAD{ z4W?*}gbdYJZ@FfRwJm|Re_01ZDa~;l|Bj`P?-l$js?;#`=-gxO5hwG)BBz+qos@Tll&<(K(1TBbQ5{Ab^~&9E%tfE; zN>N9gf?vbr6ckkTZnVRd(X;)Yq5WhS6Ui6M8;^?)M}49LWKGv|eZm*+K)Z@R?J|D} z+t`sIC_sTmMxNK;5@%ig7{BRT7*4PG3OVg%oDEjII^xU}COS>@O{)p=ePQNh59;Va z+I4@U{rvkP*^P1U%g{IOLu!fO%sW4~Vc{n-{R__xQ%^#>?tC3?JaJ)9R0+R-lIz!` z*^CPit${r)WaIMJITqV)gc-`z23IBDaYNq;>ur#Cr>SQo8}@M6KWeDGrvZZsVN8zH z7wd?$1%{q%t)J7p1X}|iHh;d+4+ai*d|X{@^K>rw@ow@JQdB!99$4x&n` zI5>tv%)){p3@kU@$ckmeU_DY;6t)ZnJ;13+*!_OZ2su2D8Mg358|a*^3LZ{f?k|Zb zgE$5Ztav!YaQVKrJ~)b`rBRHP(5K)Go6yZ^@uW)TxC?YAiu5k&E;8bX6CpzumMaVy zcm7qldMEiBrEOpA8Xo}x)b7XeSJso@qC0uNdOx8oudGP=5VaO_=9}Pt)(eSciR*1_ zCR=%2Q56voh_ft;`Y8LFl>|pg*rq5w!a^l0f|FOe(H22F)ia49JxmV#>hld_;l&4C z)K~taZl#qy);K?OlQ9`-9+Ft-#a6=_H-9@uN*d6K%ti9*z2vO0_d0GC)SK3#=z+M) z7d!X{!VnNf2jk*$EAh87vDOifo9}qC=viPD1d5z%WaD zY@!%IdEv^r<_v-dTZjS!kdB!IE!>ACMhFj60`Njitv~-W1Hw^JOWvi})GNVL1-p+eKx0geay2+jb5hnjetBlUrlr7Lr%w#oi#5 z*G{_EkS8e^u$0od*kU&u>4$l(w;;5PlZMA5-L6T*L~5{D$VwJPt_*nMJ7Qps`?bN% zkqwLy^vB&*dtK}>a52lR#%%mDjR}@%r&aWCUnvA-BHY*~i6pB;IFt+gBs)@t^+huE zhmNd?AHF#=14C|ob_rg&vAt9qQDR4R^Ei{5xvwy-*jgUxj<*?9rd9i6j@9vJ@&p~y zZ%#4ZK1`d+Iu7<86pWGNo=VF{e{>0rolz5@n%W#VQ6HIe6|v)CEU9_23%@BD?@$DO zsfE{B4f0(bSDJhy?Rx(lBS^6r_4gd|f&{>){qLW`BBVy43b0-<@MzvCf9)*1i7$Ce z_N2)6klkXo++*N> z=cjX1w21ym<~QEotBD;azSB6qdZCZHxmuOR`mM@nMqf*7G_)5&I-}q51v~I3JV;I+ zdDa>PR0Hm16TlBx%PfMdtt~R|etnNC*%Tw@GQaf+wExZFxzP(_4Wc3JGkf{eKmW4` zy(W{Z05VxGS!L37kh5(HFOga~Ih~;_EaExq#U-nc;o1s@th#H;6CaFZcL%^|74%VtJkV3?i{Nmt@`LEU*I`$PJy*Vsvg$?Y+wzt#1T#Yw^& zYowWXK^V}cDOdK5(zYjzi<$FH8dFWy=!|Z{xijVZ8S?#G59bf3tdrZ|n*fQoa&GK( z)GFcQo1XrXaodg{B&u4jdBvUL!OK^-5tOo*Ko)0KjWUc@h!$Y-TNQ7=Le#)81%zlCbmt$c8p@6 zNVd-7W89s)3<}hJ^D67{E91fAIiFPg=7&R>k&fd-3W+TS6R*R|n;7kcG*W)`+kNz# zuE~gV=Ab3f;Py%U4eC+jI@dz-HIyVB`S!!vd8?J!#0}aOe{5N^SCaR|mD2Bye2)?* z+tE)cjt2MEFDSnozd9?@@NYU&CVJr^C>8HBnv~muCx#=c$$G=9as+~|_PVrspP|oD zZAVGUV1-np6Uj~Z6Os>6j1kIp8wxRX^I>PO!KuQ+cB~?S;!>Oq?F4dDDpC$1GpISV z;F2+%a-fn?jxmqzFdwI}FMAji51+u+>u4o#cdpuaVx@kEbmg4e*qP|9EJL^;m$SjU zKiS^?=QtPb$k;EPcQKLMGB|(4($F(>Ra%r@0}Zwm8{MhgEI`bBdwIHW-j^mn9UDcB z2Wj4FEUx1$T|&JtHE@2I8*^#56xa$mS5!cx=(GV{ffja=hFpJLPYe4nxGknG^1`bY zAZ04ein3*UQ7C~xhL<;5$)5?&dM6*?;6<7D!Zu>plUcOOXYKdVdsB}$|J+j&L|_(h zPfwwo@r=9Z#H}eAIBR~05=+w1PVx}>AG;W=1L|%j&&H3G2s-)U0gWHgy85V00~TYh%=X0 zD)f%`;*ooo$GvY0`^9OgY)<<`Y)gW%6F{E|OiX(9Kh<%zxwnczy~6kUY>1;`>@PcH zFUL@!nC`z|54GTkVtaFF=c>k%I?rXEci+9VcL}$kn1V_(gXP#6XaUl2A~=5u3duhN z3|vU+#I{&lDGjdgqQm+GkV3j5Lt%456cM-~fGOna;q5_McIp}?YU8*J#T1-97@DKC zfhqF^CB%D~zV5S^UKO_R3$%SF*H8G%+VyRcb~IGA*3Y$U4dtJjVGNPW`nJJ<6JAeg za1EX!PUVBmUNCg*$O`!tbW~{am|5V!fvd^&!j`1ZP^ZKYDt6s^9BCPlGytkp%$elF zKXH`Be;B7qWV`zz1m0>!)3k1qz)BL+G^D`@oT5K{@Zg0Qq%{h*<&~-h zHhz)3u7a*L1EqB^xN$BFQ2D736}$b&xq6uBauI}MGZ%#cwFFRJ4l%5LWwj@wk4rNu zjQxbF+-%wCC-5nX*wNb$guvd&RVR{S*b4h5W2SnPs8I6@dfyAlG{gOH(B%F67uZaO zbAtz9-#%O9;DX(Kj&yV6Vi{VZTM5_|G4WW32I45RX}4}FK8KjQn#We2-n=HjnDv5S zNe(bt1o{7C%o3f7=k7Y-a4KjZaeeBt(-b_TiZeO_A$gBW`||lNoA&jRG4h&kQh!*u zxd9f-c8Q34Exa?Nei?x+?H;s-}jk-wb^}aKU?0ldOFAV6(7(9`sYze9=_%*|+JJZ$S|CeHL@)IK=le zhDsn=$d_kWv5y+X4N9-uxK+N;O*cs6Ze+21|Epm(ttIks_DBBiU7*BALZD<=Qi3p@ zA_6ip9dy-|*ilwC@z}82ZjL)m^X*N?e&CVed&ygwyb{KQxa97P z#Wq3>m`jPy^EXFpipr;&$BBa^%L12>S_IiNAvEi9M0URyF zoa1W3t#GknE6eBO*49=4WUzByI@NtVNLm0xPUU@3q}nR!9O2 zqcgyVKSqVVU{nmM^o|&>7h$TyqZa90*%YB*I5%Puh8z(?!finz0$q1sh%ILHZB?MZ zU8M9Xjr8Pyli;(6IPru7I2iwAe#p!InAj67QuT*%l*;CeQG(}PS{I0$LX*1_3qfB7 zt2Bo>@@2QWEcQHrJ_bsI7Qyf?bm=s-kS;W7EH_G88*m?Yq)jf7G`Pe7o|TcRk)`gb zN_5B&4aKT=oa{J0&bKO1vm;WC{=y4p+7{tKx%ag#!STGinHQuj1Wqf}icykc2r*>{Ti23-ju1ja(#C)NM)q<| zoewJiK(+g@?Di_AuUjKn>E)e5ZBZ`*<_E zytlsjI`{mYEzCB2hg%|Y7G-5iLwM;Z(V5zf(S)?ro!_l@{5dW@$|CS25gGE_3bBub zgE#GFNPZRf>F=MT<6PC-H~wIf%x(}pma;0e;5wK>A_xpxfpclrV#_lpaflpp_F5pa zA`mvECdl?hX^&sD~q zE+Yf+)Xz@6OZeVT!`)4v%@M{LZC_@3`$2(nb&?5U2bFLi#@k}3kwnYByvC? zF!}U*JMLBb)2p(m?d$poR-ItTm#ast5C|jh>+47$oOMmK93>F&a=FC)EHq1c34`sW zUtm}W3d=!xwly?yERp|K^I<- zo~uk@IRVxZCe#7-oVe`R4ERxrGIIgT^2<+-*DgnaHvFD0O9r;(ai}+199!pDf!=Jp zagK`b*n|Dd77*PsDE%^okFS3W35Y_K)Y&Lfr25p?6dl18Hec6MJ7%g(kzEY@FVrf! zpkXW&>jBlFtQmd5;%pRq zUV|xBmj$(ivFCe_{*{;YstS(n3^LN9hNDIUN zRXNGwa2QahW88!mb(Lq&WAyY~t(IdeH0(RAr>ECv5griF5il$z< z%i^tE$D@GQnkB(`e`mK(i>^sq`aP_#uReG$BuNJ}`^5z!z+^3`xzm;i962UoQV9c< zE})o%*x=w7m8Y$#o|Ye`Q&*v6Oc|w~<#x1n#u{}adRg3Ol$rxl%+j^kEK9#EnfF0t zu;x^B3qc>!T1F0(QnAiAlH9h%e(;4SV$^6tqqm3rlnLwgBP`r_-%>P0=wzr4II>dp zDSxu!dD{!9D0_Piu&0ez(TI>##{w|Dyx+Pio=vZ!EFMNiy$0s_+I*9RqPg%1V5%g> z`+ok3o5jTk?E07q`NYk>b}elAIBvI|hp(~e!V!Ebv9^PN1m0GP93_G}=^*1DU5cIIpNV+8K$7>p$O&}(D@6l=o+khzymG4ZvVTKX?&nD`mC+mQ zZ2&eCUPuywRWa&A6hKa8ho?xBgq2<9>w2vWUhgF_FAY2luM>nNorRi_7=S8rY>~+o z!VV$yGQ`3n$`Z9=v7O9A2WSExotIVjBiwX?=Wmlu#c zeNmpx(AHU?v$@(+ba++d{n~$W8rZj6NpyT2_QU?619C)7O&N`}AP>A*gb)Ep{09!3 zxp->cnbCJ{xy$H5jkVLLY1=_3fkRwIk-kkU$H3_mjNtfv2kvI`a6A!$L;C zp=t(0cKOH6v(41R`z{b)Ve>VwF!gr4Th zLk>kk1*|~1{7x&-LzL2M)U)2$iCxas=C{}tOBjWc zAg8Dj5C15K_+tLX7W)n;%vAYKN}Q6T{n`0|0E1Im6zx1@-Ze{Uwe z5XTA*)8dLG#R&l~xGfWt0}l>Qj!%zI{AxeIMwxSHL}@@kHc7)u=_J-S7qV!n>Ny3% z6tr9pBYXJMlGahH(y9czC9F#!L}ebB9kd!>l9err=-D{w;}1T6^u0BIcuIB+`rY}Y zMEMER>ii=1Gc3D(ze0|oDMbqYInnTst?x%F3vqOGwTKu0egcw%yZc~AK~6r!cTf2i z+Hyxcs0I!UhOb3xbh6JG)&r^M;9hBe>li2paZ5hBVk)R^vIPqCiEEvAC4Oml$DiMl zcUFBbj4$XCAwjf&R?8WSTl98FV((wXr)?$#3LZl&Ui~88^)*O9XG8*!A8&oL{UR}` zYQ>RT{fMpL14A6s`;tY7`^+sP!95zF`P;#XNZ49DW$b+D6gr^F?I}RA=f`|rM1@vu zen)-h6~$G@KVp$niAZT}LiYs-#0Sk~3?IpLY1w#MUX5rt6v~>y1&mSLYY4+_3{oE3 zpq&ryV;#q~dDn~AR+p!z4tQH%hM&5oZGyZl_At!P(I}`UTs5=ZlLbt>y3wg*xjVzi!>`Jb0-CskI_Lb)GKd*~F(X_;g)a>!B zf%t(BQH%jQb&}%5?%c{JuVYezOvE_`H1;P@FsX2^va`NKZI#lX!5m17pPp&C^CZgQWLa$yc%iacWt%U z1vHAWaW%o zo@eojc=Z5H#J{51H8)vFzvCaE#vn2ZZx((_@$e-CGX1UM4}pVv{$&_?rA8z;y#~d0 z0J-=sWO>GztYUF8v!i?1c6HLdT5T*#rDIBj-BZ42PJt5$Tuy?0uDdvT=RWbvRZdk= zvG6F$6GFbOIArQhu^xHN@0`5=O3A+pJ!hBeNN6e^H(_Xm;5LJU3AgC8PU7FhmS08zz zmnGQ6OKur{lsoIywBg2mmW8_IRD7cPQ_==)Vu+_3ZCKaJ5mj}j65^=xZzY10)Q5^ledw+kvjgR~ntg79h^V{-T^~Y*# zY~b2%jbI8{Sm|_l1rj0i$Em^s1TCOYhHeiPK*5E1wQdLT7hb*3KHYQy=pt|OO2S)_ zkCATJfTP6_F^M~Z6(LWek97O8_nO>fAkZe!^1$00;H9Ta|5;5?)T!w|7k}Sjd4hJT z{-?9K$brhPr!xk93S?e5K!a#WL4^-xmVk$kWD^nKg6cH0y&e zYsl0J4D8Fi6th1%;{QeV^a7BJiVp^9YLmrXAVahVtPJvtM<{(>0B9vQeLeCEhNMAK zb$B7*CYj&bcW>oZn4>o?T z;h%aG^`F2fR=cUk`YIUswK)h5`**J8!0C+$w6I`fyz z>h8FvyDh0zL6=vu(5;iw{BBYiikO?j7M}drY`InD?0Dr{sW=M$J&9_FBuY8VitU-% zF!OQHvY>?aAO@Q|7CCF7y_>Q6|Te-@cQvpJP(eY0_n5p%39qy5lD! z;ouuuXU$PGDU)ZjGpR1uic+XNSKr$ZaNQ0A&;RRn3z{n(W0eUbAJU4ZQ7KMh+zAn& z!9;ma6CaasDsnPjyE$V1nq;3#-mvedr3q)8L8qVs=*$N3$7_(Ck+i|@I~UV$-JtLj zyTD)wWF>YUB@0m4RD(JH`&?Jtx3_wsiT{(6Mubb@f`wH^EMIRZ^8&UtjR{-3SYM!UPn<4-n&@3q9KFPc9& z!>A%iC?-T*2_>zVumXXPuiHD1RLt49;L8LeJurlE27O+qHkOhy4_=6cNIjPr0bQR| z5Co_B1#MAblY-x%2<)R!!}0BlYqKVcxj@^Nh z8oZd{rzFJR<3yUGQ%nGsp=}VwS-TWcz#fBIWRZ42#-Nnwfvrc0?H~a@3Lrf^xZ|<*`U<;+n*z= z6-gYj2SPG#m4kA#WhHwo$dTr@3)hnvwyTQK~Y`I+#I!Dr&yzag>7&JJG}ESKfQeVzkqLs@oocf#j0oL#!h$xRFd zzqI-tax7e|@CRdrXQnwgbXVYVV}GLyMk*UmC$dR0GE}Q?eqJl3q7s))BEYDaUi!YD z=BS_&*nwedj;Thu(-~?O#`>VNIn8E|#xF`z9Qey~fL3dNI@`C#ov){j(|7+UcLD{} z1T1W5pW~9##p{7hUyBraMsO(fj_vG=-K%mw4vN{HbLZ^ebGXF%8>*AczWXWC(4l*` z9;nHVHX`(^T1DVR%D{qC#m&r<3xdY87TR_BfyMP`$;SkM=OreK!{Z=@8v@5CLzNMm z^=uz@$f49u;-44<;7YL~!T?by3@2hg{opG%32YG#jc>4jLm4)1VswVkZZS7D63F>2 z28(ZthJ_hqo;p;TLn&D%9YwQ1|4OgE7jhQ6Z6$q|Gwmu`po^~?L_&% z8t?0c3}sj065ePj(k`PN!QCUoJ5ygMLE8xFQ@~X-4>p$P)!d>+$f5ZkI+^P$_Dg*% zpmYMB9<$1J+wySRC9r{mad*eACjaDzwuIe@q(?J<9&ZX??&mzr2_gNMSbv*W$8dZG zX_J@aCrsE8&|wo_xOV`jR>q~r;%?QCEe`)(S{+n(^6p5rr(|O8MZ&e0c zdrX1wZ5&48>l>a1exD|PCKLe9HtYd@dV_NcMD589QYNS@u};_&QRee2_}z`GCWVD> zfAHivS2xE4l)cYqMK5e>fN9su<`SL+^&CWEbN}d0NL1}|>*rFsoo2&UQerJd;aa&( zCer?{)GS5;Ee*4qbCH!%nO_F3=Bc2ml*iN&m#RpjP#~QBLOE(tO0+S^O>ttd0U6Ps z+IrXx5a=X0=uGhRq%{B4etjfvr0496M|(_aiI<&@hDJ_k6p-g-=;-Lk$+Lg8?3$Q* z)S9qG2l#f}eD}I`S=Lvz23OgOX{V+vvC!CYU~HB;`6M7Hx|_CUeIlM4PRVbJqJ)pX z!S(z|D(>~DSSMN%4`5$}w6*m}TXtS!0va1bx&1It{MKLAn)V@0(d!VgkQ;1myH0En zIwesA`j|cmk32_aYM>ThgSXx9y?U zx?;b%))OwW1+R_TOfhJmv&_$EHk`a8X8Fi?*O61N93RdAyP92u+^dkwoU?!*}8M0OQFuV z*!>}bL$+At4?Hd02Hvu~$>Pkd5R2*iBaHX28(Gw62<2lJLwv^n!DF@*(WQBcMKcF) zIs##@f5r}vWn~S+{Rb%;g@ozTVO>#hB2mH#&nOzXa-}zpe$_;*N1&dJhuBE8z%ZL+ zZ3buNsbqC46`|O3JnN>2{Lx}4dh11zUh&hb^S7apV`3KghC^j#vx`X^nP0POJZtsU z?F+!@#A^`O@iFOPHl@bXodk);x4XS?M892LIImTuvPJI40F1=7YgH%XYX%|7Yfgfr z)o^Q;SlGMRP9=cUeONRUj3mUFu9CPXsoS6Rn#Q%yW9<)>@D~5THwJxRbmhq0*@#oB zMdsVDDcR9)m5!TrU4D(}rceNqTr!oKl_DRt?Ccy}zWNo)B&ck)_>UfpV z1%kRPZ<_WMuQg-v{|dYmtSy?z=V9ODcY5=p4DLi2?>Bg{%;(mR=BeGiGBQ6;kM6c(?yM z3?^K9-HZYVTY2O@PULs##VaHOFs$?SOWBhE2v0=gQKc5tiqVS&#@5lKz}N_Y3I_vN zEHy}AK`;V@3I+Eh(-NaLd$!C0rA8Wa7}|O1w3H{$(V(noQ1vi0CW@-t(z+dWI6%`#i6@Rr{DCVb@qIeq00n-M+Oc+zoQ*y$v5Wz5BWd_ zzhlN%;<@2te-!uugbZ#=kTB8Ty=T%bEv>EO zNnS~VkV=$2K7=carMc|!p%pM^MmsWT%j-0h>Cvu_M>=Jqqb-XmlUguu)>tfCI3Ba6 zwV`ut7OA8K&469hRbYqomP@P=_iyQ+Bh|$Klm>=uVDqkn=s$r#%?9xbh%r#$+rJ(u=%7uHNY#r3BNxqmru-YVE1zNeWMpve2bj`UTq4zHf7 zb&j-k{pU;w_z@<374~HkEL-{*6hIy6DSw-eRsSZWxf9M zzB9As^j?#kb8?cC-bhGDKtVc$CWum$B7$CfyK?o13O262T+8)>Tx_6M5xWSY6h%4- zkc4zX`sq1!cW37P{{EPzDJ}_-7hke3*@pF>~SMYeMQDXm>lpUita~V@WUJcT+~;7;0FM3Ju7-1 z27YMd1wT~P06zrhOwVwMbmBx{svu4p=Nf6!p1BJz&6Jfd^*x9#8{M!C{eOERO3|XM zG2Vn(m9xO3sOTQ$#sE}JrVP+yU>NP1j@D!nt@X92t}I79rbKr5c-*zliEM~>D%{P> zLVU?A=TGj>V5d!~!4LOX80Uy55~!^xM|))zT41~f)l?cP=h?|m0rqmh{KS|503ZNK zL_t)89{{lYq*G8{l^gw$Nu}`k{r5uX{;~BTM-vP{ZBr8#tvSI{WY?yRcxlV#{O5%k z`XR@hc(P|H=I$+<@$5ey&Y9*_k92)4y_@UvDOE&as zM92l}DI8cV?|tE4+j}ke+!4XIMznrBW6!+-t*x?{f_W`X*fV?xW9bZtjHnNbUdB2t zzK@sS$3@^634rjq4CN$4d9w^T$sJCTLfg-m=`9p|UlwlhN)9PZx1>PtcTr;tc*Y$5 zF>_TZ@HmI{Q~I$LQ>no2!=B|KbqXF?*yR*dD5Q?)?*p%>0xQo?2g)1E%UN8Ov>gK@ z`9Kgb69j=51YsmV++NjfxH>HmgqXbqNoQaN2tokBCdMbmtE;Qa6Uo^0?23B;0*sq9 zOYTSz%Lu@>gR5#)JyCL>PfKkaD|)JNU?`2MG8tzd+lXb|RS*R99Wqpd%i>tXKG<7v6v9!Ail}QP`!(O%F)$?jlSE=BjPu|L&YRqmg$Ns^z zFO}foT1=6!c~?J`$2Cz~rD_e;X|1wc*JFwx&dlTPLNuI@Z6hGTMUUkHL6|EF1PF=( zF|I5IS&sMA*R<{2yZ;3{478XikX1|0TeNJ!S?{W@Zh4a|$t})zxdklvMu0e8P8P6` zMNAympaTFAhF&}vIOPB!W*e3`d^RoHh93Z8+yX|_h+WJ26(_gj117najcAIL-yJ++BCSWiC_a9RxiXDNC*>H zG7pr(^6adK}hIm8(q@tpNuzw7wbOIoQcntu_Z?9>9M6{`l{-`YCJ20yFd5}3- zr?34OGAmw(w_koD4yr0X06?A`$Bm!640qjdhapDZX_hTS`@@qy0yeIIec@;L(T!K4 zcd!q)14ybFT>69mK-1bQaK)NS4GHp;3|2L6v~&Geu@1mGzc!r!%-ZYFziSIVx@QOe z005%{SXBZ1-B~^~`lAGt`0nVBAoGj3nZznNusW{9NnEpx~2&XA4+5RPzu8%#^14V zHA|Ic10jyTJnPL*X@uQ<{g{}TfNn;6=#HolMgkJkp_x3|f&@qiG&Q&4lrzuoc>3{w z-ubg{ZvWcF@5N8u$E*rD`y=`96UGr z0|)>=>@nr)egwT3G>tf9pjwh9uacT?{zGP9{Z2~1haB$`0+bi^)H`oU9hm)=Skt#^ zIZwNFKb*6$sG{fYnVSdv@X`GU0za5mI`9KzfNd7|A)xa;bLL-^E-zmha2RuJbi;P^ z-T#;?w!3uJo}7khW$jbb_z^To2-J^FpmA&*<&2@avK&=)HQ*jSk7)La20vT{{ryk* z>-klbB#x@;YE%K}&@_x3I)sB`qN=67jpI(Fn`r*PZ3R1vFXVt^84P*glXNgJ=d)e0vjItr>jnOYv0c8 zI5g0QRcD-y%G%m&3C2+0+=7Dv5iPHQAAv3V?s`Iz@s?v2;V+xFW8;BdkhR3rG(j+g zTitVe+p!QS82~}oy^npyfr>^May+}T*k58b&#{Q~WfJASEZmsPpd`c9aSLkC{@>wR zo<@r3<4A!YD;K>E@4e*X_|ok+;Q4LQXfltO=y{=~BRp~nX)?-t)YpW7_WaY3mn;XX z%TKDVteDgfI<*b5*}!KR1;KoE>Uvgx?I<7A}k#3b1iH-{1B!^~3}wi`MLCi`fM zSZ4d$MRr_%Z^9hSkWj&mtXtoG=(!X;4sRS%T`CB3ym-dzL)-;G<{t_YaaIY{NE!+Q3`8xZQuAq+|xW0=Q3uj_SZF>^84HI`~UljQPjh&6Sbc< z?9E@w$Ht96ha3H&MWDX&Gu7dE&txWEw1EZ24cRed!4J-|lvqwMV$c2&6XbA%AIwhA zhMig~A(;K43^J&*n(E8Z)7^ko%ckMXH_XQQXUxS(Yr3##UK84ys!*0tATbWfj1I8| zKA{N%{Ft1y0gvoI9YPn#XaX5k*j(DyKN13xBxCui<73^OultWXznu8yp6%I~K0jch zDB<$}3!}dBvtp^QB)`Zb6i$6*&14kW8#m%dedW~sa256kKYXG;gdpYyV9u56{445%|Fw$E=E3uXyky znNcx)a2N~s9Yjw?MQ432I@()MQ&st|3w}5}g1#kuW}-pPcyCfRLsDeaHq>Ko=M1cD zX~r^ew2n_89;Tg<&r#(+;5=iBlFo9Pnb9-XQ%Ki!Y=8dQkoH2(9s`=E&p>0l_kP;8 zem&BuiJTfi$D0ADZEE(k(YyO4WF{xQ6&yduM@I0E-~R?9g9CQfj_1~6)02+{j63vd zL?PfuSpKU8{IIha!)fzo;e_r^IAx(M69iw{DgdxKImkcRZbP`1vzk`kXheQ+$@nG< zdNqU|i%4HGuA@@InNYmqC;&eKZopDb_(}@%R@p-9DJCv?t;t(e|QLdb%cOd2UfP)H|PCsK5sDMY#~ zG^XgpBu(fs2qtS9$(lwoG)O`~5~`3j0f`CDRb7*HjUP?3-@tF0_2ud5{qSz_3U2NAd6f+ zC~t#|=hVxdHxccQvgxOIdH2j?|GiqNwnkP7FV%2nNZWs(2{^X?~*yRZ2s^1+J>Tnz@itA*~rw16P;Dw^|vBD&_^ zrUuJ%~Pco-_Jm z+h8>94?EqA{;(73fd6*~p7_Q)aOTbp_$3iKgut?A?!&z!1GwnJH{!*RVFJjF{z#d? z!{%pkp_Nu$g&actBNF`)p`1JVLoprinkm>mnI74~8DDNuUNOc&f`KW_ro3W|Ly;MX zvT6Gdj6u@{WGSn~VLK+s3NK{_2*RvfGqjapuUIkiZ5C6+6d4V5G8$^j!MZpY2T~~= zqho0t8a4jy>z~A)-ae#KlLpvfik(~Fh8GZVq*HdAgh1Q0X{fHQKKaq#J$9dv`u=;> zDY$$3BIoNMm-@IZ!oJ5XZPZ~7yPx|1ucBL}kI5S@V2;dbx zcSnP``}U*0vdja1INM@ie&7eUqPK~d9Vrq3evsgd9N>qhYg`bRt}_WFF%raxh-oJH zaiF97r19#y(>({!$0lFekKRB1-Q;a8t;tM6Pt_b$%K7=Nk49qvswXDVI696RT}Mq- zr4j8BL|$A_+X2p4*DrU0DBwq6Uex|_{IkJh2?sy&CHarl)1s?PJXwa;WEq-u9V3H7 zI50YbJ^-VMxV=Kr-{CJJc8nZo?bFmF-7798%mO2MHbCVOYTjH?m0zgB%Zfb`{Z4F=Gq30i&GrqPsZEM*T`M z#_;a9T#t9Z<$619GChf%dp#ZwPrZUIq)PNxTZFr`Bh;hg|7vMxYw(tIDZEf``B`((!D7%o2!8a0w1fXfLDffK} zB7FAF9X9QiW!v{p-~-=(0h*qDnmxUJ1l8p-Ucaywv)an=3wYaMSV<{aK2?@)(E3tXcxSiM2ZU7>iUdpCTg>i{P*BHy_jH@bVLYRltnqoWX zj6eooqNUqlMHP6WKo~cpMY8=^ixC|uj>dCMFoRE+%gU^!t1o!#gAe`Sb}KIdAmu14 z%V4V)U35%+P3xN!DbWQ}GQ#hEBmpo9V4OfsoI>P_kBD}EXX%Lm##k;+lBWx@xa0iB z?WjtmGb`f32D-`@#4q)R{48&n>@T0TH zcE0uRXn+5gy%8DTzX{Xc`AzHrfa|`Ft#^C@XFUHPejx-FkwDk>r|{=5egv0X|J7U# zl6>}^kK(wA5qt~)ILD@U-GGN8RWzSOrHKBp9PCkr&;2Yl*7rPPSpjm!83Y^}Af~2A zJjRj9WNEMj5f1c@V_I94;gm2xq!>&dX^R)ra#kVBFKvmZ15WTG3y|1lOijLILP0X2 zpsAq({bL!_w~nBrQ^CN%IQoai&^IuKfr0U0(8EE0De}s54iDOs4u6+B}%^&&m zotr*f`DbzKMeoOVZ^dZ!YnHFm2aQ2oTK{@Mt$XWn^@FWK=IU9 z+@L1S-5(2ZktIx%q(kqlXuILgvEIw}Q|2-_o~;5XdtMv+crRsscWJEo2NLJH2mB~P z_rn4|a?C+}6&3uj^Bv%aV8lQYB#FSu06%onnIJGBI0qRk@`NC+X`DmoysvHgF{6zQ z7X%!_97`YQ$ARBJ1oHEO9j3`l#@wnoD3>cr-u6@*g8_WB92!M6W2mjFL}htd3E$K{ z&e$N2t0Oro_z~dh&H3r;ko7O>+f{yJ;afg!c-(_Njx8&ROA=}t8&K2KfaxQn80hW8 zK~2MOMG~qfBFE8kkOw`|UWA$V_;b!t)8L3ZHBa(T@4O7E;jSsh7>k`fx0@z2s{Z2Okikw*V4Q>L1d>3y&d35m5HrwHNwYu@kOD@=YHkUt zOi)w~C>oe16Bs9<2ym5wVxUY$NQiOBDnlA+v48);KTqpuzs#JD!Djkr3?zs#&T<|f zs+f8JWb>X05BOo36a293#e^if}h>(phjbSQHW-?0?V?yUpHDbEXm|$MgD!_isgKQ~pg9^(E z^Kd%qotJ7BkPs{@S#Ff_?a0wqGG2M!%4HXBeEgYTJq~24u+oV0mB*|-rm?2|P2kE* z#u*vNn71vH!OM4Fd5& zM1pi;O!giPLsUE19nUxm1QK+eEcQ81tAK)xeSM~jvEtM8R*ugHj~d={1d z%58qpA5&>tint1=GWugrNZW-*e|-KbEZ+PS9{c2FI3eMP{`lCN@WBm_;qjX;#K{w* zM%rbcz=1O^#o3aK2LXTxjk~tsx1W9|P6-;1Gy3C&t%%=z4X)X{1HXj1@L}eByt|@0 z`^q~K(H~`bOL@&5{Q&^6veAvH$q5_$;EY3vT=0Y0G+0?J4#qh49vA^L!4gD z8N65kjC8}8Q69`JV^U>V=lm30B|8B*s%C00gSaW9XPxh2@J{aQf?K;*#^` z{qg5;`wLH@@s&<} z<*Z)_^%al>E}Ya?7WfgB`pTlXIvnb&Y_y5QAemz9I>cL(O+Q(zRNTaEQaRgLubw&Y z*2%q}e@UOL1#-a;KeP7BDN64Le)#ErxWNy=5T&&1Ivlm+03|K(gGgdr5aR@9fgid~ zTnNr72mAns(D^_^^Q_^P*2|+z@iYCyIPjalfz;A|v;ly^70j!i_lg8RswY$EInalN z6DiEDuf>eEW>i*`7W{BG6$ShVA3)Zd8sO^9`5DETl;5cn;?Q$lex9wsX1!w#NwAa3 ztEw<#RyUT-oQY*zLG#EMBs-?x(Q=R{I-rX@M?81S=h(`Ml6_A(j!8V3^l8h#H|Myy zBw_xst2|}KM@R7DrVVzDutVp}bpjVwYJF>)yF#EbR~xx`A^Q`dZFhdqsXJ2OM}G6a zczo{!|63riDa)EGEAWOJ20aP?dkYWrHXQoJ~V@wWOtVjAO`AW5iP(n*(vDkM!ME*Np95+`nG%xM4@D&sqM?Ae%}OuuME zp^@!%CJ+R{j7-jsRn_Dv_w}d+F6K$8MtNsY?}l9lh%s+^Ik>K)E=B1yJQQ z>_>&g7|5;s6c8y+CY2OpKwV?|d%L@rH39&mI6r3T#cR$!`MR$+*LPko$;!;!evLmt zn(<_v&ge1|*`|Z8HrFL$?UHb1yW=(7BM>300LZaJx^U7WgV`+ek>N-?k=-;@Ba6ld+tRmis`$uvLf#d*YBIUCvqRf zP}{v4?NteYl+vb>{%R_;JW6eyMb_)vhxdX|J-8otf9OhF0095*Qe2Xnz>NUPhYsK~ z!@b$-@5HMxdc|jOu^hu)002UH-(KAD@hfpjSU=zW9C~iK0Z)w%;fnwgV3=&`z+2z- z2|OQZpe4}$C_^;u4?p2^KU?^EY&kSML{4x+kfHYhmZiLk$=oAIzIVU53Wh8&129|_ z%>F2Ii=i8!hM^e%AR8rOX^EKNhm#hI0Q8NfF`-U?NPvV6BHa{#GeqFP2-Q__%~Y7Vskvk6!*}8C z`+g2XT-r^26=Wr(zA6U%2#U6h0)9C2td9aW^%Y=(5^nIr9D|$s$^t*EviZOd5kP$v zG~P3mn#azH)qNli{-Qf?9Ae=wQhi@vCq_Gr1|@q8?y?e0@WTWvoVp){f*-;J$0PtE zK=eEde!u`fxEK7;i8IoP3qf2XFbLv@s_NSMr+2;soag;+QxA<{|F8cFJyrV2T8zgq zziK|pq++1hm(MCwY0Np$hlOJknA=c`)~0$S5?)8+;aL&jM?gJiUS43sk?HG@4Xfar z6ymag|Dj)i?s2~WzpYuCeEkQ|e z$O^L^JGK+Z=1<9P`_5h?%{pAiq9pEuti>uz6a7)tu<|`;O4QL*i=Hp;S%Lri$^%%? zz0{MZ3mt!d=KheemF|R=^o$iVtbETvzd|MGhbAYXuYVF0D46T08kgn7MT_RL%0v=E zNJLE5g^-DuOgd~3MALPJgaLvG60#teAP6Z!XR@a0GBhS>8c9NBvQD~8#JQ#t*Fh3f zjc-m>5GMvERK|C|xaS_B3uXYShP#}R5es539?C|K9Tg5QMP_KIilMVPiFOmjP#w`B z+xAZ&tqPRIC3H3$&)G#?1|`|%z2kUcw=rQ~+HIswYe=9hE@9IYM}Gi-AOdzyL0?2a`bTD|I$lg~W;+Hcj>w|_*E zWLvb%-3w!`$N`_L#1C*6!e76GocbS*-#Yo12LL@l3nXWpdGa~8JRM<$g0q6OK!gKH z@Eof=rkic<8Lmja|L1Rb!)f1q(+7X@`24f?3|CCgSJ!SsF!}e-O+V|xTTi(xqvi7d z3Ox%O1)UE+lO#@sMs-AW6bn=5L@Gd>T}LL`*j=-0Ns_3C3^5}s? zV(l~OuRE>V1UUd{$uN3j~VzfV^(qHWg*ta7U{Q&^ru)_8dBg44; zBX7iQY8qF<_(tD1?|58N)0B%-cdUl`nOpGAo8Ew+MFc?tj4^c2?m<;`b=9^_n{K(|YwG`A{$YGeF)6VEsju+LroNK6oCCT9QD2Fe z>}^+;y}BQc?2L0PLAoCf>MOe~D_u4SJKZ(809zP-#^(kA03ZNKL_t)m+}Ej;fAG%9 z{qGqR+G#oY3~C2r_9BKL>MJMs;WWt&epu}U%nt;COZM+z(eo_$krh36gC7i8@Plcb zkCw%2d%L>dNu1?<1n83~9Qe)OppTb6FgDKPm{&ayab9ZRVCu{gH*eq^4fVB%#|woi zqgt4AI^4?=#bN4ShJ};~cG~z}!mhD~O}71e2peITx7(+`faB&&E~~7-{K^W<0mncr zh8+`Q80b6bS9(go4*(z`uy4n9bj-^Y3zlRVuRHew?B2QsJD-0JLwz2pGmm397LTK6 z*)g6%L%qG&w_`gB1wR0wZ{J>!5McJ4)+jS`;UWz79`KY88e48&@X^b07)CtELH^{! z0zZ7NpRijoyeI#QC+OM_^$iCe)7;F;L>!kNyBI%z>Uj)KOyrccKoHJ@$F2LUc$8xd z$x6upKkUZLe~x!O1Hi}((Dn05<)vqL9rF^;faC-N_xTJd3j8R^*g~F{#kLr!u>u}y zE<5Xl3-P)4eFuq{;r!Kwj>*&nD#{Fp@6($e#qj80z}Sk|)6nZaYMuQ37Cf@>*Rp@1 zVor3xh}b(*tYR>MUw<_y6IqMu@dF*3?ANuFC>)jS8L!=8w;G}fFMc#PGA zIY8mxEQC&sNsJ6xjA%EQMZXsHaU^tNk{>`9Bv1l?GgHpgD@9>cb&OVUfh@-2r>v2i z%z?bSY85A;8#k&?nUQo%zWKg2EAQRZu`;bmo>dc#6_W?&whZl9-Em;Y+?L_~`E7>| z2>{#nS6AMO!QV5)cQy+R0{&RRB_j#OSU!FPNXCtc+N zKSJ#&i2ld{KOB}yjqkF+56&5gxCi{OXt21Y7s3rtWBo zw?_6acL)u$P8`GapaQ6=0(7>RUgHTQ{#qUB2iKKYO)N zU%A_onAZ~#N`2*H&Zv+=zz-{`BMGj(J=y-vS#t8*%p~b#K<0J4`il)bKAuna!#VNH zp}umPB-!AHpYDe(wihCLo&j+S{IDpuR8{A?PMnCCPMk5FxKOj;M_Q4R`)AF&PM4+H zfJ11T$f!7Q_g|q7jpQp@uqCA=7F5rF#eg4@5NIDdgk^_DFsHs2?JbQ*9Q??8BjzELvd0c znfV(Y`=^Jh!9A#;Ye-F{uy@CHPldMbZqzn4`R|g?*z)z0TP4qhA9gv|)$`ps-h3AP z!!Id(3_-bh?zLjTkD$ziqTtdMi_uu&#k`4NuMBpZUxWx_Kt-(#nHvC8It6wSrBv7}#QB>sTyxRx z&1Q@%WJG`{MkEL+WKd%%Bp~Y=6ai95g(8HIb&bhFkgVw>3ouC&x+HWa3yq{qMkqoj ziHLJGLy};`bs|QZu{cPm#J6qPb+6D#1(EsOAzK)m7@%v0Oo7ZZr5BrvXm5Uf3$8r1 z4J~ysJiBugcm3laZvV?ZJh9~v06=%?gKRLPIp$BVKvkKH&ZZ>R?-&IUuzAloCek{( zTa&0v%9!0|%-*M3{{sLtbD)edk~kx7qZP&<=d~0>g=NpYO)4yR6o^NE!*la6Fu#`z z;HAvUsg<=toqkqygu8Jegl}Atlj6%crZCDV0apZrPrF4harrb7y{HxOp_9(?u6%Tj z?Y_;OE$4p!!mEGx+|1WI!4HLt%&{E@p8nQFf4k-HAG!N`w_g6>J=d(+v}H}#fq|N2 zTCGc_GRMt4IPl4{o_zBD5B&D~7cbrUJ7%{2=+36qcRtzK8GR27DPE7w2+d)QsdcnzVuUkx4HrEgt6cS=@hQ} z)U~+n(fbYT;DvRFKlKoP`>9KC%Yx&v@x$N7Pusenx)Ic)J^CZZ9BTw7Q-`*=>8*&e zlvfOfKzdx^V5V5Q1%mAF9XBQ&7Kq^#F*iSD7z_}_qRO(Si*{rP1F|CNMy^f_y(1}P zvx*^AeWB%DpKXCroPIF1Tn!692x2>kNJQf&JP^jK{<6%yy>13 zV>SOSgZ1{X^6#x+RXa+l`w;|w09oCSFwyf2j7g#een>FD55NfH7J_r88vuz$V5D)L z0hE_!&wGciDDB8&r0Y2Fo4+C57ZSr-q?OC%m{&C)3ZE(fp|n;vK7l3uLs*=MqrJHi zi75j<4D<8X1UgZ2%H;Q$`j-gv%m+JditevS@Pp-c9@1<0hBrC4T>?R5CXm?uA{OYt z>1UpU6>m5djcx5Yll$oYX%>En0sEMwCnoUlZ|=sS{_IS_T_+ZgqqeCDS|;P`d`(tV zpnKsW&tMMh+J*jo`-%cTtkmt#uFG|JFvH=oaP6ji_4W2eE#CHgiDq$L2GrDC!ffx^Fgj{%c`prkR%3KW;XZ%0UP*mf+6l}#SMZu zyiTDzITe#1Imy8#_jxIzr(y;da1(|$RbW41_g^uMI!nfsIBx#Hf8)b%`?O6%3jkmF z;in*R35uM3M?U!EpS^AU3yGdb?YAV|0HC1(h)vHT1X;9Ano(07TRV3qOpOnN4vS=+ zNG8E#p$nM^vaUlGfJ{1*At(!iWJnQ$$wKIo0F$7Rq^d#|f;cnjup|{+W5hEVArS`~ z8yXuO8b0(-62weCCL08S83{rHOqO0A0Hmfu#+l0-Kmfk;yWRNO-MjF+$NKQVvxC_9 zlCc6&bBR!F*kz=5G$$~twG4~_>vtH061pHfyK@wrG4xC;Lq}5r`v=n)9xJ_`p4&7{ zH(3#k$qi?g=%mR>$O7IN78RE38e;IF!gBo1KJVQQSd-2V~^ zqlSt)PTgnjW^`%l#F%}!3kmBz=+mb&nV56zxfO)xhuKC%@2C)Z4uRPx|FCA&NA5cD zih=R6dMizlMCR1FyZ-T~_xi#GE+fo0m((h!UCxQVaKYn`oV{?D_0VVE zdw9Mr3dI4Fe$^U>Fz3$EsJe{Vuon?23?n(Rj};9%%cZ?4?S22pKi>CNcUo0d^$r~e6o@K4{3ngDOuf3`OkRv629u)l%)uvMX zJjlZ6ul%gj{OhE@8tN--4FCOQG^QtUsWVO2aQYAa19v`hXD<9uZT@rG&9~#1P1Erf z#tb?wErauZ@=g5Z#_RCb+rENZNT5s0VC}?Mq~Nw(JBp(}0AO;W_c^z~xq!J!5LsYE zkr^b;4e-MRLG~XUg%$OYBZdyZ_;_L__~8OYoZyE^eU$}2IC@7XOz=b46j!+vSR!W| zjwla;$ZnfL=-CeuVNzwmv4qmtmSv99PVB-(Yv&=Za9c242!V#iM)b^GSh;6w+4t`J z65g$;xzDqbQePEFU8SJ3)K>ri*?XD0sjo-}3!=WVz>kaovm-A8sIQ!T`$d2FtJi=o7VL9ig7Td4j{&!y9gdmx#>XEE^#?`~B0tnWfZbcScrxmmo6+7qJGV~YB@%o# zbIw$ROC_+Iy!S+4P1o3cuAPFfPyhRf1(cZz@WcA0$P(Us%tCb3)p*LeBSHM4KkBQh z&|KAox_F&IaY_KQK8yVRS)d5uOLvu%WV=9oj!bF%$JsU+5G&{2#3I@$ypn%HXj3KW zr}#R~Bw4Hmm;>CTQwPPh4S7=rd`~Qj% zJ&$1G-~otjny?;;EkL=SD;nH(_+q|jSNm_Uu&VJP$fEfA-s zhNA?9X@O91;Z_HBuwK&2cSbRKP06P<||o} zsQ8&}w0%>Q?2WWx!?yUqz~D*lGHceXye(?4cir{Fze|$jl;mK){`K!Jur?+f|M%J$ zY~g?ct+loFwTO=*>{SJTl+wcJuY&A>h;@q5{&=}9DEcGF8UbuvkBf*f69D3Ie3vl{ z0)VdJ)ZgEZ-~ZoN&=Kb&^s_wZonT%5xg4g!D>m^(6zZ)zE=1%P-NZaej2quqk| z^N!-^4^0JwGO#f-GFN@ zKL$;W<#xUhgm^rTSv_-^BDY@qzn{TvTi3%_b@4J&Uj>05QK_%2bU)$qFzPG64+dwH zN5%)(a9TzXi$Z@R|&JU{pmAt|s-?jV)2 zGBht)idaR3cSOM(zGL-iJ|}@d(D&~K{rw@79U8&>702PUi!aB*Rcnx}sLZoJd7PU8 z7nTqL+n-&Jdw=?4Joe{%@Y0seNR4MFA&2_=kjbPy^^eX$!B9~zz+aW z$~b&9d<(Loh7|!|C`Ct8C3@b|xd6ZT$^%$Fe|1ioTYvQp{Lfuq!x?MNM{`})*Y&`Y zUMlfIqCcAIT0-*+0~qr3Tg(X!y(a?-P1*U(HL-ga#GYv1amvaWZOXFtW)e&R37G^8 zkV7Y#h$%uRg#?o|onpEmMd(I^h;D!&GE|Z^!DP~ONoSlxkfdswA~fP8IM9x$WsnaMf~orIwo1Vi*8DGyJ5n1su$>r?V^I+rKRZ&%lIijbwjTGm~K zO}odCR&T_awb@1 z7<{5Y{2r#vJ;!0b&O63}2(r9UAbz(&&?3OYF?WMOg57!!Hsm-YuF0aOJq8a(VU=+v zC-}7HCi&FUDy7Bq0pT0DLT)j1^B{-OcL7Ee$j5$t;t7A*(rMEtRm9b?8_s;}XSZJd z$3J$}kK}m01prl3IUqbC`SKl+p7iuc_oRT7g{H3^vAA% za)pYYcbb2rM1KU)UyY7{-TZTWKT(PQ7f<3VUw#lD?^=K}7{f~dAOw~@b07ZvgMUYt zU-XC5{{72%ZrKSqU6S#HGhLGL#9Kau&jr;Bq`x}Kqdx#({%UMFG&D$--UnwK1WOad zj0)i#j4{My7bwCw4)l(JndJc|6_yq0VW#_)ae^N@&^tN-U8GDPLpT08bUy%B^oLUu z1lBT03*bN&2(j`A#z&6L6OsLA0V5Cs_0MNsN+3v&Y)BXkx()}<^cLQ0Ov)<_)t0rq|PjmO_ zXTwiz#G!T3Rt^?o6>@i2Lo$ig5m1MP$x#;nMk-)7AJY!~udZ^Yh7{p@-RZ+_!0|jB!9Y%;=BOjV(_jMf5RM z;Kzw8&cIK;a1UA=r{$FS{x83Zum9vG0KnyI-z5vm8Fi&BlkJzc*9jv>)h6H2~WFepsnP3Nz zOoC)0CJCJsoeXe95R-MCB%xjQ7yAR`;HDBXhgGS=1BDxbTy zK|bN^7_XmR#%C^JQY`NTB--rC81Jv2pELbW8)n)_c4Ngv|E-t(@kei2zG-J6WA*J* z61eiXZR^dqIX3LCnN!#pgH6pBDd7Wd=HVG(>=}L_l;bJ}&H*S2vL#5u(&~Sfk zZM6=hLm9A~*3;ATuyZ?=N-ulpp+^!yG0`8Eed*`; z_LuL%X93`Yw_?kplW;oYcpd;qVCJ^<`14o)4NLR2`Ht(c`$IS5oXTo^Opf7K6;=4u zH8xyz9PUS-iA0J@LC_}JL!A?Atz$%>$Ja2OFF@mN;>!}@!$ewegIM2wukV2JJqcY#ed^_Am8%dPw2`weDBa@aiu=za)B z%qe=F1AeH)i8wPU1-PbxL+E^tcy~#AS;*4FsEt`_)#AD z!5PEM>1|lEd=aXvvQKAHWTa=bWBk}9NY9)BiWSaY7;ZjbM3~prOfCud;VBdBunBhL z=PluxG<&uJoy*<{%7z%J|)i<|zJ>Nta>h1MywovfH zvKKdP!1$0I+;D>*&j4`ZT(1Up`UJ%4>J=3S7t)T%`<>hvLiF4Ff)}X7Z3+24Za5)JWjs}w& zi@BpeEPtCTE$@z&&|>90_mCXTqUVKn5vj4lo$^l!}&y$|AB zcNpur=5#K^lAaZI{_yA^*1hn!V{Fm)RFY(T_C5cFxDv32=zEio-?-_4He}iNCrVB0hx#tp_!CeIw?dXlV<#d zrpqLltZ5``D#_3w2?0rHOi~5OLS?cbT@sq{jVc&%PKFqITGjc!eSP;r81E7cWu3N-03o_Y|4&BDXZd( z=1~B(l_v_s+|o&Bel>KG*w_BL>I`e0K~+K>x&5twx?_IJfc;UYYvfw4W^83Nl{+@G z`{U|pQOm$cU0J#p0Q$z`twQ8p47pk$#Dvej`K1B=v{YdfS5ar4x<|Vvx4tAvo<1~| zWxdpNUbh%RYev=U#;~BpLSu01=w@Y{nlx{Z5=3GE}4{z}h;X-E<3n z@R^_Cx=-AW?{>~ZCX@0X!z(fRLvxi+r^j|VqdEk#;^iD!-49vjkS*}T)B!ozJD%l) zwkfadPc8%eFx8{EsT9pw)(f5182U#iKq8YvX$2x1aLDR?IDip20SvRAxlI5mLDs&O zwg(KcbU1;L98HkyGDiYAG(pU52rOIJg7;m$5-pA85RNf1#?jo`%3?~}wYPmq`tMyY zga#J@2#)?JCH0l3ecvbuZ=ZhDSKI}DSb&M&k`@s&mRC8!k5K9>)1vBr7?C6rg!yf6 zecU*~59bF{knV@^!${b0HztyA0mS8hg0-iC*1%%RN}-HMj$Q(agD$j zaW+y`(a=AA#@mVI7u=ZK+l$_N9|>NeRiu?kWtdwz53(=O+0kRQRTVgX`C`oJnqg4x z`4~wO)V3B(EMJUFSE+yypNVLg*A)@-d>yW?l)y4UMZ>(nAeY5#H`U>d~M7eJ3c3XB;mKO0)xal$!o#Bpb= zMRk2c$Z-vSL~_e2!)k$*VghrP`?&R#ed%ci#l_ET3?h3@ut zv^O@Qy`jP5)JnwT=&I>JW2_lmaQ_GpE2_gx_e6lW{WsQTiCLn#1SmoaT^K%?6c8r1mTS$GXZEz$-5+{l&g5ohD6q!ioI+!_k zwjZ&MD3Gx4H{p61Gx$(pIerHUq8AbcLcv+CpcJy^nr_pDV8W*jJxB}0*-p-@B3P)~ zEf#Or398^M!x*cS=XJEn7o1lktvXrel?{I7%30?Ui6#6e9ggnvIY=32bmvp^yM`v> zHCE+Moc_pfJL*RR-Q1tMXZ4B`zxL*L9~>?BUidzJa>fW;pemU;R9BYnozpb3A*D$? zsJvxSl}mJJEDZ4QuXE(gudlxTp?Txulbw^3sWwg1suGE~?}H#};K(2TaBt1zWNMZx znXbL+t={l#U$fc0@y0ivKPE|1uQPYouD$IMhmvcDvOkB4YQSN?_{HJ2@T#+;+mjN} zUT*R82O@r3Z2?%J5g>;veqN|`9%lVUIm#^y63I z{Wsr^pS#O{^b)*p-Z8lQ^7mq|Uwf~X=nu zx&eML#-M5fhYqDtTa(O+o5NT$!Wc}NE0ep~)&MaqtpR-#;~+A?j~90jqCBafvOYd3iY$W%{xA{_5awW-Xk2@9WoMLsa2&!NC+n_<-=CzVfRRmHJAN zWeDK}AHb~7oE+*aS6f!}hn;3cf5@`uL)(w~$^t*~QD3<&NB2X(Hzpw;^;My|9~SuG zOMT@8KOE)f(ltL8#JiUrRl&d}321D)+Hkv$ zT6mcPUB0CNKLUF){y%Na@u;6O2OEF!bExCvsP5=Q*QuxHlplCu6ZZV`AK^VPZ{Ff7 z-;RcP^KtUcU&fw){sYhb=yr_m-Ro01$Otqt1U&i(*z7q#M+X2C2w8gp4!ratwmkDB z#+<8frx5%AGa^K+4XY?)42zC`9iIBzU!ZGRw0`{ZU7LHiZ^gpZYalDRZ;QtEX&4{wCJfW0OW6v8}wI&f*)P&v+>T0Kbn&^JUWP*Z@WHh z$VUbE5qM^c=%=KUXe|S={weU~tALoV4>Q|uO(K!JV8N`^&)07jLKwPEf&gZa*Xa^S z(iuq7NoW$dOwhQ1tZ|SmNX>94F$NADfJB-^BvdBHVjv<;YDPeb0Xhe%D)@^#_TMva zLD##54sJab7-tX=s4d@}W=s%K!79+9_V9)wJiH;;JvTV2;)}o7iOQsesxlb^BPvp+ zrpFCG+y)jfoFCk~*QPl3YxA4G-i6)$#e6FkZoPw}kR_s+q*GGSD4}R1ON^K)JI;VC z9ie56Wf=@8dw(z(K#5=g2Q%e4vt_gOIf#Te!Y;QHgF3o^o6lG%XwRs@5fvNvgFd2m zDm?uV3C5V$@vajw*#{ueb)7LeTb?=EV@%?e(!9=UdCmfkWL3W5FeWFex@In;X3&1mQH(}@$AM!JI-0KW3S(F(lx;pS)#4IwXH)FiTZCm zux!N_&VBgr0y<+%Ci{JEnh=0wxXE7M#kR*w$byX4~fD?`;WwX3y{$^mVTg}*3WSLaW;n-%H^D+svTW|f@GPq7! zB9Ykg=8NArlyQ+?#bPl^r_(?hK)~Z)mgPQO*KGl>@$vCGzjEX7cS%-OR?^uI=miT-ewTW~zmH~a+G#*_G-nWP-*$9F$^ z2|nm7_r;H3>BJareCi=Q@rzs0lyXE~yqcpw0AOt5z;kYDD4iV2XOzx+i=$(HsF`P-++4`+=eIC z?ZMXV{pjrl4TQSsEK=kMjKl7u$QX*1c$%jdOWsE%+ z`~V!FMi})K{B=K~QeTk|^_3I+$k|tuEZFZ;D@^yp6Zt`s9r+>5`%%+`Waxf?5rJt0 zMjGcTk+gT#{3~=>Y4zzg$MmsD?Em%OAkw8>Xcyx#%&nXYg_oKxs&rOSmc;613(+~P zwKz`*V^EtKFtL0Q(mgXFl7&#F`nWKoc)9aBOv9XO%|B3(r zF3VVY&2^an=1Xzz4}OR_7hH&?SHHuvf`8rr-fDSLL;B0L#zl+JcI--foYU5vfJIka z9Z))GWu);xA{}DOMqu4DfU25JGPHJd;l%Ubge51Ogm^MJ<=_VZytL&7*!l?$YwMbc zGcLapi;sUDrghIkqAcI4is0+PGEG&{yW1xEn@<<(U<;k*km zYsu0;@WWlZtg;F#PCElDPd^iJJ7R|Ul=OBQoR-Y};d$92ufNn6m> zg=8Xu#+n*Ctt^p1dqYE3@ZMpS@k-3DosFat&wd&?qd^>W=_Jf?ku^f&MFu;~VI^>j zaG60)6hBoerL(-4^B!8I#ABP@(uF(z^Ii}5v3>VuT=pNQdBBeuturxu#yopl)iU_U zy88$wFtcrs=ZKnJhGt zR8`1ACy5c~no3*};F=)5Z(sl5=;+uw5I{N^bU4BQL^(@Sxzc~cqd+Vhoz$^+AZ>#m z0FY7zCe!}MaQprV>^wLb*xtGwqZl{>vL+L06=SJ1DKb$qu8Xp`E@HB7@Q=a3vW!`E z7ToZQw(tm|yNtmn3dBL2l&$X-L=S8*f-&a*MhKe2TACm3OyTBjGA$?yq!@EoXH4PM z%HmnmV;7xYD=%Fg1^loq$!09!JQ0py{(ttqJI;=)Jo`E4%-pi~Zq*j;YFE43RaXM$IRS2^_JC2F8KZZq`hKLl-+gp1 z06e^F?zvMbRnc6c@QnMjV-zI-4MgR`>IO$ng(J99R*7X9WJ=E5P)K#a1KDiWIFHlO z3IVWZ&%V{}w5F!|wOJT|N2&5YFs!4D5XubRsD=OlCn_xU8vny)GiHKKZeCqdz%;+X1lT6h8gow`0ZX3-B)haCi^?695wmHofx(45nRU z@@i#&06-Q4+q3Bms$x}!b_X{ZASTO$Ss||&M@VJJYK0J3j4=!jr?7ZF0Gqfu05BNf zhn*P$0LdIMl1u}Xb1*yVYQi{vVge*3(m5T;WE%a)bx2)@E_INUh(#6D)`U@89YTF= z2z51K)YXLY%QW)Z9wxY9(X;dH5frxV3=p!yW#!EVf|%59061$^E81tr@%^7|ME~&# zhh|B2bv4UmLO1>B%OhvL;hnjEZ0*Jr5X}By(+GVf0>F=Q*&m+JR}%REuR)=&^c?t1 zg}!pXx=Kk!!4F61E8FSugub#dMBHuXbw6yOuiW4VcL5qY{6k*}%?o}wj?)A`h`@*$ z`h}M6M*;j0OzMWHBx#&WsqNX=ZPq?NQYi{(0%ssmHS)ACuEx3#M4OX9r;O0Y`^fSbYX2MuspkJdBBvVT=zAA!UX_3-0&J z7yPj7f}T!<6oDu9^r54<8LhKsVOC8IRM#SeNH~l+jg2@qGz8r>pH&`0Pt8IcO&`Qq zda@A1-M*aG{7sVO7YH*j)2m_5LHATVNhU}*KK;;F(`vSyd+iJ~G}EHzYkJScH*Wng z8fu)8Sk`TS5+DBJdoh_9_mp#ozgoBbNhDHJ6|+Cy_m;oIszqlz(jMDzKmPdiy%i44 z%#U+<;79rQ&grxhT&A4+Er7`h$Q@h2m#--~an$9lP5MYOoqO)^fHXz#xFq776VpK? zB&6g-T&j@VV25x?qzQsT&^Sl|BS@Vf1o0dpXT}8P3P&z0Aq0m8jvd<%K6cKzy-PWG z7(~Xm1t;Q+QEkoOM6^=L#&A#`wVMj&Js_+gYG zYvF_+vjfJrcUdeDtFBU)psaueVu*E`5hV|JHYzu4@N>_2SRkfpy3PbIXiH@E!b-*Y zEe2gT=uBuDvA3_t5+8!Pr?JQC$0~F`6W#MqnoH#ME z#$9UR!UgNxY315wmtA~YE|=qVb+uD1EiIGRUHA5ZV)^6o7){yVd4p^O`9TFYRfKXx8ZXq&HjkZ4ErNwZdbzo$e}X!2LSY* zhutHiLllp9F)P#+5zm7m%mhEIZDWCa0R$NtOM%GH_%N6r!QjVKmN1sinBa#~+oP@~ z3@N4WKavufE)%O5=KL97!7q1)YnH)TOC4v*`gz`wW<3-wtY6; z4+|tQsK(?hON7>z7;d@weEjS;Td{W25gQAIpr|V1qVdcJe=+&{o|RKKop%LZ^c(Y+ zBJ`EX{&3!m&3CGxSgeJ7<%Pa-=LO0OeN{^L!yfv|4osBN{eTHbc)*GhqUS-nAAaD6 z#r_};W}P6;I3p^Eo@<&Eq=A76Mv@p2G3cC0sq?{(uJe*LHO^(5eny1BKR%7j@!^tL zD>0QT=&k8Rgjd3bIDHllsaU>fKAP%F%Ir+bw1zrp4RsJBqX->32H^vQcpZ{O94L-F zCA{E)PF1frwj77ew855XgC9=oIRC;T?Hi!Q*1LY-DeZM)I}g0$f(tQgaj!iW`X2mW zOjv9NR>&Oe!}M>DGAUrgI$&N8SWi!WEYwgKi`Sfm_MQcJVZ&Ms9zEx)!X;oK{)#`*^z!0@r)@MqSh zP!ud&a|Xh(7$Wf)n&)-`U`ULO;)&n<+RzO1?YDCd7CrR9TR_pP+uSI2?Roe6Rd#k) zJEE$Jj?PX@W+iH3{;P1pp%CUYHR0IM5H#1Sa?Ut9qFsoHehg)Xk;}=v_rX$SCFZ(@ zEY}pv|ClilM1&Yb*g7%OaHUV{i_N#DnW@UEv8>91@9}PX$K~(Er*HZS6ybameBhbi z;uGJv37K5Rx7?qd^CrjkqwDXl82spJ>%oVvz15L6m7Ku8e)k_Myk1JTTk$z4b{`DN zG@TP&#%{XZ$7m+2?HU{gBoXJNOG$!rKxdF7i8BtJ zOHzoD)ERLQNsYh((g7ls5z}KcwxzY<5+Ru( zf-WV~Iiu#-3(2EnYsy|F|C#}Zk57>*KoLdC>MBi-M>H80k_49|2~03chRF;qmH$31 z+@q|oF~3k)Rv1>}c5MivgBNHX1`9+w%2NUBMxnL}tqf!(D2vo3V}g@c+}y~|7z>i} zD2}%HJ(FyC1&fAeDXZsKiS7lADIuJsRf)OFCgjfT&{M%wBg+E%-4IPp^pD3|03eZ3 zR4HXqaH1ui%+9T!IM_E_+x>?f-RIwO#fD9qBql^~8XXoKV$MW%e$HylZdTYs{92fV-ja#ac$z-o9S>Al}4I4@p4zPQFdgo?D zKty5FLFJrYRaH?+B+U2yDO9+UyOo_t!YT=vJo zfP9sPzv?pomLq;%wgn)S06fanpT85o{QTeJz>x#^K9K{+L^OtP{o|MM%%2kb0|4eN zMdIjV;}e{-T4w5iARhwD)bL;h@$l2Y^pyZ|x>3%d`(cWnlLlt$elRJC zYZ^GD&PQ5W7frOZ1mWHe8+m3668jF9&RBs7Ca|bxF`{Bxi zQquH>dZZfap-fCdJ<<;`V(374oR|)WN1*5PL> z=FFcD#TJ_I;I0=8M?C;81kSwdaq5%S6&?meheJw!=5dhFg{cOcNyns>6nX!tJk2mvB{BNC<@Mc{TuMi?|+Ah z;h~~_%&w)&5Oy51vG>J|8(tOQhm~XboEAXOAYNNnG(tm2RncZLLEIn+z|a(GLx_hl zsP-e1mXJCbUI+;=hbPMNlG*z@b0A14#%=YMZ|+-2Wd*$n(>eDim%TivJYx(Wy7uGv z+iO4W*?0FJzJo9R;GZGM-^wLE(lTy~-ZJGprMx@n@BvU&9IUmt&Mjk%MXp-dl^jWAXfQEJ zW{`hfN(jaXjFHqNaYc{@g82zY91OZfq?nF&O=VDW5}L}Pf|2Appb3C+;;ICb47+z6 zc&?$bdJPY$H84RC=sJsqhq4i6B$w72UcT{EUq+V6>KGWBKy^%)u_{fEM{_b3)r=5W zW*$jkoEdSP?K&VtWISt_q0`~*no3E3Cc6zzCMl z2?tP9t`QMqj8RY+Er$is2?9_SornoD#Dju(xGub+C$7v}z?eE?bC*GcYL#Wn#`Lx8 z83Y((WJIK3g+BY3uIY>mgH_PeG&;CrplJaBJb$#M^<8Ur?$2j*m6zs!^P0x``-W?~ zN0X6R-+N~H;v3K3_JY(j#ue4U0s#QGoaB!F+M2(*>yp2p%&2vKL=G28 zELOGS4R5%(l$>#ZmB!M7Y!X2Av`fEcmD(#>1LTz?eqLddFS!M=KZ2|YKqc&taKfAZ ziEm>4rEkF{p$P6|3{#9@A{xUNKmJvG_NCVT08XFwhdqBPHF?MaKe#D^&cIC#kb>?< zUI)a~1hM{}7)hC62@LUcmjiGjtzkT!0VB--K1?C;JP;xYHE|V;!OH+4Clkb;MkX*) z07odlKd0+BF`U2)dj|33a|iH?-)+OUe()T=c*j%t{?9hzz6W<vn;35SPb>qz~|Jn(FaPApx`1s#lfaY0M4kic@K~+_jOV$4E-Cv1(=S078ilqAu zG{}mCzH()ASYYTY?gTdM`SPK!Ty6M;zOvXKfuXMg*dK6#D7r?x+|XA+x*uhSzB0`( z^pyp61nPd+!H;6PAG*KjIZ0w#mW1vWJtxj4;_=3jIUU!LzplH(CSTZ(u?;iJ)#Kn; zT(cN4F+-^B3|mKQGtOJN^t6B&*7sD z?n`m-qg0ZAUp+PEKbi@Lo_qp-{LlxHP54u-TUM>X72o(4&imNMogj(Zb7}tUdBYn~ z-R5-q?EdY&NDbK?-$h2;y=vWkB>6-FMu&j4&jCI(@#glqc-^1B104%{Ju9V|=SL~? zAJnO_F>HR~QQZHdA7bqTf5e{WH{;m;eK_>uE&za{hH(BH--Nb#-2fOAMa4N+US))o zD$=%nS6ladPx|E87~JLdnahL3!GL`hGYs!sgPufPNYhm6e6Zbom3(wNGC-nQlw6bB&KK@DVk0SGzh6dNR5e{ zBt>dW5OgkcQfN8ik`d2nnm%x3=rLU<1|rk*%D|+C#`x};jnn!nw!VRJaG_IFm9i$1 zleMv&9*gKwRf#wUxuZ0Zd21~8%&67$1_}^mne> zxyu@)=lWWgWOap;B<4Ltj=R?{?Ya8D-hSO9yE-qhQh&8^;e`N@wZ3CZjLp*4@rj74 zB>-SxB0Be%o4N|&pCllqp4a#&89|~f^M7X%oKv|Wuypv(vmm|C{C?pKU1j+s{?9G% z-y4laj@kG9{O7-WeNa8j5JUI1ojYH=%AMBL)p37tul$*t#Vi_)oFuR`>YseP@Uy+W z{WZo%h4v@G04c{_ZsO#l+7YUf&AXA9lOu28>*D13n7iqv>R! zt&?JZ%z#w^n2x(|y6g|jlF6~XoU`Q?%fp~I8u}l0_6KJiLSe|}3SbH648tQS^Mjn5 z?_h;y#?m?x*&IN6x(&9h001BWNklkGQJTE*Z{#=-oEh9q)1iJayS zf>^*u9$1lN{UWYq>zS$EJi!la8#Ljr&C(7>^tW16A{5R;k%3*I53w>pk zKbg>1s$b|Uzc461p|3a(c-bit`pTQ%`(SW`A9i5lWJ6yC>3-P34>$Y6VxPFd565xB z3w~Il=ei_LoHM2qw?xmG#(5S956)Zoe&W33Ehc^J1cn}7TPj;c#sKtG_aLsE?mJv* z6P#hm{CQ}f-TadFL)O+HU0Va5NFsD(0LqD>83jLlo$;=pf$cf62KS}36?4M+dw)Hy zK_92qyvzO!p;++TVvM2l(#z0s(d*Fn(Enol-FG29=8aRYM50*om+y9@WhN%D>(}-- zsq(-N-y>nJZ2(9ofpyOTOP2#K7K<7RVfnciV9va5Y<=b_Bqk>c-;rg41isEy*Kq2Z zj)8**FmUjIql)U({;{;74H!6ua)c`~4~k%s~>N#27NMdXOi0 zNWoMgFsHd0{X;{@o5v<^wkTw$AE_iMZtaaJA^qzq#W2*vrd zJl`|pEcdxSOO}~VJJT!EGOHEe{^y@zN%u!z+hBc`wAZ}?@G8+p7g{eWXvp^gWbb<6>vOwIoV+Jn^#J)ctYRba`kpSmj#z&E` zN({y~7K5{o#hww2u{_Qpi5PtJI($t65I&Kf$Vm^0@P?{db>;lH+SLUry%6nWj6sBI z)D=rdwe=f?o4t^Kc6!U{y3Q1ES~X{IY(eALfjvX@T_dSz{l7kN!P%dC)059y`EpWW z-+6NR(*L(@;kkp8Rkn{O!orr(7q2^K=hH!b^9xHQp|h)(9(nT4wF~|d0Pb4Xeetzt z9=c1)LRhNGO@|J{cM(*c3r=!Ic^qC-gdol2$)>d|3%dZ2d_G0c!bRN=Jilev*Zr|nUo!y87E_u& zDdaUfg?37BET`ITyRG!=(d|CBu1kFK6$?2Pq=0*%jMuZ>0Bb9i$z@|@zV?j=Beu91wtf2Fn*7WCNMaha48Bqb0s`HpuTPQ zHsVXp&^P*>*Sx8KZeyLXfY4W-uuwrvHR3!d^p#a6Q23k|UKU9=zzI@~ydL(4EpOHW zRwNiW_h)~o!mC$DMwAUHxUcSq#s1&`pa@^^LkAf>v4Is*g4y4x6xdcaaUQ7qK{~i7 zqWfWi9{|9(@u>m3=y?ttOkpIE7d_Xd&JQnM_U>FX>W&BMF>NA&{(B#W%z7PECu5zl zPBev^N@qOH772%O_KIFK`7kd|tFeL`lR_%A#s=t3vj9zp2nyqCdTfijKLee`%=5FD zW7hf8r$tsWM+qmazlYURn~(EQiAHhZCqD(n7VaoBF^;3pK8xDUF30nMagK)h3ov=) z2uAnq^VGZa+IOM#OsBx^w!40a6Fax(GZuGhG3TZ`L(n)80fPfZO1*cLMKoTGjs=UL zWwRI`9?FZ823oQ6QO@}^Q`1Q!o^O+#5yK3z^!5b{k;`N-K0M?oV^yc9A)I~1l?X?p zjuw(rQ`q**Q~4#8ju9*Mh8Q@X4XbTx!s?4J^Dt(J2wNU~1ji2@^eyc?b;ggW@i8Q) zCehk857~4YYw!O<{#ey;7-wF71)ADB(6O)=QrD5oX0hU;i^1~GC8M6>2M=KX_N_ks zcAkjx&Zj%M=+$rjD0ba>_xn{;EC&O?B!No}G8`$&#NeDGUR8xuI_(ig2LOesh_M=^ zXbK_>Fb*RmR^EkWb7$H6Z3jVsiedn$Q4Td)IRN6i+$$*LO`OiTFIuFmGOXw(0IXPe zChq*~eduiMDO%I~j>Wj<^6M~>7{|_iTO9kUW3~8~4}1xN7v5*S{G(4}aHObyYN1<< z;Vb|6Lv+t^E`j^E@BI@t?071mP}zx&-4zdYkph8Ff>U-r%P&;?8Rjx6fze^GmR5il zcdhW+NEnJ>+JTWN1{ChYrdOL707D7_9Nbu&#t57^7$ft!#z0p5JJTc1i9v8~F7g6N z9V7Kk)hn4vyCx7g*N{jzC~2+n^ip_VVb(vKz>9}ZP%N60v+L8j_NHXEqbZeZsLASK zRT}V-H4m6=8hNe{^SW^8`AuK|OQI-)a$U!-- zHY+267|ZLI6y6dF*#$LyMHJRbv1kIO(g}2e;jR)pNi3*yZcjE@>Sb zx5iGAsUO0~jQz|ELZ^hG0c(!e%C_ObAFp3{jwX3{BoS`DWWnItmg;oIxNR_yBrr0@ z8j`>Sr#u+PP0bl{o*!e55CBe`Gn3hC&NJ}BSb&*q7*?o+8#%}joy~`IBUrB(+!!lM zvy3=6FA!BN9|Z@8G-IW40E(g#NtsUtjIjU*m{0~E_@Bq#0dw}~x{Phuuyx|EuD@n` ze$ohDC;(1E7<+VGLI{rcz3;=H&15ni_PNm5*l_<{cir(@vjPYK=(-WwOPCS9tO%uw z8Rz!e5*zfg_TNWaq!5PgXzJU1mhC0X@P(wIG0ekglYmKVU?f?3BimqL`M8- z-2yu7tdKk?QecJJm#AHevO$+1T;oASS1r6h_WD({rIU+t-P6S~{{1$ExA=YL^IoW!;a;Wq&Xz z9B}#{I1}c4q5RzBHt<3k@+mCj!~TF7`U(Iv-NYdP5BozW6D$!5^94UjguWsMCT#a! z0(?VXf!uSNn6Tcotd+u+o`~HMWMh9=xQK)5ZHB&5?4XEQpI!7^lJ!c>IT08$!4F+0 zP8vA4%1zO84xMvd>Y{&M&*iDwx=T^QWHyKXdmn~2;U7w9y4D5Qk@s$*3+ zXGJe!RWG$333Gizno5wW3cYa_a?OokBq5S1=bU29{~|Q&uzlb8@Av+J-V|9!;z<-M69V9)pH8+TN6hPW5c)p zqY%@;tT$3yhx2av1h_34LE`uT*8Rs<^LiNNg#PmFs^b^~#)$zK9RboAps~p_W}I_0 zw|AhfsRbhgN1^9(#s|J{Ujo|k3}?~V0f1p-U;yD*73vzB9NC2snBCch=DBkL0Lk$Q zNHXqjwT(?U>+&m5JFC&t!k*2WFf!2ZX{Y4dQ_=YhFwSw-2qCa@-7}aREztEBpK%sunV^tR6*P5ppmR~LO;FzaP?i##9(@qmv^&13 z^F$Oq^uQ@s^y)W%6uq)N`~4~^mcxGjnE64kt0h1X#t^TnLNWjZ5lkR1YLV0?0Y!(Z za!8FV@2T0U{kQ#C9GI&Y6mf%@p`y zSuO`mjDa<`mK-QCr#3FfQ(1k`cwsTbu5GL>2Ez%;tbG6kk)`KI9K<*SAOXQ4BtaU_ zIbw_h3Sn|AG1k=5(59+l7Bd}_5@0GH)rOKQSzVkB=W&q|pit~yveAb0jX5G8ZhM1`@VpMK( z*yp!x&p!rN{Z<`T|CqgMYrm=SVW^n60T7n&le1oC_1V>?x!3HsHO(2Sl(w4Y@C8d6 z!)LBkd2KCougo~b#u!&P7r8X`_rrEfR$K{?9k?j~AVh}fc-O3n#F6nD`QqTLP6Fd= z54J7-$%bWTJb$cdVMY@X00;>^dtuM9^a}IDWh?9g206=tRl(930OqUZ@tXVpF_np6* zH#L>)vd-hcz=@UNaQN}_&s}50jujjV=jLaL%!ky{b%_fuc+>k1A3l1GYbwYOeBgbz zTz1)o=1Z&&Aw&TH0ek@vAp}83VR17Q7?6hng4h9&900W#00QIzkTigZ=`)N*>j|k; z9smIV4*)Xe20;4p8UPY(uUG)&mB9W0fN+Ix7$?jAC>H+e<-q=k08pk0fLQDg_h2wh;YUc3JEkf#y|i@ zQX0~lsjJ}%cSW$k4+{vb` zKK$XKJ=nc}2u+Pu7#vFY$0;SHW#87&HOYkB(B30YIQEGG`$Glt!rZ_#LSIQRV%%5w z+#dQ$s4jgF4LlMQ`pSHP$Y=#jh5LlQGIyA-G`2&RU|exBORQtChrZ%|p|5nCSO(|5 z>Y=qX10e8363$OEziNv))|lTP_-)xYeb1q*ul^63VlDV~!dsj7 z$^!sI>*{d+t)Fy(7RRynYhMOQiOl#o4n6)ThIZ~iZC4kf4GmcL^{-*_$YD?Ot8Tav zjlD}8t!%vGn;1XPmv7Vm_?#W|=3%ABDgRZ?fXPYYg}=Gk!E&=KR$YTR-3u@^K8D1^ zI0{Y%6mQ2foJD7cXXQ$CF7Czrm8&p+#VSNh4Gw!N zQ{!XU^2B2x$3uh#b;Z-Ez-)}6bJ1dSF7dwEjt>oC^P>;@J{$eU%)K?#e-zntI-gz@ zk7MPk0K3}(Ko+&!ZZzx6C^Lb2-^Zd z5~&oV4+z4+QO#?S))UZ~1|=*Ya}p#Otd**!E6sTf6@nn47>5$AY%y-BVJlwHn=qa8 zADF$Y{K5BlqYj1}-u@AM>Vsc~DxA;9KR$IY{^3j4*8zz8aer#FqI(DGL%tdgeli}gdV<+4e(#ixt z5Cnh_jOUaUcfkTUEOL?u0AYE6gsRlehL*@B%Ns(gm#MtAcA9sX88LyH#w7La0O_&- z>J*-n%%uE~2~slC31EdKzj)!Hqni%3Rv#O$ZUF$@l-aBb=Mq=;_C52BcRcdjzc^#} z?&j)L#=5k*Ifv{3h#BNO--b!zfI<7B{CIXZCI)}8Y2HNy#*a@%XTST*z9%E9t}_<^ zVt^2wEbs)@`&R$}BB6tG11PWqAY>a0I{?DKtYFhN00ib(6#x+9eIC0FWSiMT?-HY71h2lxwdh@$+KZALX(?Y619(pSvw6{MAgGJN%WORiPkcUQyjA zsr_MPU9cQey!aNzJLHf`;Pt_QEE<3fq=-(LNL-+e!JQ$Eqf{*VEo zugW#ao$L$0I)a4Hea!?qvbK8Mc`fjR+e2enb(`!DB|vx;K%nji*#W_T&{wEL_rrV} z^Mt-Ki>mhe?V+zUVi14>{4mEbm(vZR2@%t|$_NF~b18{W#N&;_?H$*ljOXFVQ=5@G zc&t>miY%tYupmCasI%^+u#VPdoVjeV^Cj;kF)#Sx8LE5|1BFA#_H-e2&T8a3+N{89 zKGha;tTDeo@Y{0u75!>s&L6(*O#}S!Y20@o1F-bn?{$Q}0)VYQ`XQwG5^fbezGX8W z{K((oiQ7JfW9y#tG+#Yu4(45cg`=L)y?b!@=_m7T26r>i(?2} zrF<+DiQtS&Uyr3{p9cuVWV7UBMtIxt3}?~V;n`0hYmAmO-)e! zw7>vxCeW&MAwn@QNr=Q02o6A+4hhS7V*PgX$=YA!7&xHDrtu7z&f~1eJ#41hDKC5R zT#--&|NhbM;iK>Uj6<}Xi16)uzJOc4dIK_=aZj2|PT;ox`Ul+nZ-0S-p`(s^s$;dd z?WV8cj!*s^7p%I>vG4H>50uwa&T!jJUw5!f0N|@Xz70o@A1L$iN{@>DQaO9sMfldO zKf~+K{c{LWL`t-*oA^mu8Mj7nnKJGTW$*AB9Xkv|j1CV^ zjHb40nq<08<`<+yd(AWBjQQN~|J03u&3lehNRbqeYO*1o(Hd*hT74|1M?<;Y&#!t{oyx$}K;am(1`($=vp0Fcg!*jFFv zb;u3d7fd)bMFV6!gejap9SeLraJS|2sL+a)cfbbTYCimt>-)NUIvs#TCX;La)TjRa z&WkR(=K5d$^mk1FFfuYKzVL^=Y*LUcz+;v7G;l6wB`QBFpyJE9& zI6RH9s!Rx^rl#7{hF3|jLVFGPaM&vn04X>8mD?%}e-&hpm04yw;^*bq!GQKF6+iDX z|CS?u{&F!t`PS*OKkOF7{?Kf7SHk`PoNNw9odFD(p!~_i!a2O%6 z1m_4T1~bH}ESb@9cr=Mj&eVpoF)6GNS7Zk-YygAB0$~8^YQhc?bi4SuRo>40Ad-+U zbw8vluN%OC32sONV}_ncRal}XMyRhLG}lQq)Dmjrgjj?SRt@GzzMs+ydcXsO_>HdD z7-K9k8F~M&{;U3Lsf?n!h0p!065(@CS(os+3%puU%5<&SMAlU`;qTI1A`F0qUV6YfbmNw^LonaR$C&^s$%9fW$At} z5GSo5dY)q~K)Haz?wMhB12IQYQ;%v-t~p@?@S#(@`hU~<&EQrtV_KIbvu++~tUJpaUFc6*@J~;|@_7!i$ii<8mBo>GJL`=u|{c;CCtftkeNvJ*%H{GTPfwsoRKoEp6j@jy5 zR8iauf=C|_B<~wxCrmT0&Nw|(&Ic-@*S@Rg7L5WoBSb9n2e?{)w|rK$}) zv(q@Ar{xW08jZ-kyMXc0lKFUTG+g!8rSrg`Fv$cU1xcprQYsQ8h?pvMC@8WR$_AmUu+i0|Kf=y8&y>4qjFQ#esf9nl)Xn`btT z>#M-_9vj2R+Z>PNv_L>A z@D$0y|FYnywda>iW7nUv?+I)Bfn9T6XZ;R*T-!b~1?LnrMNY~wZ2PtsqFk>_u%-2k zF~0s-2!8Xs?|v&Dui9r%lTt>vZhhhA8*aGe_tn+CPjq*m_tY1@aK}A6cka0kvYW-F)+P|G0AH@}eM>zqRaNI7= zwrw|PY}>YNvq_r9wv)zIV>D@O+t#zLcYE(I^Cyfs&T(L;3P8$5P8^oQiZYjjL7;Ty z@#(rIGXNmM8HJG(q<@DFEA9tosuMd~c^s>V{k0=)sOGCq(&9RdT#NvV(y~heTJ1W_ ztVr#(4p5SjidDxbX)?}fN&OW3URaT!WXPyY_y8oY?@O~5h;+3M_$(53e82xQE*on1 zKQBN-MAxbV?|Gt0b&{Vn?caAXLs}+k=#y{9Jgv?KG^WV@2T;O|-bTY?0<`;2Op{Je zsnB42j{zOG(h88RJ&gBhM?7{Whdr^X?{30+1$6|4M_8mwrEjFJ+uL;Hhz!)x?D4Mh zr|;JTn@?5+N}ZiDt>y}GyF=o(-_5K3K%i@>HNh0187nE2u>!j9jtV+AzGwNB*Hgk}Hq@QHAIf{p{lfd}U!}i$g@-OdNV{b3}sL<8w5u zN6FB0WyH#JM_O=tR{u{pOdEoLpl`XvP{M??kB>(IlaohEz;Xu#&+zo9B`W1m!hWJd zG;~>-2a&{q+o*>Z)Ro?SGdO?L2JxgN6&fAk`7^e2nFYfz;b+{;aP#nnsX&V1%P{kJT9i#^k&k1BFT&=_L(e9!ArWjody z=Y0CibB0|l?j)JYQy@vXQ(<^?l|HJSC`>rm3OTCZY$qn zT|=6_ScIBV$NSt^Ga@#j%`T|FDD=sijiqL|=`M_;&N}`}68ZX^jP4 zjgxE0^=^VjuYbn@GED>1CF2A#k#&vC16bd+TH8hB%(Q29XgU{G z+kM}?u>}{~QYyzmL6oR|Ud(4;(tA|%$)4vOe`5)%m}>mXW=}Od6KpiQlSUO_K>G%M z9g|0lUn}>n=WHAJ)4@czR3a`^Uh@r{MPm8`WbWHNA|1^W3n0F^BYBLB30Z!q067@# z=s)!ByV_{ydt6T1v7NIvBP*R~WR0`dAm(tvUGVzCL(o-m@9Pa|t$oOl0M;WsL49&2498=7TOt>nb7at! zEB3?KZCdyqlf3LQGINA(@dE%T@O2lC3qbLV%FP1Bl&?d1!a!E+=v-SB><@jxjMCFn zX7{Hxdmp~o;4J|JL3OOqb_P=;(9}V3F7X*T70@;Xq%)rPuWQTzGc$(9!Gz;D4#zFF zez!M;2N`I>+fUnxpc<*FI(-Ye{{K^FxXbhRBk1&=)1SbY7m|zT-_@!yUo9D1{|Zj* z*1Xtj4es%NPA$}9|HW7HIQ??W7&Vofqex9A@KiEGF36{`@ItgKKXU^am)7YRpo`tfEe9gum zt=s-SVCw3Fm2c`?*Xny|KdrnqAJQI+9UAJe2C_Elw}y4PatX8 zwdF@GGS@gei25Uji;PE#0j*z+?tq^O0fAK+T>dbrgyTn2&_c0toh~{BF+Wi_$5MZI z6=aysh(I&3a;A4q_&a*&k$bp(zMiG`b+JZRjHBQCs20l-ZzA%;)##h>2iEy|Ysq=f zLmp4amcT9gP|>0mUtmk5wfB<$*2wh7Ovd?XhS2Sn)k~gK=DijV{EjMqgfKD zMvoOW>Edg$v!sb^ha?+Gs3?q&orhGO_yX7#-F^Nznay$deHH=(k9zh zPaHRtGhvdBr9`q^y1!sUkGduk)YW;2y4`iXPU?SG9a`P4tqO;koSk8rXCQ=1?`_Gd z;dxbSE5mkpLU?>Klj^kaZXJnSbRgaE2;@rKn1^X_lZH@L!q(aRr}1D(U%3cLm<`$W zqkB@$yy2C$JunN*mDOoaed@=a@ryHrR=~Q{M}+B0Aug;$1#@w-;$yZ-n+^!@qloE5_1u0qUvt|*z4Af*pk=EU@eQ6Ckj zhuUe7a}ZGGJMq&y;#-z$vj5N5r89W6`DJloED4>kpQj_EF3;XMQs0rfZ%)j zOrB0p^;2>rk)Mk-RVrhw_7Kj5yIb?uJ9h8$C*xJX6F+nq23B?lr-;fgOpn0@z}zja8lXT6^T1t1ETW7pYlV<4{l9@gAI;xirp#(83GD#I3pQR8Hn zHDnyfgOnTa*Emp)`dz*K99bT$%FX@}Bt>8u?M_$P8bwcjPIc6Zqmm(e04$^#;O|+) z&A=kQbZOwAs8pqYDy*TCj|q^2*8@-pA-{jLmgJzoYIpnSg*@iL=C|F6Ue9qPg8Qf66-C#||*QQ)I+@HN-HgtxE8I%}8i9*?pioyN7k} zY_*cA(RJlWkbq4#@Q*+6ShXTBN5j|tC_DBLlb&!GN$3^i6uM&G<$)s*ea;o=^}FnO zv0p)NCaAXtueU)|It%n?9hq(N!!&7eUw&WMOX`3k3t{QCqrHNlnYXwOhV<}1UY_%l zuAV1}{d#$t(6f85@y~Xh)IBv1EJl|h@Nw3h3wSet?av4sZ9~!WI@Hd+w_}4H!4*R- z<3hyAj~LW)`^T#!W_-Tc)>Aza^FV4vmCnBP4hL~S!?y=Mf&s`sgDIm*O8Cb&5b>-H z%B}ocjw+&75P=FJiMPQ|GX43ZC`yf1nws-C1#BHEM4By3gA$Icl%*RR&^D0&&2B>P z`{byKxMmOJI=n*ZNFyD+Pz9%8x3P*2e!hqYzD~NR3WTj?l9*q7A zZvR32({YPz=dQh(+QAok=E2e48!)?-?&-2xI0qt0J`LxFzYqal<8pDK9#;^$U6b6t z1q9;zm7CKQ{SVf>=~Psr*{-G~IHnLe(r`(&>}W|6+YlgQcr=Ho5=;lwnA*4Eli~`v ziWKR;lwd&BRGr76+2z&r!-&{+mH|3iJt@~NX3oqNF3x1#oz{_S#Sx_Y#J%ks)EKD} z1L7GgM)yoTTYoz4Dy}lg!49>s9TaZ!dikd|c&BIRoxYtGXQNTNJm>>YYfY&Gw7ShYeFz?GlGC zrHA>lw_ld}vz$C;7fU5!E#)ewDbD>dIRQlo0FqI_0|z@)b79u-`8c;A{b-;tk>S6g3I_+N*DA3?G!b|);wB@Ceg4$e0AFd};= zRv^Dwoh)Gg@h<{Zn>}|Q-Qt&5h5ePZ`FUc@@Qh+(AZB-FTHK*wuKMeKEpR;QP_O-= zdi;_I4^KksZM|!mx1abO0HDG^po9md`OVnzMn+Z36C#tKxkX4e(8N92n362bF(Ce& z*^q4`%u-}-Ly~5t!c;MBAZHv#HiO|}`HHWKsq!upvn&&1@ei4VN-y^#>9#Rq2!xVctMv~4IA1qNv4HY;Rk6d_HzRlEFYZ^a=YN~D?Y>SD zCxF7TxFlGfUS^_vZgKMU9*TUg9wL)8vg@f$az+?cXhcP^4Ne68( zr=qmN-uXp6%U)T%vWSMTQeB-fhwV8qk{gQX5&pV)o?$ZAk84M=<+Fh+E1ei~Z5b!O zT{oI|oS#uTGU^7p%qK`EXWi0IRtS*Jm(#auD{H^Gj0djBvu1eDw*5D}=-|dty=Jb9 zpAFX;GQ_py$;c~Z+0+LMP*#8aaTaHh(j-u4AEr~kKF&)`w-m*Yn*Ul)IGm{O1q<)oJ^Mn^Pm0 z&>Xq+0XFB9CKX!T(m*KObs^;U+A9?Imiz2IXIo@KzxQ~|h^|+7@7k5(@m}Z77l2S* zieyDkWSMK)lyBQts*58_-yjG;0t}jU|yqN8ubnEk^VYMQ@NqO;H3pqkECygWTh% zn;mOFs{8=}|8l?m8!o~u92fNOFN~H@20*e|ocG54yw~83_dJi|{i6^D`?OdgYgb2& zg8nA0*FI+dBTOSthbDEsuOnqE0CX*@q=Nv!XGM&n;kFc0%PwWIRa9}N;O<*6a?dAr{Z3xdXM>Rd^>gd{w%^YX=furA;sYZDwgf#HuC8>{}(fJFZ5>nr%( zp~rdW9>3w*`tq_;b0{rf&MFLO28Vc(7?Yh%ZNwn%siUch4dx3rSy$XBtnDiaMsg6* z>yl;oTxD{en2H$4NqBRYW4_OiGy5qQm6u2N9h3$m?)yIac?}^kX<&Rm;y(=wc0mSslKTQxZ3G4{W!vpF)vfO@ue0KcQ4s#)sXnljQT?Yx&vaxAk9|V(K2XWFP ziuP}x4*)9iv-0OIWIq@xkc<=@0hb8c4-2w>=%>eLMC8l*bP?f}zQ<)W^@0{3F$7!G zhcPIqmqqE9%RJHFhWrLDbdKEm4Q3lts5P=D#X%kwR)gUlQ;F|BZO%%B!KF$M&|%CpjpQ{^T+k2W&vO@oZ+6*d!Xz56 z0PzHfYi{%1#}QsP+w{QjE1q252JiRQhp8s^2VvmjBS@Bnv^nBCI^P6c%NDltTZ{VD z`BY`&Qx&(yaj9*Im)vLX{u^;2yZwe(oDYa?$CbjPtC2)~`^PXirXceT!`)ugt!u^d zGxkM?ecl&RZ@W%c@b25jg&Tw3`BK+*xy6238rU@+GSPs;^P7;@j z%b9wRN#bn?ySELOAC`%I4+9h}y`w~RLZ;VQjB959kgdt?eEn^#xy5yr02jv!H4SOd z3aV*&HO0SVUI|w8-<~LsU*h-JxVdA_zdFv{R?wW)ZWZ<%4q?C9ta5ZIMnoVUF6;Rq zl`ElYD18!Ge_hHO-K_;q$iYB&>8%k;%fL3Ow_A^~x$Gs>i0q_=BPB#LHy@ zbyqL7MV+^%T`0#kEA3CqKWbO^MQy>#QxzvNs1OR1?3?#-K9{_^MlBL7-=XxaMbHmh zpix-Bt}m+FfHvCMH4!r)CU}JiRwy+yCiNBPT@+bnh@ljky@CZUe7O4f^xx`iqe8fp zAtvCLk@^(tCNDKD^2@30vb;-BXZEM5ZM*wg0Rw2#%%Fe zjY=(Tvb^EPNR>+m%}0H!HXpUgNj8g~-d55Z7R|R%Y7c(53 zpQLa!a8WV!WOOEa$}AUn|C;GT{5no+ci5T#)EdWE<$<|NV#o|4O!iIo?Grdmw_aUn zxlg}+D64N^cD@;0vVgyS2C%oDg*|0g*4ADN9r@?7Upy!hI`Rb4;J)eW%5zPi21)&Z zq(g8uglQX)$%j#BldqX%grHE(PvRdQj54JuK2u=k1B4(ga#q51LQmZS2>YhEdkdZp zv$ht%F(C*^$i$*1T{TT5DzC&<4Yz_`caXP!2TY`2FyrImc1tWhaP@kCVuj1?uG|5= zMpH(%ws*{zU3ZV24qZ2kshH;hGFc&#R_X;0;8uaZi$2{~@8AI5Ld$lI!nsc%v9wW` z4nvMrXH*`QmE)Qs zum10b5v!Mw2^!D=Z}`PfulD-yMJpbTvJ@eU+?)GW>3O*$xp`lcp0y6W2qJ|wh=|`a zNcHsN^<3bJd_Bq8`A+$-^4qmQh(Ov_uL zhj80)!DuW(ot~EP1p>C$EwGB2|MG0V-zK0ZjLgn+&g>O`{V}#G6{+*w6e9Ki`dhMZ zhMnV$B{o-Hg|Xau;4GCcE|fRiQ=^!F)F;FsYzYn`a1pK$|1)xDtl{}O)hzfrHa-t@ zp=VPa>&t{7T#}vU7M3arkrZXjuBC?uM3$C`aJtV*yzrO_;7Qv03qp;I0M|ImYl1|; zAjV4Ejzvjea709kWrK5&CRi0U_s_!_d_EZ>nQhNBauZ+is4vV&0456Cm9e#h2S?rW z$}M->Tz*%Zju4NT(d~)apm!)?YXIi@gW1zbr%=>MTypZm!lt~}$0+mYTCF$nrtjcr z0Zrve><+r)mq5Y;@en#can4=4pe}qz#Po>riUS3yryyd$rMJlP)k%+4auZ)xxg}f4 z6&^vjnS=^3E;WqeTU^^fRFt$V8Iy<@*iWYDHk183b`)@OLLeQ66^S%TIE;LW3n;{YU0$z7U)k$y%wY0}kSnNHC{T&KJ2K|mF&0NS=hX84^5f0x zXqw8})=r(Mqv}`MI3L)9E!Tr#6VWk52I^wL&;vslEZL=VJLFS zJfgB)m*;}ISMP)2-vLHv(f`Z?+YYd|xUJ6+ZisM_Gotk*E(q)55#@&WK2p_hcGMVz zk`qR#{_YH^F%f*XAd6NL`XOyAE0Cj!uB{)B4q4{TLFEG88EI>?Y76@~#hg+NNd zelLkYpGHnrz={-@Pcl0x6{)S8X@)Gg-2@qUEN2M=;AVgi7yIGaz3P9enrHaFNBnh& z7#cdL2}eqIScWCm{P=*_^`?L2bJZgJd7~)obk!~FM*t|CgE43E>?jEMx4J5Od?j3A z+Ld$x={eW2r!7>Li?l*KisUnjr`A96)_q{v8v0&4s}C@?#t4mn?Y(H#pwpED+TPH3C;m$Ird2u;G~h_eH@`jy6&1I9Zr{K6{sjkB|J*k=x-E>5_d2L2uS$D> zfbtS-KM3={<%+snu5Hq&*O)gYL-mvoMz6XrOPy8UOTA-)~{ahD*I4^V@1_nD_=hn7@S| zVHD1{Y$X^c-P7V$8b!V8Cp{{7UMqkgOnX5MVqB96`QKM0V!HIUK;KJ6rq%;u1l+=C z2vDMVP#q58iD0z+qh#v$S;d%)z(d~$j3gNf6=9Ag%gAhx6YFXRw#iqju9MjjyOZwl zXv;!|MHSsk4s5aRN9fvej$raQmH0QC!gBQYi-Z*e_Nf!W~8Map~Y8upyOgT3C+ zUmpGQYjtwL?h=V7pavx;&)b}jYn!JVp_<{mqpF` zuVp5`7x67|9y2{hUd`+Fr>%I~&l>@`vQ$j@K~I||-WAaAi!;lZ?xFU8#Pb3mY%AF1 zgE)OTN1x#?|3vwhBbSs4%t=Ot%?T+bC5lIy^jneygo0S`4+5wXA9&hBs95{0-(3TG$@vAAEAudct^0{u7w)dlk>4@mhg;zX98-I(L$ zdzE%bePa~J{DVYGq?*AuefW2Pmanz`47eouU7aVPyaV*2$@B~oA0 z<^`lFT~!vbMa>it9IRrxe}t!KDX07ExRqGY*364<)6JyXV)Nq-tGV0l#aXergQ?IO zk+A56)5R+V;~Rh+DarYa8jf9(jgz7PUcBmuD<7W@=2>QS!V~3Qbb%QMYkI;k_59AW z`S-|2!`{mwR*a}s*=|;cL>OoiiFs4FGIYZUp<-g6%lQ{#XpFo9}-AM>#7V;Bh zO)O~1< zHQDPUBA^ETNWVk`HpQHKg9iy{-fPaZTtNMV^g`$miQaE(5X^!2KHA^-chj4?D$Z87 z5Km3j(XZAK0`V!d|MziS`$W0!HN(*wf)UAnPNd)4 zW*=4AYu-+FcZe&}G!G7YSSK&E8x4+(Iox)nIUKc>#_@F-gx1q6dgeYq4w;DhWKb*7%Izq*_11jkB~4cF{e#EQNOD-LSJPG{M_O{m&!7e zU&7Bj(Y~vn%v?>5Z(a5sZztWjWfBqgwjBfaxRoO# zSN|)nwiHg34uX=}yTxqVE+QWNle@9}SmQ|M{r>Z7U10Bd>BWB(a>63tE)dRTqg{js z$Il{e=N#TJtg_PP+}j2ohuxtb0YDBs(hwQIuV&=DP=yTuh=}X@HY8iCz{DZlzfG?B zV|hU{d<9uFYk_9!vNa(tfNVghv)sF{RyUKj1UMf@Uv7VUOOnA?yQ$CUUYnL3vXxA? z)A26ajLlj=o{}R*r2~$3Kx~C)W0MaXT%ktS7QYHrAtN^dD}hG0Jq^JM*6TD$clg!0ZgVn=}glH_bpR*-^`faKNV|fq((5x@Af4 zdSQ)DGnQlLVRu5~&JEc6+S4cH>;d`OHjzXCy9g?VaJ40S1(#mJCc+R0^3=mhhjp_Pt3dtU_-LNm27C)-g3#mGKO=rb?f5R`WJL z4lLtif`xtPC`8tI90&lkab3z@(HV6@9S3iTbw0cRzpv=UGsBMCXUDetenL4{%O4Qx z9^7&zo%kxW)2s+Az@uWkME9f=_UW!wrU3*TXMl=q>2o%G098J_NakR9OyWs74PMRL ztkG0)?}kI~2m3_t+eV(hkqeu*0p-P@aSJzEG*R@oq7N0c3A1^4_RMo!2{kQkNr~jQ ztFOC_JdhGv_qre@q$T#JDvlEDXPp8%03qa*730`LHd6|?FAB(*@}Xlk^W6lHq%9LR z`O5ubuln(MdVRSopenwNwal6WfsYS0W8SBtx~)UR0K#+fX&FFb4;)jwv((~&T0S8$ zqQxpnl^DQq6M`zwNK9E#egz#e{rUB6_L)S>pZ-rblndAH5t7d?TJLC#>mS*l#J*3U zcjWqE#s}CW(;NAI#)t9K3qupAjNZ)W%7ct9h&ZUhh*^=Kr~=`Z>3UGB-A2g}_Y1+v z#K;OR-W~O)UnvP1(**)M`H<5tgjlhJxIO|LxEuU_5}J2P6kphwJWGk(V zH4w8xnEn|R`Z!+nwo}smtKw3sq|_K~UnX6ayv|^aO5jrR#ebe%|kp;&(ez}o6 z8@HCGRXM$6^n?&@wc|%#y>(lPO@G`869sHFbV7bF>(5;Q4EnxYm1n0n z&)|VTSlDUAZboY;-s*gb;3a;i_3bOCZ^)G;JxopY3+*af^SdX!yle;+*6dKi<5_bB z9X&)j-_tu}gL}lGlL!c#raG&uf=u=TTLEpRpfG3acYo{OmHAjgQk7w6D(J98kq0hO z<+x`4c`#l7R5YOr&ZLk0M09YDq+QFwRWhVwi{T+y`)E1G<8^BV9}mDoobpM40!6MA z+dk|W%nq)w0h2?LlKOV3x_p6@hb@e53&L%~&;Zs>y?{-6=S9gS-pWTJf2gPTTYAjN znh@XUDj8|Sy}zviH6oVgD>fK zSW)fPWdp$TkYj^-@W8tCu1s# z12M5I5WlN0*w3@>q~4x8cFbx^vjReO4VvwbW^#2rv^7*s`F(zA5aZSQ8(Eve8Xo#D z1%xk@n3+q86{C^|)s_1njPRD-YL|)f5^~Werx%pN!7^))tn0uqDfrY}Q`eZkNMh^z z-hF;VZU(~zU@$UH^*&!mI=-wjwszSAU{rrbp+uvI+=mjs7hnEf6MC!t{OtGad*_8C z#qWJ=aqN9kC4Ska4)y!BGv277tNR@tz2vIJ{6h2{@e8IN8w0S*)q9?(;?a0g$FOa> zjkCN=f|C$TtSFxO3n0uM@tbl{tA?sxt!6}}1QH%I;v35lu6Q=s;!r*+DLG||3JD`j zC`ieYKXCSP!;2(d3Eq%Fd|73YD92*^2dAtKom?JX?GU6l2bEdFXb}w%fz*kGw2dI0 zRgE@RXOT_A7Rif$ezBX@;r>X=8wQ)i6_q!?sy5F$rLt-?vbVUpzGmU$=Yw;{?N1sv z&u<4;0Z_;|(ajrbi%5SNp;e`G4FI{70GN|;C{MrJ7ZSsir*URyQ6#rS=8O9ZLr^+6 zT5~#xxfoHpD^@kb8!B^Xa6X_T8ihL%}@zj{B*q! zxX8RQQz_?j=0K))aD={JtzC%DOXGfI149L&+XYEdSz%Rl(>(_oYBOg83BEn5TCgXG z{1EYabUOM13VtqV&A!_n3da2JKynfS(>!LT|ysl}MoTFpVG4jyINt z#B~GSpzG6S)Ps&ap0ShbH9=KZJyCJ<{VIV@->U5b|0d z$L_G};O{rwsC{OB8k3_j$+#d%(+U z_4VUN3!|;L-Nv+GQdkw}u%#t9Ry6!MLidTSRC)^&ZjRwih64>!y{z6?fBpPbTG_^= zW7DK#Y0B4|&k1@#3gkFeOr6}6GpP@^m`wV|H<<_XuyLPjlTbp;@dA{|;D;QlXDg4R zvUZQ;Xra0Yee&mL-&wS(>_XR2v8!rM)QzVfLK~E%x@a4Fn)tfPD;l9!unSoYY8ZrF z^@Munw8sUue(a;Iw;r7SV)EVq8lyd4>mMA2^rxLvFm`aOsvv*WOYY>BqqYk&%r zu`LxBht!;*|-BQ=>uq*HA z^KtaAw)^?H#~=E#d3p!=IL33Yy|MRSUSpylGazYY-tc9mBEPpW zC~-qENHHNa{yvylV|E#L^dPpGyby9-zQklRWWwzDSW_Cy0A(OHx{` z6l(cw0u}%KVFE+tNmar?CtwvtO#?Y{71%z(08tUa|DeRNDQpLG<}0jOMx2H@mx>D7 zas5XVcmDMIPxvGd82o^>ip7*4)z;Nd0xxjx|6kMq>e~zH}5T+u=N+%x87=>o_2T?M7r8> z;SGJli)5HGhXz~yfvHl7U;vwrj{5zyx`6@uS~`d^FrzVg1IT&E+|SFv>35!&P0sFq zOD+M3fPI$zf!lmD@$c|VUAH#p>y5bJ-P9stVmk;%>j?BLLCLtPPBU#OBzl?01{JFL zv)$`^4B|8d9%+CVxz!u~Yd<>QOQwdEDOAlq(}J_kg2{G%%IZ zpXnVs5bBUE*SspzXuZT1u=Kt-Ffj6zq&BDdX9pk7({q~(VYvmQQ9&iy2ndV?ObGjl zOCbUG|r6~ z`(5@58T_kJZ}~cAQrs9wC}9VRtKj zrYKUkQ>0xM(IhSD$f=?zsI6lPQ!yke_mfbHLq*kbL}5%~WM_*D*;68s9|RjsrV1St z!a|5(g6e^lF>EW-Z;j&%-9<$!6Q^zS0-*;fWqI+G>|XboMDxwn)!&Z`E4Ye0In8f3 zrc_^Q)8%^FnaZe5I^xQ|okG!HE3Amd6bkn;pa^4CoA}~m{$pqq@gwX!q|gJN?4PK9 zR>xQ6M3)|W=cw;oj;NwA@n0|utZIZx2HH=R24 z914AylQlnxzb6~iXBI>TD(v0HwD9~PJ)1QD#|lc0)vcsU(X^K%0>J7P4Cot_kZ&tY zqO>@)!e4G^#^umrK|yQkt*k6g3l{M>U&ajF!{7R9IXPLd=><74I(qe-hhux+a<2Ri zKtQkQ_mQEY{Sp8RCujGLYu=mA(WublW^O*a(c7a`!16Lk#CPNKM+KlLKT`|8p(r}|gb){+T(OLoQstZsii0*))K5FWE7#&d}uy8t3|4g3l>X{(8#SE&OF{aVo# zj#mJ12maJayAX*xLai$Wtf4&{+%igC(%D!Y1KR^sAvB{KR*+0_xz$B1yyXRWi+oLv zAIWd=Br{wB2+l!j{{^hfYIJ$51t+E2H;sM%guihW&a!`uEPZ~?-2-){Qk9MPf-xwb zprL09aL9`fq;uBD&?+9rnnb6_~;f9kqmGJ zwqf-kB9XN2q0}7mNwOyb<35;5*a#Xp6qWcu>NOtd zU#AFs)h8TD(`E(McuYO-bj=GdjVoFAQykZ(eX|Px)idZx7X5snv};; zV*}lznQGSU@@nj}X{^RIYhTvf4wg^`W!Mb7D?FOeQIO$bIGk$a(4jEP8+jjHK@S_HNQvbZ{3ee8k3ioAQhw?1HCjWt&V zzl}#!`t}V(^o2&*h287)95KzU&sP+oKgQQ{-muLN%b7s(_&A0>Y+2hXGsI~OxIvrj z+-H+oxn@@^3Oqxvt?(M`k2Uy&V_9;yIMeLa0|?^;Rpb)cy*;)%ozDc0ybyozm~eHc zl+^WL4f5yp_x)p(oH&{RP(o{k0uB@WLX!OtA8gxp;vn)J$Dv9{ne(F(=>eF2s%^Svpmp?hq zA%h4*7wG_Rlt9xyxW>Px)~7P{sxpD@Ufjz&8%CXZfUOsZAC;k2{-~pb%#Qs9uQUO; z8aFyzquY^r;cCsz+}rU>If-AMYqr-#8MS>?k*~8|N4OjU9~6~O_7Z+yToR9t;>XVc zG=F94^Uo7402R0(swBwPk;k4T`Y1)om3of6y>A()bue}kJ!mb8qj;2`i2;r4t3iZX zj6tHk@VPD520)4a>^EcO9|RJd5A3n@BVnVMn7cG{jKXCSYm`Qot~CiW_@k=6>#2x7 ziKh^%k%nPvrboTB&kAqnQG`&zoG=)(nVXp*B!CHui+sVb2!P2cfL9!$)% zvmjPa=XpE_akbq4Y3Fjqv2wKjHobU-cY3hh45Bym7u3k>7Q&1Dt>^Y0^r`q1!2J>H zxRv|*IMb8qeV3Ye`hET5Vg^nJa^T3JvO1=`4r3Vmy`19zc|`iSLG%#`*i(AJpjX*L zM3EwCf5>kT-yAlOtJW7j{=n*==r+DX^`|vf8t>_Pkoq^*={4bMOI3p-?gUY%A1#yZ zu>8ww0FoYXXkTsLap58aEElC*!t65iAs^B?L*Mv^ygnjNmW4Qr{N^CzV@AM$~WLX7E*(zWU5HSr_Gzf8EIO-_j$EUs)> zp6MKMI=yd$-8*ia^3N~#e|T-@35AWBj>4IPJ}d#(BF+(M1Z6Ia>+-mvjh@_Ajcg7Z z684N88H}Tqu3RJrs_@Ef89Ko7!;N9|gX^rcmx}j$|1yJfgUg%o@(dNR=ULKWH1$hd zNF*&E3QPO55Xf?Shnsue`+Exa4Zrsa-;c$ha?D4`f^eR#N4B>y@0P4A*8ok zo4g{WKZam3Z}M{W>WRwL^;mhW()+;)OcZeMwal*cLKJ$KX6AjBrM(_=?7{Y)GCV8U z9fQ(~*z}lstGAicky`o43JiVY{wg)O1_$Wi^9$I|ugu5FIkbP0KOc?;#svCr1?E#J zYc|$+0@L(->1$|MC-rz5bg!I^%6skDOG@al{KpEpXl0TiBxPwN0A@-o3o*cp`QY271_My7#AWVVAl4X@%-?%gs zqibKOQ!Bl^RF=w)nB-q6*4#7(#n%*PQ+*T0yd==4{*z95a}3v6({xvPbIu&(4|LDi zebnVrla+b^0X%W67)%bL%%JlO4eK3iAM_9)jsfMYDJOe;b3K3ya~wPf73t@d?r