Check-in [8559fc1005]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:add libwebsockets 2.0.3 (as in Debian 9.7) for undroidwish
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8559fc100523e73fa0f64a343e140b5c9f2cc8b6
User & Date: chw 2019-02-13 18:09:25
Context
2019-02-13
18:17
add tk upstream changes check-in: 788dec3465 user: chw tags: trunk
18:09
add libwebsockets 2.0.3 (as in Debian 9.7) for undroidwish check-in: 8559fc1005 user: chw tags: trunk
2019-02-12
06:15
improvements in experimental jsmpeg SDL video driver check-in: e7128384f3 user: chw tags: trunk
Changes

Added undroid/libwebsockets/Android.mk.



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# example Android Native Library makefile
# contributed by Gregory Junker <ggjunker@gmail.com>

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libwebsockets
LOCAL_CFLAGS    := -DLWS_BUILTIN_GETIFADDRS
LWS_LIB_PATH	:= ../../../shared/libwebsockets/lib
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/$(LWS_LIB_PATH)
LOCAL_SRC_FILES := \
	$(LWS_LIB_PATH)/base64-decode.c \
	$(LWS_LIB_PATH)/client.c \
	$(LWS_LIB_PATH)/client-handshake.c \
	$(LWS_LIB_PATH)/client-parser.c \
	$(LWS_LIB_PATH)/daemonize.c \
	$(LWS_LIB_PATH)/extension.c \
	$(LWS_LIB_PATH)/extension-deflate-frame.c \
	$(LWS_LIB_PATH)/extension-deflate-stream.c \
	$(LWS_LIB_PATH)/getifaddrs.c \
	$(LWS_LIB_PATH)/handshake.c \
	$(LWS_LIB_PATH)/libwebsockets.c \
	$(LWS_LIB_PATH)/md5.c \
	$(LWS_LIB_PATH)/output.c \
	$(LWS_LIB_PATH)/parsers.c \
	$(LWS_LIB_PATH)/sha-1.c

include $(BUILD_STATIC_LIBRARY)

Added undroid/libwebsockets/CMakeLists.txt.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
cmake_minimum_required(VERSION 2.8)

if(NOT DEFINED CMAKE_BUILD_TYPE)
	set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type")
endif()

project(libwebsockets C)

set(PACKAGE "libwebsockets")
set(CPACK_PACKAGE_NAME "${PACKAGE}")
set(CPACK_PACKAGE_VERSION_MAJOR "2")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "3")
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_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}")
set(SOVERSION "8.1")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
set(VERSION "${CPACK_PACKAGE_VERSION}")

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(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")

message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'")

# 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
    OUTPUT_VARIABLE GIT_HASH
    OUTPUT_STRIP_TRAILING_WHITESPACE
    )
	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})
    message("Git commit hash: ${LWS_BUILD_HASH}")
endif()

set(LWS_USE_BUNDLED_ZLIB_DEFAULT OFF)
if(WIN32)
	set(LWS_USE_BUNDLED_ZLIB_DEFAULT ON)
endif()

option(LWS_WITH_STATIC "Build the static version of the library" ON)
option(LWS_WITH_SHARED "Build the shared version of the library" ON)
option(LWS_WITH_SSL "Include SSL support (default OpenSSL, wolfSSL if LWS_USE_WOLFSSL is set)" ON)
option(LWS_USE_CYASSL "Use CyaSSL replacement for OpenSSL. When setting this, you also need to specify LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS" OFF)
option(LWS_USE_WOLFSSL "Use wolfSSL replacement for OpenSSL. When setting this, you also need to specify LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS" OFF)
option(LWS_USE_POLARSSL "Use Polarssl (or mbedtls < 2.0) replacement for OpenSSL. When setting this, you also need to specify LWS_POLARSSL_LIBRARIES and LWS_POLARSSL_INCLUDE_DIRS" OFF)
option(LWS_USE_MBEDTLS "Use mbedTLS (>=2.0) replacement for OpenSSL. When setting this, you also need to specify LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS" OFF)
option(LWS_WITH_ZLIB "Include zlib support (required for extensions)" ON)
option(LWS_WITH_LIBEV "Compile with support for libev" OFF)
option(LWS_WITH_LIBUV "Compile with support for libuv" OFF)
option(LWS_USE_BUNDLED_ZLIB "Use bundled zlib version (Windows only)" ${LWS_USE_BUNDLED_ZLIB_DEFAULT})
option(LWS_SSL_CLIENT_USE_OS_CA_CERTS "SSL support should make use of the OS-installed CA root certs" ON)
option(LWS_WITHOUT_BUILTIN_GETIFADDRS "Don't use the BSD getifaddrs implementation from libwebsockets if it is missing (this will result in a compilation error) ... The default is to assume that your libc provides it. On some systems such as uclibc it doesn't exist." OFF)
option(LWS_WITHOUT_BUILTIN_SHA1 "Don't build the lws sha-1 (eg, because openssl will provide it" OFF)
option(LWS_WITHOUT_CLIENT "Don't build the client part of the library" OFF)
option(LWS_WITHOUT_SERVER "Don't build the server part of the library" OFF)
option(LWS_LINK_TESTAPPS_DYNAMIC "Link the test apps to the shared version of the library. Default is to link statically" OFF)
option(LWS_WITHOUT_TESTAPPS "Don't build the libwebsocket-test-apps" OFF)
option(LWS_WITHOUT_TEST_SERVER "Don't build the test server" OFF)
option(LWS_WITHOUT_TEST_SERVER_EXTPOLL "Don't build the test server version that uses external poll" OFF)
option(LWS_WITHOUT_TEST_PING "Don't build the ping test application" OFF)
option(LWS_WITHOUT_TEST_ECHO "Don't build the echo test application" OFF)
option(LWS_WITHOUT_TEST_CLIENT "Don't build the client test application" OFF)
option(LWS_WITHOUT_TEST_FRAGGLE "Don't build the ping test application" OFF)
option(LWS_WITHOUT_EXTENSIONS "Don't compile with extensions" OFF)
option(LWS_WITH_LATENCY "Build latency measuring code into the library" OFF)
option(LWS_WITHOUT_DAEMONIZE "Don't build the daemonization api" ON)
option(LWS_IPV6 "Compile with support for ipv6" OFF)
option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket" OFF)
option(LWS_WITH_HTTP2 "Compile with support for http2" OFF)
option(LWS_MBED3 "Platform is MBED3" OFF)
option(LWS_SSL_SERVER_WITH_ECDH_CERT "Include SSL server use ECDH certificate" OFF)
option(LWS_WITH_CGI "Include CGI (spawn process with network-connected stdin/out/err) APIs" OFF)
option(LWS_WITH_HTTP_PROXY "Support for rewriting HTTP proxying" OFF)
option(LWS_WITH_LWSWS "Libwebsockets Webserver" OFF)
option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF)
option(LWS_WITH_ACCESS_LOG "Support generating Apache-compatible access logs" OFF)
option(LWS_WITH_SERVER_STATUS "Support json + jscript server monitoring" OFF)

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)
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 (DEFINED YOTTA_WEBSOCKETS_VERSION_STRING)

set(LWS_WITH_SHARED OFF)
set(LWS_WITH_SSL OFF)
set(LWS_WITH_ZLIB OFF)
set(LWS_WITHOUT_CLIENT ON)
set(LWS_WITHOUT_TESTAPPS ON)
set(LWS_WITHOUT_EXTENSIONS ON)
set(LWS_WITH_PLUGINS OFF)
set(LWS_MBED3 ON)
# this implies no pthreads in the lib
set(LWS_MAX_SMP 1)

endif()

if (WIN32)
# this implies no pthreads in the lib
set(LWS_MAX_SMP 1)
endif()


if (LWS_WITHOUT_SERVER)
set(LWS_WITH_LWSWS OFF)
endif()

if (LWS_WITH_HTTP_PROXY AND (LWS_WITHOUT_CLIENT OR LWS_WITHOUT_SERVER))
	message(FATAL_ERROR "You have to enable both client and server for http proxy")
endif()

# Allow the user to override installation directories.
set(LWS_INSTALL_LIB_DIR       lib CACHE PATH "Installation directory for libraries")
set(LWS_INSTALL_BIN_DIR       bin CACHE PATH "Installation directory for executables")
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_USE_CYASSL AND LWS_USE_WOLFSSL)
	message(FATAL_ERROR "LWS_USE_CYASSL and LWS_USE_WOLFSSL are mutually exclusive!")
endif()
if (LWS_USE_CYASSL)
	# Copy CyaSSL options to the wolfSSL options
	set(LWS_USE_WOLFSSL ${LWS_USE_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 (LWS_WITHOUT_CLIENT AND LWS_WITHOUT_SERVER)
	message(FATAL_ERROR "Makes no sense to compile with neither client nor server.")
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)
	if (NOT LWS_WITH_ZLIB)
		message(FATAL_ERROR "zlib is required for extensions.")
	endif()
endif()

set(LWS_ZLIB_LIBRARIES CACHE PATH "Path to the zlib library")
set(LWS_ZLIB_INCLUDE_DIRS CACHE PATH "Path to the zlib 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_POLARSSL_LIBRARIES CACHE PATH "Path to the PolarSSL library")
set(LWS_POLARSSL_INCLUDE_DIRS CACHE PATH "Path to the PolarSSL include directory")
set( 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")

if (NOT LWS_WITH_SSL)
	set(LWS_WITHOUT_BUILTIN_SHA1 OFF)
endif()

if (LWS_WITH_SSL AND NOT LWS_USE_WOLFSSL AND NOT LWS_USE_POLARSSL AND NOT LWS_USE_MBEDTLS)
	if ("${LWS_OPENSSL_LIBRARIES}" STREQUAL "" OR "${LWS_OPENSSL_INCLUDE_DIRS}" STREQUAL "")
	else()
		set(OPENSSL_LIBRARIES ${LWS_OPENSSL_LIBRARIES})
		set(OPENSSL_INCLUDE_DIRS ${LWS_OPENSSL_INCLUDE_DIRS})
		set(OPENSSL_FOUND 1)
	endif()
endif()

if (LWS_WITH_SSL AND LWS_USE_WOLFSSL)
	if ("${LWS_WOLFSSL_LIBRARIES}" STREQUAL "" OR "${LWS_WOLFSSL_INCLUDE_DIRS}" STREQUAL "")
		if (NOT WOLFSSL_FOUND)
			if (LWS_USE_CYASSL)
				message(FATAL_ERROR "You must set LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS when LWS_USE_CYASSL is turned on.")
			else()
				message(FATAL_ERROR "You must set LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS when LWS_USE_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)
	if (LWS_USE_CYASSL)
		set(USE_OLD_CYASSL 1)
	endif()
endif()

if (LWS_WITH_SSL AND LWS_USE_POLARSSL)
	if ("${LWS_POLARSSL_LIBRARIES}" STREQUAL "" OR "${LWS_POLARSSL_INCLUDE_DIRS}" STREQUAL "")
		if (NOT POLARSSL_FOUND)
			message(FATAL_ERROR "You must set LWS_POLARSSL_LIBRARIES and LWS_POLARSSL_INCLUDE_DIRS when LWS_USE_POLARSSL is turned on.")
		endif()
	else()
		set(POLARSSL_LIBRARIES ${LWS_POLARSSL_LIBRARIES})
		set(POLARSSL_INCLUDE_DIRS ${LWS_POLARSSL_INCLUDE_DIRS})
		set(POLARSSL_FOUND 1)
	endif()
	set(USE_POLARSSL 1)
endif()

if (LWS_WITH_SSL AND LWS_USE_MBEDTLS)
	if ("${LWS_MBEDTLS_LIBRARIES}" STREQUAL "" OR "${LWS_MBEDTLS_INCLUDE_DIRS}" STREQUAL "")
		if (NOT MBEDTLS_FOUND)
			message(FATAL_ERROR "You must set LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS when LWS_USE_MBEDTLS is turned on.")
		endif()
	else()
		set(MBEDTLS_LIBRARIES ${LWS_MBEDTLS_LIBRARIES})
		set(MBEDTLS_INCLUDE_DIRS ${LWS_MBEDTLS_INCLUDE_DIRS})
		set(MBEDTLS_FOUND 1)
	endif()
	set(USE_MBEDTLS 1)
endif()

if (LWS_WITH_ZLIB AND NOT LWS_USE_BUNDLED_ZLIB)
	if ("${LWS_ZLIB_LIBRARIES}" STREQUAL "" OR "${LWS_ZLIB_INCLUDE_DIRS}" STREQUAL "")
	else()
		set(ZLIB_LIBRARIES ${LWS_ZLIB_LIBRARIES})
		set(ZLIB_INCLUDE_DIRS ${LWS_ZLIB_INCLUDE_DIRS})
		set(ZLIB_FOUND 1)
	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()


# FIXME: This must be runtime-only option.
# 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_IPV6)
		set(LWS_IPV6 OFF)
		message(WARNING "IPv6 does not currently work on Windows!")
	endif()
        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()

if (LWS_WITHOUT_EXTENSIONS)
	set(LWS_NO_EXTENSIONS 1)
endif()

if (LWS_WITH_SSL)
	set(LWS_OPENSSL_SUPPORT 1)
endif()

if (LWS_SSL_CLIENT_USE_OS_CA_CERTS)
	set(LWS_SSL_CLIENT_USE_OS_CA_CERTS 1)
endif()

if (LWS_WITH_LATENCY)
	set(LWS_LATENCY 1)
endif()

if (LWS_WITHOUT_DAEMONIZE OR WIN32)
	set(LWS_NO_DAEMONIZE 1)
endif()

if (LWS_WITHOUT_SERVER)
	set(LWS_NO_SERVER 1)
endif()

if (LWS_WITHOUT_CLIENT)
	set(LWS_NO_CLIENT 1)
endif()

if (LWS_WITH_LIBEV)
	set(LWS_USE_LIBEV 1)
endif()

if (LWS_WITH_LIBUV)
	set(LWS_USE_LIBUV 1)
endif()

if (LWS_IPV6)
	set(LWS_USE_IPV6 1)
endif()

if (LWS_UNIX_SOCK)
    set(LWS_USE_UNIX_SOCK 1)
endif()

if (LWS_WITH_HTTP2)
	set(LWS_USE_HTTP2 1)
endif()

if ("${LWS_MAX_SMP}" STREQUAL "")
	set(LWS_MAX_SMP 32)
endif()


#if (LWS_MBED3)
#	set(CMAKE_C_FLAGS "-D_DEBUG ${CMAKE_C_FLAGS}")
#endif()

if (MINGW)
	set(LWS_MINGW_SUPPORT 1)
	set(CMAKE_C_FLAGS "-D__USE_MINGW_ANSI_STDIO ${CMAKE_C_FLAGS}")
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}")
	CHECK_C_SOURCE_COMPILES(
		"
		#include <stdio.h>
		static KEYWORD void a() {}
		int main(int argc, char **argv) { a(); return 0; }
		" LWS_HAVE_${KEYWORD})
endforeach()

if (NOT LWS_HAVE_inline)
	if (LWS_HAVE___inline__)
		set(inline __inline__)
	elseif(LWS_HAVE___inline)
		set(inline __inline)
	endif()
endif()

# Put the libaries and binaries that get built into directories at the
# top of the build tree rather than in hard-to-find leaf directories. 
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")

# Put absolute path of dynamic libraries into the object code. Some
# 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)

if (LWS_WITHOUT_BUILTIN_SHA1)
	set(LWS_SHA1_USE_OPENSSL_NAME 1)
endif()

CHECK_FUNCTION_EXISTS(bzero LWS_HAVE_BZERO)
CHECK_FUNCTION_EXISTS(fork LWS_HAVE_FORK)
CHECK_FUNCTION_EXISTS(getenv LWS_HAVE_GETENV)
CHECK_FUNCTION_EXISTS(malloc LWS_HAVE_MALLOC)
CHECK_FUNCTION_EXISTS(memset LWS_HAVE_MEMSET)
CHECK_FUNCTION_EXISTS(realloc LWS_HAVE_REALLOC)
CHECK_FUNCTION_EXISTS(socket LWS_HAVE_SOCKET)
CHECK_FUNCTION_EXISTS(strerror LWS_HAVE_STRERROR)
CHECK_FUNCTION_EXISTS(vfork LWS_HAVE_VFORK)
CHECK_FUNCTION_EXISTS(execvpe LWS_HAVE_EXECVPE)
CHECK_FUNCTION_EXISTS(getifaddrs LWS_HAVE_GETIFADDRS)
CHECK_FUNCTION_EXISTS(snprintf LWS_HAVE_SNPRINTF)
CHECK_FUNCTION_EXISTS(_snprintf LWS_HAVE__SNPRINTF)
CHECK_FUNCTION_EXISTS(_vsnprintf LWS_HAVE__VSNPRINTF)
CHECK_FUNCTION_EXISTS(getloadavg LWS_HAVE_GETLOADAVG)

if (NOT LWS_HAVE_GETIFADDRS)
	if (LWS_WITHOUT_BUILTIN_GETIFADDRS)
		message(FATAL_ERROR "No getifaddrs was found on the system. Turn off the LWS_WITHOUT_BUILTIN_GETIFADDRS compile option to use the supplied BSD version.")
	endif()
	set(LWS_BUILTIN_GETIFADDRS 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)
CHECK_INCLUDE_FILE(inttypes.h LWS_HAVE_INTTYPES_H)
CHECK_INCLUDE_FILE(memory.h LWS_HAVE_MEMORY_H)
CHECK_INCLUDE_FILE(netinet/in.h LWS_HAVE_NETINET_IN_H)
CHECK_INCLUDE_FILE(stdint.h LWS_HAVE_STDINT_H)
CHECK_INCLUDE_FILE(stdlib.h LWS_HAVE_STDLIB_H)
CHECK_INCLUDE_FILE(strings.h LWS_HAVE_STRINGS_H)
CHECK_INCLUDE_FILE(string.h LWS_HAVE_STRING_H)
CHECK_INCLUDE_FILE(sys/prctl.h LWS_HAVE_SYS_PRCTL_H)
CHECK_INCLUDE_FILE(sys/socket.h LWS_HAVE_SYS_SOCKET_H)
CHECK_INCLUDE_FILE(sys/stat.h LWS_HAVE_SYS_STAT_H)
CHECK_INCLUDE_FILE(sys/types.h LWS_HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILE(unistd.h LWS_HAVE_UNISTD_H)
CHECK_INCLUDE_FILE(vfork.h LWS_HAVE_VFORK_H)

if (LWS_WITH_ZLIB AND NOT LWS_USE_BUNDLED_ZLIB)
	CHECK_INCLUDE_FILE(zlib.h LWS_HAVE_ZLIB_H)
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)

# These don't work Cross...
#CHECK_TYPE_SIZE(pid_t PID_T_SIZE)
#CHECK_TYPE_SIZE(size_t SIZE_T_SIZE)
#CHECK_TYPE_SIZE("void *" LWS_SIZEOFPTR LANGUAGE C)

if (NOT PID_T_SIZE)
	set(pid_t int)
endif()

if (NOT SIZE_T_SIZE)
	set(size_t "unsigned int")
endif()

if (NOT LWS_HAVE_MALLOC)
	set(malloc rpl_malloc)
endif()

if (NOT LWS_HAVE_REALLOC)
	set(realloc rpl_realloc)
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/private-libwebsockets.h)

set(HDR_PUBLIC
	"${PROJECT_SOURCE_DIR}/lib/libwebsockets.h"
	"${PROJECT_BINARY_DIR}/lws_config.h")

set(SOURCES
	lib/base64-decode.c
	lib/handshake.c
	lib/libwebsockets.c
	lib/service.c
	lib/pollfd.c
	lib/output.c
	lib/parsers.c
	lib/context.c
	lib/alloc.c
	lib/header.c)

if (NOT LWS_WITHOUT_CLIENT)
	list(APPEND SOURCES
		lib/client.c
		lib/client-handshake.c
		lib/client-parser.c)
endif()

if (LWS_WITH_SSL)
	list(APPEND SOURCES
		lib/ssl.c)
		
	if (NOT LWS_WITHOUT_SERVER)
		list(APPEND SOURCES
		lib/ssl-server.c)
	endif()
	if (NOT LWS_WITHOUT_CLIENT)
		list(APPEND SOURCES
		lib/ssl-client.c)
	endif()
endif()

if (NOT LWS_WITHOUT_BUILTIN_SHA1)
	list(APPEND SOURCES
		lib/sha-1.c)
endif()

if (LWS_WITH_HTTP2)
	list(APPEND SOURCES
		lib/http2.c
		lib/hpack.c
		lib/ssl-http2.c)
endif()
# select the active platform files

if (WIN32)
	list(APPEND SOURCES
		lib/lws-plat-win.c)
else()
	if (LWS_MBED3)
		list(APPEND SOURCES
			lib/lws-plat-mbed3.cpp
			lib/lws-plat-mbed3.c)
	else()
		list(APPEND SOURCES
			lib/lws-plat-unix.c)
	endif()
endif()

if (NOT LWS_WITHOUT_SERVER)
	list(APPEND SOURCES
		lib/server.c
		lib/server-handshake.c)
endif()

if (NOT LWS_WITHOUT_EXTENSIONS)
	list(APPEND HDR_PRIVATE
		lib/extension-permessage-deflate.h)
	list(APPEND SOURCES
		lib/extension.c
		lib/extension-permessage-deflate.c)
endif()

if (LWS_WITH_HTTP_PROXY)
	list(APPEND SOURCES
		lib/rewrite.c)
endif()

if (LWS_WITH_LIBEV)
	list(APPEND SOURCES
		lib/libev.c)
endif()

if (LWS_WITH_LIBUV)
	list(APPEND SOURCES
		lib/libuv.c)
endif()

# Add helper files for Windows.
if (WIN32)
	set(WIN32_HELPERS_PATH win32port/win32helpers)
	include_directories(${WIN32_HELPERS_PATH})
else()
	# Unix.
	if (NOT LWS_WITHOUT_DAEMONIZE)
		list(APPEND SOURCES
			lib/daemonize.c)
	endif()
endif()

if (UNIX)
	if (NOT LWS_HAVE_GETIFADDRS)
		list(APPEND HDR_PRIVATE lib/getifaddrs.h)
		list(APPEND SOURCES lib/getifaddrs.c)
	endif()
endif()

if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
    include (CheckCCompilerFlag)
    CHECK_C_COMPILER_FLAG(-fvisibility=hidden LWS_HAVE_VISIBILITY)
    if (LWS_HAVE_VISIBILITY)
                set(VISIBILITY_FLAG -fvisibility=hidden)
    endif()
    if (UNIX)
               set(CMAKE_C_FLAGS "-Wall -Werror ${VISIBILITY_FLAG} ${CMAKE_C_FLAGS}" )
    else(UNIX)
               set(CMAKE_C_FLAGS "-Wall ${VISIBILITY_FLAG} ${CMAKE_C_FLAGS}" )
    endif(UNIX)
endif ()

if ((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT LWS_WITHOUT_TESTAPPS)
    if (UNIX)
	# jeez clang understands -pthread but dies if he sees it at link time!
	# http://stackoverflow.com/questions/2391194/what-is-gs-pthread-equiv-in-clang
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread" )
    endif()
endif()

if ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
	# otherwise osx blows a bunch of openssl deprecated api errors
	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations" )
endif()

source_group("Headers Private"  FILES ${HDR_PRIVATE})
source_group("Headers Public"   FILES ${HDR_PUBLIC})
source_group("Sources"          FILES ${SOURCES})

#
# Create the lib.
#
set(LWS_LIBRARIES)

if (LWS_WITH_STATIC)
	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()
endif()

if (LWS_WITH_SHARED)
	add_library(websockets_shared SHARED
				${HDR_PRIVATE}
				${HDR_PUBLIC}
				${SOURCES})
	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()
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 (CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
	foreach(lib ${LWS_LIBRARIES})
		set_target_properties(${lib}
			PROPERTIES
			SOVERSION ${SOVERSION})
	endforeach()
endif()

set(LIB_LIST)

#
# Find libraries.
#

#
# ZLIB (Only needed for deflate extensions).
#
if (LWS_WITH_ZLIB)
	if (LWS_USE_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}/gzclose.c
				${WIN32_ZLIB_PATH}/gzio.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)
		find_package(ZLIB REQUIRED)
	endif()
	message("zlib include dirs: ${ZLIB_INCLUDE_DIRS}")
	message("zlib libraries: ${ZLIB_LIBRARIES}")
	include_directories(${ZLIB_INCLUDE_DIRS})
	list(APPEND LIB_LIST ${ZLIB_LIBRARIES})
endif()

#
# OpenSSL
#
if (LWS_WITH_SSL)
	message("Compiling with SSL support")
	set(chose_ssl 0)
	if (LWS_USE_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_USE_CYASSL)
			foreach(inc ${WOLFSSL_INCLUDE_DIRS})
				include_directories("${inc}" "${inc}/cyassl")
			endforeach()
		else()
			foreach(inc ${WOLFSSL_INCLUDE_DIRS})
				include_directories("${inc}" "${inc}/wolfssl")
			endforeach()
		endif()

		list(APPEND LIB_LIST "${WOLFSSL_LIBRARIES}")
		set(chose_ssl 1)
	endif()

	if (LWS_USE_POLARSSL)
		message("POLARSSL include dir: ${POLARSSL_INCLUDE_DIRS}")
		message("POLARSSL libraries: ${POLARSSL_LIBRARIES}")

		foreach(inc ${POLARSSL_INCLUDE_DIRS})
			include_directories("${inc}" "${inc}/polarssl")
		endforeach()

		list(APPEND LIB_LIST "${POLARSSL_LIBRARIES}")
		set(chose_ssl 1)
	endif()
	
	if (LWS_USE_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)
			# TODO: Add support for STATIC also.
			find_package(OpenSSL REQUIRED)
			set(OPENSSL_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}")
		endif()

		message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIRS}")
		message("OpenSSL libraries: ${OPENSSL_LIBRARIES}")

		include_directories("${OPENSSL_INCLUDE_DIRS}")
		list(APPEND LIB_LIST ${OPENSSL_LIBRARIES})

	# older (0.98) Openssl lacks this
	set(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()
	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_HTTP_PROXY)
	find_library(LIBHUBBUB_LIBRARIES NAMES libhubbub)
	list(APPEND LIB_LIST ${LIBHUBBUB_LIBRARIES} )
endif()


#
# Platform specific libs.
#
if (WINCE)
	list(APPEND LIB_LIST ws2.lib)
elseif (WIN32)
	list(APPEND LIB_LIST ws2_32.lib)
endif()

if (UNIX)
	list(APPEND LIB_LIST m)
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})
CHECK_FUNCTION_EXISTS(SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param)
CHECK_FUNCTION_EXISTS(X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host)
set(CMAKE_REQUIRED_LIBRARIES ${temp})
# Generate the lws_config.h that includes all the public compilation settings.
configure_file(
       "${PROJECT_SOURCE_DIR}/lws_config.h.in"
       "${PROJECT_BINARY_DIR}/lws_config.h")

# Generate the lws_config.h that includes all the private compilation settings.
configure_file(
       "${PROJECT_SOURCE_DIR}/lws_config_private.h.in"
       "${PROJECT_BINARY_DIR}/lws_config_private.h")



#
# Test applications
#
set(TEST_APP_LIST)
if (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)
		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 (LWS_WITH_SSL AND NOT LWS_USE_WOLFSSL AND NOT LWS_USE_POLARSSL AND NOT LWS_USE_MBEDTLS)
		message("Searching for OpenSSL executable and dlls")
		find_package(OpenSSLbins)
		message("OpenSSL executable: ${OPENSSL_EXECUTABLE}")
	endif()

	if (UNIX AND LWS_WITH_PLUGINS)
		set(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
		target_link_libraries(websockets dl)
	endif()

	if (NOT LWS_WITHOUT_SERVER)
		#
		# test-server
		#
		if (NOT LWS_WITHOUT_TEST_SERVER)
			create_test_app(test-server "test-server/test-server.c"
				"test-server/test-server-http.c"
				"test-server/test-server-dumb-increment.c"
				"test-server/test-server-mirror.c"
				"test-server/test-server-status.c"
				"test-server/test-server-echogen.c")
			if (UNIX)
				create_test_app(test-fuzxy "test-server/fuzxy.c"
					""
					""
					""
					""
					"")
			endif()
			if (UNIX AND NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")))
				create_test_app(test-server-pthreads
					"test-server/test-server-pthreads.c"
					"test-server/test-server-http.c"
					"test-server/test-server-dumb-increment.c"
					"test-server/test-server-mirror.c"
					"test-server/test-server-status.c"
					"test-server/test-server-echogen.c")
			endif()
			if (NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
				AND LWS_WITH_LIBEV)
				create_test_app(test-server-libev
					"test-server/test-server-libev.c"
					"test-server/test-server-http.c"
					"test-server/test-server-dumb-increment.c"
					"test-server/test-server-mirror.c"
					"test-server/test-server-status.c"
					"test-server/test-server-echogen.c")
			endif()
			if (NOT ((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
				AND LWS_WITH_LIBUV)
				create_test_app(test-server-libuv
					"test-server/test-server-libuv.c"
					"test-server/test-server-http.c"
					"test-server/test-server-dumb-increment.c"
					"test-server/test-server-mirror.c"
					"test-server/test-server-status.c"
					"test-server/test-server-echogen.c")
			endif()
		endif()

		#
		# test-server-extpoll
		#
		if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL)
			create_test_app(test-server-extpoll "test-server/test-server.c"
				"test-server/test-server-http.c"
				"test-server/test-server-dumb-increment.c"
				"test-server/test-server-mirror.c"
				"test-server/test-server-status.c"
				"test-server/test-server-echogen.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()

		#
		# test-server-v2.0
		#
		if (LWS_WITH_PLUGINS)
			create_test_app(
				test-server-v2.0
				"test-server/test-server-v2.0.c"
				""
				""
				""
				""
				"")
		endif()

		# Data files for running the test server.
		set(TEST_SERVER_DATA
			"${PROJECT_SOURCE_DIR}/test-server/favicon.ico"
			"${PROJECT_SOURCE_DIR}/test-server/leaf.jpg"
			"${PROJECT_SOURCE_DIR}/test-server/libwebsockets.org-logo.png"
			"${PROJECT_SOURCE_DIR}/test-server/test.html")

		# Generate self-signed SSL certs for the test-server.
		if (LWS_WITH_SSL AND OPENSSL_EXECUTABLE AND NOT LWS_WITHOUT_TEST_SERVER)
			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: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}\"")
					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}"
						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:1024 -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}"
						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:1024 -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()

		add_custom_command(TARGET test-server
						POST_BUILD 
						COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:test-server>/../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}" "$<TARGET_FILE_DIR:test-server>/../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-server/test-client.c" "" "" "" "" "")
		endif()

		#
		# test-fraggle
		#
		if (NOT LWS_WITHOUT_TEST_FRAGGLE)
			create_test_app(test-fraggle "test-server/test-fraggle.c" "" "" "" "" "")
		endif()

		#
		# test-ping
		#
		if (NOT LWS_WITHOUT_TEST_PING)
			create_test_app(test-ping "test-server/test-ping.c" "" "" "" "" "")
		endif()
		#
		# test-echo
		#
		if (NOT LWS_WITHOUT_TEST_ECHO)
			create_test_app(test-echo "test-server/test-echo.c" "" "" "" "" "")
		endif()

	endif(NOT LWS_WITHOUT_CLIENT)
	
	
	if (LWS_WITH_PLUGINS AND LWS_WITH_SHARED)
		macro(create_plugin PLUGIN_NAME MAIN_SRC)

		set(PLUGIN_SRCS ${MAIN_SRC})

		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)

		# 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
#			OUTPUT_NAME ${PLUGIN_NAME})

		list(APPEND PLUGINS_LIST ${PLUGIN_NAME})
		endmacro()
		

		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")
if (LWS_WITH_SERVER_STATUS)
		create_plugin(protocol_lws_server_status
			      "plugins/protocol_lws_server_status.c")
endif()
	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_USE_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}" "$<TARGET_FILE_DIR:${TARGET_BIN}>" VERBATIM)
				add_custom_command(TARGET ${TARGET_BIN}
					POST_BUILD
					COMMAND "${CMAKE_COMMAND}" -E copy "${SSLEAY_BIN}" "$<TARGET_FILE_DIR:${TARGET_BIN}>" VERBATIM)
			endforeach()
		endif()
	endif()
endif(NOT LWS_WITHOUT_TESTAPPS)

if (LWS_WITH_LWSWS)
		list(APPEND LWSWS_SRCS
			"lwsws/main.c"
			"lwsws/lejp.c"
			"lwsws/conf.c"
			"lwsws/http.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)

if (UNIX)
	# Generate documentation.
	# TODO: Fix this on Windows.
	message("Generating API documentation")
	file(GLOB C_FILES "${PROJECT_SOURCE_DIR}/lib/*.c")
	list(SORT C_FILES)
	execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${PROJECT_BINARY_DIR}/doc/")

	execute_process(
		COMMAND "${PROJECT_SOURCE_DIR}/scripts/kernel-doc" -html ${C_FILES} ${HDR_PUBLIC}
		OUTPUT_FILE "${PROJECT_BINARY_DIR}/doc/libwebsockets-api-doc.html"
		ERROR_QUIET)

	execute_process(
		COMMAND "${PROJECT_SOURCE_DIR}/scripts/kernel-doc" -text ${C_FILES} ${HDR_PUBLIC}
		OUTPUT_FILE "${PROJECT_BINARY_DIR}/doc/libwebsockets-api-doc.txt"
		ERROR_QUIET)

# 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)
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).
export(TARGETS ${LWS_LIBRARIES}
        FILE "${PROJECT_BINARY_DIR}/LibwebsocketsTargets.cmake")
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)

# Generate the config file for the installation tree.
get_filename_component(LWS_ABSOLUTE_INSTALL_CMAKE_DIR ${LWS_INSTALL_CMAKE_DIR} ABSOLUTE)
get_filename_component(LWS_ABSOLUTE_INSTALL_INCLUDE_DIR ${LWS_INSTALL_INCLUDE_DIR} ABSOLUTE)
file(RELATIVE_PATH 
    REL_INCLUDE_DIR 
    "${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 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 AND NOT LWS_WITHOUT_CLIENT)
	install(TARGETS test-client ${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)
if (LWS_WITH_CGI)
	set(CGI_TEST_SCRIPT "${PROJECT_SOURCE_DIR}/test-server/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()

# 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 (LWS_WITH_SERVER_STATUS)
	install(FILES plugins/server-status.html;plugins/lwsws-logo.png
		DESTINATION share/libwebsockets-test-server/server-status
			COMPONENT examples)
endif()
endif()

# Install the LibwebsocketsConfig.cmake and LibwebsocketsConfigVersion.cmake
install(FILES
               "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibwebsocketsConfig.cmake"
               "${PROJECT_BINARY_DIR}/LibwebsocketsConfigVersion.cmake"
               DESTINATION "${LWS_INSTALL_CMAKE_DIR}" COMPONENT dev)

# Install exports for the install-tree.
install(EXPORT LibwebsocketsTargets
		DESTINATION "${LWS_INSTALL_CMAKE_DIR}" COMPONENT dev)

# build subdir is not part of sources
set(CPACK_SOURCE_IGNORE_FILES $(CPACK_SOURCE_IGNORE_FILES) ".git" "build" "tgz" "tar.gz")

# 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 libwebsockets.spec)
endif()

message("---------------------------------------------------------------------")
message("  Settings:  (For more help do cmake -LH <srcpath>)")
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_USE_WOLFSSL = ${LWS_USE_WOLFSSL} (wolfSSL/CyaSSL replacement for OpenSSL)")
if (LWS_USE_WOLFSSL)
	message("   LWS_WOLFSSL_LIBRARIES = ${LWS_WOLFSSL_LIBRARIES}")
	message("   LWS_WOLFSSL_INCLUDE_DIRS = ${LWS_WOLFSSL_INCLUDE_DIRS}")
endif()
message(" LWS_USE_POLARSSL = ${LWS_USE_POLARSSL} (PolarSSL replacement for OpenSSL)")
message(" LWS_USE_MBEDTLS = ${LWS_USE_MBEDTLS} (mbedtls (nee Polarssl) 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_ECHO = ${LWS_WITHOUT_TEST_ECHO}")
message(" LWS_WITHOUT_TEST_CLIENT = ${LWS_WITHOUT_TEST_CLIENT}")
message(" LWS_WITHOUT_TEST_FRAGGLE = ${LWS_WITHOUT_TEST_FRAGGLE}")
message(" LWS_WITHOUT_EXTENSIONS = ${LWS_WITHOUT_EXTENSIONS}")
message(" LWS_WITH_LATENCY = ${LWS_WITH_LATENCY}")
message(" LWS_WITHOUT_DAEMONIZE = ${LWS_WITHOUT_DAEMONIZE}")
message(" LWS_USE_LIBEV = ${LWS_USE_LIBEV}")
message(" LWS_USE_LIBUV = ${LWS_USE_LIBUV}")
message(" LWS_IPV6 = ${LWS_IPV6}")
message(" LWS_UNIX_SOCK = ${LWS_UNIX_SOCK}")
message(" LWS_WITH_HTTP2 = ${LWS_WITH_HTTP2}")
message(" LWS_MBED3 = ${LWS_MBED3}")
message(" LWS_SSL_SERVER_WITH_ECDH_CERT = ${LWS_SSL_SERVER_WITH_ECDH_CERT}")
message(" LWS_MAX_SMP = ${LWS_MAX_SMP}")
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_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("---------------------------------------------------------------------")

# 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 websocket CACHE STRING "Libwebsocket static library")
endif()
if (LWS_WITH_SHARED)
	set(LIBWEBSOCKETS_LIBRARIES_SHARED websockets_shared CACHE STRING "Libwebsocket shared library")
endif()

# This must always be last!
include(CPack)

Added undroid/libwebsockets/FindLibWebSockets.cmake.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 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
)

Added undroid/libwebsockets/LICENSE.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
Libwebsockets and included programs are provided under the terms of the GNU
Library General Public License (LGPL) 2.1, with the following exceptions:

1) Static linking of programs with the libwebsockets library does not
constitute a derivative work and does not require the author to provide 
source code for the program, use the shared libwebsockets libraries, or
link their program against a user-supplied version of libwebsockets.

If you link the program to a modified version of libwebsockets, then the
changes to libwebsockets must be provided under the terms of the LGPL in
sections 1, 2, and 4.

2) You do not have to provide a copy of the libwebsockets license with
programs that are linked to the libwebsockets library, nor do you have to
identify the libwebsockets license in your program or documentation as
required by section 6 of the LGPL.

However, programs must still identify their use of libwebsockets. The
following example statement can be included in user documentation to
satisfy this requirement:

"[program] is based in part on the work of the libwebsockets  project
(https://libwebsockets.org)"

3) Some sources included have their own, more liberal licenses, or options
to get original sources with the liberal terms.

Original liberal license retained

  - lib/sha-1.c         - 3-clause BSD license retained, link to original
  - win32port/zlib      - ZLIB license (see zlib.h)

Relicensed to libwebsocket license

  - lib/base64-decode.c - relicensed to LGPL2.1+SLE, link to original
  - lib/daemonize.c     - relicensed from Public Domain to LGPL2.1+SLE,
                          link to original Public Domain version

Public Domain (CC-zero) to simplify reuse

  - test-server/*.c
  - test-server/*.h
  
4) lwsws (Libwebsocket web server) is a bundled application that is not
part of the libwebsockets library, it's a separate application that uses
the library.  The related sources are in a separate directory.  If you don't
distribute lwsws, you do not need to observe its license.

  - lwsws/lejp.c        - LGPL2.1
  - lwsws/lejp.h        - LGPL2.1
  - lwsws/[all else]    -  GPL2.1



                  GNU LESSER GENERAL PUBLIC LICENSE
                       Version 2.1, February 1999

 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
 as the successor of the GNU Library Public License, version 2, hence
 the version number 2.1.]

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.

  This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it.  You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.

  When we speak of free software, we are referring to freedom of use,
not price.  Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.

  To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights.  These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.

  For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

  We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.

  To protect each distributor, we want to make it very clear that
there is no warranty for the free library.  Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
 
  Finally, software patents pose a constant threat to the existence of
any free program.  We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder.  Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.

  Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License.  This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License.  We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.

  When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library.  The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom.  The Lesser General
Public License permits more lax criteria for linking other code with
the library.

  We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License.  It also provides other free software developers Less
of an advantage over competing non-free programs.  These disadvantages
are the reason we use the ordinary General Public License for many
libraries.  However, the Lesser license provides advantages in certain
special circumstances.

  For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard.  To achieve this, non-free programs must be
allowed to use the library.  A more frequent case is that a free
library does the same job as widely used non-free libraries.  In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.

  In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software.  For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.

  Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.

  The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
 
                  GNU LESSER GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

  A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

  The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

  "Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.

  Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.

  1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

  You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
 
  2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) The modified work must itself be a software library.

    b) You must cause the files modified to carry prominent notices
    stating that you changed the files and the date of any change.

    c) You must cause the whole of the work to be licensed at no
    charge to all third parties under the terms of this License.

    d) If a facility in the modified Library refers to a function or a
    table of data to be supplied by an application program that uses
    the facility, other than as an argument passed when the facility
    is invoked, then you must make a good faith effort to ensure that,
    in the event an application does not supply such function or
    table, the facility still operates, and performs whatever part of
    its purpose remains meaningful.

    (For example, a function in a library to compute square roots has
    a purpose that is entirely well-defined independent of the
    application.  Therefore, Subsection 2d requires that any
    application-supplied function or table used by this function must
    be optional: if the application does not supply it, the square
    root function must still compute square roots.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.
 
  Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

  This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

  4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

  If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

  5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

  However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.

  When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

  If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

  Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
 
  6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

  You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

    a) Accompany the work with the complete corresponding
    machine-readable source code for the Library including whatever
    changes were used in the work (which must be distributed under
    Sections 1 and 2 above); and, if the work is an executable linked
    with the Library, with the complete machine-readable "work that
    uses the Library", as object code and/or source code, so that the
    user can modify the Library and then relink to produce a modified
    executable containing the modified Library.  (It is understood
    that the user who changes the contents of definitions files in the
    Library will not necessarily be able to recompile the application
    to use the modified definitions.)

    b) Use a suitable shared library mechanism for linking with the
    Library.  A suitable mechanism is one that (1) uses at run time a
    copy of the library already present on the user's computer system,
    rather than copying library functions into the executable, and (2)
    will operate properly with a modified version of the library, if
    the user installs one, as long as the modified version is
    interface-compatible with the version that the work was made with.

    c) Accompany the work with a written offer, valid for at
    least three years, to give the same user the materials
    specified in Subsection 6a, above, for a charge no more
    than the cost of performing this distribution.

    d) If distribution of the work is made by offering access to copy
    from a designated place, offer equivalent access to copy the above
    specified materials from the same place.

    e) Verify that the user has already received a copy of these
    materials or that you have already sent this user a copy.

  For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

  It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
 
  7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

    a) Accompany the combined library with a copy of the same work
    based on the Library, uncombined with any other library
    facilities.  This must be distributed under the terms of the
    Sections above.

    b) Give prominent notice with the combined library of the fact
    that part of it is a work based on the Library, and explaining
    where to find the accompanying uncombined form of the same work.

  8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.

  9. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.

  10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
 
  11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded.  In such case, this License incorporates the limitation as if
written in the body of this License.

  13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
 
  14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

                            NO WARRANTY

  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

                     END OF TERMS AND CONDITIONS
 
           How to Apply These Terms to Your New Libraries

  If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change.  You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).

  To apply these terms, attach the following notices to the library.  It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.

    <one line to give the library's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the
  library `Frob' (a library for tweaking knobs) written by James Random Hacker.

  <signature of Ty Coon>, 1 April 1990
  Ty Coon, President of Vice

That's all there is to it!

Added undroid/libwebsockets/README.build.md.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
Introduction to CMake
---------------------

CMake is a multi-platform build tool that can generate build files for many
different target platforms. See more info at http://www.cmake.org

CMake also allows/recommends you to do "out of source"-builds, that is,
the build files are separated from your sources, so there is no need to
create elaborate clean scripts to get a clean source tree, instead you
simply remove your build directory.

Libwebsockets has been tested to build successfully on the following platforms
with SSL support (both OpenSSL/wolfSSL):

- Windows (Visual Studio)
- Windows (MinGW)
- Linux (x86 and ARM)
- OSX
- NetBSD

Building the library and test apps
----------------------------------

The project settings used by CMake to generate the platform specific build
files is called [CMakeLists.txt](CMakeLists.txt). CMake then uses one of its "Generators" to
output a Visual Studio project or Make file for instance. To see a list of
the available generators for your platform, simply run the "cmake" command.

Note that by default OpenSSL will be linked, if you don't want SSL support
see below on how to toggle compile options.

Building on Unix:
-----------------

1. Install CMake 2.8 or greater: http://cmake.org/cmake/resources/software.html
   (Most Unix distributions comes with a packaged version also)

2. Install OpenSSL.

3. Generate the build files (default is Make files):

    ```bash
	$ cd /path/to/src
	$ mkdir build
	$ cd build
	$ cmake ..
    ```

	(**NOTE**: The `build/`` directory can have any name and be located anywhere
	 on your filesystem, and that the argument `..` given to cmake is simply
	 the source directory of **libwebsockets** containing the [CMakeLists.txt](CMakeLists.txt)
	 project file. All examples in this file assumes you use "..")

	**NOTE2**:
	A common option you may want to give is to set the install path, same
	as --prefix= with autotools.  It defaults to /usr/local.
	You can do this by, eg

    ```bash
	$ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr ..
    ```

	**NOTE3**:
	On machines that want libraries in lib64, you can also add the
	following to the cmake line

    ```bash
	-DLIB_SUFFIX=64
    ```

	**NOTE4**:
	If you are building against a non-distro OpenSSL (eg, in order to get
	access to ALPN support only in newer OpenSSL versions) the nice way to
	express that in one cmake command is eg,

    ```bash
	$ cmake .. -DOPENSSL_ROOT_DIR=/usr/local/ssl \
		 -DCMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE=/usr/local/ssl \
		 -DLWS_WITH_HTTP2=1
    ```

	When you run the test apps using non-distro SSL, you have to force them
	to use your libs, not the distro ones

    ```bash
	$ LD_LIBRARY_PATH=/usr/local/ssl/lib libwebsockets-test-server --ssl
    ```

	To get it to build on latest openssl (2016-04-10) it needed this approach

    ```bash
	cmake .. -DLWS_WITH_HTTP2=1 -DLWS_OPENSSL_INCLUDE_DIRS=/usr/local/include/openssl -DLWS_OPENSSL_LIBRARIES="/usr/local/lib64/libssl.so;/usr/local/lib64/libcrypto.so"
    ```

	**NOTE5**:
	To build with debug info and _DEBUG for lower priority debug messages
	compiled in, use

    ```bash
	$ cmake .. -DCMAKE_BUILD_TYPE=DEBUG
    ````

4. Finally you can build using the generated Makefile:

    ```bash
	$ make
    ```

Quirk of cmake
--------------

When changing cmake options, for some reason the only way to get it to see the
changes sometimes is delete the contents of your build directory and do the
cmake from scratch.

Building on Windows (Visual Studio)
-----------------------------------
1. Install CMake 2.6 or greater: http://cmake.org/cmake/resources/software.html

2. Install OpenSSL binaries. http://www.openssl.org/related/binaries.html

   (**NOTE**: Preferably in the default location to make it easier for CMake to find them)

   **NOTE2**: 
   Be sure that OPENSSL_CONF environment variable is defined and points at 
   <OpenSSL install location>\bin\openssl.cfg
	 
3. Generate the Visual studio project by opening the Visual Studio cmd prompt:

   ```bash
   cd <path to src>
   md build
   cd build
   cmake -G "Visual Studio 10" ..
   ```

   (**NOTE**: There is also a cmake-gui available on Windows if you prefer that)
   
   **NOTE2**:
   See this link to find out the version number corresponding to your Visual Studio edition:
   http://superuser.com/a/194065

4. Now you should have a generated Visual Studio Solution in  your
   `<path to src>/build` directory, which can be used to build.

5. Some additional deps may be needed

 - iphlpapi.lib
 - psapi.lib
 - userenv.lib

6. If you're using libuv, you must make sure to compile libuv with the same multithread-dll / Mtd attributes as libwebsockets itself


Building on Windows (MinGW)
---------------------------
1. Install MinGW: http://sourceforge.net/projects/mingw/files

   (**NOTE**: Preferably in the default location C:\MinGW)

2. Fix up MinGW headers

   a) Add the following lines to C:\MinGW\include\winsock2.h:
   
   ```c
   #if(_WIN32_WINNT >= 0x0600)

   typedef struct pollfd {

       SOCKET  fd;
       SHORT   events;
       SHORT   revents;

   } WSAPOLLFD, *PWSAPOLLFD, FAR *LPWSAPOLLFD;

   WINSOCK_API_LINKAGE int WSAAPI WSAPoll(LPWSAPOLLFD fdArray, ULONG fds, INT timeout);

   #endif // (_WIN32_WINNT >= 0x0600)
   ```

   b) Create C:\MinGW\include\mstcpip.h and copy and paste the content from following link into it:
    
   http://wine-unstable.sourcearchive.com/documentation/1.1.32/mstcpip_8h-source.html

3. Install CMake 2.6 or greater: http://cmake.org/cmake/resources/software.html

4. Install OpenSSL binaries. http://www.openssl.org/related/binaries.html

   (**NOTE**: Preferably in the default location to make it easier for CMake to find them)

   **NOTE2**: 
   Be sure that OPENSSL_CONF environment variable is defined and points at 
   <OpenSSL install location>\bin\openssl.cfg

5. Generate the build files (default is Make files) using MSYS shell:

   ```bash
   $ cd /drive/path/to/src
   $ mkdir build
   $ cd build
   $ cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=C:/MinGW ..
   ```

   (**NOTE**: The `build/`` directory can have any name and be located anywhere
    on your filesystem, and that the argument `..` given to cmake is simply
    the source directory of **libwebsockets** containing the [CMakeLists.txt](CMakeLists.txt)
    project file. All examples in this file assumes you use "..")

   **NOTE2**:
   To generate build files allowing to create libwebsockets binaries with debug information
   set the CMAKE_BUILD_TYPE flag to DEBUG:

   ```bash
   $ cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=C:/MinGW -DCMAKE_BUILD_TYPE=DEBUG ..
   ```

6. Finally you can build using the generated Makefile and get the results deployed into your MinGW installation:

   ```bash
   $ make
   $ make install
   ```

Setting compile options
-----------------------

To set compile time flags you can either use one of the CMake gui applications
or do it via command line.

Command line
------------
To list avaialable options (ommit the H if you don't want the help text):

	cmake -LH ..

Then to set an option and build (for example turn off SSL support):

	cmake -DLWS_WITH_SSL=0 ..
or
	cmake -DLWS_WITH_SSL:BOOL=OFF ..

Building on mbed3
-----------------
MBED3 is a non-posix embedded OS targeted on Cortex M class chips.

https://www.mbed.com/

It's quite unlike any other Posixy platform since the OS is linked statically
in with lws to form one binary.

At the minute server-only is supported and due to bugs in mbed3 network support,
the port is of alpha quality.  However it can serve the test html, favicon.ico
and logo png and may be able to make ws connections.  The binary for that
including the OS, test app, lws and all the assets is only 117KB.

0) Today mbed3 only properly works on FRDM K64F $35 Freescale Dev Board with
1MB Flash, 256KB SRAM and Ethernet.

http://www.freescale.com/products/arm-processors/kinetis-cortex-m/k-series/k6x-ethernet-mcus/freescale-freedom-development-platform-for-kinetis-k64-k63-and-k24-mcus:FRDM-K64F

1) Get a working mbed3 environment with arm-none-eabi-cs toolchain
(available in Fedora, Ubuntu and other distros)

2) Confirm you can build things using yotta by following the getting started guide here

https://docs.mbed.com/docs/getting-started-mbed-os/en/latest/

3)

git clone https://github.com/warmcat/lws-test-server

and cd into it

4) mkdir -p yotta_modules ; cd yotta_modules

5) git clone https://github.com/warmcat/libwebsockets ; mv libwebsockets websockets ; cd ..

6) yotta target frdm-k64f-gcc

7) yotta install

8) yotta build


Unix GUI
--------
If you have a curses-enabled build you simply type:
(not all packages include this, my debian install does not for example).

	ccmake

Windows GUI
-----------
On windows CMake comes with a gui application:
	Start -> Programs -> CMake -> CMake (cmake-gui)

wolfSSL/CyaSSL replacement for OpenSSL
--------------------------------------
wolfSSL/CyaSSL is a lightweight SSL library targeted at embedded systems:
https://www.wolfssl.com/wolfSSL/Products-wolfssl.html

It contains a OpenSSL compatibility layer which makes it possible to pretty
much link to it instead of OpenSSL, giving a much smaller footprint.

**NOTE**: wolfssl needs to be compiled using the `--enable-opensslextra` flag for
this to work.

Compiling libwebsockets with wolfSSL
------------------------------------

```bash
cmake .. -DLWS_USE_WOLFSSL=1 \
	 -DLWS_WOLFSSL_INCLUDE_DIRS=/path/to/wolfssl \
	 -DLWS_WOLFSSL_LIBRARIES=/path/to/wolfssl/wolfssl.a ..
```

**NOTE**: On windows use the .lib file extension for `LWS_WOLFSSL_LIBRARIES` instead.

Compiling libwebsockets with CyaSSL
-----------------------------------

```bash
cmake .. -DLWS_USE_CYASSL=1 \
	 -DLWS_CYASSL_INCLUDE_DIRS=/path/to/cyassl \
	 -DLWS_CYASSL_LIBRARIES=/path/to/wolfssl/cyassl.a ..
```

**NOTE**: On windows use the .lib file extension for `LWS_CYASSL_LIBRARIES` instead.

Compiling libwebsockets with PolarSSL
-------------------------------------

Caution... at some point PolarSSL became MbedTLS.  But it did not happen all at once.
The name changed first then at mbedTLS 2.0 the apis changed.  So eg in Fedora 22,
there is an "mbedtls" package which is actually using polarssl for the include dir
and polarssl apis... this should be treated as polarssl then.

Example config for this case is

cmake .. -DLWS_USE_POLARSSL=1 -DLWS_POLARSSL_LIBRARIES=/usr/lib64/libmbedtls.so \
	 -DLWS_POLARSSL_INCLUDE_DIRS=/usr/include/polarssl/
	 

Building plugins outside of lws itself
--------------------------------------

The directory ./plugin-standalone/ shows how easy it is to create plugins
outside of lws itself.  First build lws itself with -DLWS_WITH_PLUGINS,
then use the same flow to build the standalone plugin

```
cd ./plugin-standalone
mkdir build
cd build
cmake ..
make && sudo make install
```

if you changed the default plugin directory when you built lws, you must
also give the same arguments to cmake here (eg,
` -DCMAKE_INSTALL_PREFIX:PATH=/usr/something/else...` )

Otherwise if you run lwsws or libwebsockets-test-server-v2.0, it will now
find the additional plugin "libprotocol_example_standalone.so"

```
lwsts[21257]:   Plugins:
lwsts[21257]:    libprotocol_dumb_increment.so
lwsts[21257]:    libprotocol_example_standalone.so
lwsts[21257]:    libprotocol_lws_mirror.so
lwsts[21257]:    libprotocol_lws_server_status.so
lwsts[21257]:    libprotocol_lws_status.so
```

If you have multiple vhosts, you must enable plugins at the vhost
additionally, discovered plugins are not enabled automatically for security
reasons.  You do this using info->pvo or for lwsws, in the JSON config.


Reproducing HTTP2.0 tests
-------------------------

You must have built and be running lws against a version of openssl that has
ALPN / NPN.  Most distros still have older versions.  You'll know it's right by
seeing

```bash
lwsts[4752]:  Compiled with OpenSSL support
lwsts[4752]:  Using SSL mode
lwsts[4752]:  HTTP2 / ALPN enabled
```

at lws startup.

For non-SSL HTTP2.0 upgrade

```bash
$ nghttp -nvasu http://localhost:7681/test.htm
```

For SSL / ALPN HTTP2.0 upgrade

```
$ nghttp -nvas https://localhost:7681/test.html
```

Cross compiling
---------------
To enable cross-compiling **libwebsockets** using CMake you need to create
a "Toolchain file" that you supply to CMake when generating your build files.
CMake will then use the cross compilers and build paths specified in this file
to look for dependencies and such.

**Libwebsockets** includes an example toolchain file [cross-arm-linux-gnueabihf.cmake](cross-arm-linux-gnueabihf.cmake)
you can use as a starting point.

The commandline to configure for cross with this would look like

```bash
$ cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/usr \
	 -DCMAKE_TOOLCHAIN_FILE=../cross-arm-linux-gnueabihf.cmake \
	 -DWITHOUT_EXTENSIONS=1 -DWITH_SSL=0
```

The example shows how to build with no external cross lib dependencies, you
need to provide the cross libraries otherwise.

**NOTE**: start from an EMPTY build directory if you had a non-cross build in there
	before the settings will be cached and your changes ignored.

Additional information on cross compilation with CMake:
	http://www.vtk.org/Wiki/CMake_Cross_Compiling

Memory efficiency
-----------------

Embedded server-only configuration without extensions (ie, no compression
on websocket connections), but with full v13 websocket features and http
server, built on ARM Cortex-A9:

Update at 8dac94d (2013-02-18)

```bash
$ ./configure --without-client --without-extensions --disable-debug --without-daemonize

Context Creation, 1024 fd limit[2]:   16720 (includes 12 bytes per fd)
Per-connection [3]:                      72 bytes, +1328 during headers

.text	.rodata	.data	.bss
11512	2784	288	4
```

This shows the impact of the major configuration with/without options at
13ba5bbc633ea962d46d using Ubuntu ARM on a PandaBoard ES.

These are accounting for static allocations from the library elf, there are
additional dynamic allocations via malloc.  These are a bit old now but give
the right idea for relative "expense" of features.

Static allocations, ARM9

|                                | .text   | .rodata | .data | .bss |
|--------------------------------|---------|---------|-------|------|
| All (no without)               | 35024   | 9940    | 336   | 4104 |
| without client                 | 25684   | 7144    | 336   | 4104 |
| without client, exts           | 21652   | 6288    | 288   | 4104 |
| without client, exts, debug[1] | 19756   | 3768    | 288   | 4104 |
| without server                 | 30304   | 8160    | 336   | 4104 |
| without server, exts           | 25382   | 7204    | 288   | 4104 |
| without server, exts, debug[1] | 23712   | 4256    | 288   | 4104 |

[1] `--disable-debug` only removes messages below `lwsl_notice`.  Since that is
the default logging level the impact is not noticeable, error, warn and notice
logs are all still there.

[2] `1024` fd per process is the default limit (set by ulimit) in at least Fedora
and Ubuntu.  You can make significant savings tailoring this to actual expected
peak fds, ie, at a limit of `20`, context creation allocation reduces to `4432 +
240 = 4672`)

[3] known header content is freed after connection establishment

Added undroid/libwebsockets/README.coding.md.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
Daemonization
-------------

There's a helper api `lws_daemonize` built by default that does everything you
need to daemonize well, including creating a lock file.  If you're making
what's basically a daemon, just call this early in your init to fork to a
headless background process and exit the starting process.

Notice stdout, stderr, stdin are all redirected to /dev/null to enforce your
daemon is headless, so you'll need to sort out alternative logging, by, eg,
syslog.


Maximum number of connections
-----------------------------

The maximum number of connections the library can deal with is decided when
it starts by querying the OS to find out how many file descriptors it is
allowed to open (1024 on Fedora for example).  It then allocates arrays that
allow up to that many connections, minus whatever other file descriptors are
in use by the user code.

If you want to restrict that allocation, or increase it, you can use ulimit or
similar to change the avaiable number of file descriptors, and when restarted
**libwebsockets** will adapt accordingly.


Libwebsockets is singlethreaded
-------------------------------

Directly performing websocket actions from other threads is not allowed.
Aside from the internal data being inconsistent in `forked()` processes,
the scope of a `wsi` (`struct websocket`) can end at any time during service
with the socket closing and the `wsi` freed.

Websocket write activities should only take place in the
`LWS_CALLBACK_SERVER_WRITEABLE` callback as described below.

Only live connections appear in the user callbacks, so this removes any
possibility of trying to used closed and freed wsis.

If you need to service other socket or file descriptors as well as the
websocket ones, you can combine them together with the websocket ones
in one poll loop, see "External Polling Loop support" below, and
still do it all in one thread / process context.

If you insist on trying to use it from multiple threads, take special care if
you might simultaneously create more than one context from different threads.

SSL_library_init() is called from the context create api and it also is not
reentrant.  So at least create the contexts sequentially.


Only send data when socket writeable
------------------------------------

You should only send data on a websocket connection from the user callback
`LWS_CALLBACK_SERVER_WRITEABLE` (or `LWS_CALLBACK_CLIENT_WRITEABLE` for
clients).

If you want to send something, do not just send it but request a callback
when the socket is writeable using

 - `lws_callback_on_writable(context, wsi)`` for a specific `wsi`, or
 - `lws_callback_on_writable_all_protocol(protocol)` for all connections
using that protocol to get a callback when next writeable.

Usually you will get called back immediately next time around the service
loop, but if your peer is slow or temporarily inactive the callback will be
delayed accordingly.  Generating what to write and sending it should be done
in the ...WRITEABLE callback.

See the test server code for an example of how to do this.


Do not rely on only your own WRITEABLE requests appearing
---------------------------------------------------------

Libwebsockets may generate additional `LWS_CALLBACK_CLIENT_WRITEABLE` events
if it met network conditions where it had to buffer your send data internally.

So your code for `LWS_CALLBACK_CLIENT_WRITEABLE` needs to own the decision
about what to send, it can't assume that just because the writeable callback
came it really is time to send something.

It's quite possible you get an 'extra' writeable callback at any time and
just need to `return 0` and wait for the expected callback later.


Closing connections from the user side
--------------------------------------

When you want to close a connection, you do it by returning `-1` from a
callback for that connection.

You can provoke a callback by calling `lws_callback_on_writable` on
the wsi, then notice in the callback you want to close it and just return -1.
But usually, the decision to close is made in a callback already and returning
-1 is simple.

If the socket knows the connection is dead, because the peer closed or there
was an affirmitive network error like a FIN coming, then **libwebsockets**  will
take care of closing the connection automatically.

If you have a silently dead connection, it's possible to enter a state where
the send pipe on the connection is choked but no ack will ever come, so the
dead connection will never become writeable.  To cover that, you can use TCP
keepalives (see later in this document)


Fragmented messages
-------------------

To support fragmented messages you need to check for the final
frame of a message with `lws_is_final_fragment`. This
check can be combined with `libwebsockets_remaining_packet_payload`
to gather the whole contents of a message, eg:

```
    case LWS_CALLBACK_RECEIVE:
    {
        Client * const client = (Client *)user;
        const size_t remaining = lws_remaining_packet_payload(wsi);

        if (!remaining && lws_is_final_fragment(wsi)) {
            if (client->HasFragments()) {
                client->AppendMessageFragment(in, len, 0);
                in = (void *)client->GetMessage();
                len = client->GetMessageLength();
            }

            client->ProcessMessage((char *)in, len, wsi);
            client->ResetMessage();
        } else
            client->AppendMessageFragment(in, len, remaining);
    }
    break;
```

The test app libwebsockets-test-fraggle sources also show how to
deal with fragmented messages.


Debug Logging
-------------

Also using `lws_set_log_level` api you may provide a custom callback to actually
emit the log string.  By default, this points to an internal emit function
that sends to stderr.  Setting it to `NULL` leaves it as it is instead.

A helper function `lwsl_emit_syslog()` is exported from the library to simplify
logging to syslog.  You still need to use `setlogmask`, `openlog` and `closelog`
in your user code.

The logging apis are made available for user code.

- `lwsl_err(...)`
- `lwsl_warn(...)`
- `lwsl_notice(...)`
- `lwsl_info(...)`
- `lwsl_debug(...)`

The difference between notice and info is that notice will be logged by default
whereas info is ignored by default.


External Polling Loop support
-----------------------------

**libwebsockets** maintains an internal `poll()` array for all of its
sockets, but you can instead integrate the sockets into an
external polling array.  That's needed if **libwebsockets** will
cooperate with an existing poll array maintained by another
server.

Four callbacks `LWS_CALLBACK_ADD_POLL_FD`, `LWS_CALLBACK_DEL_POLL_FD`,
`LWS_CALLBACK_SET_MODE_POLL_FD` and `LWS_CALLBACK_CLEAR_MODE_POLL_FD`
appear in the callback for protocol 0 and allow interface code to
manage socket descriptors in other poll loops.

You can pass all pollfds that need service to `lws_service_fd()`, even
if the socket or file does not belong to **libwebsockets** it is safe.

If **libwebsocket** handled it, it zeros the pollfd `revents` field before returning.
So you can let **libwebsockets** try and if `pollfd->revents` is nonzero on return,
you know it needs handling by your code.


Using with in c++ apps
----------------------

The library is ready for use by C++ apps.  You can get started quickly by
copying the test server

```bash
$ cp test-server/test-server.c test.cpp
```

and building it in C++ like this

```bash
$ g++ -DINSTALL_DATADIR=\"/usr/share\" -ocpptest test.cpp -lwebsockets
```

`INSTALL_DATADIR` is only needed because the test server uses it as shipped, if
you remove the references to it in your app you don't need to define it on
the g++ line either.


Availability of header information
----------------------------------

From v1.2 of the library onwards, the HTTP header content is `free()`d as soon
as the websocket connection is established.  For websocket servers, you can
copy interesting headers by handling `LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION`
callback, for clients there's a new callback just for this purpose
`LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH`.


TCP Keepalive
-------------

It is possible for a connection which is not being used to send to die
silently somewhere between the peer and the side not sending.  In this case
by default TCP will just not report anything and you will never get any more
incoming data or sign the link is dead until you try to send.

To deal with getting a notification of that situation, you can choose to
enable TCP keepalives on all **libwebsockets** sockets, when you create the
context.

To enable keepalive, set the ka_time member of the context creation parameter
struct to a nonzero value (in seconds) at context creation time.  You should
also fill ka_probes and ka_interval in that case.

With keepalive enabled, the TCP layer will send control packets that should
stimulate a response from the peer without affecting link traffic.  If the
response is not coming, the socket will announce an error at `poll()` forcing
a close.

Note that BSDs don't support keepalive time / probes / interval per-socket
like Linux does.  On those systems you can enable keepalive by a nonzero
value in `ka_time`, but the systemwide kernel settings for the time / probes/
interval are used, regardless of what nonzero value is in `ka_time`.

Optimizing SSL connections
--------------------------

There's a member `ssl_cipher_list` in the `lws_context_creation_info` struct
which allows the user code to restrict the possible cipher selection at
context-creation time.

You might want to look into that to stop the ssl peers selecting a cipher which
is too computationally expensive.  To use it, point it to a string like

`"RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"`

if left `NULL`, then the "DEFAULT" set of ciphers are all possible to select.


Async nature of client connections
----------------------------------

When you call `lws_client_connect_info(..)` and get a `wsi` back, it does not
mean your connection is active.  It just means it started trying to connect.

Your client connection is actually active only when you receive
`LWS_CALLBACK_CLIENT_ESTABLISHED` for it.

There's a 5 second timeout for the connection, and it may give up or die for
other reasons, if any of that happens you'll get a
`LWS_CALLBACK_CLIENT_CONNECTION_ERROR` callback on protocol 0 instead for the
`wsi`.

After attempting the connection and getting back a non-`NULL` `wsi` you should
loop calling `lws_service()` until one of the above callbacks occurs.

As usual, see [test-client.c](test-server/test-client.c) for example code.

Lws platform-independent file access apis
-----------------------------------------

lws now exposes his internal platform file abstraction in a way that can be
both used by user code to make it platform-agnostic, and be overridden or
subclassed by user code.  This allows things like handling the URI "directory
space" as a virtual filesystem that may or may not be backed by a regular
filesystem.  One example use is serving files from inside large compressed
archive storage without having to unpack anything except the file being
requested.

The test server shows how to use it, basically the platform-specific part of
lws prepares a file operations structure that lives in the lws context.

The user code can get a pointer to the file operations struct

LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops *
`lws_get_fops`(struct lws_context *context);

and then can use helpers to also leverage these platform-independent
file handling apis

static inline lws_filefd_type
`lws_plat_file_open`(struct lws *wsi, const char *filename, unsigned long *filelen, int flags)

static inline int
`lws_plat_file_close`(struct lws *wsi, lws_filefd_type fd)

static inline unsigned long
`lws_plat_file_seek_cur`(struct lws *wsi, lws_filefd_type fd, long offset_from_cur_pos)

static inline int
`lws_plat_file_read`(struct lws *wsi, lws_filefd_type fd, unsigned long *amount, unsigned char *buf, unsigned long len)

static inline int
`lws_plat_file_write`(struct lws *wsi, lws_filefd_type fd, unsigned long *amount, unsigned char *buf, unsigned long len)
		    
The user code can also override or subclass the file operations, to either
wrap or replace them.  An example is shown in test server.

ECDH Support
------------

ECDH Certs are now supported.  Enable the CMake option

cmake .. -DLWS_SSL_SERVER_WITH_ECDH_CERT=1 

**and** the info->options flag

LWS_SERVER_OPTION_SSL_ECDH

to build in support and select it at runtime.

SMP / Multithreaded service
---------------------------

SMP support is integrated into LWS without any internal threading.  It's
very simple to use, libwebsockets-test-server-pthread shows how to do it,
use -j <n> argument there to control the number of service threads up to 32.

Two new members are added to the info struct

	unsigned int count_threads;
	unsigned int fd_limit_per_thread;
	
leave them at the default 0 to get the normal singlethreaded service loop.

Set count_threads to n to tell lws you will have n simultaneous service threads
operating on the context.

There is still a single listen socket on one port, no matter how many
service threads.

When a connection is made, it is accepted by the service thread with the least
connections active to perform load balancing.

The user code is responsible for spawning n threads running the service loop
associated to a specific tsi (Thread Service Index, 0 .. n - 1).  See
the libwebsockets-test-server-pthread for how to do.

If you leave fd_limit_per_thread at 0, then the process limit of fds is shared
between the service threads; if you process was allowed 1024 fds overall then
each thread is limited to 1024 / n.

You can set fd_limit_per_thread to a nonzero number to control this manually, eg
the overall supported fd limit is less than the process allowance.

You can control the context basic data allocation for multithreading from Cmake
using -DLWS_MAX_SMP=, if not given it's set to 32.  The serv_buf allocation
for the threads (currently 4096) is made at runtime only for active threads.

Because lws will limit the requested number of actual threads supported
according to LWS_MAX_SMP, there is an api lws_get_count_threads(context) to
discover how many threads were actually allowed when the context was created.

It's required to implement locking in the user code in the same way that
libwebsockets-test-server-pthread does it, for the FD locking callbacks.

There is no knowledge or dependency in lws itself about pthreads.  How the
locking is implemented is entirely up to the user code.


Libev / Libuv support
---------------------

You can select either or both

-DLWS_WITH_LIBEV=1
-DLWS_WITH_LIBUV=1

at cmake configure-time.  The user application may use one of the
context init options flags

LWS_SERVER_OPTION_LIBEV
LWS_SERVER_OPTION_LIBUV

to indicate it will use either of the event libraries.


Extension option control from user code
---------------------------------------

User code may set per-connection extension options now, using a new api
"lws_set_extension_option()".

This should be called from the ESTABLISHED callback like this

 lws_set_extension_option(wsi, "permessage-deflate",
                          "rx_buf_size", "12"); /* 1 << 12 */

If the extension is not active (missing or not negotiated for the
connection, or extensions are disabled on the library) the call is
just returns -1.  Otherwise the connection's extension has its
named option changed.

The extension may decide to alter or disallow the change, in the
example above permessage-deflate restricts the size of his rx
output buffer also considering the protocol's rx_buf_size member.

Client connections as HTTP[S] rather than WS[S]
-----------------------------------------------

You may open a generic http client connection using the same
struct lws_client_connect_info used to create client ws[s]
connections.

To stay in http[s], set the optional info member "method" to
point to the string "GET" instead of the default NULL.

After the server headers are processed, when payload from the
server is available the callback LWS_CALLBACK_RECEIVE_CLIENT_HTTP
will be made.

You can choose whether to process the data immediately, or
queue a callback when an outgoing socket is writeable to provide
flow control, and process the data in the writable callback.

Either way you use the api `lws_http_client_read()` to access the
data, eg


	case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
		{
			char buffer[1024 + LWS_PRE];
			char *px = buffer + LWS_PRE;
			int lenx = sizeof(buffer) - LWS_PRE;

			lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP\n");

			/*
			 * Often you need to flow control this by something
			 * else being writable.  In that case call the api
			 * to get a callback when writable here, and do the
			 * pending client read in the writeable callback of
			 * the output.
			 */
			if (lws_http_client_read(wsi, &px, &lenx) < 0)
				return -1;
			while (lenx--)
				putchar(*px++);
		}
		break;
		
Using lws v2 vhosts
-------------------

If you set LWS_SERVER_OPTION_EXPLICIT_VHOSTS options flag when you create
your context, it won't create a default vhost using the info struct
members for compatibility.  Instead you can call lws_create_vhost()
afterwards to attach one or more vhosts manually.

```
LWS_VISIBLE struct lws_vhost *
lws_create_vhost(struct lws_context *context,
		 struct lws_context_creation_info *info,
		 struct lws_http_mount *mounts);
```

lws_create_vhost() uses the same info struct as lws_create_context(),
it ignores members related to context and uses the ones meaningful
for vhost (marked with VH in libwebsockets.h).

```
struct lws_context_creation_info {
	int port;					/* VH */
	const char *iface;				/* VH */
	const struct lws_protocols *protocols;		/* VH */
	const struct lws_extension *extensions;		/* VH */
...
```

When you attach the vhost, if the vhost's port already has a listen socket
then both vhosts share it and use SNI (is SSL in use) or the Host: header
from the client to select the right one.  Or if no other vhost already
listening the a new listen socket is created.

There are some new members but mainly it's stuff you used to set at
context creation time.


How lws matches hostname or SNI to a vhost
------------------------------------------

LWS first strips any trailing :port number.

Then it tries to find an exact name match for a vhost listening on the correct
port, ie, if SNI or the Host: header provided abc.com:1234, it will match on a
vhost named abc.com that is listening on port 1234.

If there is no exact match, lws will consider wildcard matches, for example
if cats.abc.com:1234 is provided by the client by SNI or Host: header, it will
accept a vhost "abc.com" listening on port 1234.  If there was a better, exact,
match, it will have been chosen in preference to this.

Connections with SSL will still have the client go on to check the
certificate allows wildcards and error out if not.
 


Using lws v2 mounts on a vhost
------------------------------

The last argument to lws_create_vhost() lets you associate a linked
list of lws_http_mount structures with that vhost's URL 'namespace', in
a similar way that unix lets you mount filesystems into areas of your /
filesystem how you like and deal with the contents transparently.

```
struct lws_http_mount {
	struct lws_http_mount *mount_next;
	const char *mountpoint; /* mountpoint in http pathspace, eg, "/" */
	const char *origin; /* path to be mounted, eg, "/var/www/warmcat.com" */
	const char *def; /* default target, eg, "index.html" */

	struct lws_protocol_vhost_options *cgienv;

	int cgi_timeout;
	int cache_max_age;

	unsigned int cache_reusable:1;
	unsigned int cache_revalidate:1;
	unsigned int cache_intermediaries:1;

	unsigned char origin_protocol;
	unsigned char mountpoint_len;
};
```

The last mount structure should have a NULL mount_next, otherwise it should
point to the 'next' mount structure in your list.

Both the mount structures and the strings must persist until the context is
destroyed, since they are not copied but used in place.

`.origin_protocol` should be one of

```
enum {
	LWSMPRO_HTTP,
	LWSMPRO_HTTPS,
	LWSMPRO_FILE,
	LWSMPRO_CGI,
	LWSMPRO_REDIR_HTTP,
	LWSMPRO_REDIR_HTTPS,
};
```

LWSMPRO_FILE is used for mapping url namespace to a filesystem directory and
serve it automatically.



Added undroid/libwebsockets/README.lwsws.md.





























































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
Libwebsockets Web Server
------------------------

lwsws is an implementation of a very lightweight, ws-capable generic web
server, which uses libwebsockets to implement everything underneath.

Build
-----

Just enable -DLWS_WITH_LWSWS=1 at cmake-time.

It enables libuv and plugin support automatically.


Configuration
-------------

lwsws uses JSON config files, they're pure JSON but # may be used to turn the rest of the line into a comment.

There is a single file intended for global settings

/etc/lwsws/conf

```
# these are the server global settings
# stuff related to vhosts should go in one
# file per vhost in ../conf.d/

{
  "global": {
   "uid": "48",  # apache user
   "gid": "48",  # apache user
   "count-threads": "1",
   "server-string": "myserver v1", # returned in http headers
   "init-ssl": "yes"
 }
}
```

and a config directory intended to take one file per vhost

/etc/lwsws/conf.d/warmcat.com

```
{
	"vhosts": [{
		"name": "warmcat.com",
		"port": "443",
		"interface": "eth0",  # optional
		"host-ssl-key": "/etc/pki/tls/private/warmcat.com.key",  # if given enable ssl
		"host-ssl-cert": "/etc/pki/tls/certs/warmcat.com.crt",
		"host-ssl-ca": "/etc/pki/tls/certs/warmcat.com.cer",
		"mounts": [{  # autoserve
			"mountpoint": "/",
			"origin": "file:///var/www/warmcat.com",
			"default": "index.html"
		}]
	}]
}
```

Vhosts
------

One server can run many vhosts, where SSL is in use SNI is used to match
the connection to a vhost and its vhost-specific SSL keys during SSL
negotiation.

Listing multiple vhosts looks something like this

```
{
 "vhosts": [ {
     "name": "localhost",
     "port": "443",
     "host-ssl-key":  "/etc/pki/tls/private/libwebsockets.org.key",
     "host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt",
     "host-ssl-ca":   "/etc/pki/tls/certs/libwebsockets.org.cer",
     "mounts": [{
       "mountpoint": "/",
       "origin": "file:///var/www/libwebsockets.org",
       "default": "index.html"
       }, {
        "mountpoint": "/testserver",
        "origin": "file:///usr/local/share/libwebsockets-test-server",
        "default": "test.html"
       }],
     # which protocols are enabled for this vhost, and optional
     # vhost-specific config options for the protocol
     #
     "ws-protocols": [{
       "warmcat,timezoom": {
         "status": "ok"
       }
     }]
    },
    {
    "name": "localhost",
    "port": "7681",
     "host-ssl-key":  "/etc/pki/tls/private/libwebsockets.org.key",
     "host-ssl-cert": "/etc/pki/tls/certs/libwebsockets.org.crt",
     "host-ssl-ca":   "/etc/pki/tls/certs/libwebsockets.org.cer",
     "mounts": [{
       "mountpoint": "/",
       "origin": ">https://localhost"
     }]
   },
    {
    "name": "localhost",
    "port": "80",
     "mounts": [{
       "mountpoint": "/",
       "origin": ">https://localhost"
     }]
   }

  ]
}
```

That sets up three vhosts all called "localhost" on ports 443 and 7681 with SSL, and port 80 without SSL but with a forced redirect to https://localhost


Vhost name and port
-------------------

The vhost name field is used to match on incoming SNI or Host: header, so it
must always be the host name used to reach the vhost externally.

 - Vhosts may have the same name and different ports, these will each create a
listening socket on the appropriate port.

 - Vhosts may also have the same port and different name: these will be treated as
true vhosts on one listening socket and the active vhost decided at SSL
negotiation time (via SNI) or if no SSL, then after the Host: header from
the client has been parsed.


Protocols
---------

Vhosts by default have available the union of any initial protocols from context creation time, and
any protocols exposed by plugins.

Vhosts can select which plugins they want to offer and give them per-vhost settings using this syntax

```	
     "ws-protocols": [{
       "warmcat-timezoom": {
         "status": "ok"
       }
     }]

```

The "x":"y" parameters like "status":"ok" are made available to the protocol during its per-vhost
LWS_CALLBACK_PROTOCOL_INIT (@in is a pointer to a linked list of struct lws_protocol_vhost_options
containing the name and value pointers).

To indicate that a protocol should be used when no Protocol: header is sent
by the client, you can use "default": "1"

```	
     "ws-protocols": [{
       "warmcat-timezoom": {
         "status": "ok",
         "default": "1"
       }
     }]

```


Other vhost options
-------------------

 - If the three options `host-ssl-cert`, `host-ssl-ca` and `host-ssl-key` are given, then the vhost supports SSL.

 Each vhost may have its own certs, SNI is used during the initial connection negotiation to figure out which certs to use by the server name it's asking for from the request DNS name.

 - `keeplive-timeout` (in secs) defaults to 60 for lwsws, it may be set as a vhost option

 - `interface` lets you specify which network interface to listen on, if not given listens on all

 - "`unix-socket`": "1" causes the unix socket specified in the interface option to be used instead of an INET socket

 - "`sts`": "1" causes lwsws to send a Strict Transport Security header with responses that informs the client he should never accept to connect to this address using http.  This is needed to get the A+ security rating from SSL Labs for your server.

 - "`access-log`": "filepath"   sets where apache-compatible access logs will be written

 - "`ciphers`": "<cipher list>"   sets the allowed list of ciphers and key exchange protocols for the vhost.  The default list is restricted to only those providing PFS (Perfect Forward Secrecy) on the author's Fedora system.
 
 If you need to allow weaker ciphers,you can provide an alternative list here per-vhost.
 
 - "`ecdh-curve`": "<curve name>"   The default ecdh curve is "prime256v1", but you can override it here, per-vhost


Mounts
------

Where mounts are given in the vhost definition, then directory contents may
be auto-served if it matches the mountpoint.

Mount protocols are used to control what kind of translation happens

 - file://  serve the uri using the remainder of the url past the mountpoint based on the origin directory.

 Eg, with this mountpoint

```
       {
        "mountpoint": "/",
        "origin": "file:///var/www/mysite.com",
        "default": "/"
       }
```

 The uri /file.jpg would serve /var/www/mysite.com/file.jpg, since / matched.

 - ^http:// or ^https://  these cause any url matching the mountpoint to issue a redirect to the origin url

 - cgi://   this causes any matching url to be given to the named cgi, eg

```
       {
        "mountpoint": "/git",
        "origin": "cgi:///var/www/cgi-bin/cgit",
        "default": "/"
       }, {
        "mountpoint": "/cgit-data",
        "origin": "file:///usr/share/cgit",
        "default": "/"
       },
```

 would cause the url /git/myrepo to pass "myrepo" to the cgi /var/www/cgi-bin/cgit and send the results to the client.

Note: currently only a fixed set of mimetypes are supported.


Other mount options
-------------------

1) When using a cgi:// protcol origin at a mountpoint, you may also give cgi environment variables specific to the mountpoint like this

```
       {
        "mountpoint": "/git",
        "origin": "cgi:///var/www/cgi-bin/cgit",
        "default": "/",
        "cgi-env": [{
                "CGIT_CONFIG": "/etc/cgitrc/libwebsockets.org"
        }]
       }
```

 This allows you to customize one cgi depending on the mountpoint (and / or vhost).

2) It's also possible to set the cgi timeout (in secs) per cgi:// mount, like this

```
	"cgi-timeout": "30"
```

3) Cache policy of the files in the mount can also be set.  If no
options are given, the content is marked uncacheable.

       {
        "mountpoint": "/",
        "origin": "file:///var/www/mysite.com",
        "cache-max-age": "60",      # seconds
        "cache-reuse": "1",         # allow reuse at client at all
        "cache-revalidate": "1",    # check it with server each time
        "cache-intermediaries": "1" # allow intermediary caches to hold
       }


4) You can also define a list of additional mimetypes per-mount

        "extra-mimetypes": {
                 ".zip": "application/zip",
                 ".doc": "text/evil"
         }


Plugins
-------

Protcols and extensions may also be provided from "plugins", these are
lightweight dynamic libraries.  They are scanned for at init time, and
any protocols and extensions found are added to the list given at context
creation time.

Protocols receive init (LWS_CALLBACK_PROTOCOL_INIT) and destruction
(LWS_CALLBACK_PROTOCOL_DESTROY) callbacks per-vhost, and there are arrangements
they can make per-vhost allocations and get hold of the correct pointer from
the wsi at the callback.

This allows a protocol to choose to strictly segregate data on a per-vhost
basis, and also allows the plugin to handle its own initialization and
context storage.

To help that happen conveniently, there are some new apis

 - lws_vhost_get(wsi)
 - lws_protocol_get(wsi)
 - lws_callback_on_writable_all_protocol_vhost(vhost, protocol)
 - lws_protocol_vh_priv_zalloc(vhost, protocol, size)
 - lws_protocol_vh_priv_get(vhost, protocol)
 
dumb increment, mirror and status protocol plugins are provided as examples.


Additional plugin search paths
------------------------------

Packages that have their own lws plugins can install them in their own
preferred dir and ask lwsws to scan there by using a config fragment
like this, in its own conf.d/ file managed by the other package

{
  "global": {
   "plugin-dir": "/usr/local/share/coherent-timeline/plugins"
  }
}


lws-server-status plugin
------------------------

One provided protocol can be used to monitor the server status.

Enable the protocol like this on a vhost's ws-protocols section

       "lws-server-status": {
         "status": "ok",
         "update-ms": "5000"
       }

"update-ms" is used to control how often updated JSON is sent on a ws link.

And map the provided HTML into the vhost in the mounts section

       {
        "mountpoint": "/server-status",
        "origin": "file:///usr/local/share/libwebsockets-test-server/server-status",
        "default": "server-status.html"
       }

You might choose to put it on its own vhost which has "interface": "lo", so it's not
externally visible.


Integration with Systemd
------------------------

lwsws needs a service file like this as `/usr/lib/systemd/system/lwsws.service`

```
[Unit]
Description=Libwebsockets Web Server
After=syslog.target

[Service]
ExecStart=/usr/local/bin/lwsws
StandardError=null

[Install]
WantedBy=multi-user.target

```

You can find this prepared in `./lwsws/usr-lib-systemd-system-lwsws.service`


Integration with logrotate
--------------------------

For correct operation with logrotate, `/etc/logrotate.d/lwsws` (if that's
where we're putting the logs) should contain

```
/var/log/lwsws/*log {
    copytruncate
    missingok
    notifempty
    delaycompress
}
```

You can find this prepared in `/lwsws/etc-logrotate.d-lwsws`

Prepare the log directory like this

```
sudo mkdir /var/log/lwsws
sudo chmod 700 /var/log/lwsws
```

Added undroid/libwebsockets/README.md.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
libwebsockets
-------------

This is the libwebsockets C library for lightweight websocket clients and
servers.  For support, visit

 https://libwebsockets.org
 https://github.com/warmcat/libwebsockets

and consider joining the project mailing list at

 https://libwebsockets.org/mailman/listinfo/libwebsockets

| News |
------
| We have updated https://libwebsockets.org, if you would like your project using lws featured in the image carousel, send an image, project URL and brief summary to andy@warmcat.com |

You can get the latest version of the library from git:

- https://github.com/warmcat/libwebsockets
- https://libwebsockets.org/git

for more information:

- [README.build.md](README.build.md) - information on building the library
- [README.coding.md](README.coding.md) - information for writing code using the library
- [README.test-apps.md](README.test-apps.md) - information about the test apps built with the library

After libwebsockets 1.3, tags will be signed using a key corresponding to this public key

```
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

mQINBFRe35QBEADZA7snW7MoEXkT2deDYZeggVD3694dg1o5G4q36NWjC8Pn/b2V
d+L9Nmw8ydKIv8PLJW762rnveQpPYRqCRD8X4bVTYzYz3qsOl5BrYf6cuVn0ZrPB
13TVRg+NZwUaVxc7O+tdOvvEBdA9OCIygctPNK9Nyh53xs5gPHhghZrKVrt0xM1A
2LYsgoHmMBCCY25SHb1nuapvhA3LvuJb4cNNVRCukCoA6yx0uhSEz2AUPJSLqnZ9
XnNBMKq+1a9C+y7jo4O78upTTmuOmRmNEVAu7pxCSUXDrNa87T8n6vFkV/MiW8nv
VmhppKJrKPJ0KxJF9b7uG6eKosfoK2PKyE7pAoDN1fuNyBTB0dkFAwyTCN8hmhOg
z71QrCltotq/AxSCsKzgFkDBL7D3KUM10QR5kmznjcm8tFWHoSttPR334z/1Yepf
ATqH/tfYydW42qeeHgKjfeegnlI65nTDtwYW6lSqZsXg+/ABg0ki9m5HA6l713ig
gRbVHSNkiz56O+UOqBtfcJZBc8QZqqixq8rbP2Is0HBBEtD+aFMuKx/sQ3ULkQs2
8dZ5qsGTBT/xHmqpHJsIFX/jwjY5zeEiFbnO5bMH7YLmkjynVsn5zxTyXKQJe29C
Uq0Yd9+JpDhHnZoiz/1hIIBsr89Z4Yy6c59YNJ3yJEOast0ODERcKSaUAQARAQAB
tC9BbmR5IEdyZWVuIChMaW5hcm8ga2V5KSA8YW5keS5ncmVlbkBsaW5hcm8ub3Jn
PokCPQQTAQoAJwUCVF7flAIbAwUJBaOagAULCQgHAwUVCgkICwUWAwIBAAIeAQIX
gAAKCRA8ZxoDS3lTexApD/9WT7JWy3tK33OIACYV40XwLEhRam4Xku4rhtsoIeJK
P0k/wa7J2PpceX6gKV+QBsOx3UbUfpqZ/Mu7ff3M0J6W87XpKRROAmP43zyiBkmM
A6v0pJXozknmCU28p3DuLC8spVDFg9N52xV7Qb+9TDHcTYiVi4swKYuDEuHBC/qa
M69+ANgsGbrMFRypxtU7OEhls3AEo3Cq03xD8QvLjFyPpYp1f0vNRFm2Jjgm2CRe
YLVsCGxG35Dz7DpJHekHNxje6xsZ2w9Q38M0rLQ0ICOVQ+E1Dir3hwmZQWASzMMi
+R0P+MVYpVt5y7KtiLywJ4BzNogS7gY3wQxksJOFA1uuk5h/hO54a361mcdA0Ta5
HHhGKRw87lVjEQSaRjFZmHFClB+Sb8MuWR51JTzVS5HtJlcNqcWhF63vZ8bZ7b6y
Aj8cXNjH6ULXyX3QnTUWXX/QU3an3yh8iPONWOGP5d5Hi/qejHGIhP2L5H+h05CP
aZQYFLjjebYgEHijuA28eKWsBsoBPFSLpLloHTDkiycgFdV2AkQcxZN9ZElAqURP
xUkEIscQg3YhExGiVEtaxBp1/p/WctMxs5HNoi0Oc97ZUcKvSCz9FDGXX9wYBpRf
gzjNn055Xn4QyxBDnp5DrYT0ft/8BEnRK0JP6z3gNfnhOxZo4XA+M6w4Hjh3tI2A
3rkCDQRUXt+UARAA0yHmONtW3L1HpvWFR+VgVNHa1HBWWk7lMsI6ajeiUK/lN3F/
+vNbux46bPj/sNT9twbWmYhv6c0yVzCpmv5M5ztefS7mW/zPNLJmCmH32kAvVFr1
Z90R/X+Z1Uh8wCCU72S2pSIXQFza3LF53pbpKi5m1F2icYcx+35egAvvZVZtcrMu
TjHUa+N9mFKxa7tb5PI8Lv93nRLwB7aKkp5PKy9Yvse0jACrAAGeIpI73H467/wO
ujermKlyPOOv+Lpjd7kedWKdaweitva7FVI20K/afn4AwCI8HJUIqVbil0Yrg9Le
M1TRsRydzMQQejsb/cWi3fQ3U3HxvSJijKltckPMqjJaXbqmrLz3FOA5Km0ciIOB
WW0Qq0WREcS3rc5FHU29duS9OAieAWFYyLDieug4nQ29KQE6I0lMqLnz8vWYtbmw
6AHk9i2GsXOZiPnztuADgt9o9Os8fm7ZiacA1LISl86P7wpFk+Gf4LRvv8Fk08NV
b2K1BY4YC9KP+AynyYQmxmyB1YQCh/dZHiD4ikGKttHAy4ZsMW6IRL5bRP0Z97pA
lyBtXP0cGTJtuPt2feh0zaiA7blZ/IDXkB1UqH6jnTa71d1FeNKtVFi8FhPIREN6
Rc5imyRxubZEgsxhdjqGgdT5k6Qr42SewAN391ygutpgGizGQtTwzvmKa0UAEQEA
AYkCJQQYAQoADwUCVF7flAIbDAUJBaOagAAKCRA8ZxoDS3lTewuBD/9/rakAMCRC
+WmbUVpCbJSWP5ViH87Xko4ku437gq56whcGjQpxfCYt8oeVgS8fZetUOHs2gspJ
CEc8TYLUFntfyt2AzKU29oQoizPm33W9S1u7aRGWsVVutd2sqUaQUDsl9z35+Ka9
YcWoATJSWBgnhSAmNcM60OG0P5qrZloTlbRSlDZTSZT3RvY4JWtWCubGsjEpXO4h
ZqbKCu3KgV/6NOuTLciriSOZ/iyva3WsCP2S8mRRvma7x04oMTEWX80zozTCK8gG
XqqS9eDhCkRbdmMyUQbHIhc/ChYchO5+fQ1o0zMS5cv6xgkhWI3NJRUkNdXolH9a
5F9q4CmCTcdEZkqpnjsLNiQLIENfHbgC0A5IjR6YgN6qAP8ZJ5hBgyTfyKkwB7bW
DcCnuoC9R79hkI8nWkoRVou9tdzKxo0bGR6O4CfLj+4d3hpWkv9Rw7Xxygo5JOqN
4cNZGtHkmIFFk9fSXul5rkjfF/XmThIwoI8aHSBZ7j3IMtmkKVkBjNjiTfbgW8RT
XIIR+QQdVLOyJqq+NZC/SrKVQITg0ToYJutRTUJViqyz5b3psJo5o2SW6jcexQpE
cX6tdPyGz3o0aywfJ9dcN6izleSV1gYmXmIoS0cQyezVqTUkT8C12zeRB7mtWsDa
+AWJGq/WfB7N6pPh8S/XMW4e6ptuUodjiA==
=HV8t
-----END PGP PUBLIC KEY BLOCK-----
```

Added undroid/libwebsockets/README.test-apps.md.

























































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
Testing server with a browser
-----------------------------

If you run [libwebsockets-test-server](test-server/test-server.c) and point your browser
(eg, Chrome) to

  http://127.0.0.1:7681

It will fetch a script in the form of `test.html`, and then run the
script in there on the browser to open a websocket connection.
Incrementing numbers should appear in the browser display.

By default the test server logs to both stderr and syslog, you can control
what is logged using `-d <log level>`, see later.


Running test server as a Daemon
-------------------------------

You can use the -D option on the test server to have it fork into the
background and return immediately.  In this daemonized mode all stderr is
disabled and logging goes only to syslog, eg, `/var/log/messages` or similar.

The server maintains a lockfile at `/tmp/.lwsts-lock` that contains the pid
of the master process, and deletes this file when the master process
terminates.

To stop the daemon, do

```bash
$ kill `cat /tmp/.lwsts-lock`
```

If it finds a stale lock (the pid mentioned in the file does not exist
any more) it will delete the lock and create a new one during startup.

If the lock is valid, the daemon will exit with a note on stderr that
it was already running.


Using SSL on the server side
----------------------------

To test it using SSL/WSS, just run the test server with

```bash
$ libwebsockets-test-server --ssl
```

and use the URL

  https://127.0.0.1:7681

The connection will be entirely encrypted using some generated
certificates that your browser will not accept, since they are
not signed by any real Certificate Authority.  Just accept the
certificates in the browser and the connection will proceed
in first https and then websocket wss, acting exactly the
same.

[test-server.c](test-server/test-server.c) is all that is needed to use libwebsockets for
serving both the script html over http and websockets.


Testing websocket client support
--------------------------------

If you run the test server as described above, you can also
connect to it using the test client as well as a browser.

```bash
$ libwebsockets-test-client localhost
```

will by default connect to the test server on localhost:7681
and print the dumb increment number from the server at the
same time as drawing random circles in the mirror protocol;
if you connect to the test server using a browser at the
same time you will be able to see the circles being drawn.

The test client supports SSL too, use

```bash
$ libwebsockets-test-client localhost --ssl -s
```

the -s tells it to accept the default selfsigned cert from the server,
otherwise it will strictly fail the connection if there is no CA cert to
validate the server's certificate.


Choosing between test server variations
---------------------------------------

If you will be doing standalone serving with lws, ideally you should avoid
making your own server at all, and use lwsws with your own protocol plugins.

The second best option is follow test-server-v2.0.c, which uses a mount to
autoserve a directory, and lws protocol plugins for ws, without needing any
user callback code (other than what's needed in the protocol plugin).

For those two options libuv is needed to support the protocol plugins, if
that's not possible then the other variations with their own protocol code
should be considered.


Testing simple echo
-------------------

You can test against `echo.websockets.org` as a sanity test like
this (the client connects to port `80` by default):

```bash
$ libwebsockets-test-echo --client echo.websocket.org
```

This echo test is of limited use though because it doesn't
negotiate any protocol.  You can run the same test app as a
local server, by default on localhost:7681

```bash
$ libwebsockets-test-echo
```

and do the echo test against the local echo server

```bash
$ libwebsockets-test-echo --client localhost --port 7681
```

If you add the `--ssl` switch to both the client and server, you can also test
with an encrypted link.


Testing SSL on the client side
------------------------------

To test SSL/WSS client action, just run the client test with

```bash
$ libwebsockets-test-client localhost --ssl
```

By default the client test applet is set to accept selfsigned
certificates used by the test server, this is indicated by the
`use_ssl` var being set to `2`.  Set it to `1` to reject any server
certificate that it doesn't have a trusted CA cert for.


Using the websocket ping utility
--------------------------------

libwebsockets-test-ping connects as a client to a remote
websocket server using 04 protocol and pings it like the
normal unix ping utility.

```bash
$ libwebsockets-test-ping localhost
handshake OK for protocol lws-mirror-protocol
Websocket PING localhost.localdomain (127.0.0.1) 64 bytes of data.
64 bytes from localhost: req=1 time=0.1ms
64 bytes from localhost: req=2 time=0.1ms
64 bytes from localhost: req=3 time=0.1ms
64 bytes from localhost: req=4 time=0.2ms
64 bytes from localhost: req=5 time=0.1ms
64 bytes from localhost: req=6 time=0.2ms
64 bytes from localhost: req=7 time=0.2ms
64 bytes from localhost: req=8 time=0.1ms
^C
--- localhost.localdomain websocket ping statistics ---
8 packets transmitted, 8 received, 0% packet loss, time 7458ms
rtt min/avg/max = 0.110/0.185/0.218 ms
$
```

By default it sends 64 byte payload packets using the 04
PING packet opcode type.  You can change the payload size
using the `-s=` flag, up to a maximum of 125 mandated by the
04 standard.

Using the lws-mirror protocol that is provided by the test
server, libwebsockets-test-ping can also use larger payload
sizes up to 4096 is BINARY packets; lws-mirror will copy
them back to the client and they appear as a PONG.  Use the
`-m` flag to select this operation.

The default interval between pings is 1s, you can use the -i=
flag to set this, including fractions like `-i=0.01` for 10ms
interval.

Before you can even use the PING opcode that is part of the
standard, you must complete a handshake with a specified
protocol.  By default lws-mirror-protocol is used which is
supported by the test server.  But if you are using it on
another server, you can specify the protcol to handshake with
by `--protocol=protocolname`


Fraggle test app
----------------

By default it runs in server mode

```bash
$ libwebsockets-test-fraggle
libwebsockets test fraggle
(C) Copyright 2010-2011 Andy Green <andy@warmcat.com> licensed under LGPL2.1
 Compiled with SSL support, not using it
 Listening on port 7681
server sees client connect
accepted v06 connection
Spamming 360 random fragments
Spamming session over, len = 371913. sum = 0x2D3C0AE
Spamming 895 random fragments
Spamming session over, len = 875970. sum = 0x6A74DA1
...
```

You need to run a second session in client mode, you have to
give the `-c` switch and the server address at least:

```bash
$ libwebsockets-test-fraggle -c localhost
libwebsockets test fraggle
(C) Copyright 2010-2011 Andy Green <andy@warmcat.com> licensed under LGPL2.1
 Client mode
Connecting to localhost:7681
denied deflate-stream extension
handshake OK for protocol fraggle-protocol
client connects to server
EOM received 371913 correctly from 360 fragments
EOM received 875970 correctly from 895 fragments
EOM received 247140 correctly from 258 fragments
EOM received 695451 correctly from 692 fragments
...
```

The fraggle test sends a random number up to 1024 fragmented websocket frames
each of a random size between 1 and 2001 bytes in a single message, then sends
a checksum and starts sending a new randomly sized and fragmented message.

The fraggle test client receives the same message fragments and computes the
same checksum using websocket framing to see when the message has ended.  It
then accepts the server checksum message and compares that to its checksum.


proxy support
-------------

The http_proxy environment variable is respected by the client
connection code for both `ws://` and `wss://`.  It doesn't support
authentication.

You use it like this

```bash
$ export http_proxy=myproxy.com:3128
$ libwebsockets-test-client someserver.com
```


debug logging
-------------

By default logging of severity "notice", "warn" or "err" is enabled to stderr.

Again by default other logging is compiled in but disabled from printing.

If you want to eliminate the debug logging below notice  in severity, use the
`--disable-debug` configure option to have it removed from the code by the
preprocesser.

If you want to see more detailed debug logs, you can control a bitfield to
select which logs types may print using the `lws_set_log_level()` api, in the
test apps you can use `-d <number>` to control this.  The types of logging
available are (OR together the numbers to select multiple)

 - 1   ERR
 - 2   WARN
 - 4   NOTICE
 - 8   INFO
 - 16  DEBUG
 - 32  PARSER
 - 64  HEADER
 - 128 EXTENSION
 - 256 CLIENT
 - 512 LATENCY


Websocket version supported
---------------------------

The final IETF standard is supported for both client and server, protocol
version 13.


Latency Tracking
----------------

Since libwebsockets runs using `poll()` and a single threaded approach, any
unexpected latency coming from system calls would be bad news.  There's now
a latency tracking scheme that can be built in with `--with-latency` at
configure-time, logging the time taken for system calls to complete and if
the whole action did complete that time or was deferred.

You can see the detailed data by enabling logging level 512 (eg, `-d 519` on
the test server to see that and the usual logs), however even without that
the "worst" latency is kept and reported to the logs with NOTICE severity
when the context is destroyed.

Some care is needed interpreting them, if the action completed the first figure
(in us) is the time taken for the whole action, which may have retried through
the poll loop many times and will depend on network roundtrip times.  High
figures here don't indicate a problem.  The figure in us reported after "lat"
in the logging is the time taken by this particular attempt.  High figures
here may indicate a problem, or if you system is loaded with another app at
that time, such as the browser, it may simply indicate the OS gave preferential
treatment to the other app during that call.


Autobahn Test Suite
-------------------

Lws can be tested against the autobahn websocket fuzzer.

1) pip install autobahntestsuite

2) wstest -m fuzzingserver

3) Run tests like this

libwebsockets-test-echo --client localhost --port 9001 -u "/runCase?case=20&agent=libwebsockets" -v -d 65535 -n 1

(this runs test 20)

4) In a browser, go here

http://localhost:8080/test_browser.html

fill in "libwebsockets" in "User Agent Identifier" and press "Update Reports (Manual)"

5) In a browser go to the directory you ran wstest in (eg, /projects/libwebsockets)

file:///projects/libwebsockets/reports/clients/index.html

to see the results


Autobahn Test Notes
-------------------

1) Autobahn tests the user code + lws implementation.  So to get the same
results, you need to follow test-echo.c in terms of user implmentation.

2) Some of the tests make no sense for Libwebsockets to support and we fail them.

 - Tests 2.10 + 2.11: sends multiple pings on one connection.  Lws policy is to
only allow one active ping in flight on each connection, the rest are dropped.
The autobahn test itself admits this is not part of the standard, just someone's
random opinion about how they think a ws server should act.  So we will fail
this by design and it is no problem about RFC6455 compliance.

 
 

Added undroid/libwebsockets/appveyor.yml.











































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
environment:
  matrix:
    - LWS_METHOD: lwsws
      CMAKE_ARGS: -DLWS_WITH_LWSWS=1 -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://slproweb.com/download/Win32OpenSSL-1_0_2h.exe
  - appveyor DownloadFile https://libwebsockets.org:444/Win32OpenSSL-1_0_2h.exe
  - Win32OpenSSL-1_0_2h.exe /silent /verysilent /sp- /suppressmsgboxes
  - appveyor DownloadFile https://libwebsockets.org:444/nsis-3.0rc1-setup.exe
  - cmd /c start /wait nsis-3.0rc1-setup.exe /S /D=C:\nsis
  - SET PATH=C:\Program Files\NSIS\;C:\Program Files (x86)\NSIS\;c:\nsis;%PATH%
build:

build_script:
  - md build
  - cd build
  - cmake -DCMAKE_BUILD_TYPE=Release %CMAKE_ARGS% ..
  - cmake --build . --config Release

# TODO: Keeps breaking Windows build, should be rewritten using CPack properly instead...
#after_build:
#  - cd ..
#  - cd win32port
#  - makensis -DVERSION=%APPVEYOR_BUILD_VERSION% libwebsockets.nsi


artifacts:
  - name: Installer
    path: 'win32port/libwebsockets-*-install.exe'

cache:
  - C:\OpenSSL-Win32

matrix:
  fast_finish: true

Added undroid/libwebsockets/autobahn-test.sh.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/bin/sh

N=1

for i in '1.1.1' '1.1.2' '1.1.3' '1.1.4' '1.1.5' '1.1.6' '1.1.7' '1.1.8' '1.2.1' '1.2.2' '1.2.3' '1.2.4' '1.2.5' '1.2.6' '1.2.7' '1.2.8' '2.1' '2.2' '2.3' '2.4' '2.5' '2.6' '2.7' '2.8' '2.9' '2.10' '2.11' '3.1' '3.2' '3.3' '3.4' '3.5' '3.6' '3.7' '4.1.1' '4.1.2' '4.1.3' '4.1.4' '4.1.5' '4.2.1' '4.2.2' '4.2.3' '4.2.4' '4.2.5' '5.1' '5.2' '5.3' '5.4' '5.5' '5.6' '5.7' '5.8' '5.9' '5.10' '5.11' '5.12' '5.13' '5.14' '5.15' '5.16' '5.17' '5.18' '5.19' '5.20' '6.1.1' '6.1.2' '6.1.3' '6.2.1' '6.2.2' '6.2.3' '6.2.4' '6.3.1' '6.3.2' '6.4.1' '6.4.2' '6.4.3' '6.4.4' '6.5.1' '6.5.2' '6.5.3' '6.5.4' '6.5.5' '6.6.1' '6.6.2' '6.6.3' '6.6.4' '6.6.5' '6.6.6' '6.6.7' '6.6.8' '6.6.9' '6.6.10' '6.6.11' '6.7.1' '6.7.2' '6.7.3' '6.7.4' '6.8.1' '6.8.2' '6.9.1' '6.9.2' '6.9.3' '6.9.4' '6.10.1' '6.10.2' '6.10.3' '6.11.1' '6.11.2' '6.11.3' '6.11.4' '6.11.5' '6.12.1' '6.12.2' '6.12.3' '6.12.4' '6.12.5' '6.12.6' '6.12.7' '6.12.8' '6.13.1' '6.13.2' '6.13.3' '6.13.4' '6.13.5' '6.14.1' '6.14.2' '6.14.3' '6.14.4' '6.14.5' '6.14.6' '6.14.7' '6.14.8' '6.14.9' '6.14.10' '6.15.1' '6.16.1' '6.16.2' '6.16.3' '6.17.1' '6.17.2' '6.17.3' '6.17.4' '6.17.5' '6.18.1' '6.18.2' '6.18.3' '6.18.4' '6.18.5' '6.19.1' '6.19.2' '6.19.3' '6.19.4' '6.19.5' '6.20.1' '6.20.2' '6.20.3' '6.20.4' '6.20.5' '6.20.6' '6.20.7' '6.21.1' '6.21.2' '6.21.3' '6.21.4' '6.21.5' '6.21.6' '6.21.7' '6.21.8' '6.22.1' '6.22.2' '6.22.3' '6.22.4' '6.22.5' '6.22.6' '6.22.7' '6.22.8' '6.22.9' '6.22.10' '6.22.11' '6.22.12' '6.22.13' '6.22.14' '6.22.15' '6.22.16' '6.22.17' '6.22.18' '6.22.19' '6.22.20' '6.22.21' '6.22.22' '6.22.23' '6.22.24' '6.22.25' '6.22.26' '6.22.27' '6.22.28' '6.22.29' '6.22.30' '6.22.31' '6.22.32' '6.22.33' '6.22.34' '6.23.1' '6.23.2' '6.23.3' '6.23.4' '6.23.5' '6.23.6' '6.23.7' '7.1.1' '7.1.2' '7.1.3' '7.1.4' '7.1.5' '7.1.6' '7.3.1' '7.3.2' '7.3.3' '7.3.4' '7.3.5' '7.3.6' '7.5.1' '7.7.1' '7.7.2' '7.7.3' '7.7.4' '7.7.5' '7.7.6' '7.7.7' '7.7.8' '7.7.9' '7.7.10' '7.7.11' '7.7.12' '7.7.13' '7.9.1' '7.9.2' '7.9.3' '7.9.4' '7.9.5' '7.9.6' '7.9.7' '7.9.8' '7.9.9' '7.9.10' '7.9.11' '7.9.12' '7.9.13' '7.13.1' '7.13.2' '9.1.1' '9.1.2' '9.1.3' '9.1.4' '9.1.5' '9.1.6' '9.2.1' '9.2.2' '9.2.3' '9.2.4' '9.2.5' '9.2.6' '9.3.1' '9.3.2' '9.3.3' '9.3.4' '9.3.5' '9.3.6' '9.3.7' '9.3.8' '9.3.9' '9.4.1' '9.4.2' '9.4.3' '9.4.4' '9.4.5' '9.4.6' '9.4.7' '9.4.8' '9.4.9' '9.5.1' '9.5.2' '9.5.3' '9.5.4' '9.5.5' '9.5.6' '9.6.1' '9.6.2' '9.6.3' '9.6.4' '9.6.5' '9.6.6' '9.7.1' '9.7.2' '9.7.3' '9.7.4' '9.7.5' '9.7.6' '9.8.1' '9.8.2' '9.8.3' '9.8.4' '9.8.5' '9.8.6' '10.1.1' '12.1.1' '12.1.2' '12.1.3' '12.1.4' '12.1.5' '12.1.6' '12.1.7' '12.1.8' '12.1.9' '12.1.10' '12.1.11' '12.1.12' '12.1.13' '12.1.14' '12.1.15' '12.1.16' '12.1.17' '12.1.18' '12.2.1' '12.2.2' '12.2.3' '12.2.4' '12.2.5' '12.2.6' '12.2.7' '12.2.8' '12.2.9' '12.2.10' '12.2.11' '12.2.12' '12.2.13' '12.2.14' '12.2.15' '12.2.16' '12.2.17' '12.2.18' '12.3.1' '12.3.2' '12.3.3' '12.3.4' '12.3.5' '12.3.6' '12.3.7' '12.3.8' '12.3.9' '12.3.10' '12.3.11' '12.3.12' '12.3.13' '12.3.14' '12.3.15' '12.3.16' '12.3.17' '12.3.18' '12.4.1' '12.4.2' '12.4.3' '12.4.4' '12.4.5' '12.4.6' '12.4.7' '12.4.8' '12.4.9' '12.4.10' '12.4.11' '12.4.12' '12.4.13' '12.4.14' '12.4.15' '12.4.16' '12.4.17' '12.4.18' '12.5.1' '12.5.2' '12.5.3' '12.5.4' '12.5.5' '12.5.6' '12.5.7' '12.5.8' '12.5.9' '12.5.10' '12.5.11' '12.5.12' '12.5.13' '12.5.14' '12.5.15' '12.5.16' '12.5.17' '12.5.18' '13.1.1' '13.1.2' '13.1.3' '13.1.4' '13.1.5' '13.1.6' '13.1.7' '13.1.8' '13.1.9' '13.1.10' '13.1.11' '13.1.12' '13.1.13' '13.1.14' '13.1.15' '13.1.16' '13.1.17' '13.1.18' '13.2.1' '13.2.2' '13.2.3' '13.2.4' '13.2.5' '13.2.6' '13.2.7' '13.2.8' '13.2.9' '13.2.10' '13.2.11' '13.2.12' '13.2.13' '13.2.14' '13.2.15' '13.2.16' '13.2.17' '13.2.18' '13.3.1' '13.3.2' '13.3.3' '13.3.4' '13.3.5' '13.3.6' '13.3.7' '13.3.8' '13.3.9' '13.3.10' '13.3.11' '13.3.12' '13.3.13' '13.3.14' '13.3.15' '13.3.16' '13.3.17' '13.3.18' '13.4.1' '13.4.2' '13.4.3' '13.4.4' '13.4.5' '13.4.6' '13.4.7' '13.4.8' '13.4.9' '13.4.10' '13.4.11' '13.4.12' '13.4.13' '13.4.14' '13.4.15' '13.4.16' '13.4.17' '13.4.18' '13.5.1' '13.5.2' '13.5.3' '13.5.4' '13.5.5' '13.5.6' '13.5.7' '13.5.8' '13.5.9' '13.5.10' '13.5.11' '13.5.12' '13.5.13' '13.5.14' '13.5.15' '13.5.16' '13.5.17' '13.5.18' '13.6.1' '13.6.2' '13.6.3' '13.6.4' '13.6.5' '13.6.6' '13.6.7' '13.6.8' '13.6.9' '13.6.10' '13.6.11' '13.6.12' '13.6.13' '13.6.14' '13.6.15' '13.6.16' '13.6.17' '13.6.18' '13.7.1' '13.7.2' '13.7.3' '13.7.4' '13.7.5' '13.7.6' '13.7.7' '13.7.8' '13.7.9' '13.7.10' '13.7.11' '13.7.12' '13.7.13' '13.7.14' '13.7.15' '13.7.16' '13.7.17' '13.7.18' ; do
	libwebsockets-test-echo --client localhost --port 9001 -u "/runCase?case=$N&agent=libwebsockets" -v -n 1 &

	C=99
	while [ $C -gt 8 ] ; do
		C=`ps fax | grep libwebsockets-test-echo | wc -l`
		if [ $C -gt 8 ] ; then
			sleep 1s
		fi
	done 

	N=$(( $N + 1 ))
done

echo "waiting for forks to complete..."

while [ 1 ] ; do
	n=`ps fax | grep libwebsocket | grep -v grep | wc -l`
	echo "$n forks running..."
	if [ $n -eq 0 ] ; then
		echo "Completed"
		exit 0
	fi
	sleep 1s
done

Added undroid/libwebsockets/changelog.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
Changelog
---------

v2.0.3
======

NB New api lws_snprintf() -> SONAME bump to 8.1

Fixes
-----

1) Remove duplicate close in one error path

2) Build fix for ecdh and non-openssl

3) Client confirms server cert

4) SNI falls back to match wildcard DNS names (this is later checked against
the cert for actual validity at SSL level)

5) Fix one error path on vhost adopt_socket where we are left on timeout list

6) lws_snprintf() - fix critical problem with snprintf not truncating buffer
lengths (it truncated the buffer write) as (wrongly) expected


v2.0.2
======

Fixes
-----

1) Fix possible pthread mutex leak

2) Make sure ACCESS_LOG can't touch freed area

3) extra options in lwsws conf for cipher list and ecdh curve

4) extra options in lwsws conf for extra mimetypes

5) fix default rxbuf trimming for output

6) lwsl_timestamp month number was off-by-one

7) fix daemonize.c


v2.0.1
======

Fixes
-----

1) OpenSSL version tests not needed on LibreSSL and BoringSSL

2) Fix IPV6 build breakage

3) Some fixes for WinCE build

4) Additional canned mimetypes for mounts, the full list is

	.ico    image/x-icon
	.gif    image/gif
	.js     text/javascript
	.png    image/png
	.jpg    image/jpeg
	.gz     application/gzip
	.JPG    image/jpeg
	.html   text/html
	.css    text/css
	.txt    text/plain
	.ttf    application/x-font-ttf
	.woff   application/font-woff
	.xml    application/xml

5) Allow per-vhost setting of which protocol should get used
when the protocol: header is not sent by the client

6) MINOR: user_space arg was mistakenly NULL on
LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER

7) MINOR: treating recv() returning 0 as peer close destroyed throughput on ab
tests, reverted

8) MINOR: %3d on URL part was always turned to _... this should only happen in
?na%3dme=x part of the URL

9) MINOR: some malloc escaped check for NULL / OOM

10) MINOR: libuv cleanups and client connections can operate correctly with
libuv

11) MINOR: POST used to hang up the connection when the body had all arrived.
Change it so you can reply with a 200 directly rather than requiring a
redirect

12) MINOR: API docs were a little behind the docs in the code



v2.0.0
======

Summary
-------

 - There are only api additions, the api is compatible with v1.7.x.  But
   there is necessarily an soname bump to 8.
 
 - If you are using lws client, you mainly need to be aware the option
   LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT is needed at context-creation time
   if you will use SSL.
   
 - If you are using lws for serving, the above is also true but there are
   many new features to simplify your code (and life).  There is a
   summany online here
   
     https://libwebsockets.org/lws-2.0-new-features.html
     
   but basically the keywords are vhosts, mounts and plugins.  You can now
   do the web serving part from lws without any user callback code at all.
   See ./test-server/test-server-v2.0.c for an example, it has no user
   code for ws either since it uses the protocol plugins... that one C file
   is all that is needed to do the whole test server function.
   
   You now have the option to use a small generic ws-capable webserver
   "lwsws" and write your ws part as a plugin.  That eliminates even
   cut-and-pasting the test server code and offers more configurable
   features like control over http cacheability in JSON.


Fixes
-----

These are already in 1.7.x series

1) MAJOR (Windows-only) fix assert firing

2) MAJOR http:/1.1 connections handled by  lws_return_http_status() did not
get sent a content-length resulting in the link hanging until the peer closed
it.  attack.sh updated to add a test for this.

3) MINOR An error about hdr struct in _lws_ws_related is corrected, it's not
known to affect anything until after it was fixed

4) MINOR During the close shutdown wait state introduced at v1.7, if something
requests callback on writeable for the socket it will busywait until the
socket closes

5) MAJOR Although the test server has done it for a few versions already, it
is now required for the user code to explicitly call

	if (lws_http_transaction_completed(wsi))
		return -1;

when it finishes replying to a transaction in http.  Previously the library
did it for you, but that disallowed large, long transfers with multiple
trips around the event loop (and cgi...).

6) MAJOR connections on ah waiting list that closed did not get removed from
the waiting list...

7) MAJOR since we added the ability to hold an ah across http keepalive
transactions where more headers had already arrived, we broke the ability
to tell if more headers had arrived.  Result was if the browser didn't
close the keepalive, we retained ah for the lifetime of the keepalive,
using up the pool.

8) MAJOR windows-only-POLLHUP was not coming

9) Client should not send ext hdr if no exts

Changes
-------

1) MINOR test-server gained some new switches

   -C <file>  use external SSL cert file
   -K <file>  use external SSL key file
   -A <file>  use external SSL CA cert file
   
   -u <uid>  set effective uid
   -g <gid>  set effective gid

together you can use them like this to have the test-server work with the
usual purchased SSL certs from an official CA.

   --ssl -C your.crt -K your.key -A your.cer -u 99 -g 99

2) MINOR the OpenSSL magic to setup ECDH cipher usage is implemented in the
library, and the ciphers restricted to use ECDH only.
Using this, the lws test server can score an A at SSLLABS test

3) MINOR STS (SSL always) header is added to the test server if you use --ssl.  With
that, we score A+ at SSLLABS test

4) MINOR daemonize function (disabled at cmake by default) is updated to work
with systemd

5) MINOR example systemd .service file now provided for test server
(not installed by default)

6) test server html is updated with tabs and a new live server monitoring
feature.  Input sanitization added to the js.

7) client connections attempted when no ah is free no longer fail, they are
just deferred until an ah becomes available.

8) The test client pays attention to if you give it an http:/ or https://
protocol string to its argument in URL format.  If so, it stays in http[s]
client mode and doesn't upgrade to ws[s], allowing you to do generic http client
operations.  Receiving transfer-encoding: chunked is supported.

9) If you enable -DLWS_WITH_HTTP_PROXY=1 at cmake, the test server has a
new URI path http://localhost:7681/proxytest If you visit here, a client
connection to http://example.com:80 is spawned, and the results piped on
to your original connection.

10) Also with LWS_WITH_HTTP_PROXY enabled at cmake, lws wants to link to an
additional library, "libhubbub".  This allows lws to do html rewriting on the
fly, adjusting proxied urls in a lightweight and fast way.

11) There's a new context creation flag LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT,
this is included automatically if you give any other SSL-related option flag.
If you give no SSL-related option flag, nor this one directly, then even
though SSL support may be compiled in, it is never initialized nor used for the
whole lifetime of the lws context.

Conversely in order to prepare the context to use SSL, even though, eg, you
are not listening on SSL but will use SSL client connections later, you must
give this flag explicitly to make sure SSL is initialized.


User API additions
------------------

1) MINOR APIBREAK There's a new member in struct lws_context_creation_info, ecdh_curve,
which lets you set the name of the ECDH curve OpenSSL should use.  By
default (if you leave ecdh_curve NULL) it will use "prime256v1"

2) MINOR NEWAPI It was already possible to adopt a foreign socket that had not
been read from using lws_adopt_socket() since v1.7.  Now you can adopt a
partially-used socket if you don't need SSL, by passing it what you read
so it can drain that before reading from the socket.

LWS_VISIBLE LWS_EXTERN struct lws *
lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
		const char *readbuf, size_t len);

3) MINOR NEWAPI CGI type "network io" subprocess execution is now possible from
a simple api.

LWS_VISIBLE LWS_EXTERN int
lws_cgi(struct lws *wsi, char * const *exec_array,  int script_uri_path_len,
        int timeout_secs);

LWS_VISIBLE LWS_EXTERN int
lws_cgi_kill(struct lws *wsi);

To use it, you must first set the cmake option

$ cmake .. -DLWS_WITH_CGI=1

See test-server-http.c and  test server path

http://localhost:7681/cgitest

stdin gets http body, you can test it with wget

$ echo hello > hello.txt
$ wget http://localhost:7681/cgitest --post-file=hello.txt -O- --quiet
lwstest script
read="hello"

The test script returns text/html table showing /proc/meminfo.  But the cgi
support is complete enough to run cgit cgi.

4) There is a helper api for forming logging timestamps

LWS_VISIBLE int
lwsl_timestamp(int level, char *p, int len)

this generates this kind of timestamp for use as logging preamble

lwsts[13116]: [2016/01/25 14:52:52:8386] NOTICE: Initial logging level 7

5) struct lws_client_connect_info has a new member

 const char *method
 
If it's NULL, then everything happens as before, lws_client_connect_via_info()
makes a ws or wss connection to the address given.

If you set method to a valid http method like "GET", though, then this method
is used and the connection remains in http[s], it's not upgraded to ws[s].

So with this, you can perform http[s] client operations as well as ws[s] ones.

There are 4 new related callbacks

	LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP			= 44,
	LWS_CALLBACK_CLOSED_CLIENT_HTTP				= 45,
	LWS_CALLBACK_RECEIVE_CLIENT_HTTP			= 46,
	LWS_CALLBACK_COMPLETED_CLIENT_HTTP			= 47,

6) struct lws_client_connect_info has a new member

 const char *parent_wsi
 
if non-NULL, the client wsi is set to be a child of parent_wsi.  This ensures
if parent_wsi closes, then the client child is closed just before.

7) If you're using SSL, there's a new context creation-time option flag
LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS.  If you give this, non-ssl
connections to the server listen port are accepted and receive a 301
redirect to / on the same host and port using https://

8) User code may set per-connection extension options now, using a new api
"lws_set_extension_option()".

This should be called from the ESTABLISHED callback like this

 lws_set_extension_option(wsi, "permessage-deflate",
                          "rx_buf_size", "12"); /* 1 << 12 */

If the extension is not active (missing or not negotiated for the
connection, or extensions are disabled on the library) the call is
just returns -1.  Otherwise the connection's extension has its
named option changed.

The extension may decide to alter or disallow the change, in the
example above permessage-deflate restricts the size of his rx
output buffer also considering the protocol's rx_buf_size member.


New application lwsws
---------------------

A libwebsockets-based general webserver is built by default now, lwsws.

It's configured by JSON, by default in

  /etc/lwsws/conf

which contains global lws context settings like this

{
  "global": {
   "uid": "99",
   "gid": "99",
   "interface": "eth0",
   "count-threads": "1"
 }
}

  /etc/lwsws/conf.d/*

which contains zero or more files describing vhosts, like this

{
 "vhosts": [
  { "name": "warmcat.com",
    "port": "443",
    "host-ssl-key": "/etc/pki/tls/private/warmcat.com.key",
    "host-ssl-cert": "/etc/pki/tls/certs/warmcat.com.crt",
    "host-ssl-ca": "/etc/pki/tls/certs/warmcat.com.cer",
    "mounts": [
      { "/": [
       { "home": "file:///var/www/warmcat.com" },
       { "default": "index.html" }
      ]
     }
    ]
   }
 ]
}



v1.7.0
======

Extension Changes
-----------------

1) There is now a "permessage-deflate" / RFC7692 implementation.  It's very
similar to "deflate-frame" we have offered for a long while; deflate-frame is
now provided as an alias of permessage-deflate.

The main differences are that the new permessage-deflate implementation:

 - properly performs streaming respecting input and output buffer limits.  The
   old deflate-frame implementation could only work on complete deflate input
   and produce complete inflate output for each frame.  The new implementation
   only mallocs buffers at initialization.

 - goes around the event loop after each input package is processed allowing
   interleaved output processing.  The RX flow control api can be used to
   force compressed input processing to match the rate of compressed output
   processing (test--echo shows an example of how to do this).

 - when being "deflate-frame" for compatibility he uses the same default zlib
   settings as the old "deflate-frame", but instead of exponentially increasing
   malloc allocations until the whole output will fit, he observes the default
   input and output chunking buffer sizes of "permessage-deflate", that's
   1024 in and 1024 out at a time.

2) deflate-stream has been disabled for many versions (for over a year) and is
now removed.  Browsers are now standardizing on "permessage-deflate" / RFC7692

3) struct lws_extension is simplified, and lws extensions now have a public
api (their callback) for use in user code to compose extensions and options
the user code wants.  lws_get_internal_exts() is deprecated but kept around
as a NOP.  The changes allow one extension implementation to go by different
names and allows the user client code to control option offers per-ext.

The test client and server are updated to use the new way.  If you use
the old way it should still work, but extensions will be disabled until you
update your code.

Extensions are now responsible for allocating and per-instance private struct
at instance construction time and freeing it when the instance is destroyed.
Not needing to know the size means the extension's struct can be opaque
to user code.


User api additions
------------------

1) The info struct gained three new members

 - max_http_header_data: 0 for default (1024) or set the maximum amount of known
    http header payload that lws can deal with.  Payload in unknown http
    headers is dropped silently.  If for some reason you need to send huge
    cookies or other HTTP-level headers, you can now increase this at context-
    creation time.

 - max_http_header_pool: 0 for default (16) or set the maximum amount of http
     headers that can be tracked by lws in this context.  For the server, if
     the header pool is completely in use then accepts on the listen socket
     are disabled until one becomes free.  For the client, if you simultaneously
     have pending connects for more than this number of client connections,
     additional connects will fail until some of the pending connections timeout
     or complete.

 - timeout_secs: 0 for default (currently 20s), or set the library's
     network activity timeout to the given number of seconds

HTTP header processing in lws only exists until just after the first main
callback after the HTTP handshake... for ws connections that is ESTABLISHED and
for HTTP connections the HTTP callback.

So these settings are not related to the maximum number of simultaneous
connections, but the number of HTTP handshakes that may be expected or ongoing,
or have just completed, at one time.  The reason it's useful is it changes the
memory allocation for header processing to be one-time at context creation
instead of every time there is a new connection, and gives you control over
the peak allocation.

Setting max_http_header_pool to 1 is fine it will just queue incoming
connections before the accept as necessary, you can still have as many
simultaneous post-header connections as you like.  Since the http header
processing is completed and the allocation released after ESTABLISHED or the
HTTP callback, even with a pool of 1 many connections can be handled rapidly.

2) There is a new callback that allows the user code to get acccess to the
optional close code + aux data that may have been sent by the peer.

LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
             The peer has sent an unsolicited Close WS packet.  @in and
             @len are the optional close code (first 2 bytes, network
             order) and the optional additional information which is not
             defined in the standard, and may be a string or non-human-
             readble data.
             If you return 0 lws will echo the close and then close the
             connection.  If you return nonzero lws will just close the
             connection.

As usual not handling it does the right thing, if you're not interested in it
just ignore it.

The test server has "open and close" testing buttons at the bottom, if you
open and close that connection, on close it will send a close code 3000 decimal
and the string "Bye!" as the aux data.

The test server dumb-increment callback handles this callback reason and prints

lwsts[15714]: LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: len 6
lwsts[15714]:  0: 0x0B
lwsts[15714]:  1: 0xB8
lwsts[15714]:  2: 0x42
lwsts[15714]:  3: 0x79
lwsts[15714]:  4: 0x65
lwsts[15714]:  5: 0x21

3) There is a new API to allow the user code to control the content of the
close frame sent when about to return nonzero from the user callback to
indicate the connection should close.

/**
 * lws_close_reason - Set reason and aux data to send with Close packet
 *		If you are going to return nonzero from the callback
 *		requesting the connection to close, you can optionally
 *		call this to set the reason the peer will be told if
 *		possible.
 *
 * @wsi:	The websocket connection to set the close reason on
 * @status:	A valid close status from websocket standard
 * @buf:	NULL or buffer containing up to 124 bytes of auxiliary data
 * @len:	Length of data in @buf to send
 */
LWS_VISIBLE LWS_EXTERN void
lws_close_reason(struct lws *wsi, enum lws_close_status status,
		 unsigned char *buf, size_t len);

An extra button is added to the "open and close" test server page that requests
that the test server close the connection from his end.

The test server code will do so by

			lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY,
					 (unsigned char *)"seeya", 5);
			return -1;

The browser shows the close code and reason he received

websocket connection CLOSED, code: 1001, reason: seeya

4) There's a new context creation time option flag

LWS_SERVER_OPTION_VALIDATE_UTF8

if you set it in info->options, then TEXT and CLOSE frames will get checked to
confirm that they contain valid UTF-8.  If they don't, the connection will get
closed by lws.

5) ECDH Certs are now supported.  Enable the CMake option

cmake .. -DLWS_SSL_SERVER_WITH_ECDH_CERT=1 

**and** the info->options flag

LWS_SERVER_OPTION_SSL_ECDH

to build in support and select it at runtime.

6) There's a new api lws_parse_uri() that simplifies chopping up
https://xxx:yyy/zzz uris into parts nicely.  The test client now uses this
to allow proper uris as well as the old address style.

7) SMP support is integrated into LWS without any internal threading.  It's
very simple to use, libwebsockets-test-server-pthread shows how to do it,
use -j <n> argument there to control the number of service threads up to 32.

Two new members are added to the info struct

	unsigned int count_threads;
	unsigned int fd_limit_per_thread;
	
leave them at the default 0 to get the normal singlethreaded service loop.

Set count_threads to n to tell lws you will have n simultaneous service threads
operating on the context.

There is still a single listen socket on one port, no matter how many
service threads.

When a connection is made, it is accepted by the service thread with the least
connections active to perform load balancing.

The user code is responsible for spawning n threads running the service loop
associated to a specific tsi (Thread Service Index, 0 .. n - 1).  See
the libwebsockets-test-server-pthread for how to do.

If you leave fd_limit_per_thread at 0, then the process limit of fds is shared
between the service threads; if you process was allowed 1024 fds overall then
each thread is limited to 1024 / n.

You can set fd_limit_per_thread to a nonzero number to control this manually, eg
the overall supported fd limit is less than the process allowance.

You can control the context basic data allocation for multithreading from Cmake
using -DLWS_MAX_SMP=, if not given it's set to 32.  The serv_buf allocation
for the threads (currently 4096) is made at runtime only for active threads.

Because lws will limit the requested number of actual threads supported
according to LWS_MAX_SMP, there is an api lws_get_count_threads(context) to
discover how many threads were actually allowed when the context was created.

It's required to implement locking in the user code in the same way that
libwebsockets-test-server-pthread does it, for the FD locking callbacks.

If LWS_MAX_SMP=1, then there is no code related to pthreads compiled in the
library.  If more than 1, a small amount of pthread mutex code is built into
the library.

8) New API

LWS_VISIBLE struct lws *
lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)

allows foreign sockets accepted by non-lws code to be adopted by lws as if they
had just been accepted by lws' own listen socket.

9) X-Real-IP: header has been added as WSI_TOKEN_HTTP_X_REAL_IP

10) Libuv support is added, there are new related user apis

typedef void (lws_uv_signal_cb_t)(uv_loop_t *l, uv_signal_t *w, int revents);

LWS_VISIBLE LWS_EXTERN int
lws_uv_sigint_cfg(struct lws_context *context, int use_uv_sigint,
		  lws_uv_signal_cb_t *cb);

LWS_VISIBLE LWS_EXTERN int
lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi);

LWS_VISIBLE void
lws_uv_sigint_cb(uv_loop_t *loop, uv_signal_t *watcher, int revents);

and CMAKE option

LWS_WITH_LIBUV


User api changes
----------------

1) LWS_SEND_BUFFER_POST_PADDING is now 0 and deprecated.  You can remove it; if
you still use it, obviously it does nothing.  Old binary code with nonzero
LWS_SEND_BUFFER_POST_PADDING is perfectly compatible, the old code just
allocated a buffer bigger than the library is going to use.

The example apps no longer use LWS_SEND_BUFFER_POST_PADDING.

The only path who made use of it was sending with LWS_WRITE_CLOSE --->

2) Because of lws_close_reason() formalizing handling close frames,
LWS_WRITE_CLOSE is removed from libwebsockets.h.  It was only of use to send
close frames...close frame content should be managed using lws_close_reason()
now.

3) We check for invalid CLOSE codes and complain about protocol violation in
our close code.  But it changes little since we were in the middle of closing
anyway.

4) zero-length RX frames and zero length TX frames are now allowed.

5) Pings and close used to be limited to 124 bytes, the correct limit is 125
so that is now also allowed.

6) LWS_PRE is provided as a synonym for LWS_SEND_BUFFER_PRE_PADDING, either is
valid to use now.

7) There's generic support for RFC7462 style extension options built into the
library now.  As a consequence, a field "options" is added to lws_extension.
It can be NULL if there are no options on the extension.  Extension internal
info is part of the public abi because extensions may be implemented outside
the library.

8) WSI_TOKEN_PROXY enum was accidentally defined to collide with another token
of value 73.  That's now corrected and WSI_TOKEN_PROXY moved to his own place at
77.

9) With the addition of libuv support, libev is not the only event loop
library in town and his api names must be elaborated with _ev_

  Callback typedef: lws_signal_cb ---> lws_ev_signal_cb_t
  lws_sigint_cfg --> lws_ev_sigint_cfg
  lws_initloop --> lws_ev_initloop
  lws_sigint_cb --> lws_ev_sigint_cb

10) Libev support is made compatible with multithreaded service,
lws_ev_initloop (was lws_initloop) gets an extra argument for the
thread service index (use 0 if you will just have 1 service thread).

LWS_VISIBLE LWS_EXTERN int
lws_ev_initloop(struct lws_context *context, ev_loop_t *loop, int tsi);


v1.6.0-chrome48-firefox42
=======================

Major API improvements
----------------------

v1.6.0 has many cleanups and improvements in the API.  Although at first it
looks pretty drastic, user code will only need four actions to update it.

 - Do the three search/replaces in your user code, /libwebsocket_/lws_/,
   /libwebsockets_/lws_/, and /struct\ libwebsocket/struct\ lws/

 - Remove the context parameter from your user callbacks

 - Remove context as the first parameter from the "Eleven APIS" listed in the
   User Api Changes section

 - Add lws_get_context(wsi) as the first parameter on the "Three APIS" listed
   in the User Api Changes section, and anywhere else you still need context

That's it... generally only a handful of the 14 affected APIs are actually in
use in your user code and you can find them quickest by compiling and visiting
the errors each in turn.  And the end results are much cleaner, more
predictable and maintainable.


User api additions
------------------

1) lws now exposes his internal platform file abstraction in a way that can be
both used by user code to make it platform-agnostic, and be overridden or
subclassed by user code.  This allows things like handling the URI "directory
space" as a virtual filesystem that may or may not be backed by a regular
filesystem.  One example use is serving files from inside large compressed
archive storage without having to unpack anything except the file being
requested.

The test server shows how to use it, basically the platform-specific part of
lws prepares a file operations structure that lives in the lws context.

Helpers are provided to also leverage these platform-independent file handling
apis

static inline lws_filefd_type
lws_plat_file_open(struct lws *wsi, const char *filename,
		   unsigned long *filelen, int flags)
static inline int
lws_plat_file_close(struct lws *wsi, lws_filefd_type fd)

static inline unsigned long
lws_plat_file_seek_cur(struct lws *wsi, lws_filefd_type fd, long offset)

static inline int
lws_plat_file_read(struct lws *wsi, lws_filefd_type fd, unsigned long *amount,
		   unsigned char *buf, unsigned long len)

static inline int
lws_plat_file_write(struct lws *wsi, lws_filefd_type fd, unsigned long *amount,
		    unsigned char *buf, unsigned long len)
		    
The user code can also override or subclass the file operations, to either
wrap or replace them.  An example is shown in test server.

A wsi can be associated with the file activity, allowing per-connection
authentication and state to be used when interpreting the file request.

2) A new API void * lws_wsi_user(struct lws *wsi) lets you get the pointer to
the user data associated with the wsi, just from the wsi.

3) URI argument handling.  Libwebsockets parses and protects URI arguments
like test.html?arg1=1&arg2=2, it decodes %xx uriencoding format and reduces
path attacks like ../.../../etc/passwd so they cannot go behind the web
server's /.  There is a list of confirmed attacks we're proof against in
./test-server/attack.sh.

There is a new API lws_hdr_copy_fragment that should be used now to access
the URI arguments (it returns the fragments length)

               while (lws_hdr_copy_fragment(wsi, buf, sizeof(buf),
                                            WSI_TOKEN_HTTP_URI_ARGS, n) > 0) {
                       lwsl_info("URI Arg %d: %s\n", ++n, buf);
               }

For the example above, calling with n=0 will return "arg1=1" and n=1 "arg2=2".
All legal uriencodings will have been reduced in those strings.

lws_hdr_copy_fragment() returns the length of the x=y fragment, so it's also
possible to deal with arguments containing %00.  If you don't care about that,
the returned string has '\0' appended to simplify processing.


User api changes
----------------

1) Three APIS

 - lws_callback_on_writable_all_protocol(const struct lws_protocols *protocol)
 - lws_callback_all_protocol(const struct lws_protocols *protocol)
 - lws_rx_flow_allow_all_protocol(lws_rx_flow_allow_all_protocol)

Now take an additional pointer to the lws_context in their first argument.

The reason for this change is struct lws_protocols has been changed to remove
members that lws used for private storage: so the protocols struct in now
truly const and may be reused serially or simultaneously by different contexts.

2) Eleven APIs

LWS_VISIBLE LWS_EXTERN int
lws_add_http_header_by_name(struct lws_context *context,
                struct lws *wsi,
                const unsigned char *name,
                const unsigned char *value,
                int length,
                unsigned char **p,
                unsigned char *end);
LWS_VISIBLE LWS_EXTERN int
lws_finalize_http_header(struct lws_context *context,
             struct lws *wsi,
             unsigned char **p,
             unsigned char *end);
LWS_VISIBLE LWS_EXTERN int
lws_add_http_header_by_token(struct lws_context *context,
                 struct lws *wsi,
                 enum lws_token_indexes token,
                 const unsigned char *value,
                 int length,
                 unsigned char **p,
                 unsigned char *end);
LWS_VISIBLE LWS_EXTERN int
lws_add_http_header_content_length(struct lws_context *context,
                   struct lws *wsi,
                   unsigned long content_length,
                   unsigned char **p,
                   unsigned char *end);
LWS_VISIBLE LWS_EXTERN int
lws_add_http_header_status(struct lws_context *context, struct lws *wsi,
               unsigned int code, unsigned char **p,
               unsigned char *end);

LWS_VISIBLE LWS_EXTERN int
lws_serve_http_file(struct lws_context *context, struct lws *wsi,
            const char *file, const char *content_type,
            const char *other_headers, int other_headers_len);
LWS_VISIBLE LWS_EXTERN int
lws_serve_http_file_fragment(struct lws_context *context, struct lws *wsi);

LWS_VISIBLE LWS_EXTERN int
lws_return_http_status(struct lws_context *context, struct lws *wsi,
               unsigned int code, const char *html_body);

LWS_VISIBLE LWS_EXTERN int
lws_callback_on_writable(const struct lws_context *context, struct lws *wsi);

LWS_VISIBLE LWS_EXTERN void
lws_get_peer_addresses(struct lws_context *context, struct lws *wsi,
               lws_sockfd_type fd, char *name, int name_len,
               char *rip, int rip_len);

LWS_VISIBLE LWS_EXTERN int
lws_read(struct lws_context *context, struct lws *wsi,
     unsigned char *buf, size_t len); 

no longer require their initial struct lws_context * parameter.

3) Several older apis start with libwebsocket_ or libwebsockets_ while newer ones
all begin lws_.  These apis have been changed to all begin with lws_.

To convert, search-replace

 - libwebsockets_/lws_
 - libwebsocket_/lws_
 - struct\ libwebsocket/struct\ lws
 
4) context parameter removed from user callback.

Since almost all apis no longer need the context as a parameter, it's no longer
provided at the user callback directly.

However if you need it, for ALL callbacks wsi is valid and has a valid context
pointer you can recover using lws_get_context(wsi).


v1.5-chrome47-firefox41
=======================

User api changes
----------------

LWS_CALLBACK_CLIENT_CONNECTION_ERROR may provide an error string if in is
non-NULL.  If so, the string has length len.

LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED is available to relax the requirement
for peer certs if you are using the option to require client certs.

LWS_WITHOUT_BUILTIN_SHA1 cmake option forces lws to use SHA1() defined
externally, eg, byOpenSSL, and disables build of libwebsockets_SHA1()


v1.4-chrome43-firefox36
=======================

User api additions
------------------

There's a new member in the info struct used to control context creation,
ssl_private_key_password, which allows passing into lws the passphrase on
an SSL cetificate

There's a new member in struct protocols, id, which is ignored by lws but can
be used by the user code to mark the selected protocol by user-defined version
or capabliity flag information, for the case multiple versions of a protocol are
supported.

int lws_is_ssl(wsi) added to allow user code to know if the connection was made
over ssl or not.  If LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT is used, both
ssl and non-ssl connections are possible and may need to be treated differently
in the user code.

int lws_partial_buffered(wsi) added... should be checked after any
libwebsocket_write that will be followed by another libwebsocket_write inside
the same writeable callback.  If set, you can't do any more writes until the
writeable callback is called again.  If you only do one write per writeable callback,
you can ignore this.

HTTP2-related: HTTP2 changes how headers are handled, lws now has new version-
agnositic header creation APIs.  These do the right thing depending on each
connection's HTTP version without the user code having to know or care, except
to make sure to use the new APIs for headers (test-server is updated to use
them already, so look there for examples)

The APIs "render" the headers into a user-provided buffer and bump *p as it
is used.  If *p reaches end, then the APIs return nonzero for error.

LWS_VISIBLE LWS_EXTERN int
lws_add_http_header_status(struct libwebsocket_context *context,
			    struct libwebsocket *wsi,
			    unsigned int code,
			    unsigned char **p,
			    unsigned char *end);

Start a response header reporting status like 200, 500, etc

LWS_VISIBLE LWS_EXTERN int
lws_add_http_header_by_name(struct libwebsocket_context *context,
			    struct libwebsocket *wsi,
			    const unsigned char *name,
			    const unsigned char *value,
			    int length,
			    unsigned char **p,
			    unsigned char *end);

Add a header like name: value in HTTP1.x

LWS_VISIBLE LWS_EXTERN int 
lws_finalize_http_header(struct libwebsocket_context *context,
			    struct libwebsocket *wsi,
			    unsigned char **p,
			    unsigned char *end);

Finish off the headers, like add the extra \r\n in HTTP1.x

LWS_VISIBLE LWS_EXTERN int
lws_add_http_header_by_token(struct libwebsocket_context *context,
			    struct libwebsocket *wsi,
			    enum lws_token_indexes token,
			    const unsigned char *value,
			    int length,
			    unsigned char **p,
			    unsigned char *end);

Add a header by using a lws token as the name part.  In HTTP2, this can be
compressed to one or two bytes.


User api removal
----------------

protocols struct member no_buffer_all_partial_tx is removed.  Under some
conditions like rewriting extension such as compression in use, the built-in
partial send buffering is the only way to deal with the problem, so turning
it off is deprecated.


User api changes
----------------

HTTP2-related: API libwebsockets_serve_http_file() takes an extra parameter at
the end now

int other_headers_len)

If you are providing other headers, they must be generated using the new
HTTP-version-agnostic APIs, and you must provide the length of them using this
additional parameter.

struct lws_context_creation_info now has an additional member
SSL_CTX *provided_client_ssl_ctx you may set to an externally-initialized
SSL_CTX managed outside lws.  Defaulting to zero keeps the existing behaviour of
lws managing the context, if you memset the struct to 0 or have as a filescope
initialized struct in bss, no need to change anything.


v1.3-chrome37-firefox30
=======================

 .gitignore                                               |    1 -
 CMakeLists.txt                                           |  447 +++--
 README.build                                             |   35 +-
 README.coding                                            |   14 +
 changelog                                                |   66 +
 cmake/LibwebsocketsConfig.cmake.in                       |   17 +
 cmake/LibwebsocketsConfigVersion.cmake.in                |   11 +
 config.h.cmake                                           |   18 +
 cross-ming.cmake                                         |   31 +
 cross-openwrt-makefile                                   |   91 +
 lib/client-handshake.c                                   |  205 ++-
 lib/client-parser.c                                      |   58 +-
 lib/client.c                                             |  158 +-
 lib/context.c                                            |  341 ++++
 lib/extension-deflate-frame.c                            |    2 +-
 lib/extension.c                                          |  178 ++
 lib/handshake.c                                          |  287 +---
 lib/lextable.h                                           |  338 ++++
 lib/libev.c                                              |  175 ++
 lib/libwebsockets.c                                      | 2089 +++--------------------
 lib/libwebsockets.h                                      |  253 ++-
 lib/lws-plat-unix.c                                      |  404 +++++
 lib/lws-plat-win.c                                       |  358 ++++
 lib/minilex.c                                            |  530 +++---
 lib/output.c                                             |  445 ++---
 lib/parsers.c                                            |  682 ++++----
 lib/pollfd.c                                             |  239 +++
 lib/private-libwebsockets.h                              |  501 +++++-
 lib/server-handshake.c                                   |  274 +--
 lib/server.c                                             |  858 ++++++++--
 lib/service.c                                            |  517 ++++++
 lib/sha-1.c                                              |   38 +-
 lib/ssl-http2.c                                          |   78 +
 lib/ssl.c                                                |  571 +++++++
 test-server/attack.sh                                    |  101 +-
 test-server/test-client.c                                |    9 +-
 test-server/test-echo.c                                  |   17 +-
 test-server/test-fraggle.c                               |    7 -
 test-server/test-ping.c                                  |   12 +-
 test-server/test-server.c                                |  330 ++--
 test-server/test.html                                    |    4 +-
 win32port/client/client.vcxproj                          |  259 ---
 win32port/client/client.vcxproj.filters                  |   39 -
 .../libwebsocketswin32.vcxproj.filters                   |   93 -
 win32port/server/server.vcxproj                          |  276 ---
 win32port/server/server.vcxproj.filters                  |   51 -
 win32port/win32helpers/gettimeofday.h                    |   59 +-
 win32port/win32helpers/netdb.h                           |    1 -
 win32port/win32helpers/strings.h                         |    0
 win32port/win32helpers/sys/time.h                        |    1 -
 win32port/win32helpers/unistd.h                          |    0
 win32port/win32helpers/websock-w32.c                     |  104 --
 win32port/win32helpers/websock-w32.h                     |   62 -
 win32port/win32port.sln                                  |  100 --
 win32port/zlib/gzio.c                                    |    3 +-
 55 files changed, 6779 insertions(+), 5059 deletions(-)


User api additions
------------------

POST method is supported

The protocol 0 / HTTP callback can now get two new kinds of callback,
LWS_CALLBACK_HTTP_BODY (in and len are a chunk of the body of the HTTP request)
and LWS_CALLBACK_HTTP_BODY_COMPLETION (the expected amount of body has arrived
and been passed to the user code already).  These callbacks are used with the
post method (see the test server for details).

The period between the HTTP header completion and the completion of the body
processing is protected by a 5s timeout.

The chunks are stored in a malloc'd buffer of size protocols[0].rx_buffer_size.


New server option you can enable from user code
LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT allows non-SSL connections to
also be accepted on an SSL listening port.  It's disabled unless you enable
it explicitly.


Two new callbacks are added in protocols[0] that are optional for allowing
limited thread access to libwebsockets, LWS_CALLBACK_LOCK_POLL and
LWS_CALLBACK_UNLOCK_POLL.

If you use them, they protect internal and external poll list changes, but if
you want to use external thread access to libwebsocket_callback_on_writable()
you have to implement your locking here even if you don't use external
poll support.

If you will use another thread for this, take a lot of care about managing
your list of live wsi by doing it from ESTABLISHED and CLOSED callbacks
(with your own locking).

If you configure cmake with -DLWS_WITH_LIBEV=1 then the code allowing the libev
eventloop instead of the default poll() one will also be compiled in.  But to
use it, you must also set the LWS_SERVER_OPTION_LIBEV flag on the context
creation info struct options member.

IPV6 is supported and enabled by default except for Windows, you can disable
the support at build-time by giving -DLWS_IPV6=, and disable use of it even if
compiled in by making sure the flag LWS_SERVER_OPTION_DISABLE_IPV6 is set on
the context creation info struct options member.

You can give LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS option flag to
guarantee the OS CAs will not be used, even if that support was selected at
build-time.

Optional "token limits" may be enforced by setting the member "token_limits"
in struct lws_context_creation_info to point to a struct lws_token_limits.
NULL means no token limits used for compatibility.


User api changes
----------------

Extra optional argument to libwebsockets_serve_http_file() allows injecion
of HTTP headers into the canned response.  Eg, cookies may be added like
that without getting involved in having to send the header by hand.

A new info member http_proxy_address may be used at context creation time to
set the http proxy.  If non-NULL, it overrides http_proxy environment var.

Cmake supports LWS_SSL_CLIENT_USE_OS_CA_CERTS defaulting to on, which gets
the client to use the OS CA Roots.  If you're worried somebody with the
ability to forge for force creation of a client cert from the root CA in
your OS, you should disable this since your selfsigned $0 cert is a lot safer
then...


v1.23-chrome32-firefox24
========================

 Android.mk                            |   29 +
 CMakeLists.txt                        |  573 ++++++++----
 COPYING                               |  503 -----------
 INSTALL                               |  365 --------
 Makefile.am                           |   13 -
 README.build                          |  371 ++------
 README.coding                         |   63 ++
 autogen.sh                            | 1578 ---------------------------------
 changelog                             |   69 ++
 cmake/FindGit.cmake                   |  163 ++++
 cmake/FindOpenSSLbins.cmake           |   15 +-
 cmake/UseRPMTools.cmake               |  176 ++++
 config.h.cmake                        |   25 +-
 configure.ac                          |  226 -----
 cross-arm-linux-gnueabihf.cmake       |   28 +
 lib/Makefile.am                       |   89 --
 lib/base64-decode.c                   |   98 +-
 lib/client-handshake.c                |  123 ++-
 lib/client-parser.c                   |   19 +-
 lib/client.c                          |  145 ++-
 lib/daemonize.c                       |    4 +-
 lib/extension.c                       |    2 +-
 lib/getifaddrs.h                      |    4 +-
 lib/handshake.c                       |   76 +-
 lib/libwebsockets.c                   |  491 ++++++----
 lib/libwebsockets.h                   |  164 ++--
 lib/output.c                          |  214 ++++-
 lib/parsers.c                         |  102 +--
 lib/private-libwebsockets.h           |   66 +-
 lib/server-handshake.c                |    5 +-
 lib/server.c                          |   29 +-
 lib/sha-1.c                           |    2 +-
 libwebsockets-api-doc.html            |  249 +++---
 libwebsockets.pc.in                   |   11 -
 libwebsockets.spec                    |   14 +-
 m4/ignore-me                          |    2 -
 scripts/FindLibWebSockets.cmake       |   33 +
 scripts/kernel-doc                    |    1 +
 test-server/Makefile.am               |  131 ---
 test-server/leaf.jpg                  |  Bin 0 -> 2477518 bytes
 test-server/test-client.c             |   78 +-
 test-server/test-echo.c               |   33 +-
 test-server/test-fraggle.c            |   26 +-
 test-server/test-ping.c               |   15 +-
 test-server/test-server.c             |  197 +++-
 test-server/test.html                 |    5 +-
 win32port/win32helpers/gettimeofday.c |   74 +-
 win32port/win32helpers/websock-w32.h  |    6 +-
 48 files changed, 2493 insertions(+), 4212 deletions(-)


User api additions
------------------

 - You can now call libwebsocket_callback_on_writable() on http connectons,
 	and get a LWS_CALLBACK_HTTP_WRITEABLE callback, the same way you can
	regulate writes with a websocket protocol connection.

 - A new member in the context creation parameter struct "ssl_cipher_list" is
 	added, replacing CIPHERS_LIST_STRING.  NULL means use the ssl library
	default list of ciphers.

 - Not really an api addition, but libwebsocket_service_fd() will now zero
 	the revents field of the pollfd it was called with if it handled the
	descriptor.  So you can tell if it is a non-lws fd by checking revents
	after the service call... if it's still nonzero, the descriptor
	belongs to you and you need to take care of it.

 - libwebsocket_rx_flow_allow_all_protocol(protocol) will unthrottle all
 	connections with the established protocol.  It's designed to be
	called from user server code when it sees it can accept more input
	and may have throttled connections using the server rx flow apis
	while it was unable to accept any other input  The user server code
	then does not have to try to track while connections it choked, this
	will free up all of them in one call.

 - there's a new, optional callback LWS_CALLBACK_CLOSED_HTTP which gets
	called when an HTTP protocol socket closes

 - for LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION callback, the user_space alloc
	has already been done before the callback happens.  That means we can
	use the user parameter to the callback to contain the user pointer, and
	move the protocol name to the "in" parameter.  The docs for this
	callback are also updated to reflect how to check headers in there.

 - libwebsocket_client_connect() is now properly nonblocking and async.  See
	README.coding and test-client.c for information on the callbacks you
	can rely on controlling the async connection period with.

 - if your OS does not support the http_proxy environment variable convention
 	(eg, reportedly OSX), you can use a new api libwebsocket_set_proxy()
 	to set the proxy details in between context creation and the connection
 	action.  For OSes that support http_proxy, that's used automatically.

User api changes
----------------

 - the external poll callbacks now get the socket descriptor coming from the
 	"in" parameter.  The user parameter provides the user_space for the
	wsi as it normally does on the other callbacks.
	LWS_CALLBACK_FILTER_NETWORK_CONNECTION also has the socket descriptor
	delivered by @in now instead of @user.

 - libwebsocket_write() now returns -1 for error, or the amount of data
 	actually accepted for send.  Under load, the OS may signal it is
	ready to send new data on the socket, but have only a restricted
	amount of memory to buffer the packet compared to usual.


User api removal
----------------

 - libwebsocket_ensure_user_space() is removed from the public api, if you
 	were using it to get user_space, you need to adapt your code to only
	use user_space inside the user callback.

 - CIPHERS_LIST_STRING is removed

 - autotools build has been removed.  See README.build for info on how to
 	use CMake for your platform


v1.21-chrome26-firefox18
========================

 - Fixes buffer overflow bug in max frame size handling if you used the
 	default protocol buffer size.  If you declared rx_buffer_size in your
	protocol, which is recommended anyway, your code was unaffected.

v1.2-chrome26-firefox18
=======================

Diffstat
--------

 .gitignore                                                      |  16 +++
 CMakeLists.txt                                                  | 544 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 LICENSE                                                         | 526 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Makefile.am                                                     |   1 +
 README                                                          |  20 +++
 README.build                                                    | 258 ++++++++++++++++++++++++++++++++-----
 README.coding                                                   |  52 ++++++++
 changelog                                                       | 136 ++++++++++++++++++++
 cmake/FindOpenSSLbins.cmake                                     |  33 +++++
 config.h.cmake                                                  | 173 +++++++++++++++++++++++++
 configure.ac                                                    |  22 +++-
 lib/Makefile.am                                                 |  20 ++-
 lib/base64-decode.c                                             |   2 +-
 lib/client-handshake.c                                          | 190 +++++++++++-----------------
 lib/client-parser.c                                             |  88 +++++++------
 lib/client.c                                                    | 384 ++++++++++++++++++++++++++++++-------------------------
 lib/daemonize.c                                                 |  32 +++--
 lib/extension-deflate-frame.c                                   |  58 +++++----
 lib/extension-deflate-stream.c                                  |  19 ++-
 lib/extension-deflate-stream.h                                  |   4 +-
 lib/extension.c                                                 |  11 +-
 lib/getifaddrs.c                                                | 315 +++++++++++++++++++++++-----------------------
 lib/getifaddrs.h                                                |  30 ++---
 lib/handshake.c                                                 | 124 +++++++++++-------
 lib/libwebsockets.c                                             | 736 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------
 lib/libwebsockets.h                                             | 237 ++++++++++++++++++++++------------
 lib/output.c                                                    | 192 +++++++++++-----------------
 lib/parsers.c                                                   | 966 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------
 lib/private-libwebsockets.h                                     | 225 +++++++++++++++++++++------------
 lib/server-handshake.c                                          |  82 ++++++------
 lib/server.c                                                    |  96 +++++++-------
 libwebsockets-api-doc.html                                      | 189 ++++++++++++++++++----------
 libwebsockets.spec                                              |  17 +--
 test-server/attack.sh                                           | 148 ++++++++++++++++++++++
 test-server/test-client.c                                       | 125 +++++++++---------
 test-server/test-echo.c                                         |  31 +++--
 test-server/test-fraggle.c                                      |  32 ++---
 test-server/test-ping.c                                         |  52 ++++----
 test-server/test-server.c                                       | 129 ++++++++++++-------
 win32port/libwebsocketswin32/libwebsocketswin32.vcxproj         | 279 ----------------------------------------
 win32port/libwebsocketswin32/libwebsocketswin32.vcxproj.filters |  23 +++-
 41 files changed, 4398 insertions(+), 2219 deletions(-)


User api additions
------------------

 - lws_get_library_version() returns a const char * with a string like
 	 "1.1 9e7f737", representing the library version from configure.ac
	 and the git HEAD hash the library was built from

 - TCP Keepalive can now optionally be applied to all lws sockets, on Linux
 	also with controllable timeout, number of probes and probe interval.
	(On BSD type OS, you can only use system default settings for the
	timing and retries, although enabling it is supported by setting
	ka_time to nonzero, the exact value has no meaning.)
	This enables detection of idle connections which are logically okay,
	but are in fact dead, due to network connectivity issues at the server,
	client, or any intermediary.  By default it's not enabled, but you
	can enable it by setting a non-zero timeout (in seconds) at the new
	ka_time member at context creation time.

 - Two new optional user callbacks added, LWS_CALLBACK_PROTOCOL_DESTROY which
 	is called one-time per protocol as the context is being destroyed, and
	LWS_CALLBACK_PROTOCOL_INIT which is called when the context is created
	and the protocols are added, again it's a one-time affair.
	This lets you manage per-protocol allocations properly including
	cleaning up after yourself when the server goes down.

User api changes
----------------

 - libwebsocket_create_context() has changed from taking a ton of parameters
	to just taking a pointer to a struct containing the parameters.  The
	struct lws_context_creation_info is in libwebsockets.h, the members
	are in the same order as when they were parameters to the call
	previously.  The test apps are all updated accordingly so you can
	see example code there.

 - Header tokens are now deleted after the websocket connection is
	established.  Not just the header data is saved, but the pointer and
	length array is also removed from (union) scope saving several hundred
	bytes per connection once it is established

 - struct libwebsocket_protocols has a new member rx_buffer_size, this
	controls rx buffer size per connection of that protocol now.  Sources
	for apps built against older versions of the library won't declare
	this in their protocols, defaulting it to 0.  Zero buffer is legal,
	it causes a default buffer to be allocated (currently 4096)

	If you want to receive only atomic frames in your user callback, you
	should set this to greater than your largest frame size.  If a frame
	comes that exceeds that, no error occurs but the callback happens as
	soon as the buffer limit is reached, and again if it is reached again
	or the frame completes.  You can detect that has happened by seeing
	there is still frame content pending using
	libwebsockets_remaining_packet_payload()

	By correctly setting this, you can save a lot of memory when your
	protocol has small frames (see the test server and client sources).

 - LWS_MAX_HEADER_LEN now defaults to 1024 and is the total amount of known
 	header payload lws can cope with, that includes the GET URL, origin
	etc.  Headers not understood by lws are ignored and their payload
	not included in this.


User api removals
-----------------

 - The configuration-time option MAX_USER_RX_BUFFER has been replaced by a
	buffer size chosen per-protocol.  For compatibility, there's a default
	of 4096 rx buffer, but user code should set the appropriate size for
	the protocol frames.

 - LWS_INITIAL_HDR_ALLOC and LWS_ADDITIONAL_HDR_ALLOC are no longer needed
 	and have been removed.  There's a new header management scheme that
	handles them in a much more compact way.

 - libwebsockets_hangup_on_client() is removed.  If you want to close the
 	connection you must do so from the user callback and by returning
	-1 from there.

 - libwebsocket_close_and_free_session() is now private to the library code
 	only and not exposed for user code.  If you want to close the
	connection, you must do so from the user callback by returning -1
	from there.


New features
------------

 - Cmake project file added, aimed initially at Windows support: this replaces
	the visual studio project files that were in the tree until now.

 - CyaSSL now supported in place of OpenSSL (--use-cyassl on configure)

 - PATH_MAX or MAX_PATH no longer needed

 - cutomizable frame rx buffer size by protocol

 - optional TCP keepalive so dead peers can be detected, can be enabled at
 	context-creation time

 - valgrind-clean: no SSL or CyaSSL: completely clean.  With OpenSSL, 88 bytes
 	lost at OpenSSL library init and symptomless reports of uninitialized
	memory usage... seems to be a known and ignored problem at OpenSSL

 - By default debug is enabled and the library is built for -O0 -g to faclitate
	that.  Use --disable-debug configure option to build instead with -O4
	and no -g (debug info), obviously providing best performance and
	reduced binary size.

 - 1.0 introduced some code to try to not deflate small frames, however this
 	seems to break when confronted with a mixture of frames above and
	below the threshold, so it's removed.  Veto the compression extension
	in your user callback if you will typically have very small frames.

 - There are many memory usage improvements, both a reduction in malloc/
 	realloc and architectural changes.  A websocket connection now
	consumes only 296 bytes with SSL or 272 bytes without on x86_64,
	during header processing an additional 1262 bytes is allocated in a
	single malloc, but is freed when the websocket connection starts.
	The RX frame buffer defined by the protocol in user
	code is also allocated per connection, this represents the largest
	frame you can receive atomically in that protocol.

 - On ARM9 build, just http+ws server no extensions or ssl, <12Kbytes .text
 	and 112 bytes per connection (+1328 only during header processing)


v1.1-chrome26-firefox18
=======================

Diffstat
--------

 Makefile.am                            |    4 +
 README-test-server                     |  291 ---
 README.build                           |  239 ++
 README.coding                          |  138 ++
 README.rst                             |   72 -
 README.test-apps                       |  272 +++
 configure.ac                           |  116 +-
 lib/Makefile.am                        |   55 +-
 lib/base64-decode.c                    |    5 +-
 lib/client-handshake.c                 |  121 +-
 lib/client-parser.c                    |  394 ++++
 lib/client.c                           |  807 +++++++
 lib/daemonize.c                        |  212 ++
 lib/extension-deflate-frame.c          |  132 +-
 lib/extension-deflate-stream.c         |   12 +-
 lib/extension-x-google-mux.c           | 1223 ----------
 lib/extension-x-google-mux.h           |   96 -
 lib/extension.c                        |    8 -
 lib/getifaddrs.c                       |  271 +++
 lib/getifaddrs.h                       |   76 +
 lib/handshake.c                        |  582 +----
 lib/libwebsockets.c                    | 2493 ++++++---------------
 lib/libwebsockets.h                    |  115 +-
 lib/md5.c                              |  217 --
 lib/minilex.c                          |  440 ++++
 lib/output.c                           |  628 ++++++
 lib/parsers.c                          | 2016 +++++------------
 lib/private-libwebsockets.h            |  284 +--
 lib/server-handshake.c                 |  275 +++
 lib/server.c                           |  377 ++++
 libwebsockets-api-doc.html             |  300 +--
 m4/ignore-me                           |    2 +
 test-server/Makefile.am                |  111 +-
 test-server/libwebsockets.org-logo.png |  Bin 0 -> 7029 bytes
 test-server/test-client.c              |   45 +-
 test-server/test-echo.c                |  330 +++
 test-server/test-fraggle.c             |   20 +-
 test-server/test-ping.c                |   22 +-
 test-server/test-server-extpoll.c      |  554 -----
 test-server/test-server.c              |  349 ++-
 test-server/test.html                  |    3 +-
 win32port/zlib/ZLib.vcxproj            |  749 ++++---
 win32port/zlib/ZLib.vcxproj.filters    |  188 +-
 win32port/zlib/adler32.c               |  348 ++-
 win32port/zlib/compress.c              |  160 +-
 win32port/zlib/crc32.c                 |  867 ++++----
 win32port/zlib/crc32.h                 |  882 ++++----
 win32port/zlib/deflate.c               | 3799 +++++++++++++++-----------------
 win32port/zlib/deflate.h               |  688 +++---
 win32port/zlib/gzclose.c               |   50 +-
 win32port/zlib/gzguts.h                |  325 ++-
 win32port/zlib/gzlib.c                 | 1157 +++++-----
 win32port/zlib/gzread.c                | 1242 ++++++-----
 win32port/zlib/gzwrite.c               | 1096 +++++----
 win32port/zlib/infback.c               | 1272 ++++++-----
 win32port/zlib/inffast.c               |  680 +++---
 win32port/zlib/inffast.h               |   22 +-
 win32port/zlib/inffixed.h              |  188 +-
 win32port/zlib/inflate.c               | 2976 +++++++++++++------------
 win32port/zlib/inflate.h               |  244 +-
 win32port/zlib/inftrees.c              |  636 +++---
 win32port/zlib/inftrees.h              |  124 +-
 win32port/zlib/trees.c                 | 2468 +++++++++++----------
 win32port/zlib/trees.h                 |  256 +--
 win32port/zlib/uncompr.c               |  118 +-
 win32port/zlib/zconf.h                 |  934 ++++----
 win32port/zlib/zlib.h                  | 3357 ++++++++++++++--------------
 win32port/zlib/zutil.c                 |  642 +++---
 win32port/zlib/zutil.h                 |  526 ++---
 69 files changed, 19556 insertions(+), 20145 deletions(-)

user api changes
----------------

 - libwebsockets_serve_http_file() now takes a context as first argument

 - libwebsockets_get_peer_addresses() now takes a context and wsi as first
	two arguments


user api additions
------------------

 - lwsl_...() logging apis, default to stderr but retargetable by user code;
	may be used also by user code

 - lws_set_log_level() set which logging apis are able to emit (defaults to
	notice, warn, err severities), optionally set the emit callback

 - lwsl_emit_syslog() helper callback emits to syslog

 - lws_daemonize() helper code that forks the app into a headless daemon
	properly, maintains a lock file with pid in suitable for sysvinit etc to
	control lifecycle

 - LWS_CALLBACK_HTTP_FILE_COMPLETION callback added since http file
	transfer is now asynchronous (see test server code)

 - lws_frame_is_binary() from a wsi pointer, let you know if the received
	data was sent in BINARY mode


user api removals
-----------------

 - libwebsockets_fork_service_loop() - no longer supported (had intractable problems)
	arrange your code to act from the user callback instead from same
	process context as the service loop

 - libwebsockets_broadcast() - use libwebsocket_callback_on_writable[_all_protocol]()
	instead from same process context as the service loop.  See the test apps
	for examples.

 - x-google-mux() removed until someone wants it

 - pre -v13 (ancient) protocol support removed


New features
------------

 - echo test server and client compatible with echo.websocket.org added

 - many new configure options (see README.build) to reduce footprint of the
	library to what you actually need, eg, --without-client and
	--without-server

 - http + websocket server can build to as little as 12K .text for ARM

 - no more MAX_CLIENTS limitation; adapts to support the max number of fds
	allowed to the process by ulimit, defaults to 1024 on Fedora and
	Ubuntu.  Use ulimit to control this without needing to configure
	the library.  Code here is smaller and faster.

 - adaptive ratio of listen socket to connection socket service allows
	good behaviour under Apache ab test load.  Tested with thousands
	of simultaneous connections

 - reduction in per-connection memory footprint by moving to a union to hold
	mutually-exclusive state for the connection

 - robustness: Out of Memory taken care of for all allocation code now

 - internal getifaddrs option if your toolchain lacks it (some uclibc)

 - configurable memory limit for deflate operations

 - improvements in SSL code nonblocking operation, possible hang solved,
	some SSL operations broken down into pollable states so there is
	no library blocking, timeout coverage for SSL_connect

 - extpoll test server merged into single test server source

 - robustness: library should deal with all recoverable socket conditions

 - rx flowcontrol for backpressure notification fixed and implmeneted
	correctly in the test server

 - optimal lexical parser added for header processing; all headers in a
	single 276-byte state table

 - latency tracking api added (configure --with-latency)

 - Improved in-tree documentation, REAME.build, README.coding,
	README.test-apps, changelog

 - Many small fixes


v1.0-chrome25-firefox17 (6cd1ea9b005933f)

Added undroid/libwebsockets/cmake/FindGit.cmake.







































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
################################################################################
#
#  Program: 3D Slicer
#
#  Copyright (c) Kitware Inc.
#
#  See COPYRIGHT.txt
#  or http://www.slicer.org/copyright/copyright.txt for details.
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#
#  This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.
#  and was partially funded by NIH grant 3P41RR013218-12S1
#
#  AG 2013-02-18: I got it from here
#  https://github.com/Slicer/Slicer/blob/master/CMake/FindGit.cmake
#  license is BSD
#
################################################################################

#
# The module defines the following variables:
#   GIT_EXECUTABLE - path to git command line client
#   GIT_FOUND - true if the command line client was found
#
# If the command line client executable is found the macro
#  GIT_WC_INFO(<dir> <var-prefix>)
# is defined to extract information of a git working copy at
# a given location.
#
# The macro defines the following variables:
#  <var-prefix>_WC_REVISION_HASH - Current SHA1 hash
#  <var-prefix>_WC_REVISION - Current SHA1 hash
#  <var-prefix>_WC_REVISION_NAME - Name associated with <var-prefix>_WC_REVISION_HASH
#  <var-prefix>_WC_URL - output of command `git config --get remote.origin.url'
#  <var-prefix>_WC_ROOT - Same value as working copy URL
#  <var-prefix>_WC_GITSVN - Set to false
#
# ... and also the following ones if it's a git-svn repository:
#  <var-prefix>_WC_GITSVN - Set to True if it is a
#  <var-prefix>_WC_INFO - output of command `git svn info'
#  <var-prefix>_WC_URL - url of the associated SVN repository
#  <var-prefix>_WC_ROOT - root url of the associated SVN repository
#  <var-prefix>_WC_REVISION - current SVN revision number
#  <var-prefix>_WC_LAST_CHANGED_AUTHOR - author of last commit
#  <var-prefix>_WC_LAST_CHANGED_DATE - date of last commit
#  <var-prefix>_WC_LAST_CHANGED_REV - revision of last commit
#  <var-prefix>_WC_LAST_CHANGED_LOG - last log of base revision
#
# Example usage:
#   find_package(Git)
#   if(GIT_FOUND)
#    GIT_WC_INFO(${PROJECT_SOURCE_DIR} Project)
#    message("Current revision is ${Project_WC_REVISION_HASH}")
#    message("git found: ${GIT_EXECUTABLE}")
#   endif()
#

# Look for 'git' or 'eg' (easy git)
#
set(git_names git eg)

# Prefer .cmd variants on Windows unless running in a Makefile
# in the MSYS shell.
#
if(WIN32)
  if(NOT CMAKE_GENERATOR MATCHES "MSYS")
    # Note: Due to a bug in 'git.cmd' preventing it from returning the exit code of 'git',
    #       we excluded it from the list of executables to search.
    # See http://code.google.com/p/msysgit/issues/detail?id=428
    # TODO Check if 'git' exists, get the associated version, if the corresponding version
    #      is known to have a working version of 'git.cmd', use it.
    set(git_names git eg.cmd eg)
  endif()
endif()

find_program(GIT_EXECUTABLE ${git_names}
  PATHS
    "C:/Program Files/Git/bin"
    "C:/Program Files (x86)/Git/bin"
  DOC "git command line client")
mark_as_advanced(GIT_EXECUTABLE)

if(GIT_EXECUTABLE)
  macro(GIT_WC_INFO dir prefix)
    execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --verify -q --short=7 HEAD
       WORKING_DIRECTORY ${dir}
       ERROR_VARIABLE GIT_error
       OUTPUT_VARIABLE ${prefix}_WC_REVISION_HASH
       OUTPUT_STRIP_TRAILING_WHITESPACE)
    set(${prefix}_WC_REVISION ${${prefix}_WC_REVISION_HASH})
    if(NOT ${GIT_error} EQUAL 0)
      message(SEND_ERROR "Command \"${GIT_EXECUTBALE} rev-parse --verify -q --short=7 HEAD\" in directory ${dir} failed with output:\n${GIT_error}")
    else(NOT ${GIT_error} EQUAL 0)
      execute_process(COMMAND ${GIT_EXECUTABLE} name-rev ${${prefix}_WC_REVISION_HASH}
         WORKING_DIRECTORY ${dir}
         OUTPUT_VARIABLE ${prefix}_WC_REVISION_NAME
          OUTPUT_STRIP_TRAILING_WHITESPACE)
    endif(NOT ${GIT_error} EQUAL 0)

    execute_process(COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url
       WORKING_DIRECTORY ${dir}
       OUTPUT_VARIABLE ${prefix}_WC_URL
       OUTPUT_STRIP_TRAILING_WHITESPACE)

    set(${prefix}_WC_GITSVN False)

    # Check if this git is likely to be a git-svn repository
    execute_process(COMMAND ${GIT_EXECUTABLE} config --get-regexp "^svn-remote"
      WORKING_DIRECTORY ${dir}
      OUTPUT_VARIABLE git_config_output
      OUTPUT_STRIP_TRAILING_WHITESPACE
      )

    if(NOT "${git_config_output}" STREQUAL "")
      # In case git-svn is used, attempt to extract svn info
      execute_process(COMMAND ${GIT_EXECUTABLE} svn info
        WORKING_DIRECTORY ${dir}
        TIMEOUT 3
        ERROR_VARIABLE git_svn_info_error
        OUTPUT_VARIABLE ${prefix}_WC_INFO
        RESULT_VARIABLE git_svn_info_result
        OUTPUT_STRIP_TRAILING_WHITESPACE)

      if(${git_svn_info_result} EQUAL 0)
        set(${prefix}_WC_GITSVN True)
        string(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*"
          "\\2" ${prefix}_WC_URL "${${prefix}_WC_INFO}")
        string(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*"
          "\\2" ${prefix}_WC_REVISION "${${prefix}_WC_INFO}")
        string(REGEX REPLACE "^(.*\n)?Repository Root: ([^\n]+).*"
          "\\2" ${prefix}_WC_ROOT "${${prefix}_WC_INFO}")
        string(REGEX REPLACE "^(.*\n)?Last Changed Author: ([^\n]+).*"
          "\\2" ${prefix}_WC_LAST_CHANGED_AUTHOR "${${prefix}_WC_INFO}")
        string(REGEX REPLACE "^(.*\n)?Last Changed Rev: ([^\n]+).*"
          "\\2" ${prefix}_WC_LAST_CHANGED_REV "${${prefix}_WC_INFO}")
        string(REGEX REPLACE "^(.*\n)?Last Changed Date: ([^\n]+).*"
          "\\2" ${prefix}_WC_LAST_CHANGED_DATE "${${prefix}_WC_INFO}")
      endif(${git_svn_info_result} EQUAL 0)
    endif(NOT "${git_config_output}" STREQUAL "")

    # If there is no 'remote.origin', default to "NA" value and print a warning message.
    if(NOT ${prefix}_WC_URL)
      message(WARNING "No remote origin set for git repository: ${dir}" )
      set( ${prefix}_WC_URL "NA" )
    else()
      set(${prefix}_WC_ROOT ${${prefix}_WC_URL})
    endif()

  endmacro(GIT_WC_INFO)
endif(GIT_EXECUTABLE)

# Handle the QUIETLY and REQUIRED arguments and set GIT_FOUND to TRUE if
# all listed variables are TRUE

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Git DEFAULT_MSG GIT_EXECUTABLE)


Added undroid/libwebsockets/cmake/FindOpenSSLbins.cmake.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

if(OPENSSL_FOUND)

	find_program(OPENSSL_EXECUTABLE openssl openssl.exe bin/openssl.exe
		HINTS ${_OPENSSL_ROOT_HINTS}
		PATH 
			/usr/bin/ 
			bin/
	  	DOC "Openssl executable")

	mark_as_advanced(OPENSSL_EXECUTABLE)
	
	# On Windows, we need to copy the OpenSSL dlls 
	# to the output directory.
	if(WIN32)
		set(OPENSSL_BIN_FOUND 0)

		find_file(LIBEAY_BIN
			NAMES
			libeay32.dll
			HINTS
			${_OPENSSL_ROOT_HINTS}
			PATH_SUFFIXES
			bin)
		
		find_file(SSLEAY_BIN
			NAMES
			ssleay32.dll
			HINTS
			${_OPENSSL_ROOT_HINTS}
			PATH_SUFFIXES
			bin)
		
		if(LIBEAY_BIN)
			if(SSLEAY_BIN)
				set(OPENSSL_BIN_FOUND 1)
			endif(SSLEAY_BIN)
		endif(LIBEAY_BIN)
	endif(WIN32)
		
endif(OPENSSL_FOUND)

Added undroid/libwebsockets/cmake/LibwebsocketsConfig.cmake.in.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# - Config file for the Libevent package
# It defines the following variables
#  LIBWEBSOCKETS_INCLUDE_DIRS - include directories for FooBar
#  LIBWEBSOCKETS_LIBRARIES    - libraries to link against

# Get the path of the current file.
get_filename_component(LWS_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)

# Set the include directories.
set(LIBWEBSOCKETS_INCLUDE_DIRS "@LWS__INCLUDE_DIRS@")

# Include the project Targets file, this contains definitions for IMPORTED targets.
include(${LWS_CMAKE_DIR}/LibwebsocketsTargets.cmake)

# IMPORTED targets from LibwebsocketsTargets.cmake
set(LIBWEBSOCKETS_LIBRARIES websockets websockets_shared)

Added undroid/libwebsockets/cmake/LibwebsocketsConfigVersion.cmake.in.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
set(PACKAGE_VERSION "@CPACK_PACKAGE_VERSION@")

# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
  set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
  set(PACKAGE_VERSION_COMPATIBLE TRUE)
  if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
    set(PACKAGE_VERSION_EXACT TRUE)
  endif()
endif()	

Added undroid/libwebsockets/cmake/UseRPMTools.cmake.

































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#
# - Find tools needed for building RPM Packages
#   on Linux systems and defines macro that helps to
#   build source or binary RPM, the MACRO assumes
#   CMake 2.4.x which includes CPack support.
#   CPack is used to build tar.gz source tarball
#   which may be used by a custom user-made spec file.
#
# - Define RPMTools_ADD_RPM_TARGETS which defines
#   two (top-level) CUSTOM targets for building
#   source and binary RPMs
#
# Those CMake macros are provided by the TSP Developer Team
# https://savannah.nongnu.org/projects/tsp
#

IF (WIN32)
  MESSAGE(STATUS "RPM tools not available on Win32 systems")
ENDIF(WIN32)

IF (UNIX)
  # Look for RPM builder executable
  FIND_PROGRAM(RPMTools_RPMBUILD_EXECUTABLE
    NAMES rpmbuild
    PATHS "/usr/bin;/usr/lib/rpm"
    PATH_SUFFIXES bin
    DOC "The RPM builder tool")

  IF (RPMTools_RPMBUILD_EXECUTABLE)
    MESSAGE(STATUS "Looking for RPMTools... - found rpmuild is ${RPMTools_RPMBUILD_EXECUTABLE}")
    SET(RPMTools_RPMBUILD_FOUND "YES")
    GET_FILENAME_COMPONENT(RPMTools_BINARY_DIRS ${RPMTools_RPMBUILD_EXECUTABLE} PATH)
  ELSE (RPMTools_RPMBUILD_EXECUTABLE)
    SET(RPMTools_RPMBUILD_FOUND "NO")
    MESSAGE(STATUS "Looking for RPMTools... - rpmbuild NOT FOUND")
  ENDIF (RPMTools_RPMBUILD_EXECUTABLE)

  # Detect if CPack was included or not
  IF (NOT DEFINED "CPACK_PACKAGE_NAME")
    MESSAGE(FATAL_ERROR "CPack was not included, you should include CPack before Using RPMTools")
  ENDIF (NOT DEFINED "CPACK_PACKAGE_NAME")

  IF (RPMTools_RPMBUILD_FOUND)
    SET(RPMTools_FOUND TRUE)
    #
    # - first arg  (ARGV0) is RPM name
    # - second arg (ARGV1) is the RPM spec file path [optional]
    # - third arg  (ARGV2) is the RPM ROOT DIRECTORY used to build RPMs [optional]
    #
    MACRO(RPMTools_ADD_RPM_TARGETS RPMNAME)

      #
      # If no spec file is provided create a minimal one
      #
      IF ("${ARGV1}" STREQUAL "")
	SET(SPECFILE_PATH "${CMAKE_BINARY_DIR}/${RPMNAME}.spec")
      ELSE ("${ARGV1}" STREQUAL "")
	SET(SPECFILE_PATH "${ARGV1}")
      ENDIF("${ARGV1}" STREQUAL "")

      # Verify whether if RPM_ROOTDIR was provided or not
      IF("${ARGV2}" STREQUAL "")
	SET(RPM_ROOTDIR ${CMAKE_BINARY_DIR}/RPM)
      ELSE ("${ARGV2}" STREQUAL "")
	SET(RPM_ROOTDIR "${ARGV2}")
      ENDIF("${ARGV2}" STREQUAL "")
      MESSAGE(STATUS "RPMTools:: Using RPM_ROOTDIR=${RPM_ROOTDIR}")

      # Prepare RPM build tree
      FILE(MAKE_DIRECTORY ${RPM_ROOTDIR})
      FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/tmp)
      FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/BUILD)
      FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/RPMS)
      FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/SOURCES)
      FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/SPECS)
      FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/SRPMS)

      #
      # We check whether if the provided spec file is
      # to be configure or not.
      #
      IF ("${ARGV1}" STREQUAL "")
	SET(SPECFILE_PATH "${RPM_ROOTDIR}/SPECS/${RPMNAME}.spec")
	SET(SPECFILE_NAME "${RPMNAME}.spec")
	MESSAGE(STATUS "No Spec file given generate a minimal one --> ${RPM_ROOTDIR}/SPECS/${RPMNAME}.spec")
      	FILE(WRITE ${RPM_ROOTDIR}/SPECS/${RPMNAME}.spec
	  "# -*- rpm-spec -*-
Summary:        ${RPMNAME}
Name:           ${RPMNAME}
Version:        ${CPACK_PACKAGE_VERSION}
Release:        1
License:        Unknown
Group:          Unknown
Source:         ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz
BuildRoot:      %{_tmppath}/%{name}-%{CPACK_PACKAGE_VERSION}-1-root
BuildRequires:	cmake

%define prefix /opt/${RPMNAME}-%{version}
%define rpmprefix $RPM_BUILD_ROOT%{prefix}
%define srcdirname %{name}-%{version}

%description
${RPMNAME} : No description for now

%prep
%setup -q -n %{srcdirname}

%build
cd ..
rm -rf build_tree
mkdir build_tree
cd build_tree
cmake -DCMAKE_INSTALL_PREFIX=%{rpmprefix} ../%{srcdirname}
make

%install
cd ../build_tree
make install

%clean
rm -rf %{srcdirname}
rm -rf build_tree

%files
%defattr(-,root,root,-)
%dir %{prefix}
%{prefix}/*

%changelog
* Wed Feb 28 2007 Erk <eric.noulard@gmail.com>
  Generated by CMake UseRPMTools macros"
	)

      ELSE ("${ARGV1}" STREQUAL "")
	SET(SPECFILE_PATH "${ARGV1}")

	GET_FILENAME_COMPONENT(SPECFILE_EXT ${SPECFILE_PATH} EXT)
	IF ("${SPECFILE_EXT}" STREQUAL ".spec")
	  # This is a 'ready-to-use' spec file which does not need to be CONFIGURED
	  GET_FILENAME_COMPONENT(SPECFILE_NAME ${SPECFILE_PATH} NAME)
	  MESSAGE(STATUS "Simple copy spec file <${SPECFILE_PATH}> --> <${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}>")
	  CONFIGURE_FILE(
	    ${SPECFILE_PATH}
	    ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}
	    COPYONLY)
	ELSE ("${SPECFILE_EXT}" STREQUAL ".spec")
	  # This is a to-be-configured spec file
	  GET_FILENAME_COMPONENT(SPECFILE_NAME ${SPECFILE_PATH} NAME_WE)
	  SET(SPECFILE_NAME "${SPECFILE_NAME}.spec")
	  MESSAGE(STATUS "Configuring spec file <${SPECFILE_PATH}> --> <${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}>")
	  CONFIGURE_FILE(
	    ${SPECFILE_PATH}
	    ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}
	    @ONLY)
	ENDIF ("${SPECFILE_EXT}" STREQUAL ".spec")
      ENDIF("${ARGV1}" STREQUAL "")

      ADD_CUSTOM_TARGET(${RPMNAME}_srpm
	COMMAND cpack -G TGZ --config CPackSourceConfig.cmake
	COMMAND ${CMAKE_COMMAND} -E copy ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz ${RPM_ROOTDIR}/SOURCES
	COMMAND ${RPMTools_RPMBUILD_EXECUTABLE} -bs --define=\"_topdir ${RPM_ROOTDIR}\" --buildroot=${RPM_ROOTDIR}/tmp ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}
	)

      ADD_CUSTOM_TARGET(${RPMNAME}_rpm
	COMMAND cpack -G TGZ --config CPackSourceConfig.cmake
	COMMAND ${CMAKE_COMMAND} -E copy ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz ${RPM_ROOTDIR}/SOURCES
	COMMAND ${RPMTools_RPMBUILD_EXECUTABLE} -bb --define=\"_topdir ${RPM_ROOTDIR}\" --buildroot=${RPM_ROOTDIR}/tmp ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}
	)
    ENDMACRO(RPMTools_ADD_RPM_TARGETS)

  ELSE (RPMTools_RPMBUILD_FOUND)
    SET(RPMTools FALSE)
  ENDIF (RPMTools_RPMBUILD_FOUND)

ENDIF (UNIX)

Added undroid/libwebsockets/contrib/abi/README.md.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
ABI Compatility Tracking
========================

This directory contains files that can be used to generate an ABI compatibility
timeline for libwebsockets. This gives users an idea of where the library has
changed and can be used by the developers to see when incompatible changes have
been introduced and either increase the library SO version or fix the changes.

The tools used are the abi-\* family available at https://github.com/lvc/ and
some example output is here: http://abi-laboratory.pro/tracker/timeline/libuv/

The tools download existing source tarballs and git repository to generate this
data, so past versions are compared and in-development code can be compared as
well.

Although the application is not being included here, FYI the license is dual
LGPL2 / GPL2 at your choice.


Installation
------------

The author provides an easy way to install the various tools he provides:

    git clone https://github.com/lvc/installer
	cd installer
	make prefix=/usr/local target=abi-tracker

It will also list any dependencies that you need to install through normal
means.  (Although in the case of needing "elfutils-libelf-devel", it may
crash during install of vtable-dumper without giving a nice list)


Generating the output
---------------------

Use the `lws-abi-update.sh` script to download the source files, build them and
generate the output html. The output can be deployed to a directory on a web
server for example. Modify the commented line in lws-abi-update.sh to do this.

As it is configured, lws-abi-update.sh will only download new source - ones
that it hasn't built before - so is suitable for use with a cron job.


Viewing the output
------------------

The best place to start looking at the data is the `timeline/libwebsockets`
directory. If your path is on a web server, navigate there, otherwise you could
try:

    lynx timeline/libwebsockets/

Added undroid/libwebsockets/contrib/abi/libwebsockets.json.























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{
  "Name":           "libwebsockets",
  "SourceUrl":      "https://github.com/warmcat/libwebsockets/releases",
  "Git":            "https://github.com/warmcat/libwebsockets",

  "Versions": [
  {
    "Number":         "current",
    "Installed":      "installed/libwebsockets/current",
    "Source":         "src/libwebsockets/current",
    "Changelog":      "On",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  },
  {
    "Number":         "1.7.4",
    "Installed":      "installed/libwebsockets/1.7.4",
    "Source":         "src/libwebsockets/1.7.4/libwebsockets-1.7.4.tar.gz",
    "Changelog":      "Off",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  },
  {
    "Number":         "1.7.3",
    "Installed":      "installed/libwebsockets/1.7.3",
    "Source":         "src/libwebsockets/1.7.3/libwebsockets-1.7.3.tar.gz",
    "Changelog":      "Off",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  },
  {
    "Number":         "1.7.2",
    "Installed":      "installed/libwebsockets/1.7.2",
    "Source":         "src/libwebsockets/1.7.2/libwebsockets-1.7.2.tar.gz",
    "Changelog":      "Off",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  },
  {
    "Number":         "1.7.1",
    "Installed":      "installed/libwebsockets/1.7.1",
    "Source":         "src/libwebsockets/1.7.1/libwebsockets-1.7.1.tar.gz",
    "Changelog":      "Off",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  },
  {
    "Number":         "1.7.0",
    "Installed":      "installed/libwebsockets/1.7.0",
    "Source":         "src/libwebsockets/1.7.0/libwebsockets-1.7.0.tar.gz",
    "Changelog":      "Off",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  },
  {
    "Number":         "1.6.3",
    "Installed":      "installed/libwebsockets/1.6.3",
    "Source":         "src/libwebsockets/1.6.3/libwebsockets-1.6.3.tar.gz",
    "Changelog":      "Off",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  },
  {
    "Number":         "1.6.2",
    "Installed":      "installed/libwebsockets/1.6.2",
    "Source":         "src/libwebsockets/1.6.2/libwebsockets-1.6.2.tar.gz",
    "Changelog":      "Off",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  },
  {
    "Number":         "1.6.1",
    "Installed":      "installed/libwebsockets/1.6.1",
    "Source":         "src/libwebsockets/1.6.1/libwebsockets-1.6.1.tar.gz",
    "Changelog":      "Off",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  },
  {
    "Number":         "1.5.1",
    "Installed":      "installed/libwebsockets/1.5.1",
    "Source":         "src/libwebsockets/1.5.1/libwebsockets-1.5.1.tar.gz",
    "Changelog":      "Off",
    "HeadersDiff":    "On",
    "PkgDiff":        "Off",
    "ABIView":        "Off",
    "ABIDiff":        "Off"
  }]
}

Added undroid/libwebsockets/contrib/abi/lws-abi-update.sh.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/sh

if [ ! -z "$1" ] ; then
 OUT=$1
else
 OUT="/tmp/lws-abi-track-htdocs"
fi

D=`dirname $0`
if [ ! -z "$D" ] ; then
 D=$D/
fi
J=$D"libwebsockets.json"

abi-monitor -get -build-new $J
abi-tracker -build $J
abi-tracker -deploy $OUT $J

Added undroid/libwebsockets/contrib/android-make-script.sh.





































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/bin/bash

#
# Build libwebsockets static library for Android
#
# requires debian package xutils-dev for makedepend (openssl make depend)
#

# This is based on http://stackoverflow.com/questions/11929773/compiling-the-latest-openssl-for-android/
# via https://github.com/warmcat/libwebsockets/pull/502

# path to NDK
export NDK=/opt/Android/SDK/ndk-bundle

set -e

# Download packages libz, openssl and libwebsockets

[ ! -f zlib-1.2.8.tar.gz ] && {
wget http://prdownloads.sourceforge.net/libpng/zlib-1.2.8.tar.gz
}

[ ! -f openssl-1.0.2g.tar.gz ] && {
wget https://openssl.org/source/openssl-1.0.2g.tar.gz
}

[ ! -f libwebsockets.tar.gz ] && {
git clone https://github.com/warmcat/libwebsockets.git
tar caf libwebsockets.tar.gz libwebsockets
}

# Clean then Unzip

[ -d zlib-1.2.8 ] && rm -fr zlib-1.2.8
[ -d openssl-1.0.2g ] && rm -fr openssl-1.0.2g
[ -d libwebsockets ] && rm -fr libwebsockets
[ -d android-toolchain-arm ] && rm -fr android-toolchain-arm
tar xf zlib-1.2.8.tar.gz
tar xf openssl-1.0.2g.tar.gz
tar xf libwebsockets.tar.gz

# create a local android toolchain
$NDK/build/tools/make-standalone-toolchain.sh \
 --platform=android-9 \
 --toolchain=arm-linux-androideabi-4.9 \
 --install-dir=`pwd`/android-toolchain-arm

# setup environment to use the gcc/ld from the android toolchain
export TOOLCHAIN_PATH=`pwd`/android-toolchain-arm/bin
export TOOL=arm-linux-androideabi
export NDK_TOOLCHAIN_BASENAME=${TOOLCHAIN_PATH}/${TOOL}
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

# setup buildflags
export ARCH_FLAGS="-mthumb"
export ARCH_LINK=
export CPPFLAGS=" ${ARCH_FLAGS} -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-strict-aliasing -finline-limit=64 "
export CXXFLAGS=" ${ARCH_FLAGS} -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-strict-aliasing -finline-limit=64 -frtti -fexceptions "
export CFLAGS=" ${ARCH_FLAGS} -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-strict-aliasing -finline-limit=64 "
export LDFLAGS=" ${ARCH_LINK} "

# configure and build zlib
[ ! -f ./android-toolchain-arm/lib/libz.a ] && {
cd zlib-1.2.8
PATH=$TOOLCHAIN_PATH:$PATH ./configure --static --prefix=$TOOLCHAIN_PATH/..
PATH=$TOOLCHAIN_PATH:$PATH make
PATH=$TOOLCHAIN_PATH:$PATH make install
cd ..
}

# configure and build openssl
[ ! -f ./android-toolchain-arm/lib/libssl.a ] && {
PREFIX=$TOOLCHAIN_PATH/..
cd openssl-1.0.2g
./Configure android --prefix=${PREFIX} no-shared no-idea no-mdc2 no-rc5 no-zlib no-zlib-dynamic enable-tlsext no-ssl2 no-ssl3 enable-ec enable-ecdh enable-ecp
PATH=$TOOLCHAIN_PATH:$PATH make depend
PATH=$TOOLCHAIN_PATH:$PATH make
PATH=$TOOLCHAIN_PATH:$PATH make install_sw
cd ..
}

# configure and build libwebsockets
[ ! -f ./android-toolchain-arm/lib/libwebsockets.a ] && {
cd libwebsockets
[ ! -d build ] && mkdir build
cd build
PATH=$TOOLCHAIN_PATH:$PATH cmake \
  -DCMAKE_C_COMPILER=$CC \
  -DCMAKE_AR=$AR \
  -DCMAKE_RANLIB=$RANLIB \
  -DCMAKE_C_FLAGS="$CFLAGS" \
  -DCMAKE_INSTALL_PREFIX=$TOOLCHAIN_PATH/.. \
  -DLWS_WITH_SHARED=OFF \
  -DLWS_WITH_STATIC=ON \
  -DLWS_WITHOUT_DAEMONIZE=ON \
  -DLWS_WITHOUT_TESTAPPS=ON \
  -DLWS_IPV6=OFF \
  -DLWS_USE_BUNDLED_ZLIB=OFF \
  -DLWS_WITH_SSL=ON  \
  -DLWS_WITH_HTTP2=ON \
  -DLWS_OPENSSL_LIBRARIES="$TOOLCHAIN_PATH/../lib/libssl.a;$TOOLCHAIN_PATH/../lib/libcrypto.a" \
  -DLWS_OPENSSL_INCLUDE_DIRS=$TOOLCHAIN_PATH/../include \
  -DCMAKE_BUILD_TYPE=Debug \
  ..
PATH=$TOOLCHAIN_PATH:$PATH make
PATH=$TOOLCHAIN_PATH:$PATH make install
cd ../..
}

Added undroid/libwebsockets/cross-arm-linux-gnueabihf.cmake.

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#
# CMake Toolchain file for crosscompiling on ARM.
#
# This can be used when running cmake in the following way:
#  cd build/
#  cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-arm-linux-gnueabihf.cmake
#

set(CROSS_PATH /opt/gcc-linaro-arm-linux-gnueabihf-4.7-2013.02-01-20130221_linux)

# Target operating system name.
set(CMAKE_SYSTEM_NAME Linux)

# Name of C compiler.
set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-gcc")
set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-g++")

# Where to look for the target environment. (More paths can be added here)
set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}")

# Adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# Search headers and libraries in the target environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Added undroid/libwebsockets/cross-ming.cmake.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#
# CMake Toolchain file for crosscompiling on MingW.
#
# This can be used when running cmake in the following way:
#  cd build/
#  cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-ming.cmake
#

set(CROSS_PATH /usr/bin)

# Target operating system name.
set(CMAKE_SYSTEM_NAME Windows)
set(BUILD_SHARED_LIBS OFF)

# Name of C compiler.
set(CMAKE_C_COMPILER "${CROSS_PATH}/x86_64-w64-mingw32-gcc")
#set(CMAKE_CXX_COMPILER "${CROSS_PATH}/x86_64-w64-mingw32-g++")
set(CMAKE_RC_COMPILER "${CROSS_PATH}/x86_64-w64-mingw32-windres")
set(CMAKE_C_FLAGS "-Wno-error")

# Where to look for the target environment. (More paths can be added here)
set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}")

# Adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# Search headers and libraries in the target environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Added undroid/libwebsockets/cross-openwrt-makefile.



































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#
# libwebsockets makefile for openwrt
#

include $(TOPDIR)/rules.mk

PKG_NAME:=libwebsockets
PKG_VERSION:=2014-03-01
PKG_RELEASE=$(PKG_SOURCE_VERSION)

PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/warmcat/libwebsockets.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=388dc7d201d8d123841869fb49ec4d94d6dd7f54
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
CMAKE_INSTALL:=1

include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk

CMAKE_OPTIONS += -DLWS_OPENSSL_CLIENT_CERTS=/etc/ssl/certs
CMAKE_OPTIONS += -DLWS_OPENSSL_SUPPORT=ON
CMAKE_OPTIONS += -DLWS_WITH_SSL=ON
CMAKE_OPTIONS += -DLWS_WITHOUT_TESTAPPS=$(if $(CONFIG_PACKAGE_libwebsockets-examples),"OFF","ON")

# for wolfssl, define these in addition to LWS_OPENSSL_SUPPORT and
# edit package/libs/wolfssl/Makefile to include --enable-opensslextra
# CMAKE_OPTIONS += -DLWS_USE_WOLFSSL=ON
# CMAKE_OPTIONS += -DLWS_WOLFSSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libwolfssl.so
# CMAKE_OPTIONS += -DLWS_WOLFSSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include

# for cyassl, define these in addition to LWS_OPENSSL_SUPPORT and
# edit package/libs/wolfssl/Makefile to include --enable-opensslextra
# CMAKE_OPTIONS += -DLWS_USE_CYASSL=ON
# CMAKE_OPTIONS += -DLWS_CYASSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libcyassl.so
# CMAKE_OPTIONS += -DLWS_CYASSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include

# other options worth noting
# CMAKE_OPTIONS += -DLWS_WITHOUT_EXTENSIONS=ON
# CMAKE_OPTIONS += -DLWS_WITHOUT_DAEMONIZE=ON
# CMAKE_OPTIONS += -DLWS_WITHOUT_SERVER=ON
# CMAKE_OPTIONS += -DLWS_WITHOUT_DEBUG=ON


define Package/libwebsockets/Default
	SECTION:=libs
	CATEGORY:=Libraries
	TITLE:=libwebsockets
	DEPENDS:=+zlib +libopenssl
endef

define Package/libwebsockets
	$(call Package/libwebsockets/Default)
	TITLE+= (libraries)
endef

define Package/libwebsockets/description
	libwebsockets
	This package contains libwebsocket libraries
endef

define Package/libwebsockets-examples
	$(call Package/libwebsockets/Default)
	DEPENDS:=libwebsockets
	TITLE+= (examples)
endef

define Package/libwebsockets-examples/description
	libwebsockets examples
	This package contains libwebsockets examples
endef

define Package/libwebsockets/install
	$(INSTALL_DIR) $(1)/usr/lib
	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libwebsockets.so* $(1)/usr/lib/
endef

define Package/libwebsockets-examples/install
	$(INSTALL_DIR) $(1)/usr/bin
	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-client $(1)/usr/bin/
	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-echo $(1)/usr/bin/
	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-fraggle $(1)/usr/bin/
	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-ping $(1)/usr/bin/
	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-server $(1)/usr/bin/
	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-server-extpoll $(1)/usr/bin/

	$(INSTALL_DIR) $(1)/usr/share/libwebsockets-test-server
	$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/favicon.ico $(1)/usr/share/libwebsockets-test-server/
	$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/leaf.jpg $(1)/usr/share/libwebsockets-test-server/
	$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/libwebsockets.org-logo.png $(1)/usr/share/libwebsockets-test-server/
	$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/libwebsockets-test-server.key.pem $(1)/usr/share/libwebsockets-test-server/
	$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/libwebsockets-test-server.pem $(1)/usr/share/libwebsockets-test-server/
	$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/test.html $(1)/usr/share/libwebsockets-test-server/
endef

$(eval $(call BuildPackage,libwebsockets))
$(eval $(call BuildPackage,libwebsockets-examples))

Added undroid/libwebsockets/lib/alloc.c.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "private-libwebsockets.h"

static void *_realloc(void *ptr, size_t size)
{
	if (size)
		return realloc(ptr, size);
	else if (ptr)
		free(ptr);
	return NULL;
}

void *(*_lws_realloc)(void *ptr, size_t size) = _realloc;

void *lws_realloc(void *ptr, size_t size)
{
	return _lws_realloc(ptr, size);
}

void *lws_zalloc(size_t size)
{
	void *ptr = _lws_realloc(NULL, size);
	if (ptr)
		memset(ptr, 0, size);
	return ptr;
}

void lws_set_allocator(void *(*cb)(void *ptr, size_t size))
{
	_lws_realloc = cb;
}

Added undroid/libwebsockets/lib/base64-decode.c.























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 * This code originally came from here
 *
 * http://base64.sourceforge.net/b64.c
 *
 * with the following license:
 *
 * LICENCE:        Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
 *
 *                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.
 *
 * VERSION HISTORY:
 *               Bob Trower 08/04/01 -- Create Version 0.00.00B
 *
 * I cleaned it up quite a bit to match the (linux kernel) style of the rest
 * of libwebsockets; this version is under LGPL2.1 + SLE like the rest of lws
 * since he explicitly allows sublicensing, but I give the URL above so you can
 * get the original with Bob's super-liberal terms directly if you prefer.
 */


#include <stdio.h>
#include <string.h>
#include "private-libwebsockets.h"

static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
			     "abcdefghijklmnopqrstuvwxyz0123456789+/";
static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW"
			     "$$$$$$XYZ[\\]^_`abcdefghijklmnopq";

LWS_VISIBLE int
lws_b64_encode_string(const char *in, int in_len, char *out, int out_size)
{
	unsigned char triple[3];
	int i;
	int len;
	int line = 0;
	int done = 0;

	while (in_len) {
		len = 0;
		for (i = 0; i < 3; i++) {
			if (in_len) {
				triple[i] = *in++;
				len++;
				in_len--;
			} else
				triple[i] = 0;
		}

		if (done + 4 >= out_size)
			return -1;

		*out++ = encode[triple[0] >> 2];
		*out++ = encode[((triple[0] & 0x03) << 4) |
					     ((triple[1] & 0xf0) >> 4)];
		*out++ = (len > 1 ? encode[((triple[1] & 0x0f) << 2) |
					     ((triple[2] & 0xc0) >> 6)] : '=');
		*out++ = (len > 2 ? encode[triple[2] & 0x3f] : '=');

		done += 4;
		line += 4;
	}

	if (done + 1 >= out_size)
		return -1;

	*out++ = '\0';

	return done;
}

/*
 * returns length of decoded string in out, or -1 if out was too small
 * according to out_size
 */

LWS_VISIBLE int
lws_b64_decode_string(const char *in, char *out, int out_size)
{
	int len;
	int i, c;
	int done = 0;
	unsigned char v;
	unsigned char quad[4];

	while (*in) {

		len = 0;
		for (i = 0; i < 4 && *in; i++) {

			v = 0;
			c = 0;
			while (*in && !v) {
				c = v = *in++;
				v = (v < 43 || v > 122) ? 0 : decode[v - 43];
				if (v)
					v = (v == '$') ? 0 : v - 61;
			}
			if (c) {
				len++;
				if (v)
					quad[i] = v - 1;
			} else
				quad[i] = 0;
		}

		if (out_size < (done + len - 1))
			/* out buffer is too small */
			return -1;

		if (len >= 2)
			*out++ = quad[0] << 2 | quad[1] >> 4;
		if (len >= 3)
			*out++ = quad[1] << 4 | quad[2] >> 2;
		if (len >= 4)
			*out++ = ((quad[2] << 6) & 0xc0) | quad[3];

		done += len - 1;
	}

	if (done + 1 >= out_size)
		return -1;

	*out++ = '\0';

	return done;
}

#if 0
int
lws_b64_selftest(void)
{
	char buf[64];
	unsigned int n;
	unsigned int test;
	static const char * const plaintext[] = {
		"sanity check base 64"
	};
	static const char * const coded[] = {
		"c2FuaXR5IGNoZWNrIGJhc2UgNjQ="
	};

	for (test = 0; test < sizeof plaintext / sizeof(plaintext[0]); test++) {

		buf[sizeof(buf) - 1] = '\0';
		n = lws_b64_encode_string(plaintext[test],
				      strlen(plaintext[test]), buf, sizeof buf);
		if (n != strlen(coded[test]) || strcmp(buf, coded[test])) {
			lwsl_err("Failed lws_b64 encode selftest "
					   "%d result '%s' %d\n", test, buf, n);
			return -1;
		}

		buf[sizeof(buf) - 1] = '\0';
		n = lws_b64_decode_string(coded[test], buf, sizeof buf);
		if (n != strlen(plaintext[test]) ||
						 strcmp(buf, plaintext[test])) {
			lwsl_err("Failed lws_b64 decode selftest "
					   "%d result '%s' %d\n", test, buf, n);
			return -1;
		}
	}

	return 0;
}
#endif

Added undroid/libwebsockets/lib/client-handshake.c.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
#include "private-libwebsockets.h"

struct lws *
lws_client_connect_2(struct lws *wsi)
{
#ifdef LWS_USE_IPV6
	struct sockaddr_in6 server_addr6;
	struct addrinfo hints, *result;
#endif
	struct lws_context *context = wsi->context;
	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
	struct sockaddr_in server_addr4;
	struct lws_pollfd pfd;
	struct sockaddr *v;
	int n, plen = 0;
	const char *ads;

	lwsl_client("%s\n", __func__);

	/* proxy? */

	if (wsi->vhost->http_proxy_port) {
		plen = sprintf((char *)pt->serv_buf,
			"CONNECT %s:%u HTTP/1.0\x0d\x0a"
			"User-agent: libwebsockets\x0d\x0a",
			lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
			wsi->u.hdr.c_port);

		if (wsi->vhost->proxy_basic_auth_token[0])
			plen += sprintf((char *)pt->serv_buf + plen,
					"Proxy-authorization: basic %s\x0d\x0a",
					wsi->vhost->proxy_basic_auth_token);

		plen += sprintf((char *)pt->serv_buf + plen, "\x0d\x0a");
		ads = wsi->vhost->http_proxy_address;

#ifdef LWS_USE_IPV6
		if (LWS_IPV6_ENABLED(context)) {
			memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
			server_addr6.sin6_port = htons(wsi->vhost->http_proxy_port);
		} else
#endif
			server_addr4.sin_port = htons(wsi->vhost->http_proxy_port);

	} else {
		ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
#ifdef LWS_USE_IPV6
		if (LWS_IPV6_ENABLED(context)) {
			memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
			server_addr6.sin6_port = htons(wsi->u.hdr.c_port);
		} else
#endif
			server_addr4.sin_port = htons(wsi->u.hdr.c_port);
	}

	/*
	 * prepare the actual connection (to the proxy, if any)
	 */
       lwsl_client("%s: address %s\n", __func__, ads);

#ifdef LWS_USE_IPV6
	if (LWS_IPV6_ENABLED(context)) {
		memset(&hints, 0, sizeof(struct addrinfo));
#if !defined(__ANDROID__)
		hints.ai_family = AF_INET6;
		hints.ai_flags = AI_V4MAPPED;
#endif
		n = getaddrinfo(ads, NULL, &hints, &result);
		if (n) {
#ifdef _WIN32
			lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n));
#else
			lwsl_err("getaddrinfo: %s\n", gai_strerror(n));
#endif
			goto oom4;
		}

		server_addr6.sin6_family = AF_INET6;
		switch (result->ai_family) {
#if defined(__ANDROID__)
		case AF_INET:
			/* map IPv4 to IPv6 */
			bzero((char *)&server_addr6.sin6_addr,
						sizeof(struct in6_addr));
			server_addr6.sin6_addr.s6_addr[10] = 0xff;
			server_addr6.sin6_addr.s6_addr[11] = 0xff;
			memcpy(&server_addr6.sin6_addr.s6_addr[12],
				&((struct sockaddr_in *)result->ai_addr)->sin_addr,
							sizeof(struct in_addr));
			break;
#endif
		case AF_INET6:
			memcpy(&server_addr6.sin6_addr,
			  &((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
						sizeof(struct in6_addr));
			break;
		default:
			lwsl_err("Unknown address family\n");
			freeaddrinfo(result);
			goto oom4;
		}

		freeaddrinfo(result);
	} else
#endif
	{
		struct addrinfo ai, *res, *result;
		void *p = NULL;

		memset (&ai, 0, sizeof ai);
		ai.ai_family = PF_UNSPEC;
		ai.ai_socktype = SOCK_STREAM;
		ai.ai_flags = AI_CANONNAME;

		if (getaddrinfo(ads, NULL, &ai, &result)) {
			lwsl_err("getaddrinfo failed\n");
			goto oom4;
		}

		res = result;
		while (!p && res) {
			switch (res->ai_family) {
			case AF_INET:
				p = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
				break;
			}

			res = res->ai_next;
		}

		if (!p) {
			lwsl_err("Couldn't identify address\n");
			freeaddrinfo(result);
			goto oom4;
		}

		server_addr4.sin_family = AF_INET;
		server_addr4.sin_addr = *((struct in_addr *)p);
		bzero(&server_addr4.sin_zero, 8);
		freeaddrinfo(result);
	}

	if (!lws_socket_is_valid(wsi->sock)) {

#ifdef LWS_USE_IPV6
		if (LWS_IPV6_ENABLED(context))
			wsi->sock = socket(AF_INET6, SOCK_STREAM, 0);
		else
#endif
			wsi->sock = socket(AF_INET, SOCK_STREAM, 0);

		if (!lws_socket_is_valid(wsi->sock)) {
			lwsl_warn("Unable to open socket\n");
			goto oom4;
		}

		if (lws_plat_set_socket_options(wsi->vhost, wsi->sock)) {
			lwsl_err("Failed to set wsi socket options\n");
			compatible_close(wsi->sock);
			goto oom4;
		}

		wsi->mode = LWSCM_WSCL_WAITING_CONNECT;

		lws_libev_accept(wsi, wsi->sock);
		lws_libuv_accept(wsi, wsi->sock);
		if (insert_wsi_socket_into_fds(context, wsi)) {
			compatible_close(wsi->sock);
			goto oom4;
		}

		/*
		 * past here, we can't simply free the structs as error
		 * handling as oom4 does.  We have to run the whole close flow.
		 */

		if (!wsi->protocol)
			wsi->protocol = &wsi->vhost->protocols[0];

		wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE,
					wsi->user_space, NULL, 0);

		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
				AWAITING_TIMEOUT);

		n = lws_socket_bind(wsi->vhost, wsi->sock, 0, wsi->vhost->iface);
		if (n < 0)
			goto failed;
	}

#ifdef LWS_USE_IPV6
	if (LWS_IPV6_ENABLED(context)) {
		v = (struct sockaddr *)&server_addr6;
		n = sizeof(struct sockaddr_in6);
	} else
#endif
	{
		v = (struct sockaddr *)&server_addr4;
		n = sizeof(struct sockaddr);
	}

	if (connect(wsi->sock, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
		if (LWS_ERRNO == LWS_EALREADY ||
		    LWS_ERRNO == LWS_EINPROGRESS ||
		    LWS_ERRNO == LWS_EWOULDBLOCK
#ifdef _WIN32
			|| LWS_ERRNO == WSAEINVAL
#endif
		) {
			lwsl_client("nonblocking connect retry\n");

			/*
			 * must do specifically a POLLOUT poll to hear
			 * about the connect completion
			 */
			if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
				goto failed;

			return wsi;
		}

		if (LWS_ERRNO != LWS_EISCONN) {
			lwsl_debug("Connect failed errno=%d\n", LWS_ERRNO);
			goto failed;
		}
	}

	lwsl_client("connected\n");

	/* we are connected to server, or proxy */

	if (wsi->vhost->http_proxy_port) {

		/*
		 * OK from now on we talk via the proxy, so connect to that
		 *
		 * (will overwrite existing pointer,
		 * leaving old string/frag there but unreferenced)
		 */
		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
					  wsi->vhost->http_proxy_address))
			goto failed;
		wsi->u.hdr.c_port = wsi->vhost->http_proxy_port;

		n = send(wsi->sock, (char *)pt->serv_buf, plen,
			 MSG_NOSIGNAL);
		if (n < 0) {
			lwsl_debug("ERROR writing to proxy socket\n");
			goto failed;
		}

		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
				AWAITING_TIMEOUT);

		wsi->mode = LWSCM_WSCL_WAITING_PROXY_REPLY;

		return wsi;
	}

	/*
	 * provoke service to issue the handshake directly
	 * we need to do it this way because in the proxy case, this is the
	 * next state and executed only if and when we get a good proxy
	 * response inside the state machine... but notice in SSL case this
	 * may not have sent anything yet with 0 return, and won't until some
	 * many retries from main loop.  To stop that becoming endless,
	 * cover with a timeout.
	 */

	lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
			AWAITING_TIMEOUT);

	wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE;
	pfd.fd = wsi->sock;
	pfd.events = LWS_POLLIN;
	pfd.revents = LWS_POLLIN;

	n = lws_service_fd(context, &pfd);
	if (n < 0)
		goto failed;
	if (n) /* returns 1 on failure after closing wsi */
		return NULL;

	return wsi;

oom4:
	/* we're closing, losing some rx is OK */
	wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
	//lwsl_err("%d\n", wsi->mode);
	if (wsi->mode == LWSCM_HTTP_CLIENT)
		wsi->vhost->protocols[0].callback(wsi,
			LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
			wsi->user_space, NULL, 0);
	/* take care that we might be inserted in fds already */
	if (wsi->position_in_fds_table != -1)
		goto failed;
	lws_header_table_detach(wsi, 0);
	lws_free(wsi);

	return NULL;

failed:
	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);

	return NULL;
}

/**
 * lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect)
 *			this only works if still in HTTP, ie, not upgraded yet
 * wsi:		connection to reset
 * address:	network address of the new server
 * port:	port to connect to
 * path:	uri path to connect to on the new server
 * host:	host header to send to the new server
 */
LWS_VISIBLE struct lws *
lws_client_reset(struct lws *wsi, int ssl, const char *address, int port, const char *path, const char *host)
{
	if (wsi->u.hdr.redirects == 3) {
		lwsl_err("%s: Too many redirects\n", __func__);
		return NULL;
	}
	wsi->u.hdr.redirects++;

#ifdef LWS_OPENSSL_SUPPORT
	wsi->use_ssl = ssl;
#else
	if (ssl) {
		lwsl_err("%s: not configured for ssl\n", __func__);
		return NULL;
	}
#endif

	lwsl_notice("redirect ads='%s', port=%d, path='%s'\n", address, port, path);

	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
		return NULL;

	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
		return NULL;

	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
		return NULL;

	compatible_close(wsi->sock);
	remove_wsi_socket_from_fds(wsi);
	wsi->sock = LWS_SOCK_INVALID;
	wsi->state = LWSS_CLIENT_UNCONNECTED;
	wsi->protocol = NULL;
	wsi->pending_timeout = NO_PENDING_TIMEOUT;
	wsi->u.hdr.c_port = port;

	return lws_client_connect_2(wsi);
}

#ifdef LWS_WITH_HTTP_PROXY
static hubbub_error
html_parser_cb(const hubbub_token *token, void *pw)
{
	struct lws_rewrite *r = (struct lws_rewrite *)pw;
	char buf[1024], *start = buf + LWS_PRE, *p = start,
	     *end = &buf[sizeof(buf) - 1];
	size_t i;

	switch (token->type) {
	case HUBBUB_TOKEN_DOCTYPE:

		p += lws_snprintf(p, end - p, "<!DOCTYPE %.*s %s ",
				(int) token->data.doctype.name.len,
				token->data.doctype.name.ptr,
				token->data.doctype.force_quirks ?
						"(force-quirks) " : "");

		if (token->data.doctype.public_missing)
			printf("\tpublic: missing\n");
		else
			p += lws_snprintf(p, end - p, "PUBLIC \"%.*s\"\n",
				(int) token->data.doctype.public_id.len,
				token->data.doctype.public_id.ptr);

		if (token->data.doctype.system_missing)
			printf("\tsystem: missing\n");
		else
			p += lws_snprintf(p, end - p, " \"%.*s\">\n",
				(int) token->data.doctype.system_id.len,
				token->data.doctype.system_id.ptr);

		break;
	case HUBBUB_TOKEN_START_TAG:
		p += lws_snprintf(p, end - p, "<%.*s", (int)token->data.tag.name.len,
				token->data.tag.name.ptr);

/*				(token->data.tag.self_closing) ?
						"(self-closing) " : "",
				(token->data.tag.n_attributes > 0) ?
						"attributes:" : "");
*/
		for (i = 0; i < token->data.tag.n_attributes; i++) {
			if (!hstrcmp(&token->data.tag.attributes[i].name, "href", 4) ||
			    !hstrcmp(&token->data.tag.attributes[i].name, "action", 6) ||
			    !hstrcmp(&token->data.tag.attributes[i].name, "src", 3)) {
				const char *pp = (const char *)token->data.tag.attributes[i].value.ptr;
				int plen = (int) token->data.tag.attributes[i].value.len;

				if (!hstrcmp(&token->data.tag.attributes[i].value,
					     r->from, r->from_len)) {
					pp += r->from_len;
					plen -= r->from_len;
				}
				p += lws_snprintf(p, end - p, " %.*s=\"%s/%.*s\"",
				       (int) token->data.tag.attributes[i].name.len,
				       token->data.tag.attributes[i].name.ptr,
				       r->to, plen, pp);

			} else

				p += lws_snprintf(p, end - p, " %.*s=\"%.*s\"",
					(int) token->data.tag.attributes[i].name.len,
					token->data.tag.attributes[i].name.ptr,
					(int) token->data.tag.attributes[i].value.len,
					token->data.tag.attributes[i].value.ptr);
		}
		p += lws_snprintf(p, end - p, ">\n");
		break;
	case HUBBUB_TOKEN_END_TAG:
		p += lws_snprintf(p, end - p, "</%.*s", (int) token->data.tag.name.len,
				token->data.tag.name.ptr);
/*
				(token->data.tag.self_closing) ?
						"(self-closing) " : "",
				(token->data.tag.n_attributes > 0) ?
						"attributes:" : "");
*/
		for (i = 0; i < token->data.tag.n_attributes; i++) {
			p += lws_snprintf(p, end - p, " %.*s='%.*s'\n",
				(int) token->data.tag.attributes[i].name.len,
				token->data.tag.attributes[i].name.ptr,
				(int) token->data.tag.attributes[i].value.len,
				token->data.tag.attributes[i].value.ptr);
		}
		p += lws_snprintf(p, end - p, ">\n");
		break;
	case HUBBUB_TOKEN_COMMENT:
		p += lws_snprintf(p, end - p, "<!-- %.*s -->\n",
				(int) token->data.comment.len,
				token->data.comment.ptr);
		break;
	case HUBBUB_TOKEN_CHARACTER:
		p += lws_snprintf(p, end - p, "%.*s", (int) token->data.character.len,
				token->data.character.ptr);
		break;
	case HUBBUB_TOKEN_EOF:
		p += lws_snprintf(p, end - p, "\n");
		break;
	}

	if (user_callback_handle_rxflow(r->wsi->protocol->callback,
			r->wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
			r->wsi->user_space, start, p - start))
		return -1;

	return HUBBUB_OK;
}
#endif
/**
 * lws_client_connect_via_info() - Connect to another websocket server
 * @i:pointer to lws_client_connect_info struct
 *
 *	This function creates a connection to a remote server
 */


LWS_VISIBLE struct lws *
lws_client_connect_via_info(struct lws_client_connect_info *i)
{
	struct lws *wsi;
	int v = SPEC_LATEST_SUPPORTED;

	if (i->context->requested_kill)
		return NULL;

	wsi = lws_zalloc(sizeof(struct lws));
	if (wsi == NULL)
		goto bail;

	wsi->context = i->context;
	/* assert the mode and union status (hdr) clearly */
	lws_union_transition(wsi, LWSCM_HTTP_CLIENT);
	wsi->sock = LWS_SOCK_INVALID;

	/* 1) fill up the wsi with stuff from the connect_info as far as it
	 * can go.  It's because not only is our connection async, we might
	 * not even be able to get ahold of an ah at this point.
	 */

	/* -1 means just use latest supported */
	if (i->ietf_version_or_minus_one != -1 && i->ietf_version_or_minus_one)
		v = i->ietf_version_or_minus_one;

	wsi->ietf_spec_revision = v;
	wsi->user_space = NULL;
	wsi->state = LWSS_CLIENT_UNCONNECTED;
	wsi->protocol = NULL;
	wsi->pending_timeout = NO_PENDING_TIMEOUT;
	wsi->position_in_fds_table = -1;
	wsi->u.hdr.c_port = i->port;
	wsi->vhost = i->vhost;
	if (!wsi->vhost)
		wsi->vhost = i->context->vhost_list;

	wsi->protocol = &wsi->vhost->protocols[0];
	if (wsi && !wsi->user_space && i->userdata) {
		wsi->user_space_externally_allocated = 1;
		wsi->user_space = i->userdata;
	} else
		/* if we stay in http, we can assign the user space now,
		 * otherwise do it after the protocol negotiated
		 */
		if (i->method)
			if (lws_ensure_user_space(wsi))
				goto bail;

#ifdef LWS_OPENSSL_SUPPORT
	wsi->use_ssl = i->ssl_connection;
#else
	if (i->ssl_connection) {
		lwsl_err("libwebsockets not configured for ssl\n");
		goto bail;
	}
#endif

	/* 2) stash the things from connect_info that we can't process without
	 * an ah.  Because if no ah, we will go on the ah waiting list and
	 * process those things later (after the connect_info and maybe the
	 * things pointed to have gone out of scope.
	 */

	wsi->u.hdr.stash = lws_malloc(sizeof(*wsi->u.hdr.stash));
	if (!wsi->u.hdr.stash) {
		lwsl_err("%s: OOM\n", __func__);
		goto bail;
	}

	wsi->u.hdr.stash->origin[0] = '\0';
	wsi->u.hdr.stash->protocol[0] = '\0';
	wsi->u.hdr.stash->method[0] = '\0';

	strncpy(wsi->u.hdr.stash->address, i->address,
		sizeof(wsi->u.hdr.stash->address) - 1);
	strncpy(wsi->u.hdr.stash->path, i->path,
		sizeof(wsi->u.hdr.stash->path) - 1);
	strncpy(wsi->u.hdr.stash->host, i->host,
		sizeof(wsi->u.hdr.stash->host) - 1);
	if (i->origin)
		strncpy(wsi->u.hdr.stash->origin, i->origin,
			sizeof(wsi->u.hdr.stash->origin) - 1);
	if (i->protocol)
		strncpy(wsi->u.hdr.stash->protocol, i->protocol,
			sizeof(wsi->u.hdr.stash->protocol) - 1);
	if (i->method)
		strncpy(wsi->u.hdr.stash->method, i->method,
			sizeof(wsi->u.hdr.stash->method) - 1);

	wsi->u.hdr.stash->address[sizeof(wsi->u.hdr.stash->address) - 1] = '\0';
	wsi->u.hdr.stash->path[sizeof(wsi->u.hdr.stash->path) - 1] = '\0';
	wsi->u.hdr.stash->host[sizeof(wsi->u.hdr.stash->host) - 1] = '\0';
	wsi->u.hdr.stash->origin[sizeof(wsi->u.hdr.stash->origin) - 1] = '\0';
	wsi->u.hdr.stash->protocol[sizeof(wsi->u.hdr.stash->protocol) - 1] = '\0';
	wsi->u.hdr.stash->method[sizeof(wsi->u.hdr.stash->method) - 1] = '\0';

	/* if we went on the waiting list, no probs just return the wsi
	 * when we get the ah, now or later, he will call
	 * lws_client_connect_via_info2() below.
	 */
	if (lws_header_table_attach(wsi, 0) < 0)
		return NULL;

	if (i->parent_wsi) {
		lwsl_info("%s: created child %p of parent %p\n", __func__,
				wsi, i->parent_wsi);
		wsi->parent = i->parent_wsi;
		wsi->sibling_list = i->parent_wsi->child_list;
		i->parent_wsi->child_list = wsi;
	}
#ifdef LWS_WITH_HTTP_PROXY
	if (i->uri_replace_to)
		wsi->rw = lws_rewrite_create(wsi, html_parser_cb,
					     i->uri_replace_from,
					     i->uri_replace_to);
#endif

	return wsi;

bail:
	lws_free(wsi);

	return NULL;
}

struct lws *
lws_client_connect_via_info2(struct lws *wsi)
{
	struct client_info_stash *stash = wsi->u.hdr.stash;

	if (!stash)
		return wsi;

	/*
	 * we're not necessarily in a position to action these right away,
	 * stash them... we only need during connect phase so u.hdr is fine
	 */
	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
				  stash->address))
		goto bail1;

	/* these only need u.hdr lifetime as well */

	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, stash->path))
		goto bail1;

	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, stash->host))
		goto bail1;

	if (stash->origin[0])
		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
					  stash->origin))
			goto bail1;
	/*
	 * this is a list of protocols we tell the server we're okay with
	 * stash it for later when we compare server response with it
	 */
	if (stash->protocol[0])
		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
					  stash->protocol))
			goto bail1;
	if (stash->method[0])
		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
					  stash->method))
			goto bail1;

	lws_free_set_NULL(wsi->u.hdr.stash);

	/*
	 * Check with each extension if it is able to route and proxy this
	 * connection for us.  For example, an extension like x-google-mux
	 * can handle this and then we don't need an actual socket for this
	 * connection.
	 */

	if (lws_ext_cb_all_exts(wsi->context, wsi,
				LWS_EXT_CB_CAN_PROXY_CLIENT_CONNECTION,
				(void *)stash->address,
				wsi->u.hdr.c_port) > 0) {
		lwsl_client("lws_client_connect: ext handling conn\n");

		lws_set_timeout(wsi,
			PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
			        AWAITING_TIMEOUT);

		wsi->mode = LWSCM_WSCL_WAITING_EXTENSION_CONNECT;
		return wsi;
	}
	lwsl_client("lws_client_connect: direct conn\n");
	wsi->context->count_wsi_allocated++;

	return lws_client_connect_2(wsi);

bail1:
	lws_free_set_NULL(wsi->u.hdr.stash);

	return NULL;
}


/**
 * lws_client_connect_extended() - Connect to another websocket server
 * 				DEPRECATED use lws_client_connect_via_info
 * @context:	Websocket context
 * @address:	Remote server address, eg, "myserver.com"
 * @port:	Port to connect to on the remote server, eg, 80
 * @ssl_connection:	0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
 *			signed certs
 * @path:	Websocket path on server
 * @host:	Hostname on server
 * @origin:	Socket origin name
 * @protocol:	Comma-separated list of protocols being asked for from
 *		the server, or just one.  The server will pick the one it
 *		likes best.
 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
 *		protocol supported, or the specific protocol ordinal
 * @userdata: Pre-allocated user data
 *
 *	This function creates a connection to a remote server
 */

LWS_VISIBLE struct lws *
lws_client_connect_extended(struct lws_context *context, const char *address,
			    int port, int ssl_connection, const char *path,
			    const char *host, const char *origin,
			    const char *protocol, int ietf_version_or_minus_one,
			    void *userdata)
{
	struct lws_client_connect_info i;

	memset(&i, 0, sizeof(i));

	i.context = context;
	i.address = address;
	i.port = port;
	i.ssl_connection = ssl_connection;
	i.path = path;
	i.host = host;
	i.origin = origin;
	i.protocol = protocol;
	i.ietf_version_or_minus_one = ietf_version_or_minus_one;
	i.userdata = userdata;

	return lws_client_connect_via_info(&i);
}
/**
 * lws_client_connect_info() - Connect to another websocket server
 * 				DEPRECATED use lws_client_connect_via_info
 * @context:	Websocket context
 * @address:	Remote server address, eg, "myserver.com"
 * @port:	Port to connect to on the remote server, eg, 80
 * @ssl_connection:	0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
 *			signed certs
 * @path:	Websocket path on server
 * @host:	Hostname on server
 * @origin:	Socket origin name
 * @protocol:	Comma-separated list of protocols being asked for from
 *		the server, or just one.  The server will pick the one it
 *		likes best.  If you don't want to specify a protocol, which is
 *		legal, use NULL here.
 * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
 *		protocol supported, or the specific protocol ordinal
 *
 *	This function creates a connection to a remote server
 */


LWS_VISIBLE struct lws *
lws_client_connect(struct lws_context *context, const char *address,
			    int port, int ssl_connection, const char *path,
			    const char *host, const char *origin,
			    const char *protocol, int ietf_version_or_minus_one)
{
	struct lws_client_connect_info i;

	memset(&i, 0, sizeof(i));

	i.context = context;
	i.address = address;
	i.port = port;
	i.ssl_connection = ssl_connection;
	i.path = path;
	i.host = host;
	i.origin = origin;
	i.protocol = protocol;
	i.ietf_version_or_minus_one = ietf_version_or_minus_one;
	i.userdata = NULL;

	return lws_client_connect_via_info(&i);
}

Added undroid/libwebsockets/lib/client-parser.c.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
/*
 * libwebsockets - small server side websockets and web server implementation
 *
 * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation:
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */

#include "private-libwebsockets.h"

int lws_client_rx_sm(struct lws *wsi, unsigned char c)
{
	struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
	int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
	int handled, n, m, rx_draining_ext = 0;
	unsigned short close_code;
	struct lws_tokens eff_buf;
	unsigned char *pp;

	if (wsi->u.ws.rx_draining_ext) {
		struct lws **w = &pt->rx_draining_ext_list;
		lwsl_ext("%s: RX EXT DRAINING: Removing from list\n", __func__, c);
		assert(!c);
		eff_buf.token = NULL;
		eff_buf.token_len = 0;
		wsi->u.ws.rx_draining_ext = 0;
		/* remove us from context draining ext list */
		while (*w) {
			if (*w == wsi) {
				*w = wsi->u.ws.rx_draining_ext_list;
				break;
			}
			w = &((*w)->u.ws.rx_draining_ext_list);
		}
		wsi->u.ws.rx_draining_ext_list = NULL;
		rx_draining_ext = 1;

		goto drain_extension;
	}

	switch (wsi->lws_rx_parse_state) {
	case LWS_RXPS_NEW:
		/* control frames (PING) may interrupt checkable sequences */
		wsi->u.ws.defeat_check_utf8 = 0;

		switch (wsi->ietf_spec_revision) {
		case 13:
			wsi->u.ws.opcode = c & 0xf;
			/* revisit if an extension wants them... */
			switch (wsi->u.ws.opcode) {
			case LWSWSOPC_TEXT_FRAME:
				wsi->u.ws.rsv_first_msg = (c & 0x70);
				wsi->u.ws.continuation_possible = 1;
				wsi->u.ws.check_utf8 = lws_check_opt(
					wsi->context->options,
					LWS_SERVER_OPTION_VALIDATE_UTF8);
				wsi->u.ws.utf8 = 0;
				break;
			case LWSWSOPC_BINARY_FRAME:
				wsi->u.ws.rsv_first_msg = (c & 0x70);
				wsi->u.ws.check_utf8 = 0;
				wsi->u.ws.continuation_possible = 1;
				break;
			case LWSWSOPC_CONTINUATION:
				if (!wsi->u.ws.continuation_possible) {
					lwsl_info("disordered continuation\n");
					return -1;
				}
				break;
			case LWSWSOPC_CLOSE:
				wsi->u.ws.check_utf8 = 0;
				wsi->u.ws.utf8 = 0;
				break;
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 0xb:
			case 0xc:
			case 0xd:
			case 0xe:
			case 0xf:
				lwsl_info("illegal opcode\n");
				return -1;
			default:
				wsi->u.ws.defeat_check_utf8 = 1;
				break;
			}
			wsi->u.ws.rsv = (c & 0x70);
			/* revisit if an extension wants them... */
			if (
#ifndef LWS_NO_EXTENSIONS
				!wsi->count_act_ext &&
#endif
				wsi->u.ws.rsv) {
				lwsl_info("illegal rsv bits set\n");
				return -1;
			}
			wsi->u.ws.final = !!((c >> 7) & 1);
			lwsl_ext("%s:    This RX frame Final %d\n", __func__, wsi->u.ws.final);

			if (wsi->u.ws.owed_a_fin &&
			    (wsi->u.ws.opcode == LWSWSOPC_TEXT_FRAME ||
			     wsi->u.ws.opcode == LWSWSOPC_BINARY_FRAME)) {
				lwsl_info("hey you owed us a FIN\n");
				return -1;
			}
			if ((!(wsi->u.ws.opcode & 8)) && wsi->u.ws.final) {
				wsi->u.ws.continuation_possible = 0;
				wsi->u.ws.owed_a_fin = 0;
			}

			if ((wsi->u.ws.opcode & 8) && !wsi->u.ws.final) {
				lwsl_info("control message cannot be fragmented\n");
				return -1;
			}
			if (!wsi->u.ws.final)
				wsi->u.ws.owed_a_fin = 1;

			switch (wsi->u.ws.opcode) {
			case LWSWSOPC_TEXT_FRAME:
			case LWSWSOPC_BINARY_FRAME:
				wsi->u.ws.frame_is_binary = wsi->u.ws.opcode ==
						 LWSWSOPC_BINARY_FRAME;
				break;
			}
			wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
			break;

		default:
			lwsl_err("unknown spec version %02d\n",
						       wsi->ietf_spec_revision);
			break;
		}
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN:

		wsi->u.ws.this_frame_masked = !!(c & 0x80);

		switch (c & 0x7f) {
		case 126:
			/* control frames are not allowed to have big lengths */
			if (wsi->u.ws.opcode & 8)
				goto illegal_ctl_length;
			wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
			break;
		case 127:
			/* control frames are not allowed to have big lengths */
			if (wsi->u.ws.opcode & 8)
				goto illegal_ctl_length;
			wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
			break;
		default:
			wsi->u.ws.rx_packet_length = c;
			if (wsi->u.ws.this_frame_masked)
				wsi->lws_rx_parse_state =
						LWS_RXPS_07_COLLECT_FRAME_KEY_1;
			else {
				if (c)
					wsi->lws_rx_parse_state =
					LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
				else {
					wsi->lws_rx_parse_state = LWS_RXPS_NEW;
					goto spill;
				}
			}
			break;
		}
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN16_2:
		wsi->u.ws.rx_packet_length = c << 8;
		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN16_1:
		wsi->u.ws.rx_packet_length |= c;
		if (wsi->u.ws.this_frame_masked)
			wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1;
		else {
			if (wsi->u.ws.rx_packet_length)
				wsi->lws_rx_parse_state =
					LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
			else {
				wsi->lws_rx_parse_state = LWS_RXPS_NEW;
				goto spill;
			}
		}
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN64_8:
		if (c & 0x80) {
			lwsl_warn("b63 of length must be zero\n");
			/* kill the connection */
			return -1;
		}
#if defined __LP64__
		wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
#else
		wsi->u.ws.rx_packet_length = 0;
#endif
		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN64_7:
#if defined __LP64__
		wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
#endif
		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN64_6:
#if defined __LP64__
		wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
#endif
		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN64_5:
#if defined __LP64__
		wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
#endif
		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN64_4:
		wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN64_3:
		wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN64_2:
		wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
		break;

	case LWS_RXPS_04_FRAME_HDR_LEN64_1:
		wsi->u.ws.rx_packet_length |= (size_t)c;
		if (wsi->u.ws.this_frame_masked)
			wsi->lws_rx_parse_state =
					LWS_RXPS_07_COLLECT_FRAME_KEY_1;
		else {
			if (wsi->u.ws.rx_packet_length)
				wsi->lws_rx_parse_state =
					LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
			else {
				wsi->lws_rx_parse_state = LWS_RXPS_NEW;
				goto spill;
			}
		}
		break;

	case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
		wsi->u.ws.mask[0] = c;
		if (c)
			wsi->u.ws.all_zero_nonce = 0;
		wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
		break;

	case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
		wsi->u.ws.mask[1] = c;
		if (c)
			wsi->u.ws.all_zero_nonce = 0;
		wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
		break;

	case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
		wsi->u.ws.mask[2] = c;
		if (c)
			wsi->u.ws.all_zero_nonce = 0;
		wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
		break;

	case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
		wsi->u.ws.mask[3] = c;
		if (c)
			wsi->u.ws.all_zero_nonce = 0;

		if (wsi->u.ws.rx_packet_length)
			wsi->lws_rx_parse_state =
					LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
		else {
			wsi->lws_rx_parse_state = LWS_RXPS_NEW;
			goto spill;
		}
		break;

	case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:

		assert(wsi->u.ws.rx_ubuf);

		if (wsi->u.ws.this_frame_masked && !wsi->u.ws.all_zero_nonce)
			c ^= wsi->u.ws.mask[(wsi->u.ws.mask_idx++) & 3];

		wsi->u.ws.rx_ubuf[LWS_PRE + (wsi->u.ws.rx_ubuf_head++)] = c;

		if (--wsi->u.ws.rx_packet_length == 0) {
			/* spill because we have the whole frame */
			wsi->lws_rx_parse_state = LWS_RXPS_NEW;
			goto spill;
		}

		/*
		 * if there's no protocol max frame size given, we are
		 * supposed to default to LWS_MAX_SOCKET_IO_BUF
		 */
		if (!wsi->protocol->rx_buffer_size &&
		    wsi->u.ws.rx_ubuf_head != LWS_MAX_SOCKET_IO_BUF)
			break;

		if (wsi->protocol->rx_buffer_size &&
		    wsi->u.ws.rx_ubuf_head != wsi->protocol->rx_buffer_size)
			break;

		/* spill because we filled our rx buffer */
spill:

		handled = 0;

		/*
		 * is this frame a control packet we should take care of at this
		 * layer?  If so service it and hide it from the user callback
		 */

		switch (wsi->u.ws.opcode) {
		case LWSWSOPC_CLOSE:
			pp = (unsigned char *)&wsi->u.ws.rx_ubuf[LWS_PRE];
			if (lws_check_opt(wsi->context->options,
					  LWS_SERVER_OPTION_VALIDATE_UTF8) &&
			    wsi->u.ws.rx_ubuf_head > 2 &&
			    lws_check_utf8(&wsi->u.ws.utf8, pp + 2,
					   wsi->u.ws.rx_ubuf_head - 2))
				goto utf8_fail;

			/* is this an acknowledgement of our close? */
			if (wsi->state == LWSS_AWAITING_CLOSE_ACK) {
				/*
				 * fine he has told us he is closing too, let's
				 * finish our close
				 */
				lwsl_parser("seen server's close ack\n");
				return -1;
			}

			lwsl_parser("client sees server close len = %d\n",
						 wsi->u.ws.rx_ubuf_head);
			if (wsi->u.ws.rx_ubuf_head >= 2) {
				close_code = (pp[0] << 8) | pp[1];
				if (close_code < 1000 || close_code == 1004 ||
				    close_code == 1005 || close_code == 1006 ||
				    close_code == 1012 || close_code == 1013 ||
				    close_code == 1014 || close_code == 1015 ||
				    (close_code >= 1016 && close_code < 3000)
				) {
					pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
					pp[1] = LWS_CLOSE_STATUS_PROTOCOL_ERR & 0xff;
				}
			}
			if (user_callback_handle_rxflow(
					wsi->protocol->callback, wsi,
					LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
					wsi->user_space, pp,
					wsi->u.ws.rx_ubuf_head))
				return -1;
			/*
			 * parrot the close packet payload back
			 * we do not care about how it went, we are closing
			 * immediately afterwards
			 */
			lws_write(wsi, (unsigned char *)&wsi->u.ws.rx_ubuf[LWS_PRE],
				  wsi->u.ws.rx_ubuf_head, LWS_WRITE_CLOSE);
			wsi->state = LWSS_RETURNED_CLOSE_ALREADY;
			/* close the connection */
			return -1;

		case LWSWSOPC_PING:
			lwsl_info("received %d byte ping, sending pong\n",
				  wsi->u.ws.rx_ubuf_head);

			/* he set a close reason on this guy, ignore PING */
			if (wsi->u.ws.close_in_ping_buffer_len)
				goto ping_drop;

			if (wsi->u.ws.ping_pending_flag) {
				/*
				 * there is already a pending ping payload
				 * we should just log and drop
				 */
				lwsl_parser("DROP PING since one pending\n");
				goto ping_drop;
			}

			/* control packets can only be < 128 bytes long */
			if (wsi->u.ws.rx_ubuf_head > 128 - 3) {
				lwsl_parser("DROP PING payload too large\n");
				goto ping_drop;
			}

			/* stash the pong payload */
			memcpy(wsi->u.ws.ping_payload_buf + LWS_PRE,
			       &wsi->u.ws.rx_ubuf[LWS_PRE],
				wsi->u.ws.rx_ubuf_head);

			wsi->u.ws.ping_payload_len = wsi->u.ws.rx_ubuf_head;
			wsi->u.ws.ping_pending_flag = 1;

			/* get it sent as soon as possible */
			lws_callback_on_writable(wsi);
ping_drop:
			wsi->u.ws.rx_ubuf_head = 0;
			handled = 1;
			break;

		case LWSWSOPC_PONG:
			lwsl_info("client receied pong\n");
			lwsl_hexdump(&wsi->u.ws.rx_ubuf[LWS_PRE],
				     wsi->u.ws.rx_ubuf_head);

			/* issue it */
			callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
			break;

		case LWSWSOPC_CONTINUATION:
		case LWSWSOPC_TEXT_FRAME:
		case LWSWSOPC_BINARY_FRAME:
			break;

		default:

			lwsl_parser("Reserved opc 0x%2X\n", wsi->u.ws.opcode);

			/*
			 * It's something special we can't understand here.
			 * Pass the payload up to the extension's parsing
			 * state machine.
			 */

			eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE];
			eff_buf.token_len = wsi->u.ws.rx_ubuf_head;

			if (lws_ext_cb_active(wsi,
				LWS_EXT_CB_EXTENDED_PAYLOAD_RX,
					&eff_buf, 0) <= 0) { /* not handle or fail */

				lwsl_ext("Unhandled ext opc 0x%x\n", wsi->u.ws.opcode);
				wsi->u.ws.rx_ubuf_head = 0;

				return 0;
			}
			handled = 1;
			break;
		}

		/*
		 * No it's real payload, pass it up to the user callback.
		 * It's nicely buffered with the pre-padding taken care of
		 * so it can be sent straight out again using lws_write
		 */
		if (handled)
			goto already_done;

		eff_buf.token = &wsi->u.ws.rx_ubuf[LWS_PRE];
		eff_buf.token_len = wsi->u.ws.rx_ubuf_head;

drain_extension:
		n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &eff_buf, 0);
		lwsl_ext("Ext RX returned %d\n", n);
		if (n < 0) /* fail */
			return -1;

		lwsl_ext("post inflate eff_buf len %d\n", eff_buf.token_len);

		if (rx_draining_ext && !eff_buf.token_len) {
			lwsl_err("   --- ignoring zero drain result, ending drain\n");
			goto already_done;
		}

		if (wsi->u.ws.check_utf8 && !wsi->u.ws.defeat_check_utf8) {
			if (lws_check_utf8(&wsi->u.ws.utf8,
					   (unsigned char *)eff_buf.token,
					   eff_buf.token_len))
				goto utf8_fail;

			/* we are ending partway through utf-8 character? */
			if (!wsi->u.ws.rx_packet_length && wsi->u.ws.final && wsi->u.ws.utf8 && !n) {
				lwsl_info("FINAL utf8 error\n");
utf8_fail:			lwsl_info("utf8 error\n");
				return -1;
			}
		}

		if (eff_buf.token_len < 0 &&
		    callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
			goto already_done;

		if (!eff_buf.token)
			goto already_done;

		eff_buf.token[eff_buf.token_len] = '\0';

		if (!wsi->protocol->callback)
			goto already_done;

		if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
			lwsl_info("Client doing pong callback\n");

		if (n && eff_buf.token_len) {
			/* extension had more... main loop will come back
			 * we want callback to be done with this set, if so,
			 * because lws_is_final() hides it was final until the
			 * last chunk
			 */
			wsi->u.ws.rx_draining_ext = 1;
			wsi->u.ws.rx_draining_ext_list = pt->rx_draining_ext_list;
			pt->rx_draining_ext_list = wsi;
			lwsl_ext("%s: RX EXT DRAINING: Adding to list\n", __func__);
		}
		if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
		    wsi->state == LWSS_AWAITING_CLOSE_ACK)
			goto already_done;

		m = wsi->protocol->callback(wsi,
			(enum lws_callback_reasons)callback_action,
			wsi->user_space, eff_buf.token, eff_buf.token_len);

		/* if user code wants to close, let caller know */
		if (m)
			return 1;

already_done:
		wsi->u.ws.rx_ubuf_head = 0;
		break;
	default:
		lwsl_err("client rx illegal state\n");
		return 1;
	}

	return 0;

illegal_ctl_length:
	lwsl_warn("Control frame asking for extended length is illegal\n");
	/* kill the connection */
	return -1;
}


Added undroid/libwebsockets/lib/client.c.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
/*
 * libwebsockets - small server side websockets and web server implementation
 *
 * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation:
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */

#include "private-libwebsockets.h"

int
lws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len)
{
	int m;

	switch (wsi->mode) {
	case LWSCM_WSCL_WAITING_PROXY_REPLY:
	case LWSCM_WSCL_ISSUE_HANDSHAKE:
	case LWSCM_WSCL_WAITING_SERVER_REPLY:
	case LWSCM_WSCL_WAITING_EXTENSION_CONNECT:
	case LWSCM_WS_CLIENT:
		while (len) {
			/*
			 * we were accepting input but now we stopped doing so
			 */
			if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
				lwsl_debug("%s: caching %d\n", __func__, len);
				lws_rxflow_cache(wsi, *buf, 0, len);
				return 0;
			}
			if (wsi->u.ws.rx_draining_ext) {
				m = lws_rx_sm(wsi, 0);
				if (m < 0)
					return -1;
				continue;
			}
			/* account for what we're using in rxflow buffer */
			if (wsi->rxflow_buffer)
				wsi->rxflow_pos++;

			if (lws_client_rx_sm(wsi, *(*buf)++)) {
				lwsl_debug("client_rx_sm exited\n");
				return -1;
			}
			len--;
		}
		lwsl_debug("%s: finished with %d\n", __func__, len);
		return 0;
	default:
		break;
	}

	return 0;
}

int
lws_client_socket_service(struct lws_context *context, struct lws *wsi,
			  struct lws_pollfd *pollfd)
{
	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
	char *p = (char *)&pt->serv_buf[0];
	char *sb = p;
	unsigned char c;
	int n, len;

	switch (wsi->mode) {

	case LWSCM_WSCL_WAITING_CONNECT:

		/*
		 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
		 * timeout protection set in client-handshake.c
		 */

		if (!lws_client_connect_2(wsi)) {
			/* closed */
			lwsl_client("closed\n");
			return -1;
		}

		/* either still pending connection, or changed mode */
		return 0;

	case LWSCM_WSCL_WAITING_PROXY_REPLY:

		/* handle proxy hung up on us */

		if (pollfd->revents & LWS_POLLHUP) {

			lwsl_warn("Proxy connection %p (fd=%d) dead\n",
				  (void *)wsi, pollfd->fd);

			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		}

		n = recv(wsi->sock, sb, LWS_MAX_SOCKET_IO_BUF, 0);
		if (n < 0) {
			if (LWS_ERRNO == LWS_EAGAIN) {
				lwsl_debug("Proxy read returned EAGAIN... retrying\n");
				return 0;
			}

			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			lwsl_err("ERROR reading from proxy socket\n");
			return 0;
		}

		pt->serv_buf[13] = '\0';
		if (strcmp(sb, "HTTP/1.0 200 ") &&
		    strcmp(sb, "HTTP/1.1 200 ")) {
			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			lwsl_err("ERROR proxy: %s\n", sb);
			return 0;
		}

		/* clear his proxy connection timeout */

		lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);

		/* fallthru */

	case LWSCM_WSCL_ISSUE_HANDSHAKE:

		/*
		 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
		 * timeout protection set in client-handshake.c
		 *
		 * take care of our lws_callback_on_writable
		 * happening at a time when there's no real connection yet
		 */
		if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
			return -1;

#ifdef LWS_OPENSSL_SUPPORT
		/* we can retry this... just cook the SSL BIO the first time */

		if (wsi->use_ssl && !wsi->ssl) {
			if (lws_ssl_client_bio_create(wsi))
				return -1;
		}

		if (wsi->use_ssl) {
			n = lws_ssl_client_connect1(wsi);
			if (!n)
				return 0;
			if (n < 0)
				goto bail3;
		} else
			wsi->ssl = NULL;

		/* fallthru */

	case LWSCM_WSCL_WAITING_SSL:

		if (wsi->use_ssl) {
			n = lws_ssl_client_connect2(wsi);
			if (!n)
				return 0;
			if (n < 0)
				goto bail3;
		} else
			wsi->ssl = NULL;
#endif

		wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE2;
		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
				context->timeout_secs);

		/* fallthru */

	case LWSCM_WSCL_ISSUE_HANDSHAKE2:
		p = lws_generate_client_handshake(wsi, p);
		if (p == NULL) {
			lwsl_err("Failed to generate handshake for client\n");
			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		}

		/* send our request to the server */

		lws_latency_pre(context, wsi);

		n = lws_ssl_capable_write(wsi, (unsigned char *)sb, p - sb);
		lws_latency(context, wsi, "send lws_issue_raw", n,
			    n == p - sb);
		switch (n) {
		case LWS_SSL_CAPABLE_ERROR:
			lwsl_debug("ERROR writing to client socket\n");
			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		case LWS_SSL_CAPABLE_MORE_SERVICE:
			lws_callback_on_writable(wsi);
			break;
		}

		wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
		wsi->u.hdr.lextable_pos = 0;
		wsi->mode = LWSCM_WSCL_WAITING_SERVER_REPLY;
		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
				context->timeout_secs);
		break;

	case LWSCM_WSCL_WAITING_SERVER_REPLY:

		/* handle server hung up on us */

		if (pollfd->revents & LWS_POLLHUP) {

			lwsl_debug("Server connection %p (fd=%d) dead\n",
				(void *)wsi, pollfd->fd);

			goto bail3;
		}

		if (!(pollfd->revents & LWS_POLLIN))
			break;

		/* interpret the server response */

		/*
		 *  HTTP/1.1 101 Switching Protocols
		 *  Upgrade: websocket
		 *  Connection: Upgrade
		 *  Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
		 *  Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
		 *  Sec-WebSocket-Protocol: chat
		 */

		/*
		 * we have to take some care here to only take from the
		 * socket bytewise.  The browser may (and has been seen to
		 * in the case that onopen() performs websocket traffic)
		 * coalesce both handshake response and websocket traffic
		 * in one packet, since at that point the connection is
		 * definitively ready from browser pov.
		 */
		len = 1;
		while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
		       len > 0) {
			n = lws_ssl_capable_read(wsi, &c, 1);
			lws_latency(context, wsi, "send lws_issue_raw", n,
				    n == 1);
			switch (n) {
			case 0:
			case LWS_SSL_CAPABLE_ERROR:
				goto bail3;
			case LWS_SSL_CAPABLE_MORE_SERVICE:
				return 0;
			}

			if (lws_parse(wsi, c)) {
				lwsl_warn("problems parsing header\n");
				goto bail3;
			}
		}

		/*
		 * hs may also be coming in multiple packets, there is a 5-sec
		 * libwebsocket timeout still active here too, so if parsing did
		 * not complete just wait for next packet coming in this state
		 */

		if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
			break;

		/*
		 * otherwise deal with the handshake.  If there's any
		 * packet traffic already arrived we'll trigger poll() again
		 * right away and deal with it that way
		 */

		return lws_client_interpret_server_handshake(wsi);

bail3:
		lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n");
		wsi->vhost->protocols[0].callback(wsi,
			LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
					wsi->user_space, NULL, 0);
		lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
		return -1;

	case LWSCM_WSCL_WAITING_EXTENSION_CONNECT:
		lwsl_ext("LWSCM_WSCL_WAITING_EXTENSION_CONNECT\n");
		break;

	case LWSCM_WSCL_PENDING_CANDIDATE_CHILD:
		lwsl_ext("LWSCM_WSCL_PENDING_CANDIDATE_CHILD\n");
		break;
	default:
		break;
	}

	return 0;
}

/*
 * In-place str to lower case
 */

static void
strtolower(char *s)
{
	while (*s) {
		*s = tolower((int)*s);
		s++;
	}
}

/**
 * lws_http_transaction_completed() - wait for new http transaction or close
 * @wsi:	websocket connection
 *
 *	Returns 1 if the HTTP connection must close now
 *	Returns 0 and resets connection to wait for new HTTP header /
 *	  transaction if possible
 */

int LWS_WARN_UNUSED_RESULT
lws_http_transaction_completed_client(struct lws *wsi)
{
	lwsl_debug("%s: wsi %p\n", __func__, wsi);
	/* if we can't go back to accept new headers, drop the connection */
	if (wsi->u.http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
		lwsl_info("%s: %p: close connection\n", __func__, wsi);
		return 1;
	}

	/* otherwise set ourselves up ready to go again */
	wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED;
	wsi->mode = LWSCM_HTTP_CLIENT_ACCEPTED;
	wsi->u.http.content_length = 0;
	wsi->hdr_parsing_completed = 0;

	/* He asked for it to stay alive indefinitely */
	lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);

	/*
	 * As client, nothing new is going to come until we ask for it
	 * we can drop the ah, if any
	 */
	if (wsi->u.hdr.ah) {
		wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen;
		lws_header_table_detach(wsi, 0);
	}

	/* If we're (re)starting on headers, need other implied init */
	wsi->u.hdr.ues = URIES_IDLE;

	lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi);

	return 0;
}

int
lws_client_interpret_server_handshake(struct lws *wsi)
{
	int n, len, okay = 0, isErrorCodeReceived = 0, port = 0, ssl = 0;
	int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
	const char *pc, *prot, *ads = NULL, *path;
	struct allocated_headers *ah;
	char *p;
#ifndef LWS_NO_EXTENSIONS
	struct lws_context *context = wsi->context;
	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
	char *sb = (char *)&pt->serv_buf[0];
	const struct lws_ext_options *opts;
	const struct lws_extension *ext;
	char ext_name[128];
	const char *c, *a;
	char ignore;
	int more = 1;
	void *v;
#endif

	if (!wsi->do_ws) {
		/* we are being an http client...
		 */
		ah = wsi->u.hdr.ah;
		lws_union_transition(wsi, LWSCM_HTTP_CLIENT_ACCEPTED);
		wsi->state = LWSS_CLIENT_HTTP_ESTABLISHED;
		wsi->u.http.ah = ah;
	}

	/*
	 * well, what the server sent looked reasonable for syntax.
	 * Now let's confirm it sent all the necessary headers
	 *
	 * http (non-ws) client will expect something like this
	 *
	 * HTTP/1.0.200
	 * server:.libwebsockets
	 * content-type:.text/html
	 * content-length:.17703
	 * set-cookie:.test=LWS_1456736240_336776_COOKIE;Max-Age=360000
	 *
	 *
	 *
	 */

	wsi->u.http.connection_type = HTTP_CONNECTION_KEEP_ALIVE;
	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
	if (wsi->do_ws && !p) {
		lwsl_info("no URI\n");
		goto bail3;
	}
	if (!p) {
		p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP1_0);
		wsi->u.http.connection_type = HTTP_CONNECTION_CLOSE;
	}
	if (!p) {
		lwsl_info("no URI\n");
		goto bail3;
	}
	n = atoi(p);
	if (n == 301 || n == 302 || n == 303 || n == 307 || n == 308) {
		p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_LOCATION);
		if (!p)
			goto bail3;

		if (lws_parse_uri(p, &prot, &ads, &port, &path))
			goto bail3;

		if (!strcmp(prot, "wss://") || !strcmp(prot, "https://"))
			ssl = 1;

		if (lws_client_reset(wsi, ssl, ads, port, path, ads)) {
			lwsl_err("Redirect failed\n");
			goto bail3;
		}
		return 0;
	}

	if (!wsi->do_ws) {
		if (n != 200) {
			lwsl_notice("Connection failed with code %d", n);
			goto bail2;
		}

#ifdef LWS_WITH_HTTP_PROXY
		wsi->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->perform_rewrite = 1;
		}
#endif

		/* allocate the per-connection user memory (if any) */
		if (lws_ensure_user_space(wsi)) {
			lwsl_err("Problem allocating wsi user mem\n");
			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;
		}

		if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
			wsi->u.http.content_length =
					atoi(lws_hdr_simple_ptr(wsi,
						WSI_TOKEN_HTTP_CONTENT_LENGTH));
			lwsl_notice("%s: incoming content length %d\n", __func__,
					wsi->u.http.content_length);
			wsi->u.http.content_remain = wsi->u.http.content_length;
		} else /* can't do 1.1 without a content length or chunked */
			if (!wsi->chunked)
				wsi->u.http.connection_type = HTTP_CONNECTION_CLOSE;

		/*
		 * we seem to be good to go, give client last chance to check
		 * headers and OK it
		 */
		if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
					    wsi->user_space, NULL, 0))
			goto bail2;

		/* clear his proxy connection timeout */
		lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);

		wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;

		/* call him back to inform him he is up */
		if (wsi->protocol->callback(wsi,
					    LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
					    wsi->user_space, NULL, 0))
			goto bail3;

		/* free up his parsing allocations */
		lws_header_table_detach(wsi, 0);

		lwsl_notice("%s: client connection up\n", __func__);

		return 0;
	}

	if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
		lwsl_info("no ACCEPT\n");
		isErrorCodeReceived = 1;
		goto bail3;
	}

	if (p && strncmp(p, "101", 3)) {
		lwsl_warn(
		       "lws_client_handshake: got bad HTTP response '%s'\n", p);
		goto bail3;
	}

	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
	if (!p) {
		lwsl_info("no UPGRADE\n");
		goto bail3;
	}
	strtolower(p);
	if (strcmp(p, "websocket")) {
		lwsl_warn(
		      "lws_client_handshake: got bad Upgrade header '%s'\n", p);
		goto bail3;
	}

	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION);
	if (!p) {
		lwsl_info("no Connection hdr\n");
		goto bail3;
	}
	strtolower(p);
	if (strcmp(p, "upgrade")) {
		lwsl_warn("lws_client_int_s_hs: bad header %s\n", p);
		goto bail3;
	}

	pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
	if (!pc) {
		lwsl_parser("lws_client_int_s_hs: no protocol list\n");
	} else
		lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc);

	/*
	 * confirm the protocol the server wants to talk was in the list
	 * of protocols we offered
	 */

	len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
	if (!len) {
		lwsl_info("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n");
		/*
		 * no protocol name to work from,
		 * default to first protocol
		 */
		wsi->protocol = &wsi->vhost->protocols[0];
		goto check_extensions;
	}

	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
	len = strlen(p);

	while (pc && *pc && !okay) {
		if (!strncmp(pc, p, len) &&
		    (pc[len] == ',' || pc[len] == '\0')) {
			okay = 1;
			continue;
		}
		while (*pc && *pc++ != ',')
			;
		while (*pc && *pc == ' ')
			pc++;
	}

	if (!okay) {
		lwsl_err("lws_client_int_s_hs: got bad protocol %s\n", p);
		goto bail2;
	}

	/*
	 * identify the selected protocol struct and set it
	 */
	n = 0;
	wsi->protocol = NULL;
	while (wsi->vhost->protocols[n].callback && !wsi->protocol) {
		if (strcmp(p, wsi->vhost->protocols[n].name) == 0) {
			wsi->protocol = &wsi->vhost->protocols[n];
			break;
		}
		n++;
	}

	if (wsi->protocol == NULL) {
		lwsl_err("lws_client_int_s_hs: fail protocol %s\n", p);
		goto bail2;
	}


check_extensions:
#ifndef LWS_NO_EXTENSIONS
	/* instantiate the accepted extensions */

	if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
		lwsl_ext("no client extensions allowed by server\n");
		goto check_accept;
	}

	/*
	 * break down the list of server accepted extensions
	 * and go through matching them or identifying bogons
	 */

	if (lws_hdr_copy(wsi, sb, LWS_MAX_SOCKET_IO_BUF, WSI_TOKEN_EXTENSIONS) < 0) {
		lwsl_warn("ext list from server failed to copy\n");
		goto bail2;
	}

	c = sb;
	n = 0;
	ignore = 0;
	a = NULL;
	while (more) {

		if (*c && (*c != ',' && *c != '\t')) {
			if (*c == ';') {
				ignore = 1;
				if (!a)
					a = c + 1;
			}
			if (ignore || *c == ' ') {
				c++;
				continue;
			}

			ext_name[n] = *c++;
			if (n < sizeof(ext_name) - 1)
				n++;
			continue;
		}
		ext_name[n] = '\0';
		ignore = 0;
		if (!*c)
			more = 0;
		else {
			c++;
			if (!n)
				continue;
		}

		/* check we actually support it */

		lwsl_notice("checking client ext %s\n", ext_name);

		n = 0;
		ext = wsi->vhost->extensions;
		while (ext && ext->callback) {
			if (strcmp(ext_name, ext->name)) {
				ext++;
				continue;
			}

			n = 1;
			lwsl_notice("instantiating client ext %s\n", ext_name);

			/* instantiate the extension on this conn */

			wsi->active_extensions[wsi->count_act_ext] = ext;

			/* allow him to construct his ext instance */

			if (ext->callback(lws_get_context(wsi), ext, wsi,
				      LWS_EXT_CB_CLIENT_CONSTRUCT,
				      (void *)&wsi->act_ext_user[wsi->count_act_ext],
				      (void *)&opts, 0)) {
				lwsl_notice(" ext %s failed construction\n", ext_name);
				ext++;
				continue;
			}

			/*
			 * allow the user code to override ext defaults if it
			 * wants to
			 */
			ext_name[0] = '\0';
			if (user_callback_handle_rxflow(wsi->protocol->callback,
					wsi, LWS_CALLBACK_WS_EXT_DEFAULTS,
					(char *)ext->name, ext_name,
					sizeof(ext_name)))
				goto bail2;

			if (ext_name[0] &&
			    lws_ext_parse_options(ext, wsi, wsi->act_ext_user[
						  wsi->count_act_ext], opts, ext_name,
						  strlen(ext_name))) {
				lwsl_err("%s: unable to parse user defaults '%s'",
					 __func__, ext_name);
				goto bail2;
			}

			/*
			 * give the extension the server options
			 */
			if (a && lws_ext_parse_options(ext, wsi,
					wsi->act_ext_user[wsi->count_act_ext],
					opts, a, c - a)) {
				lwsl_err("%s: unable to parse remote def '%s'",
					 __func__, a);
				goto bail2;
			}

			if (ext->callback(lws_get_context(wsi), ext, wsi,
					LWS_EXT_CB_OPTION_CONFIRM,
				      wsi->act_ext_user[wsi->count_act_ext],
				      NULL, 0)) {
				lwsl_err("%s: ext %s rejects server options %s",
					 ext->name, a);
				goto bail2;
			}

			wsi->count_act_ext++;

			ext++;
		}

		if (n == 0) {
			lwsl_warn("Unknown ext '%s'!\n", ext_name);
			goto bail2;
		}

		a = NULL;
		n = 0;
	}

check_accept:
#endif

	/*
	 * Confirm his accept token is the one we precomputed
	 */

	p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
	if (strcmp(p, wsi->u.hdr.ah->initial_handshake_hash_base64)) {
		lwsl_warn("lws_client_int_s_hs: accept '%s' wrong vs '%s'\n", p,
				  wsi->u.hdr.ah->initial_handshake_hash_base64);
		goto bail2;
	}

	/* allocate the per-connection user memory (if any) */
	if (lws_ensure_user_space(wsi)) {
		lwsl_err("Problem allocating wsi user mem\n");
		goto bail2;
	}

	/*
	 * we seem to be good to go, give client last chance to check
	 * headers and OK it
	 */
	if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
				    wsi->user_space, NULL, 0))
		goto bail2;

	/* clear his proxy connection timeout */
	lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);

	/* free up his parsing allocations */
	lws_header_table_detach(wsi, 0);

	lws_union_transition(wsi, LWSCM_WS_CLIENT);
	wsi->state = LWSS_ESTABLISHED;

	wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;

	/*
	 * create the frame buffer for this connection according to the
	 * size mentioned in the protocol definition.  If 0 there, then
	 * use a big default for compatibility
	 */
	n = wsi->protocol->rx_buffer_size;
	if (!n)
		n = LWS_MAX_SOCKET_IO_BUF;
	n += LWS_PRE;
	wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */);
	if (!wsi->u.ws.rx_ubuf) {
		lwsl_err("Out of Mem allocating rx buffer %d\n", n);
		goto bail2;
	}
       wsi->u.ws.rx_ubuf_alloc = n;
	lwsl_info("Allocating client RX buffer %d\n", n);

	if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n,
		       sizeof n)) {
		lwsl_warn("Failed to set SNDBUF to %d", n);
		goto bail3;
	}

	lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);

	/* call him back to inform him he is up */

	if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_ESTABLISHED,
				    wsi->user_space, NULL, 0))
		goto bail3;
#ifndef LWS_NO_EXTENSIONS
	/*
	 * inform all extensions, not just active ones since they
	 * already know
	 */
	ext = wsi->vhost->extensions;

	while (ext && ext->callback) {
		v = NULL;
		for (n = 0; n < wsi->count_act_ext; n++)
			if (wsi->active_extensions[n] == ext)
				v = wsi->act_ext_user[n];

		ext->callback(context, ext, wsi,
			  LWS_EXT_CB_ANY_WSI_ESTABLISHED, v, NULL, 0);
		ext++;
	}
#endif

	return 0;

bail3:
	close_reason = LWS_CLOSE_STATUS_NOSTATUS;

bail2:
	if (wsi->protocol && wsi->state == LWSS_ESTABLISHED) {
		if (isErrorCodeReceived && p) {
			wsi->protocol->callback(wsi,
				LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
						wsi->user_space, p,
						(unsigned int)strlen(p));
		} else {
			wsi->protocol->callback(wsi,
				LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
						wsi->user_space, NULL, 0);
		}
	}

	lwsl_info("closing connection due to bail2 connection error\n");

	/* closing will free up his parsing allocations */
	lws_close_free_wsi(wsi, close_reason);

	return 1;
}


char *
lws_generate_client_handshake(struct lws *wsi, char *pkt)
{
	char buf[128], hash[20], key_b64[40], *p = pkt;
	struct lws_context *context = wsi->context;
	const char *meth;
	int n;
#ifndef LWS_NO_EXTENSIONS
	const struct lws_extension *ext;
	int ext_count = 0;
#endif

	meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
	if (!meth) {
		meth = "GET";
		wsi->do_ws = 1;
	} else
		wsi->do_ws = 0;

	if (wsi->do_ws) {
		/*
		 * create the random key
		 */
		n = lws_get_random(context, hash, 16);
		if (n != 16) {
			lwsl_err("Unable to read from random dev %s\n",
				 SYSTEM_RANDOM_FILEPATH);
			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			return NULL;
		}

		lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
	}

	/*
	 * 04 example client handshake
	 *
	 * GET /chat HTTP/1.1
	 * Host: server.example.com
	 * Upgrade: websocket
	 * Connection: Upgrade
	 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
	 * Sec-WebSocket-Origin: http://example.com
	 * Sec-WebSocket-Protocol: chat, superchat
	 * Sec-WebSocket-Version: 4
	 */

	p += sprintf(p, "%s %s HTTP/1.1\x0d\x0a", meth,
		     lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));

	p += sprintf(p, "Pragma: no-cache\x0d\x0a"
			"Cache-Control: no-cache\x0d\x0a");

	p += sprintf(p, "Host: %s\x0d\x0a",
		     lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));

	if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN))
		p += sprintf(p, "Origin: http://%s\x0d\x0a",
			     lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));

	if (wsi->do_ws) {
		p += sprintf(p, "Upgrade: websocket\x0d\x0a"
				"Connection: Upgrade\x0d\x0a"
				"Sec-WebSocket-Key: ");
		strcpy(p, key_b64);
		p += strlen(key_b64);
		p += sprintf(p, "\x0d\x0a");
		if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
			p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
			     lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));

		/* tell the server what extensions we could support */

#ifndef LWS_NO_EXTENSIONS
		ext = wsi->vhost->extensions;
		while (ext && ext->callback) {
			n = lws_ext_cb_all_exts(context, wsi,
				   LWS_EXT_CB_CHECK_OK_TO_PROPOSE_EXTENSION,
				   (char *)ext->name, 0);
			if (n) { /* an extension vetos us */
				lwsl_ext("ext %s vetoed\n", (char *)ext->name);
				ext++;
				continue;
			}
			n = wsi->vhost->protocols[0].callback(wsi,
				LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
					wsi->user_space, (char *)ext->name, 0);

			/*
			 * zero return from callback means
			 * go ahead and allow the extension,
			 * it's what we get if the callback is
			 * unhandled
			 */

			if (n) {
				ext++;
				continue;
			}

			/* apply it */

			if (ext_count)
				*p++ = ',';
			else
				p += sprintf(p, "Sec-WebSocket-Extensions: ");
			p += sprintf(p, "%s", ext->client_offer);
			ext_count++;

			ext++;
		}
		if (ext_count)
			p += sprintf(p, "\x0d\x0a");
#endif

		if (wsi->ietf_spec_revision)
			p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
				     wsi->ietf_spec_revision);

		/* prepare the expected server accept response */

		key_b64[39] = '\0'; /* enforce composed length below buf sizeof */
		n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key_b64);

		lws_SHA1((unsigned char *)buf, n, (unsigned char *)hash);

		lws_b64_encode_string(hash, 20,
				      wsi->u.hdr.ah->initial_handshake_hash_base64,
				      sizeof(wsi->u.hdr.ah->initial_handshake_hash_base64));
	}

	/* give userland a chance to append, eg, cookies */

	wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
				wsi->user_space, &p, (pkt + LWS_MAX_SOCKET_IO_BUF) - p - 12);

	p += sprintf(p, "\x0d\x0a");

	return p;
}

Added undroid/libwebsockets/lib/context.c.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
/*
 * libwebsockets - small server side websockets and web server implementation
 *
 * Copyright (C) 2010-2015 Andy Green <andy@warmcat.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation:
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */

#include "private-libwebsockets.h"

#ifndef LWS_BUILD_HASH
#define LWS_BUILD_HASH "unknown-build-hash"
#endif

static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;

/**
 * lws_get_library_version: get version and git hash library built from
 *
 *	returns a const char * to a string like "1.1 178d78c"
 *	representing the library version followed by the git head hash it
 *	was built from
 */
LWS_VISIBLE const char *
lws_get_library_version(void)
{
	return library_version;
}

static const char * const mount_protocols[] = {
	"http://",
	"https://",
	"file://",
	"cgi://",
	">http://",
	">https://",
};

LWS_VISIBLE void *
lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, const struct lws_protocols *prot,
			    int size)
{
	int n = 0;

	/* allocate the vh priv array only on demand */
	if (!vhost->protocol_vh_privs) {
		vhost->protocol_vh_privs = (void **)lws_zalloc(
				vhost->count_protocols * sizeof(void *));
		if (!vhost->protocol_vh_privs)
			return NULL;
	}

	while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
		n++;

	if (n == vhost->count_protocols)
		return NULL;

	vhost->protocol_vh_privs[n] = lws_zalloc(size);
	return vhost->protocol_vh_privs[n];
}

LWS_VISIBLE void *
lws_protocol_vh_priv_get(struct lws_vhost *vhost, const struct lws_protocols *prot)
{
	int n = 0;

	if (!vhost->protocol_vh_privs)
		return NULL;

	while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
		n++;

	if (n == vhost->count_protocols) {
		lwsl_err("%s: unknown protocol %p\n", __func__, prot);
		return NULL;
	}

	return vhost->protocol_vh_privs[n];
}

static const struct lws_protocol_vhost_options *
lws_vhost_protocol_options(struct lws_vhost *vh, const char *name)
{
	const struct lws_protocol_vhost_options *pvo = vh->pvo;

	while (pvo) {
		// lwsl_notice("%s: '%s' '%s'\n", __func__, pvo->name, name);
		if (!strcmp(pvo->name, name))
			return pvo;
		pvo = pvo->next;
	}

	return NULL;
}

int
lws_protocol_init(struct lws_context *context)
{
	struct lws_vhost *vh = context->vhost_list;
	const struct lws_protocol_vhost_options *pvo, *pvo1;
	struct lws wsi;
	int n;

	memset(&wsi, 0, sizeof(wsi));
	wsi.context = context;

	lwsl_notice("%s\n", __func__);

	while (vh) {
		wsi.vhost = vh;

		/* initialize supported protocols on this vhost */

		for (n = 0; n < vh->count_protocols; n++) {
			wsi.protocol = &vh->protocols[n];

			pvo = lws_vhost_protocol_options(vh,
							 vh->protocols[n].name);
			if (pvo) {
				/*
				 * linked list of options specific to
				 * vh + protocol
				 */
				pvo1 = pvo;
				pvo = pvo1->options;

				while (pvo) {
					lwsl_notice("    vh %s prot %s opt %s\n",
							vh->name,
							vh->protocols[n].name,
							pvo->name);

					if (!strcmp(pvo->name, "default")) {
						lwsl_notice("Setting default "
						   "protocol for vh %s to %s\n",
						   vh->name,
						   vh->protocols[n].name);
						vh->default_protocol_index = n;
					}
					pvo = pvo->next;
				}

				pvo = pvo1->options;
			}

			/*
			 * inform all the protocols that they are doing their one-time
			 * initialization if they want to.
			 *
			 * NOTE the wsi is all zeros except for the context, vh and
			 * protocol ptrs so lws_get_context(wsi) etc can work
			 */
			vh->protocols[n].callback(&wsi,
				LWS_CALLBACK_PROTOCOL_INIT, NULL,
				(void *)pvo, 0);
		}

		vh = vh->vhost_next;
	}

	context->protocol_init_done = 1;

	return 0;
}

static int callback_http_dummy(
		struct lws *wsi, enum lws_callback_reasons reason, void *user,
		  void *in, size_t len)
{
	return 0;
}

/* list of supported protocols and callbacks */

static const struct lws_protocols protocols_dummy[] = {
	/* first protocol must always be HTTP handler */

	{
		"http-only",		/* name */
		callback_http_dummy,		/* callback */
		0,	/* per_session_data_size */
		0,			/* max frame size / rx buffer */
	},
	/*
	 * the other protocols are provided by lws plugins
	 */
	{ NULL, NULL, 0, 0 } /* terminator */
};

LWS_VISIBLE struct lws_vhost *
lws_create_vhost(struct lws_context *context,
		 struct lws_context_creation_info *info)
{
	struct lws_vhost *vh = lws_zalloc(sizeof(*vh)),
			 **vh1 = &context->vhost_list;
	const struct lws_http_mount *mounts;
#ifdef LWS_WITH_PLUGINS
	struct lws_plugin *plugin = context->plugin_list;
	struct lws_protocols *lwsp;
	int m, n, f = !info->pvo;
#endif
	char *p;

	if (!vh)
		return NULL;

	if (!info->protocols)
		info->protocols = &protocols_dummy[0];

	vh->context = context;
	if (!info->vhost_name)
		vh->name = "default";
	else
		vh->name = info->vhost_name;

	vh->iface = info->iface;
	for (vh->count_protocols = 0;
	     info->protocols[vh->count_protocols].callback;
	     vh->count_protocols++)
		;

	vh->options = info->options;
	vh->pvo = info->pvo;
	vh->keepalive_timeout = info->keepalive_timeout;

#ifdef LWS_WITH_PLUGINS
	if (plugin) {
		/*
		 * give the vhost a unified list of protocols including the
		 * ones that came from plugins
		 */
		lwsp = lws_zalloc(sizeof(struct lws_protocols) *
					   (vh->count_protocols +
					   context->plugin_protocol_count + 1));
		if (!lwsp)
			return NULL;

		m = vh->count_protocols;
		memcpy(lwsp, info->protocols,
		       sizeof(struct lws_protocols) * m);

		/* for compatibility, all protocols enabled on vhost if only
		 * the default vhost exists.  Otherwise only vhosts who ask
		 * for a protocol get it enabled.
		 */

		if (info->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS)
			f = 0;

		while (plugin) {
			for (n = 0; n < plugin->caps.count_protocols; n++) {
				/*
				 * for compatibility's sake, no pvo implies
				 * allow all protocols
				 */
				if (f || lws_vhost_protocol_options(vh,
				    plugin->caps.protocols[n].name)) {
					memcpy(&lwsp[m],
					       &plugin->caps.protocols[n],
					       sizeof(struct lws_protocols));
					m++;
					vh->count_protocols++;
				}
			}
			plugin = plugin->list;
		}
		vh->protocols = lwsp;
	} else
#endif
		vh->protocols = info->protocols;

	vh->same_vh_protocol_list = (struct lws **)
			lws_zalloc(sizeof(struct lws *) * vh->count_protocols);

	vh->mount_list = info->mounts;

#ifdef LWS_USE_UNIX_SOCK
	if (LWS_UNIX_SOCK_ENABLED(context)) {
		lwsl_notice("Creating Vhost '%s' path \"%s\", %d protocols\n",
				vh->name, info->iface, vh->count_protocols);
	} else
#endif
	lwsl_notice("Creating Vhost '%s' port %d, %d protocols\n",
			vh->name, info->port, vh->count_protocols);

	mounts = info->mounts;
	while (mounts) {
		lwsl_notice("   mounting %s%s to %s\n",
				mount_protocols[mounts->origin_protocol],
				mounts->origin, mounts->mountpoint);
		mounts = mounts->mount_next;
	}

#ifndef LWS_NO_EXTENSIONS
#ifdef LWS_WITH_PLUGINS
	if (context->plugin_extension_count) {

		m = 0;
		while (info->extensions && info->extensions[m].callback)
			m++;

		/*
		 * give the vhost a unified list of extensions including the
		 * ones that came from plugins
		 */
		vh->extensions = lws_zalloc(sizeof(struct lws_extension) *
					   (m +
					   context->plugin_extension_count + 1));
		if (!vh->extensions)
			return NULL;

		memcpy((struct lws_extension *)vh->extensions, info->extensions,
		       sizeof(struct lws_extension) * m);
		plugin = context->plugin_list;
		while (plugin) {
			memcpy((struct lws_extension *)&vh->extensions[m],
				plugin->caps.extensions,
			       sizeof(struct lws_extension) *
			       plugin->caps.count_extensions);
			m += plugin->caps.count_extensions;
			plugin = plugin->list;
		}
	} else
#endif
		vh->extensions = info->extensions;
#endif

	vh->listen_port = info->port;
	vh->http_proxy_port = 0;
	vh->http_proxy_address[0] = '\0';

	/* either use proxy from info, or try get it from env var */

	if (info->http_proxy_address) {
		/* override for backwards compatibility */
		if (info->http_proxy_port)
			vh->http_proxy_port = info->http_proxy_port;
		lws_set_proxy(vh, info->http_proxy_address);
	} else {
#ifdef LWS_HAVE_GETENV
		p = getenv("http_proxy");
		if (p)
			lws_set_proxy(vh, p);
#endif
	}

	vh->ka_time = info->ka_time;
	vh->ka_interval = info->ka_interval;
	vh->ka_probes = info->ka_probes;

	if (vh->options & LWS_SERVER_OPTION_STS)
		lwsl_notice("   STS enabled\n");

#ifdef LWS_WITH_ACCESS_LOG
	if (info->log_filepath) {
		vh->log_fd = open(info->log_filepath, O_CREAT | O_APPEND | O_RDWR, 0600);
		if (vh->log_fd == LWS_INVALID_FILE) {
			lwsl_err("unable to open log filepath %s\n",
				 info->log_filepath);
			goto bail;
		}
#ifndef WIN32
		if (context->uid != -1)
			if (chown(info->log_filepath, context->uid,
				  context->gid) == -1)
				lwsl_err("unable to chown log file %s\n",
						info->log_filepath);
#endif
	} else
		vh->log_fd = LWS_INVALID_FILE;
#endif

	if (lws_context_init_server_ssl(info, vh))
		goto bail;

	if (lws_context_init_client_ssl(info, vh))
		goto bail;

	if (lws_context_init_server(info, vh))
		goto bail;

	while (1) {
		if (!(*vh1)) {
			*vh1 = vh;
			break;
		}
		vh1 = &(*vh1)->vhost_next;
	};

	return vh;

bail:
	lws_free(vh);

	return NULL;
}

/**
 * lws_create_context() - Create the websocket handler
 * @info:	pointer to struct with parameters
 *
 *	This function creates the listening socket (if serving) and takes care
 *	of all initialization in one step.
 *
 *	After initialization, it returns a struct lws_context * that
 *	represents this server.  After calling, user code needs to take care
 *	of calling lws_service() with the context pointer to get the
 *	server's sockets serviced.  This must be done in the same process
 *	context as the initialization call.
 *
 *	The protocol callback functions are called for a handful of events
 *	including http requests coming in, websocket connections becoming
 *	established, and data arriving; it's also called periodically to allow
 *	async transmission.
 *
 *	HTTP requests are sent always to the FIRST protocol in @protocol, since
 *	at that time websocket protocol has not been negotiated.  Other
 *	protocols after the first one never see any HTTP callack activity.
 *
 *	The server created is a simple http server by default; part of the
 *	websocket standard is upgrading this http connection to a websocket one.
 *
 *	This allows the same server to provide files like scripts and favicon /
 *	images or whatever over http and dynamic data over websockets all in
 *	one place; they're all handled in the user callback.
 */
LWS_VISIBLE struct lws_context *
lws_create_context(struct lws_context_creation_info *info)
{
	struct lws_context *context = NULL;
	struct lws wsi;
#ifndef LWS_NO_DAEMONIZE
	int pid_daemon = get_daemonize_pid();
#endif
	int n, m;
#if defined(__ANDROID__)
	struct rlimit rt;
#endif

	lwsl_notice("Initial logging level %d\n", log_level);
	lwsl_notice("Libwebsockets version: %s\n", library_version);
#if LWS_POSIX
#ifdef LWS_USE_IPV6
	if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_IPV6))
		lwsl_notice("IPV6 compiled in and enabled\n");
	else
		lwsl_notice("IPV6 compiled in but disabled\n");
#else
	lwsl_notice("IPV6 not compiled in\n");
#endif
	lws_feature_status_libev(info);
	lws_feature_status_libuv(info);
#endif
	lwsl_info(" LWS_DEF_HEADER_LEN    : %u\n", LWS_DEF_HEADER_LEN);
	lwsl_info(" LWS_MAX_PROTOCOLS     : %u\n", LWS_MAX_PROTOCOLS);
	lwsl_info(" LWS_MAX_SMP           : %u\n", LWS_MAX_SMP);
	lwsl_info(" SPEC_LATEST_SUPPORTED : %u\n", SPEC_LATEST_SUPPORTED);
	lwsl_info(" sizeof (*info)        : %u\n", sizeof(*info));
#if LWS_POSIX
	lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
#endif
	if (lws_plat_context_early_init())
		return NULL;

	context = lws_zalloc(sizeof(struct lws_context));
	if (!context) {
		lwsl_err("No memory for websocket context\n");
		return NULL;
	}

	context->time_up = time(NULL);
#ifndef LWS_NO_DAEMONIZE
	if (pid_daemon) {
		context->started_with_parent = pid_daemon;
		lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
	}
#endif
#if defined(__ANDROID__)
		n = getrlimit ( RLIMIT_NOFILE,&rt);
		if (-1 == n) {
			lwsl_err("Get RLIMIT_NOFILE failed!\n");
			return NULL;
		}
		context->max_fds = rt.rlim_cur;
#else
		context->max_fds = getdtablesize();
#endif

	if (info->count_threads)
		context->count_threads = info->count_threads;
	else
		context->count_threads = 1;

	if (context->count_threads > LWS_MAX_SMP)
		context->count_threads = LWS_MAX_SMP;

	context->token_limits = info->token_limits;

	context->options = info->options;

	if (info->timeout_secs)
		context->timeout_secs = info->timeout_secs;
	else
		context->timeout_secs = AWAITING_TIMEOUT;

	lwsl_info(" default timeout (secs): %u\n", context->timeout_secs);

	if (info->max_http_header_data)
		context->max_http_header_data = info->max_http_header_data;
	else
		context->max_http_header_data = LWS_DEF_HEADER_LEN;
	if (info->max_http_header_pool)
		context->max_http_header_pool = info->max_http_header_pool;
	else
		context->max_http_header_pool = LWS_DEF_HEADER_POOL;

	/*
	 * Allocate the per-thread storage for scratchpad buffers,
	 * and header data pool
	 */
	for (n = 0; n < context->count_threads; n++) {
		context->pt[n].serv_buf = lws_zalloc(LWS_MAX_SOCKET_IO_BUF);
		if (!context->pt[n].serv_buf) {
			lwsl_err("OOM\n");
			return NULL;
		}

		context->pt[n].context = context;
		context->pt[n].tid = n;
		context->pt[n].http_header_data = lws_malloc(context->max_http_header_data *
						       context->max_http_header_pool);
		if (!context->pt[n].http_header_data)
			goto bail;

		context->pt[n].ah_pool = lws_zalloc(sizeof(struct allocated_headers) *
					      context->max_http_header_pool);
		for (m = 0; m < context->max_http_header_pool; m++)
			context->pt[n].ah_pool[m].data =
				(char *)context->pt[n].http_header_data +
				(m * context->max_http_header_data);
		if (!context->pt[n].ah_pool)
			goto bail;

		lws_pt_mutex_init(&context->pt[n]);
	}

	if (info->fd_limit_per_thread)
		context->fd_limit_per_thread = info->fd_limit_per_thread;
	else
		context->fd_limit_per_thread = context->max_fds /
					       context->count_threads;

	lwsl_notice(" Threads: %d each %d fds\n", context->count_threads,
		    context->fd_limit_per_thread);

	memset(&wsi, 0, sizeof(wsi));
	wsi.context = context;

	if (!info->ka_interval && info->ka_time > 0) {
		lwsl_err("info->ka_interval can't be 0 if ka_time used\n");
		return NULL;
	}

#ifdef LWS_USE_LIBEV
	/* (Issue #264) In order to *avoid breaking backwards compatibility*, we
	 * enable libev mediated SIGINT handling with a default handler of
	 * lws_sigint_cb. The handler can be overridden or disabled
	 * by invoking lws_sigint_cfg after creating the context, but
	 * before invoking lws_initloop:
	 */
	context->use_ev_sigint = 1;
	context->lws_ev_sigint_cb = &lws_ev_sigint_cb;
#endif /* LWS_USE_LIBEV */
#ifdef LWS_USE_LIBUV
	/* (Issue #264) In order to *avoid breaking backwards compatibility*, we
	 * enable libev mediated SIGINT handling with a default handler of
	 * lws_sigint_cb. The handler can be overridden or disabled
	 * by invoking lws_sigint_cfg after creating the context, but
	 * before invoking lws_initloop:
	 */
	context->use_ev_sigint = 1;
	context->lws_uv_sigint_cb = &lws_uv_sigint_cb;
#endif

	lwsl_info(" mem: context:         %5u bytes (%d ctx + (%d thr x %d))\n",
		  sizeof(struct lws_context) +
		  (context->count_threads * LWS_MAX_SOCKET_IO_BUF),
		  sizeof(struct lws_context),
		  context->count_threads,
		  LWS_MAX_SOCKET_IO_BUF);

	lwsl_info(" mem: http hdr rsvd:   %5u bytes (%u thr x (%u + %u) x %u))\n",
		    (context->max_http_header_data +
		     sizeof(struct allocated_headers)) *
		    context->max_http_header_pool * context->count_threads,
		    context->count_threads,
		    context->max_http_header_data,
		    sizeof(struct allocated_headers),
		    context->max_http_header_pool);
	n = sizeof(struct lws_pollfd) * context->count_threads *
	    context->fd_limit_per_thread;
	context->pt[0].fds = lws_zalloc(n);
	if (context->pt[0].fds == NULL) {
		lwsl_err("OOM allocating %d fds\n", context->max_fds);
		goto bail;
	}
	lwsl_info(" mem: pollfd map:      %5u\n", n);

	if (info->server_string) {
		context->server_string = info->server_string;
		context->server_string_len = (short)
				strlen(context->server_string);
	} else {
		context->server_string = "libwebsockets";
		context->server_string_len = 13;
	}

#if LWS_MAX_SMP > 1
	/* each thread serves his own chunk of fds */
	for (n = 1; n < (int)info->count_threads; n++)
		context->pt[n].fds = context->pt[n - 1].fds +
				     context->fd_limit_per_thread;
#endif

	if (lws_plat_init(context, info))
		goto bail;

	lws_context_init_ssl_library(info);

	context->user_space = info->user;

	/*
	 * if he's not saying he'll make his own vhosts later then act
	 * compatibly and make a default vhost using the data in the info
	 */
	if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
		if (!lws_create_vhost(context, info)) {
			lwsl_err("Failed to create default vhost\n");
			return NULL;
		}

	lws_context_init_extensions(info, context);

	lwsl_notice(" mem: per-conn:        %5u bytes + protocol rx buf\n",
		    sizeof(struct lws));

	strcpy(context->canonical_hostname, "unknown");
	lws_server_get_canonical_hostname(context, info);

	context->uid = info->uid;
	context->gid = info->gid;

	/*
	 * drop any root privs for this process
	 * to listen on port < 1023 we would have needed root, but now we are
	 * listening, we don't want the power for anything else
	 */
	if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
		lws_plat_drop_app_privileges(info);

	/*
	 * give all extensions a chance to create any per-context
	 * allocations they need
	 */
	if (info->port != CONTEXT_PORT_NO_LISTEN) {
		if (lws_ext_cb_all_exts(context, NULL,
			LWS_EXT_CB_SERVER_CONTEXT_CONSTRUCT, NULL, 0) < 0)
			goto bail;
	} else
		if (lws_ext_cb_all_exts(context, NULL,
			LWS_EXT_CB_CLIENT_CONTEXT_CONSTRUCT, NULL, 0) < 0)
			goto bail;

	return context;

bail:
	lws_context_destroy(context);
	return NULL;
}

/**
 * lws_context_destroy() - Destroy the websocket context
 * @context:	Websocket context
 *
 *	This function closes any active connections and then frees the
 *	context.  After calling this, any further use of the context is
 *	undefined.
 */
LWS_VISIBLE void
lws_context_destroy(struct lws_context *context)
{
	const struct lws_protocols *protocol = NULL;
	struct lws_context_per_thread *pt;
	struct lws_vhost *vh = NULL, *vh1;
	struct lws wsi;
	int n, m;

	lwsl_notice("%s\n", __func__);

	if (!context)
		return;

	m = context->count_threads;
	context->being_destroyed = 1;

	memset(&wsi, 0, sizeof(wsi));
	wsi.context = context;

#ifdef LWS_LATENCY
	if (context->worst_latency_info[0])
		lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
#endif

	while (m--) {
		pt = &context->pt[m];

		for (n = 0; (unsigned int)n < context->pt[m].fds_count; n++) {
			struct lws *wsi = wsi_from_fd(context, pt->fds[n].fd);
			if (!wsi)
				continue;

			lws_close_free_wsi(wsi,
				LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY
				/* no protocol close */);
			n--;
		}
		lws_pt_mutex_destroy(pt);
	}
	/*
	 * give all extensions a chance to clean up any per-context
	 * allocations they might have made
	 */

	n = lws_ext_cb_all_exts(context, NULL,
				LWS_EXT_CB_SERVER_CONTEXT_DESTRUCT, NULL, 0);

	n = lws_ext_cb_all_exts(context, NULL,
				LWS_EXT_CB_CLIENT_CONTEXT_DESTRUCT, NULL, 0);

	/*
	 * inform all the protocols that they are done and will have no more
	 * callbacks.
	 *
	 * We can't free things until after the event loop shuts down.
	 */
	if (context->protocol_init_done)
		vh = context->vhost_list;
	while (vh) {
		wsi.vhost = vh;
		protocol = vh->protocols;
		if (protocol) {
			n = 0;
			while (n < vh->count_protocols) {
				wsi.protocol = protocol;
				protocol->callback(&wsi, LWS_CALLBACK_PROTOCOL_DESTROY,
						   NULL, NULL, 0);
				protocol++;
				n++;
			}
		}

		vh = vh->vhost_next;
	}

	for (n = 0; n < context->count_threads; n++) {
		pt = &context->pt[n];

		lws_libev_destroyloop(context, n);
		lws_libuv_destroyloop(context, n);

		lws_free_set_NULL(context->pt[n].serv_buf);
		if (pt->ah_pool)
			lws_free(pt->ah_pool);
		if (pt->http_header_data)
			lws_free(pt->http_header_data);
	}
	lws_plat_context_early_destroy(context);
	lws_ssl_context_destroy(context);

	if (context->pt[0].fds)
		lws_free_set_NULL(context->pt[0].fds);

	/* free all the vhost allocations */

	vh = context->vhost_list;
	while (vh) {
		protocol = vh->protocols;
		if (protocol) {
			n = 0;
			while (n < vh->count_protocols) {
				if (vh->protocol_vh_privs &&
				    vh->protocol_vh_privs[n]) {
					lws_free(vh->protocol_vh_privs[n]);
					vh->protocol_vh_privs[n] = NULL;
				}
				protocol++;
				n++;
			}
		}
		if (vh->protocol_vh_privs)
			lws_free(vh->protocol_vh_privs);
		lws_ssl_SSL_CTX_destroy(vh);
		lws_free(vh->same_vh_protocol_list);
#ifdef LWS_WITH_PLUGINS
		if (context->plugin_list)
			lws_free((void *)vh->protocols);
#ifndef LWS_NO_EXTENSIONS
		if (context->plugin_extension_count)
			lws_free((void *)vh->extensions);
#endif
#endif
#ifdef LWS_WITH_ACCESS_LOG
		if (vh->log_fd != LWS_INVALID_FILE)
			close(vh->log_fd);
#endif

		vh1 = vh->vhost_next;
		lws_free(vh);
		vh = vh1;
	}

	lws_plat_context_late_destroy(context);

	lws_free(context);
}

Added undroid/libwebsockets/lib/daemonize.c.

























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
 * This code is mainly taken from Doug Potter's page
 *
 * http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize
 *
 * I contacted him 2007-04-16 about the license for the original code,
 * he replied it is Public Domain.  Use the URL above to get the original
 * Public Domain version if you want it.
 *
 * This version is LGPL2.1+SLE like the rest of libwebsockets and is
 * Copyright (c)2006 - 2013 Andy Green <andy@warmcat.com>
 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>

#include "private-libwebsockets.h"

int pid_daemon;
static char *lock_path;

int get_daemonize_pid()
{
	return pid_daemon;
}

static void
child_handler(int signum)
{
	int fd, len, sent;
	char sz[20];

	switch (signum) {

	case SIGALRM: /* timed out daemonizing */
		exit(0);
		break;

	case SIGUSR1: /* positive confirmation we daemonized well */
		/* Create the lock file as the current user */

		fd = open(lock_path, O_TRUNC | O_RDWR | O_CREAT, 0640);
		if (fd < 0) {
			fprintf(stderr,
			   "unable to create lock file %s, code=%d (%s)\n",
				lock_path, errno, strerror(errno));
			exit(5);
		}
		len = sprintf(sz, "%u", pid_daemon);
		sent = write(fd, sz, len);
		if (sent != len)
			fprintf(stderr,
			  "unable to write pid to lock file %s, code=%d (%s)\n",
					     lock_path, errno, strerror(errno));

		close(fd);
		exit(0);
		//!!(sent == len));

	case SIGCHLD: /* daemonization failed */
		exit(6);
		break;
	}
}

static void lws_daemon_closing(int sigact)
{
	if (getpid() == pid_daemon)
		if (lock_path) {
			unlink(lock_path);
			lws_free_set_NULL(lock_path);
		}

	kill(getpid(), SIGKILL);
}

/*
 * You just need to call this from your main(), when it
 * returns you are all set "in the background" decoupled
 * from the console you were started from.
 *
 * The process context you called from has been terminated then.
 */

LWS_VISIBLE int
lws_daemonize(const char *_lock_path)
{
	struct sigaction act;
	pid_t sid, parent;
	int n, fd, ret;
	char buf[10];

	/* already a daemon */
//	if (getppid() == 1)
//		return 1;

	fd = open(_lock_path, O_RDONLY);
	if (fd >= 0) {
		n = read(fd, buf, sizeof(buf));
		close(fd);
		if (n) {
			n = atoi(buf);
			ret = kill(n, 0);
			if (ret >= 0) {
				fprintf(stderr,
				     "Daemon already running from pid %d\n", n);
				exit(1);
			}
			fprintf(stderr,
			    "Removing stale lock file %s from dead pid %d\n",
								 _lock_path, n);
			unlink(lock_path);
		}
	}

	n = strlen(_lock_path) + 1;
	lock_path = lws_malloc(n);
	if (!lock_path) {
		fprintf(stderr, "Out of mem in lws_daemonize\n");
		return 1;
	}
	strcpy(lock_path, _lock_path);

	/* Trap signals that we expect to receive */
	signal(SIGCHLD, child_handler);	/* died */
	signal(SIGUSR1, child_handler); /* was happy */
	signal(SIGALRM, child_handler); /* timeout daemonizing */

	/* Fork off the parent process */
	pid_daemon = fork();
	if (pid_daemon < 0) {
		fprintf(stderr, "unable to fork daemon, code=%d (%s)",
		    errno, strerror(errno));
		exit(9);
	}

        /* If we got a good PID, then we can exit the parent process. */
	if (pid_daemon > 0) {

               /*
                * Wait for confirmation signal from the child via
                * SIGCHILD / USR1, or for two seconds to elapse
                * (SIGALRM).  pause() should not return.
                */
               alarm(2);

               pause();
               /* should not be reachable */
               exit(1);
       }

	/* At this point we are executing as the child process */
	parent = getppid();
	pid_daemon = getpid();

	/* Cancel certain signals */
	signal(SIGCHLD, SIG_DFL); /* A child process dies */
	signal(SIGTSTP, SIG_IGN); /* Various TTY signals */
	signal(SIGTTOU, SIG_IGN);
	signal(SIGTTIN, SIG_IGN);
	signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */

	/* Change the file mode mask */
	umask(0);

	/* Create a new SID for the child process */
	sid = setsid();
	if (sid < 0) {
		fprintf(stderr,
			"unable to create a new session, code %d (%s)",
			errno, strerror(errno));
		exit(2);
	}

	/*
	 * Change the current working directory.  This prevents the current
	 * directory from being locked; hence not being able to remove it.
	 */
	if (chdir("/tmp") < 0) {
		fprintf(stderr,
			"unable to change directory to %s, code %d (%s)",
			"/", errno, strerror(errno));
		exit(3);
	}

	/* Redirect standard files to /dev/null */
	if (!freopen("/dev/null", "r", stdin))
		fprintf(stderr, "unable to freopen() stdin, code %d (%s)",
						       errno, strerror(errno));

	if (!freopen("/dev/null", "w", stdout))
		fprintf(stderr, "unable to freopen() stdout, code %d (%s)",
						       errno, strerror(errno));

	if (!freopen("/dev/null", "w", stderr))
		fprintf(stderr, "unable to freopen() stderr, code %d (%s)",
						       errno, strerror(errno));

	/* Tell the parent process that we are A-okay */
	kill(parent, SIGUSR1);

	act.sa_handler = lws_daemon_closing;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;

	sigaction(SIGTERM, &act, NULL);

	/* return to continue what is now "the daemon" */

	return 0;
}

Added undroid/libwebsockets/lib/extension-permessage-deflate.c.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
/*
 * ./lib/extension-permessage-deflate.c
 *
 *  Copyright (C) 2016 Andy Green <andy@warmcat.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation:
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */

#include "private-libwebsockets.h"
#include "extension-permessage-deflate.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>

#define LWS_ZLIB_MEMLEVEL 8

const struct lws_ext_options lws_ext_pm_deflate_options[] = {
	/* public RFC7692 settings */
	{ "server_no_context_takeover", EXTARG_NONE },
	{ "client_no_context_takeover", EXTARG_NONE },
	{ "server_max_window_bits",	EXTARG_OPT_DEC },
	{ "client_max_window_bits",	EXTARG_OPT_DEC },
	/* ones only user code can set */
	{ "rx_buf_size",		EXTARG_DEC },
	{ "tx_buf_size",		EXTARG_DEC },
	{ "compression_level",		EXTARG_DEC },
	{ "mem_level",			EXTARG_DEC },
	{ NULL, 0 }, /* sentinel */
};

static void
lws_extension_pmdeflate_restrict_args(struct lws *wsi,
				      struct lws_ext_pm_deflate_priv *priv)
{
	int n, extra;

	/* cap the RX buf at the nearest power of 2 to protocol rx buf */

	n = LWS_MAX_SOCKET_IO_BUF;
	if (wsi->protocol->rx_buffer_size)
		n =  wsi->protocol->rx_buffer_size;

	extra = 7;
	while (n >= 1 << (extra + 1))
		extra++;

	if (extra < priv->args[PMD_RX_BUF_PWR2]) {
		priv->args[PMD_RX_BUF_PWR2] = extra;
		lwsl_err(" Capping pmd rx to %d\n", 1 << extra);
	}
}

LWS_VISIBLE int
lws_extension_callback_pm_deflate(struct lws_context *context,
				  const struct lws_extension *ext,
				  struct lws *wsi,
				  enum lws_extension_callback_reasons reason,
				  void *user, void *in, size_t len)
{
	struct lws_ext_pm_deflate_priv *priv =
				     (struct lws_ext_pm_deflate_priv *)user;
	struct lws_tokens *eff_buf = (struct lws_tokens *)in;
	static unsigned char trail[] = { 0, 0, 0xff, 0xff };
	int n, ret = 0, was_fin = 0, extra;
	struct lws_ext_option_arg *oa;

	switch (reason) {
	case LWS_EXT_CB_NAMED_OPTION_SET:
		oa = in;
		if (!oa->option_name)
			break;
		for (n = 0; n < ARRAY_SIZE(lws_ext_pm_deflate_options); n++)
			if (!strcmp(lws_ext_pm_deflate_options[n].name, oa->option_name))
				break;

		if (n == ARRAY_SIZE(lws_ext_pm_deflate_options))
			break;
		oa->option_index = n;

		/* fallthru */

	case LWS_EXT_CB_OPTION_SET:
		oa = in;
		lwsl_info("%s: option set: idx %d, %s, len %d\n", __func__,
			  oa->option_index, oa->start, oa->len);
		if (oa->start)
			priv->args[oa->option_index] = atoi(oa->start);
		else
			priv->args[oa->option_index] = 1;

		lws_extension_pmdeflate_restrict_args(wsi, priv);
		break;

	case LWS_EXT_CB_OPTION_CONFIRM:
		if (priv->args[PMD_SERVER_MAX_WINDOW_BITS] < 8 ||
		    priv->args[PMD_SERVER_MAX_WINDOW_BITS] > 15 ||
		    priv->args[PMD_CLIENT_MAX_WINDOW_BITS] < 8 ||
		    priv->args[PMD_CLIENT_MAX_WINDOW_BITS] > 15)
			return -1;
		break;

	case LWS_EXT_CB_CLIENT_CONSTRUCT:
	case LWS_EXT_CB_CONSTRUCT:

		n = LWS_MAX_SOCKET_IO_BUF;
		if (wsi->protocol->rx_buffer_size)
			n =  wsi->protocol->rx_buffer_size;

		if (n < 128) {
			lwsl_err(" permessage-deflate requires the protocol (%s) to have an RX buffer >= 128\n",
					wsi->protocol->name);
			return -1;
		}

		/* fill in **user */
		priv = lws_zalloc(sizeof(*priv));
		*((void **)user) = priv;
		lwsl_ext("%s: LWS_EXT_CB_*CONSTRUCT\n", __func__);
		memset(priv, 0, sizeof(*priv));

		/* fill in pointer to options list */
		if (in)
			*((const struct lws_ext_options **)in) =
					lws_ext_pm_deflate_options;

		/* fallthru */

	case LWS_EXT_CB_OPTION_DEFAULT:

		/* set the public, RFC7692 defaults... */

		priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER] = 0,
		priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER] = 0;
		priv->args[PMD_SERVER_MAX_WINDOW_BITS] = 15;
		priv->args[PMD_CLIENT_MAX_WINDOW_BITS] = 15;

		/* ...and the ones the user code can override */

		priv->args[PMD_RX_BUF_PWR2] = 10; /* ie, 1024 */
		priv->args[PMD_TX_BUF_PWR2] = 10; /* ie, 1024 */
		priv->args[PMD_COMP_LEVEL] = 1;
		priv->args[PMD_MEM_LEVEL] = 8;

		lws_extension_pmdeflate_restrict_args(wsi, priv);
		break;

	case LWS_EXT_CB_DESTROY:
		lwsl_ext("%s: LWS_EXT_CB_DESTROY\n", __func__);
		lws_free(priv->buf_rx_inflated);
		lws_free(priv->buf_tx_deflated);
		if (priv->rx_init)
			(void)inflateEnd(&priv->rx);
		if (priv->tx_init)
			(void)deflateEnd(&priv->tx);
		lws_free(priv);
		return ret;

	case LWS_EXT_CB_PAYLOAD_RX:
		lwsl_ext(" %s: LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d\n",
			 __func__, eff_buf->token_len, priv->rx.avail_in);
		if (!(wsi->u.ws.rsv_first_msg & 0x40))
			return 0;

#if 0
		for (n = 0; n < eff_buf->token_len; n++) {
			printf("%02X ", (unsigned char)eff_buf->token[n]);
			if ((n & 15) == 15)
				printf("\n");
		}
		printf("\n");
#endif
		if (!priv->rx_init)
			if (inflateInit2(&priv->rx, -priv->args[PMD_SERVER_MAX_WINDOW_BITS]) != Z_OK) {
				lwsl_err("%s: iniflateInit failed\n", __func__);
				return -1;
			}
		priv->rx_init = 1;
		if (!priv->buf_rx_inflated)
			priv->buf_rx_inflated = lws_malloc(LWS_PRE + 7 + 5 +
					    (1 << priv->args[PMD_RX_BUF_PWR2]));
		if (!priv->buf_rx_inflated) {
			lwsl_err("%s: OOM\n", __func__);
			return -1;
		}

		/*
		 * We have to leave the input stream alone if we didn't
		 * finish with it yet.  The input stream is held in the wsi
		 * rx buffer by the caller, so this assumption is safe while
		 * we block new rx while draining the existing rx
		 */
		if (eff_buf->token && eff_buf->token_len) {
			priv->rx.next_in = (unsigned char *)eff_buf->token;
			priv->rx.avail_in = eff_buf->token_len;
		}
		priv->rx.next_out = priv->buf_rx_inflated + LWS_PRE;
		eff_buf->token = (char *)priv->rx.next_out;
		priv->rx.avail_out = 1 << priv->args[PMD_RX_BUF_PWR2];

		if (priv->rx_held_valid) {
			lwsl_ext("-- RX piling on held byte --\n");
			*(priv->rx.next_out++) = priv->rx_held;
			priv->rx.avail_out--;
			priv->rx_held_valid = 0;
		}

		/* if...
		 *
		 *  - he has no remaining input content for this message, and
		 *  - and this is the final fragment, and
		 *  - we used everything that could be drained on the input side
		 *
		 * ...then put back the 00 00 FF FF the sender stripped as our
		 * input to zlib
		 */
		if (!priv->rx.avail_in && wsi->u.ws.final &&
		    !wsi->u.ws.rx_packet_length) {
			lwsl_ext("RX APPEND_TRAILER-DO\n");
			was_fin = 1;
			priv->rx.next_in = trail;
			priv->rx.avail_in = sizeof(trail);
		}

		n = inflate(&priv->rx, Z_NO_FLUSH);
		lwsl_ext("inflate ret %d, avi %d, avo %d, wsifinal %d\n", n,
			 priv->rx.avail_in, priv->rx.avail_out, wsi->u.ws.final);
		switch (n) {
		case Z_NEED_DICT:
		case Z_STREAM_ERROR:
		case Z_DATA_ERROR:
		case Z_MEM_ERROR:
			lwsl_info("zlib error inflate %d: %s\n",
				  n, priv->rx.msg);
			return -1;
		}
		/*
		 * If we did not already send in the 00 00 FF FF, and he's
		 * out of input, he did not EXACTLY fill the output buffer
		 * (which is ambiguous and we will force it to go around
		 * again by withholding a byte), and he's otherwise working on
		 * being a FIN fragment, then do the FIN message processing
		 * of faking up the 00 00 FF FF that the sender stripped.
		 */
		if (!priv->rx.avail_in && wsi->u.ws.final &&
		    !wsi->u.ws.rx_packet_length && !was_fin &&
		    priv->rx.avail_out /* ambiguous as to if it is the end */
		) {
			lwsl_ext("RX APPEND_TRAILER-DO\n");
			was_fin = 1;
			priv->rx.next_in = trail;
			priv->rx.avail_in = sizeof(trail);
			n = inflate(&priv->rx, Z_SYNC_FLUSH);
			lwsl_ext("RX trailer inf returned %d, avi %d, avo %d\n", n,
				 priv->rx.avail_in, priv->rx.avail_out);
			switch (n) {
			case Z_NEED_DICT:
			case Z_STREAM_ERROR:
			case Z_DATA_ERROR:
			case Z_MEM_ERROR:
				lwsl_info("zlib error inflate %d: %s\n",
					  n, priv->rx.msg);
				return -1;
			}
		}
		/*
		 * we must announce in our returncode now if there is more
		 * output to be expected from inflate, so we can decide to
		 * set the FIN bit on this bufferload or not.  However zlib
		 * is ambiguous when we exactly filled the inflate buffer.  It
		 * does not give us a clue as to whether we should understand
		 * that to mean he ended on a buffer boundary, or if there is
		 * more in the pipeline.
		 *
		 * So to work around that safely, if it used all output space
		 * exactly, we ALWAYS say there is more coming and we withhold
		 * the last byte of the buffer to guarantee that is true.
		 *
		 * That still leaves us at least one byte to finish with a FIN
		 * on, even if actually nothing more is coming from the next
		 * inflate action itself.
		 */
		if (!priv->rx.avail_out) { /* he used all available out buf */
			lwsl_ext("-- rx grabbing held --\n");
			/* snip the last byte and hold it for next time */
			priv->rx_held = *(--priv->rx.next_out);
			priv->rx_held_valid = 1;
		}

		eff_buf->token_len = (char *)priv->rx.next_out - eff_buf->token;
		priv->count_rx_between_fin += eff_buf->token_len;

		lwsl_ext("  %s: RX leaving with new effbuff len %d, "
			 "ret %d, rx.avail_in=%d, TOTAL RX since FIN %d\n",
			 __func__, eff_buf->token_len, priv->rx_held_valid,
			 priv->rx.avail_in, priv->count_rx_between_fin);

		if (was_fin) {
			priv->count_rx_between_fin = 0;
			if (priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER]) {
				(void)inflateEnd(&priv->rx);
				priv->rx_init = 0;
			}
		}
#if 0
		for (n = 0; n < eff_buf->token_len; n++)
			putchar(eff_buf->token[n]);
		puts("\n");
#endif

		return priv->rx_held_valid;

	case LWS_EXT_CB_PAYLOAD_TX:

		if (!priv->tx_init)
			if (deflateInit2(&priv->tx, priv->args[PMD_COMP_LEVEL],
					 Z_DEFLATED,
					 -priv->args[PMD_CLIENT_MAX_WINDOW_BITS +
						     !wsi->vhost->listen_port],
					 priv->args[PMD_MEM_LEVEL],
					 Z_DEFAULT_STRATEGY) != Z_OK) {
				lwsl_ext("inflateInit2 failed\n");
				return 1;
			}
		priv->tx_init = 1;
		if (!priv->buf_tx_deflated)
			priv->buf_tx_deflated = lws_malloc(LWS_PRE + 7 + 5 +
					    (1 << priv->args[PMD_TX_BUF_PWR2]));
		if (!priv->buf_tx_deflated) {
			lwsl_err("%s: OOM\n", __func__);
			return -1;
		}

		if (eff_buf->token) {
			lwsl_ext("%s: TX: eff_buf length %d\n", __func__,
				 eff_buf->token_len);
			priv->tx.next_in = (unsigned char *)eff_buf->token;
			priv->tx.avail_in = eff_buf->token_len;
		}

#if 0
		for (n = 0; n < eff_buf->token_len; n++) {
			printf("%02X ", (unsigned char)eff_buf->token[n]);
			if ((n & 15) == 15)
				printf("\n");
		}
		printf("\n");
#endif

		priv->tx.next_out = priv->buf_tx_deflated + LWS_PRE + 5;
		eff_buf->token = (char *)priv->tx.next_out;
		priv->tx.avail_out = 1 << priv->args[PMD_TX_BUF_PWR2];

		n = deflate(&priv->tx, Z_SYNC_FLUSH);
		if (n == Z_STREAM_ERROR) {
			lwsl_ext("%s: Z_STREAM_ERROR\n", __func__);
			return -1;
		}

		if (priv->tx_held_valid) {
			priv->tx_held_valid = 0;
			if (priv->tx.avail_out == 1 << priv->args[PMD_TX_BUF_PWR2])
				/*
				 * we can get a situation he took something in
				 * but did not generate anything out, at the end
				 * of a message (eg, next thing he sends is 80
				 * 00, a zero length FIN, like Authobahn can
				 * send).
				 * If we have come back as a FIN, we must not
				 * place the pending trailer 00 00 FF FF, just
				 * the 1 byte of live data
				 */
				*(--eff_buf->token) = priv->tx_held[0];
			else {
				/* he generated data, prepend whole pending */
				eff_buf->token -= 5;
				for (n = 0; n < 5; n++)
					eff_buf->token[n] = priv->tx_held[n];

			}
		}
		priv->compressed_out = 1;
		eff_buf->token_len = (int)(priv->tx.next_out -
					   (unsigned char *)eff_buf->token);

		/*
		 * we must announce in our returncode now if there is more
		 * output to be expected from inflate, so we can decide to
		 * set the FIN bit on this bufferload or not.  However zlib
		 * is ambiguous when we exactly filled the inflate buffer.  It
		 * does not give us a clue as to whether we should understand
		 * that to mean he ended on a buffer boundary, or if there is
		 * more in the pipeline.
		 *
		 * Worse, the guy providing the stuff we are sending may not
		 * know until after that this was, actually, the last chunk,
		 * that can happen even if we did not fill the output buf, ie
		 * he may send after this a zero-length FIN fragment.
		 *
		 * This is super difficult because we must snip the last 4
		 * bytes in the case this is the last compressed output of the
		 * message.  The only way to deal with it is defer sending the
		 * last 5 bytes of each frame until the next one, when we will
		 * be in a position to understand if that has a FIN or not.
		 */

		extra = !!(len & LWS_WRITE_NO_FIN) || !priv->tx.avail_out;

		if (eff_buf->token_len >= 4 + extra) {
			lwsl_ext("tx held %d\n", 4 + extra);
			priv->tx_held_valid = extra;
			for (n = 3 + extra; n >= 0; n--)
				priv->tx_held[n] = *(--priv->tx.next_out);
			eff_buf->token_len -= 4 + extra;
		}
		lwsl_ext("  TX rewritten with new effbuff len %d, ret %d\n",
			 eff_buf->token_len, !priv->tx.avail_out);

		return !priv->tx.avail_out; /* 1 == have more tx pending */

	case LWS_EXT_CB_PACKET_TX_PRESEND:
		if (!priv->compressed_out)
			break;
		priv->compressed_out = 0;

		if ((*(eff_buf->token) & 0x80) && priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER]) {
			(void)deflateEnd(&priv->tx);
			priv->tx_init = 0;
		}

		n = *(eff_buf->token) & 15;
		/* set RSV1, but not on CONTINUATION */
		if (n == LWSWSOPC_TEXT_FRAME || n == LWSWSOPC_BINARY_FRAME)
			*eff_buf->token |= 0x40;
#if 0
		for (n = 0; n < eff_buf->token_len; n++) {
			printf("%02X ", (unsigned char)eff_buf->token[n]);
			if ((n & 15) == 15)
				puts("\n");
		}
		puts("\n");
#endif
		lwsl_ext("%s: tx opcode 0x%02X\n", __func__,
			 (unsigned char)*eff_buf->token);
		break;

	default:
		break;
	}

	return 0;
}

Added undroid/libwebsockets/lib/extension-permessage-deflate.h.



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

#include <zlib.h>

#define DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER 1
#define DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT Z_DEFAULT_COMPRESSION

enum arg_indexes {
	PMD_SERVER_NO_CONTEXT_TAKEOVER,
	PMD_CLIENT_NO_CONTEXT_TAKEOVER,
	PMD_SERVER_MAX_WINDOW_BITS,
	PMD_CLIENT_MAX_WINDOW_BITS,
	PMD_RX_BUF_PWR2,
	PMD_TX_BUF_PWR2,
	PMD_COMP_LEVEL,
	PMD_MEM_LEVEL,

	PMD_ARG_COUNT
};

struct lws_ext_pm_deflate_priv {
	z_stream rx;
	z_stream tx;

	unsigned char *buf_rx_inflated; /* RX inflated output buffer */
	unsigned char *buf_tx_deflated; /* TX deflated output buffer */

	size_t count_rx_between_fin;

	unsigned char args[PMD_ARG_COUNT];
	unsigned char tx_held[5];
	unsigned char rx_held;

	unsigned char tx_init:1;
	unsigned char rx_init:1;
	unsigned char compressed_out:1;
	unsigned char rx_held_valid:1;
	unsigned char tx_held_valid:1;
	unsigned char rx_append_trailer:1;
	unsigned char pending_tx_trailer:1;
};

Added undroid/libwebsockets/lib/extension.c.



































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
#include "private-libwebsockets.h"

#include "extension-permessage-deflate.h"

LWS_VISIBLE void
lws_context_init_extensions(struct lws_context_creation_info *info,
			    struct lws_context *context)
{
	lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
}

enum lws_ext_option_parser_states {
	LEAPS_SEEK_NAME,
	LEAPS_EAT_NAME,
	LEAPS_SEEK_VAL,
	LEAPS_EAT_DEC,
	LEAPS_SEEK_ARG_TERM
};

LWS_VISIBLE int
lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
		      void *ext_user, const struct lws_ext_options *opts,
		      const char *in, int len)
{
	enum lws_ext_option_parser_states leap = LEAPS_SEEK_NAME;
	unsigned int match_map = 0, n, m, w = 0, count_options = 0,
		     pending_close_quote = 0;
	struct lws_ext_option_arg oa;

	oa.option_name = NULL;

	while (opts[count_options].name)
		count_options++;
	while (len) {
		lwsl_ext("'%c' %d", *in, leap);
		switch (leap) {
		case LEAPS_SEEK_NAME:
			if (*in == ' ')
				break;
			if (*in == ',') {
				len = 1;
				break;
			}
			match_map = (1 << count_options) - 1;
			leap = LEAPS_EAT_NAME;
			w = 0;

		/* fallthru */

		case LEAPS_EAT_NAME:
			oa.start = NULL;
			oa.len = 0;
			m = match_map;
			n = 0;
			pending_close_quote = 0;
			while (m) {
				if (m & 1) {
					lwsl_ext("    m=%d, n=%d, w=%d\n", m, n, w);

					if (*in == opts[n].name[w]) {
						if (!opts[n].name[w + 1]) {
							oa.option_index = n;
							lwsl_ext("hit %d\n", oa.option_index);
							leap = LEAPS_SEEK_VAL;
							if (len ==1)
								goto set_arg;
							break;
						}
					} else {
						match_map &= ~(1 << n);
						if (!match_map) {
							lwsl_ext("empty match map\n");
							return -1;
						}
					}
				}
				m >>= 1;
				n++;
			}
			w++;
			break;
		case LEAPS_SEEK_VAL:
			if (*in == ' ')
				break;
			if (*in == ',') {
				len = 1;
				break;
			}
			if (*in == ';' || len == 1) { /* ie,nonoptional */
				if (opts[oa.option_index].type == EXTARG_DEC)
					return -1;
				leap = LEAPS_SEEK_NAME;
				goto set_arg;
			}
			if (*in == '=') {
				w = 0;
				pending_close_quote = 0;
				if (opts[oa.option_index].type == EXTARG_NONE)
					return -1;

				leap = LEAPS_EAT_DEC;
				break;
			}
			return -1;

		case LEAPS_EAT_DEC:
			if (*in >= '0' && *in <= '9') {
				if (!w)
					oa.start = in;
				w++;
				if (len != 1)
					break;
			}
			if (!w && *in =='"') {
				pending_close_quote = 1;
				break;
			}
			if (!w)
				return -1;
			if (pending_close_quote && *in != '"' && len != 1)
				return -1;
			leap = LEAPS_SEEK_ARG_TERM;
			if (oa.start)
				oa.len = in - oa.start;
			if (len == 1)
				oa.len++;

set_arg:
			ext->callback(lws_get_context(wsi),
				ext, wsi, LWS_EXT_CB_OPTION_SET,
				ext_user, (char *)&oa, 0);
			if (len == 1)
				break;
			if (pending_close_quote && *in == '"')
				break;

			/* fallthru */

		case LEAPS_SEEK_ARG_TERM:
			if (*in == ' ')
				break;
			if (*in == ';') {
				leap = LEAPS_SEEK_NAME;
				break;
			}
			if (*in == ',') {
				len = 1;
				break;
			}
			return -1;
		}
		len--;
		in++;
	}

	return 0;
}


/* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */

int lws_ext_cb_active(struct lws *wsi, int reason, void *arg, int len)
{
	int n, m, handled = 0;

	for (n = 0; n < wsi->count_act_ext; n++) {
		m = wsi->active_extensions[n]->callback(lws_get_context(wsi),
			wsi->active_extensions[n], wsi, reason,
			wsi->act_ext_user[n], arg, len);
		if (m < 0) {
			lwsl_ext("Ext '%s' failed to handle callback %d!\n",
				 wsi->active_extensions[n]->name, reason);
			return -1;
		}
		/* valgrind... */
		if (reason == LWS_EXT_CB_DESTROY)
			wsi->act_ext_user[n] = NULL;
		if (m > handled)
			handled = m;
	}

	return handled;
}

int lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi,
			int reason, void *arg, int len)
{
	int n = 0, m, handled = 0;
	const struct lws_extension *ext;

	if (!wsi || !wsi->vhost)
		return 0;

	ext = wsi->vhost->extensions;

	while (ext && ext->callback && !handled) {
		m = ext->callback(context, ext, wsi, reason,
				  (void *)(long)n, arg, len);
		if (m < 0) {
			lwsl_ext("Ext '%s' failed to handle callback %d!\n",
				 wsi->active_extensions[n]->name, reason);
			return -1;
		}
		if (m)
			handled = 1;

		ext++;
		n++;
	}

	return 0;
}

int
lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len)
{
	struct lws_tokens eff_buf;
	int ret, m, n = 0;

	eff_buf.token = (char *)buf;
	eff_buf.token_len = len;

	/*
	 * while we have original buf to spill ourselves, or extensions report
	 * more in their pipeline
	 */

	ret = 1;
	while (ret == 1) {

		/* default to nobody has more to spill */

		ret = 0;

		/* show every extension the new incoming data */
		m = lws_ext_cb_active(wsi,
			       LWS_EXT_CB_PACKET_TX_PRESEND, &eff_buf, 0);
		if (m < 0)
			return -1;
		if (m) /* handled */
			ret = 1;

		if ((char *)buf != eff_buf.token)
			/*
			 * extension recreated it:
			 * need to buffer this if not all sent
			 */
			wsi->u.ws.clean_buffer = 0;

		/* assuming they left us something to send, send it */

		if (eff_buf.token_len) {
			n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
							    eff_buf.token_len);
			if (n < 0) {
				lwsl_info("closing from ext access\n");
				return -1;
			}

			/* always either sent it all or privately buffered */
			if (wsi->u.ws.clean_buffer)
				len = n;
		}

		lwsl_parser("written %d bytes to client\n", n);

		/* no extension has more to spill?  Then we can go */

		if (!ret)
			break;

		/* we used up what we had */

		eff_buf.token = NULL;
		eff_buf.token_len = 0;

		/*
		 * Did that leave the pipe choked?
		 * Or we had to hold on to some of it?
		 */

		if (!lws_send_pipe_choked(wsi) && !wsi->trunc_len)
			/* no we could add more, lets's do that */
			continue;

		lwsl_debug("choked\n");

		/*
		 * Yes, he's choked.  Don't spill the rest now get a callback
		 * when he is ready to send and take care of it there
		 */
		lws_callback_on_writable(wsi);
		wsi->extension_data_pending = 1;
		ret = 0;
	}

	return len;
}

int
lws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r,
			  void *v, size_t len)
{
	struct lws_context *context = wsi->context;
	int n, handled = 0;

	/* maybe an extension will take care of it for us */

	for (n = 0; n < wsi->count_act_ext && !handled; n++) {
		if (!wsi->active_extensions[n]->callback)
			continue;

		handled |= wsi->active_extensions[n]->callback(context,
			wsi->active_extensions[n], wsi,
			r, wsi->act_ext_user[n], v, len);
	}

	return handled;
}

/**
 * lws_set_extension_option(): set extension option if possible
 *
 * @wsi:	websocket connection
 * @ext_name:	name of ext, like "permessage-deflate"
 * @opt_name:	name of option, like "rx_buf_size"
 * @opt_val:	value to set option to
 */

int
lws_set_extension_option(struct lws *wsi, const char *ext_name,
			 const char *opt_name, const char *opt_val)
{
	struct lws_ext_option_arg oa;
	int idx = 0;

	/* first identify if the ext is active on this wsi */
	while (idx < wsi->count_act_ext &&
	       strcmp(wsi->active_extensions[idx]->name, ext_name))
		idx++;

	if (idx == wsi->count_act_ext)
		return -1; /* request ext not active on this wsi */

	oa.option_name = opt_name;
	oa.option_index = 0;
	oa.start = opt_val;
	oa.len = 0;

	return wsi->active_extensions[idx]->callback(
			wsi->context, wsi->active_extensions[idx], wsi,
			LWS_EXT_CB_NAMED_OPTION_SET, wsi->act_ext_user[idx], &oa, 0);
}

Added undroid/libwebsockets/lib/getifaddrs.c.

































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*
 * downloaded from
 * http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c
 */
#if !LWS_HAVE_GETIFADDRS
/*
 * Copyright (c) 2000 - 2001 Kungliga Tekniska H�gskolan
 * (Royal Institute of Technology, Stockholm, Sweden).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "private-libwebsockets.h"

#ifdef LWS_HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif

#ifdef LWS_HAVE_NETINET_IN6_VAR_H
#include <netinet/in6_var.h>
#endif

#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif

#include "getifaddrs.h"

static int
getifaddrs2(struct ifaddrs **ifap, int af, int siocgifconf, int siocgifflags,
	    size_t ifreq_sz)
{
	int ret;
	int fd;
	size_t buf_size;
	char *buf;
	struct ifconf ifconf;
	char *p;
	size_t sz;
	struct sockaddr sa_zero;
	struct ifreq *ifr;
	struct ifaddrs *start,  **end = &start;

	buf = NULL;

	memset(&sa_zero, 0, sizeof(sa_zero));
	fd = socket(af, SOCK_DGRAM, 0);
	if (fd < 0)
		return -1;

	buf_size = 8192;
	for (;;) {
		buf = lws_zalloc(buf_size);
		if (buf == NULL) {
			ret = ENOMEM;
			goto error_out;
		}
		ifconf.ifc_len = buf_size;
		ifconf.ifc_buf = buf;

		/*
		 * Solaris returns EINVAL when the buffer is too small.
		 */
		if (ioctl(fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
			ret = errno;
			goto error_out;
		}
		/*
		 * Can the difference between a full and a overfull buf
		 * be determined?
		 */

		if (ifconf.ifc_len < (int)buf_size)
			break;
		lws_free(buf);
		buf_size *= 2;
	}

	for (p = ifconf.ifc_buf; p < ifconf.ifc_buf + ifconf.ifc_len; p += sz) {
		struct ifreq ifreq;
		struct sockaddr *sa;
		size_t salen;

		ifr = (struct ifreq *)p;
		sa  = &ifr->ifr_addr;

		sz = ifreq_sz;
		salen = sizeof(struct sockaddr);
#ifdef LWS_HAVE_STRUCT_SOCKADDR_SA_LEN
		salen = sa->sa_len;
		sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
#endif
#ifdef SA_LEN
		salen = SA_LEN(sa);
		sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
#endif
		memset(&ifreq, 0, sizeof(ifreq));
		memcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));

		if (ioctl(fd, siocgifflags, &ifreq) < 0) {
			ret = errno;
			goto error_out;
		}

		*end = lws_malloc(sizeof(**end));

		(*end)->ifa_next = NULL;
		(*end)->ifa_name = strdup(ifr->ifr_name);
		(*end)->ifa_flags = ifreq.ifr_flags;
		(*end)->ifa_addr = lws_malloc(salen);
		memcpy((*end)->ifa_addr, sa, salen);
		(*end)->ifa_netmask = NULL;

#if 0
		/* fix these when we actually need them */
		if (ifreq.ifr_flags & IFF_BROADCAST) {
			(*end)->ifa_broadaddr =
				lws_malloc(sizeof(ifr->ifr_broadaddr));
			memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr,
						    sizeof(ifr->ifr_broadaddr));
		} else if (ifreq.ifr_flags & IFF_POINTOPOINT) {
			(*end)->ifa_dstaddr =
				lws_malloc(sizeof(ifr->ifr_dstaddr));
			memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr,
						      sizeof(ifr->ifr_dstaddr));
		} else
			(*end)->ifa_dstaddr = NULL;
#else
		(*end)->ifa_dstaddr = NULL;
#endif
		(*end)->ifa_data = NULL;

		end = &(*end)->ifa_next;

	}
	*ifap = start;
	close(fd);
	lws_free(buf);
	return 0;

error_out:
	close(fd);
	lws_free(buf);
	errno = ret;

	return -1;
}

int
getifaddrs(struct ifaddrs **ifap)
{
	int ret = -1;
	errno = ENXIO;
#if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
	if (ret)
		ret = getifaddrs2(ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
			   sizeof(struct in6_ifreq));
#endif
#if defined(LWS_HAVE_IPV6) && defined(SIOCGIFCONF)
	if (ret)
		ret = getifaddrs2(ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
			   sizeof(struct ifreq));
#endif
#if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
	if (ret)
		ret = getifaddrs2(ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
			   sizeof(struct ifreq));
#endif
	return ret;
}

void
freeifaddrs(struct ifaddrs *ifp)
{
	struct ifaddrs *p, *q;

	for (p = ifp; p; ) {
		lws_free(p->ifa_name);
		lws_free(p->ifa_addr);
		lws_free(p->ifa_dstaddr);
		lws_free(p->ifa_netmask);
		lws_free(p->ifa_data);
		q = p;
		p = p->ifa_next;
		lws_free(q);
	}
}

#ifdef TEST

void
print_addr(const char *s, struct sockaddr *sa)
{
	int i;
	printf("  %s=%d/", s, sa->sa_family);
#ifdef LWS_HAVE_STRUCT_SOCKADDR_SA_LEN
	for (i = 0;
	       i < sa->sa_len - ((long)sa->sa_data - (long)&sa->sa_family); i++)
		printf("%02x", ((unsigned char *)sa->sa_data)[i]);
#else
	for (i = 0; i < sizeof(sa->sa_data); i++)
		printf("%02x", ((unsigned char *)sa->sa_data)[i]);
#endif
	printf("\n");
}

void
print_ifaddrs(struct ifaddrs *x)
{
	struct ifaddrs *p;

	for (p = x; p; p = p->ifa_next) {
		printf("%s\n", p->ifa_name);
		printf("  flags=%x\n", p->ifa_flags);
		if (p->ifa_addr)
			print_addr("addr", p->ifa_addr);
		if (p->ifa_dstaddr)
			print_addr("dstaddr", p->ifa_dstaddr);
		if (p->ifa_netmask)
			print_addr("netmask", p->ifa_netmask);
		printf("  %p\n", p->ifa_data);
	}
}

int
main()
{
	struct ifaddrs *a = NULL, *b;
	getifaddrs2(&a, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
		    sizeof(struct ifreq));
	print_ifaddrs(a);
	printf("---\n");
	getifaddrs(&b);
	print_ifaddrs(b);
	return 0;
}
#endif
#endif

Added undroid/libwebsockets/lib/getifaddrs.h.

























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#if LWS_HAVE_GETIFADDRS
#include <sys/types.h>
#include <ifaddrs.h>
#else
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Copyright (c) 2000 Kungliga Tekniska H�gskolan
 * (Royal Institute of Technology, Stockholm, Sweden).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/* $KTH: ifaddrs.hin,v 1.3 2000/12/11 00:01:13 assar Exp $ */

#ifndef ifaddrs_h_7467027A95AD4B5C8DDD40FE7D973791
#define ifaddrs_h_7467027A95AD4B5C8DDD40FE7D973791

/*
 * the interface is defined in terms of the fields below, and this is
 * sometimes #define'd, so there seems to be no simple way of solving
 * this and this seemed the best. */

#undef ifa_dstaddr

struct ifaddrs {
	struct ifaddrs *ifa_next;
	char *ifa_name;
	unsigned int ifa_flags;
	struct sockaddr *ifa_addr;
	struct sockaddr *ifa_netmask;
	struct sockaddr *ifa_dstaddr;
	void *ifa_data;
};

#ifndef ifa_broadaddr
#define ifa_broadaddr ifa_dstaddr
#endif

int getifaddrs(struct ifaddrs **);

void freeifaddrs(struct ifaddrs *);

#endif /* __ifaddrs_h__ */

#ifdef __cplusplus
}
#endif
#endif

Added undroid/libwebsockets/lib/handshake.c.























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/*
 * libwebsockets - small server side websockets and web server implementation
 *
 * Copyright (C) 2010-2015 Andy Green <andy@warmcat.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation:
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */

#include "private-libwebsockets.h"

/*
 * -04 of the protocol (actually the 80th version) has a radically different
 * handshake.  The 04 spec gives the following idea
 *
 *    The handshake from the client looks as follows:
 *
 *      GET /chat HTTP/1.1
 *      Host: server.example.com
 *      Upgrade: websocket
 *      Connection: Upgrade
 *      Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
 *      Sec-WebSocket-Origin: http://example.com
 *      Sec-WebSocket-Protocol: chat, superchat
 *	Sec-WebSocket-Version: 4
 *
 *  The handshake from the server looks as follows:
 *
 *       HTTP/1.1 101 Switching Protocols
 *       Upgrade: websocket
 *       Connection: Upgrade
 *       Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
 *       Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
 *       Sec-WebSocket-Protocol: chat
 */

#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif

/*
 * We have to take care about parsing because the headers may be split
 * into multiple fragments.  They may contain unknown headers with arbitrary
 * argument lengths.  So, we parse using a single-character at a time state
 * machine that is completely independent of packet size.
 *
 * Returns <0 for error or length of chars consumed from buf (up to len)
 */

LWS_VISIBLE int
lws_read(struct lws *wsi, unsigned char *buf, size_t len)
{
	unsigned char *last_char, *oldbuf = buf;
	int body_chunk_len;
	size_t n;

	lwsl_debug("%s: incoming len %d  state %d\n", __func__, (int)len, wsi->state);

	switch (wsi->state) {
#ifdef LWS_USE_HTTP2
	case LWSS_HTTP2_AWAIT_CLIENT_PREFACE:
	case LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS:
	case LWSS_HTTP2_ESTABLISHED:
		n = 0;
		while (n < len) {
			/*
			 * we were accepting input but now we stopped doing so
			 */
			if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
				lws_rxflow_cache(wsi, buf, n, len);

				return 1;
			}

			/* account for what we're using in rxflow buffer */
			if (wsi->rxflow_buffer)
				wsi->rxflow_pos++;
			if (lws_http2_parser(wsi, buf[n++])) {
				lwsl_debug("%s: http2_parser bailed\n", __func__);
				goto bail;
			}
		}
		break;
#endif

	case LWSS_CLIENT_HTTP_ESTABLISHED:
		break;

	case LWSS_HTTP:
		wsi->hdr_parsing_completed = 0;
		/* fallthru */
	case LWSS_HTTP_ISSUING_FILE:
		wsi->state = LWSS_HTTP_HEADERS;
		wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
		wsi->u.hdr.lextable_pos = 0;
		/* fallthru */
	case LWSS_HTTP_HEADERS:
		if (!wsi->u.hdr.ah) {
			lwsl_err("%s: LWSS_HTTP_HEADERS: NULL ah\n", __func__);
			assert(0);
		}
		lwsl_parser("issuing %d bytes to parser\n", (int)len);

		if (lws_handshake_client(wsi, &buf, len))
			goto bail;

		last_char = buf;
		if (lws_handshake_server(wsi, &buf, len))
			/* Handshake indicates this session is done. */
			goto bail;

		/*
		 * It's possible that we've exhausted our data already, or
		 * rx flow control has stopped us dealing with this early,
		 * but lws_handshake_server doesn't update len for us.
		 * Figure out how much was read, so that we can proceed
		 * appropriately:
		 */
		len -= (buf - last_char);
		lwsl_debug("%s: thinks we have used %d\n", __func__, len);

		if (!wsi->hdr_parsing_completed)
			/* More header content on the way */
			goto read_ok;

		switch (wsi->state) {
			case LWSS_HTTP:
			case LWSS_HTTP_HEADERS:
				goto read_ok;
			case LWSS_HTTP_ISSUING_FILE:
				goto read_ok;
			case LWSS_HTTP_BODY:
				wsi->u.http.content_remain =
						wsi->u.http.content_length;
				if (wsi->u.http.content_remain)
					goto http_postbody;

				/* there is no POST content */
				goto postbody_completion;
			default:
				break;
		}
		break;

	case LWSS_HTTP_BODY:
http_postbody:
		while (len && wsi->u.http.content_remain) {
			/* Copy as much as possible, up to the limit of:
			 * what we have in the read buffer (len)
			 * remaining portion of the POST body (content_remain)
			 */
			body_chunk_len = min(wsi->u.http.content_remain,len);
			wsi->u.http.content_remain -= body_chunk_len;
			len -= body_chunk_len;
#ifdef LWS_WITH_CGI
			if (wsi->cgi) {
				struct lws_cgi_args args;

				args.ch = LWS_STDIN;
				args.stdwsi = &wsi->cgi->stdwsi[0];
				args.data = buf;
				args.len = body_chunk_len;

				/* returns how much used */
				n = user_callback_handle_rxflow(
					wsi->protocol->callback,
					wsi, LWS_CALLBACK_CGI_STDIN_DATA,
					wsi->user_space,
					(void *)&args, 0);
				if ((int)n < 0)
					goto bail;
			} else {
#endif
				n = wsi->protocol->callback(wsi,
					LWS_CALLBACK_HTTP_BODY, wsi->user_space,
					buf, body_chunk_len);
				if (n)
					goto bail;
				n = body_chunk_len;
#ifdef LWS_WITH_CGI
			}
#endif
			buf += n;

			if (wsi->u.http.content_remain)  {
				lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
						wsi->context->timeout_secs);
				break;
			}
			/* he sent all the content in time */
postbody_completion:
			lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
#ifdef LWS_WITH_CGI
			if (!wsi->cgi)
#endif
			{
				n = wsi->protocol->callback(wsi,
					LWS_CALLBACK_HTTP_BODY_COMPLETION,
					wsi->user_space, NULL, 0);
				if (n)
					goto bail;
			}

			break;
		}
		break;

	case LWSS_ESTABLISHED:
	case LWSS_AWAITING_CLOSE_ACK:
	case LWSS_SHUTDOWN:
		if (lws_handshake_client(wsi, &buf, len))
			goto bail;
		switch (wsi->mode) {
		case LWSCM_WS_SERVING:

			if (lws_interpret_incoming_packet(wsi, &buf, len) < 0) {
				lwsl_info("interpret_incoming_packet has bailed\n");
				goto bail;
			}
			break;
		}
		break;
	default:
		lwsl_err("%s: Unhandled state %d\n", __func__, wsi->state);
		break;
	}

read_ok:
	/* Nothing more to do for now */
	lwsl_info("%s: read_ok, used %d\n", __func__, buf - oldbuf);

	return buf - oldbuf;

bail:
	lwsl_debug("closing connection at lws_read bail:\n");
	lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);

	return -1;
}

Added undroid/libwebsockets/lib/header.c.













































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/*
 * libwebsockets - small server side websockets and web server implementation
 *
 * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation:
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */

#include "private-libwebsockets.h"
#include "lextable-strings.h"

const unsigned char *lws_token_to_string(enum lws_token_indexes token)
{
	if ((unsigned int)token >= ARRAY_SIZE(set))
		return NULL;

	return (unsigned char *)set[token];
}

int
lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name,
			    const unsigned char *value, int length,
			    unsigned char **p, unsigned char *end)
{
#ifdef LWS_USE_HTTP2
	if (wsi->mode == LWSCM_HTTP2_SERVING)
		return lws_add_http2_header_by_name(wsi, name,
						    value, length, p, end);
#else
	(void)wsi;
#endif
	if (name) {
		while (*p < end && *name)
			*((*p)++) = *name++;
		if (*p == end)
			return 1;
		*((*p)++) = ' ';
	}
	if (*p + length + 3 >= end)
		return 1;

	memcpy(*p, value, length);
	*p += length;
	*((*p)++) = '\x0d';
	*((*p)++) = '\x0a';

	return 0;
}

int lws_finalize_http_header(struct lws *wsi, unsigned char **p,
			     unsigned char *end)
{
#ifdef LWS_USE_HTTP2
	if (wsi->mode == LWSCM_HTTP2_SERVING)
		return 0;
#else
	(void)wsi;
#endif
	if ((long)(end - *p) < 3)
		return 1;
	*((*p)++) = '\x0d';
	*((*p)++) = '\x0a';

	return 0;
}

int
lws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token,
			     const unsigned char *value, int length,
			     unsigned char **p, unsigned char *end)
{
	const unsigned char *name;
#ifdef LWS_USE_HTTP2
	if (wsi->mode == LWSCM_HTTP2_SERVING)
		return lws_add_http2_header_by_token(wsi, token, value, length, p, end);
#endif
	name = lws_token_to_string(token);
	if (!name)
		return 1;
	return lws_add_http_header_by_name(wsi, name, value, length, p, end);
}

int lws_add_http_header_content_length(struct lws *wsi,
				       unsigned long content_length,
				       unsigned char **p, unsigned char *end)
{
	char b[24];
	int n;

	n = sprintf(b, "%lu", content_length);
	if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
					 (unsigned char *)b, n, p, end))
		return 1;
	wsi->u.http.content_length = content_length;
	wsi->u.http.content_remain = content_length;

	return 0;
}

static const char *err400[] = {
	"Bad Request",
	"Unauthorized",
	"Payment Required",
	"Forbidden",
	"Not Found",
	"Method Not Allowed",
	"Not Acceptable",
	"Proxy Auth Required",
	"Request Timeout",
	"Conflict",
	"Gone",
	"Length Required",
	"Precondition Failed",
	"Request Entity Too Large",
	"Request URI too Long",
	"Unsupported Media Type",
	"Requested Range Not Satisfiable",
	"Expectation Failed"
};

static const char *err500[] = {
	"Internal Server Error",
	"Not Implemented",
	"Bad Gateway",
	"Service Unavailable",
	"Gateway Timeout",
	"HTTP Version Not Supported"
};

int
lws_add_http_header_status(struct lws *wsi, unsigned int code,
			   unsigned char **p, unsigned char *end)
{
	unsigned char code_and_desc[60];
	const char *description = "", *p1;
	int n;
	static const char * const hver[] = {
		"HTTP/1.0", "HTTP/1.1", "HTTP/2"
	};

#ifdef LWS_WITH_ACCESS_LOG
	wsi->access_log.response = code;
#endif

#ifdef LWS_USE_HTTP2
	if (wsi->mode == LWSCM_HTTP2_SERVING)
		return lws_add_http2_header_status(wsi, code, p, end);
#endif
	if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
		description = err400[code - 400];
	if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
		description = err500[code - 500];

	if (code == 200)
		description = "OK";

	if (code == 304)
		description = "Not Modified";
	else
		if (code >= 300 && code < 400)
			description = "Redirect";

	if (wsi->u.http.request_version < ARRAY_SIZE(hver))
		p1 = hver[wsi->u.http.request_version];
	else
		p1 = hver[0];

	n = sprintf((char *)code_and_desc, "%s %u %s",
		    p1, code, description);

	if (lws_add_http_header_by_name(wsi, NULL, code_and_desc,
					   n, p, end))
		return 1;

	if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,
					 (unsigned char *)
					 	 wsi->context->server_string,
					 wsi->context->server_string_len,
					 p, end))
		return 1;

	if (wsi->vhost->options & LWS_SERVER_OPTION_STS)
		if (lws_add_http_header_by_name(wsi, (unsigned char *)
				"Strict-Transport-Security:",
				(unsigned char *)"max-age=15768000 ; "
				"includeSubDomains", 36, p, end))
			return 1;

	return 0;
}

/**
 * lws_return_http_status() - Return simple http status
 * @wsi:		Websocket instance (available from user callback)
 * @code:		Status index, eg, 404
 * @html_body:		User-readable HTML description < 1KB, or NULL
 *
 *	Helper to report HTTP errors back to the client cleanly and
 *	consistently
 */
LWS_VISIBLE int
lws_return_http_status(struct lws *wsi, unsigned int code,
		       const char *html_body)
{
	struct lws_context *context = lws_get_context(wsi);
	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
	unsigned char *p = pt->serv_buf + LWS_PRE;
	unsigned char *start = p, *body = p + 512;
	unsigned char *end = p + LWS_MAX_SOCKET_IO_BUF - LWS_PRE;
	int n, m, len;
	char slen[20];

	if (!html_body)
		html_body = "";

	len = sprintf((char *)body, "<html><body><h1>%u</h1>%s</body></html>",
		      code, html_body);

	if (lws_add_http_header_status(wsi, code, &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;
	n = sprintf(slen, "%d", len);
	if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
					 (unsigned char *)slen, n,
					 &p, end))
		return 1;

	if (lws_finalize_http_header(wsi, &p, end))
		return 1;

	m = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
	if (m != (int)(p - start))
		return 1;

	m = lws_write(wsi, body, len, LWS_WRITE_HTTP);

	return m != n;
}

LWS_VISIBLE int
lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len,
		  unsigned char **p, unsigned char *end)
{
	unsigned char *start = *p;
	int n;

	if (lws_add_http_header_status(wsi, code, p, end))
		return -1;

	if (lws_add_http_header_by_token(wsi,
			WSI_TOKEN_HTTP_LOCATION,
			loc, len, p, end))
		return -1;
	/*
	 * if we're going with http/1.1 and keepalive,
	 * we have to give fake content metadata so the
	 * client knows we completed the transaction and
	 * it can do the redirect...
	 */
	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_by_token(wsi,
			WSI_TOKEN_HTTP_CONTENT_LENGTH,
			(unsigned char *)"0", 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);

	return n;
}

Added undroid/libwebsockets/lib/hpack.c.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
/*
 * lib/hpack.c
 *
 * Copyright (C) 2014 Andy Green <andy@warmcat.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation:
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */

#include "private-libwebsockets.h"

/*
 * Official static header table for HPACK
 *        +-------+-----------------------------+---------------+
          | 1     | :authority                  |               |
          | 2     | :method                     | GET           |
          | 3     | :method                     | POST          |
          | 4     | :path                       | /             |
          | 5     | :path                       | /index.html   |
          | 6     | :scheme                     | http          |
          | 7     | :scheme                     | https         |
          | 8     | :status                     | 200           |
          | 9     | :status                     | 204           |
          | 10    | :status                     | 206           |
          | 11    | :status                     | 304           |
          | 12    | :status                     | 400           |
          | 13    | :status                     | 404           |
          | 14    | :status                     | 500           |
          | 15    | accept-charset              |               |
          | 16    | accept-encoding             | gzip, deflate |
          | 17    | accept-language             |               |
          | 18    | accept-ranges               |               |
          | 19    | accept                      |               |
          | 20    | access-control-allow-origin |               |
          | 21    | age                         |               |
          | 22    | allow                       |               |
          | 23    | authorization               |               |
          | 24    | cache-control               |               |
          | 25    | content-disposition         |               |
          | 26    | content-encoding            |               |
          | 27    | content-language            |               |
          | 28    | content-length              |               |
          | 29    | content-location            |               |
          | 30    | content-range               |               |
          | 31    | content-type                |               |
          | 32    | cookie                      |               |
          | 33    | date                        |               |
          | 34    | etag                        |               |
          | 35    | expect                      |               |
          | 36    | expires                     |               |
          | 37    | from                        |               |
          | 38    | host                        |               |
          | 39    | if-match                    |               |
          | 40    | if-modified-since           |               |
          | 41    | if-none-match               |               |
          | 42    | if-range                    |               |
          | 43    | if-unmodified-since         |               |
          | 44    | last-modified               |               |
          | 45    | link                        |               |
          | 46    | location                    |               |
          | 47    | max-forwards                |               |
          | 48    | proxy-authenticate          |               |
          | 49    | proxy-authorization         |               |
          | 50    | range                       |               |
          | 51    | referer                     |               |
          | 52    | refresh                     |               |
          | 53    | retry-after                 |               |
          | 54    | server                      |               |
          | 55    | set-cookie                  |               |
          | 56    | strict-transport-security   |               |
          | 57    | transfer-encoding           |               |
          | 58    | user-agent                  |               |
          | 59    | vary                        |               |
          | 60    | via                         |               |
          | 61    | www-authenticate            |               |
          +-------+-----------------------------+---------------+
*/

static const unsigned char static_token[] = {
	0,
	WSI_TOKEN_HTTP_COLON_AUTHORITY,
	WSI_TOKEN_HTTP_COLON_METHOD,
	WSI_TOKEN_HTTP_COLON_METHOD,
	WSI_TOKEN_HTTP_COLON_PATH,
	WSI_TOKEN_HTTP_COLON_PATH,
	WSI_TOKEN_HTTP_COLON_SCHEME,
	WSI_TOKEN_HTTP_COLON_SCHEME,
	WSI_TOKEN_HTTP_COLON_STATUS,
	WSI_TOKEN_HTTP_COLON_STATUS,
	WSI_TOKEN_HTTP_COLON_STATUS,
	WSI_TOKEN_HTTP_COLON_STATUS,
	WSI_TOKEN_HTTP_COLON_STATUS,
	WSI_TOKEN_HTTP_COLON_STATUS,
	WSI_TOKEN_HTTP_COLON_STATUS,
	WSI_TOKEN_HTTP_ACCEPT_CHARSET,
	WSI_TOKEN_HTTP_ACCEPT_ENCODING,
	WSI_TOKEN_HTTP_ACCEPT_LANGUAGE,
	WSI_TOKEN_HTTP_ACCEPT_RANGES,
	WSI_TOKEN_HTTP_ACCEPT,
	WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN,
	WSI_TOKEN_HTTP_AGE,
	WSI_TOKEN_HTTP_ALLOW,
	WSI_TOKEN_HTTP_AUTHORIZATION,
	WSI_TOKEN_HTTP_CACHE_CONTROL,
	WSI_TOKEN_HTTP_CONTENT_DISPOSITION,
	WSI_TOKEN_HTTP_CONTENT_ENCODING,
	WSI_TOKEN_HTTP_CONTENT_LANGUAGE,
	WSI_TOKEN_HTTP_CONTENT_LENGTH,
	WSI_TOKEN_HTTP_CONTENT_LOCATION,
	WSI_TOKEN_HTTP_CONTENT_RANGE,
	WSI_TOKEN_HTTP_CONTENT_TYPE,
	WSI_TOKEN_HTTP_COOKIE,
	WSI_TOKEN_HTTP_DATE,
	WSI_TOKEN_HTTP_ETAG,
	WSI_TOKEN_HTTP_EXPECT,
	WSI_TOKEN_HTTP_EXPIRES,
	WSI_TOKEN_HTTP_FROM,
	WSI_TOKEN_HOST,
	WSI_TOKEN_HTTP_IF_MATCH,
	WSI_TOKEN_HTTP_IF_MODIFIED_SINCE,
	WSI_TOKEN_HTTP_IF_NONE_MATCH,
	WSI_TOKEN_HTTP_IF_RANGE,
	WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE,
	WSI_TOKEN_HTTP_LAST_MODIFIED,
	WSI_TOKEN_HTTP_LINK,
	WSI_TOKEN_HTTP_LOCATION,
	WSI_TOKEN_HTTP_MAX_FORWARDS,
	WSI_TOKEN_HTTP_PROXY_AUTHENTICATE,
	WSI_TOKEN_HTTP_PROXY_AUTHORIZATION,
	WSI_TOKEN_HTTP_RANGE,
	WSI_TOKEN_HTTP_REFERER,
	WSI_TOKEN_HTTP_REFRESH,
	WSI_TOKEN_HTTP_RETRY_AFTER,
	WSI_TOKEN_HTTP_SERVER,
	WSI_TOKEN_HTTP_SET_COOKIE,
	WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY,
	WSI_TOKEN_HTTP_TRANSFER_ENCODING,
	WSI_TOKEN_HTTP_USER_AGENT,
	WSI_TOKEN_HTTP_VARY,
	WSI_TOKEN_HTTP_VIA,
	WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
};

/* some of the entries imply values as well as header names */

static const char * const http2_canned[] = {
	"",
	"",
	"GET",
	"POST",
	"/",
	"/index.html",
	"http",
	"https",
	"200",
	"204",
	"206",
	"304",
	"400",
	"404",
	"500",
	"",
	"gzip, deflate"
};

/* see minihuf.c */

#include "huftable.h"

static int huftable_decode(int pos, char c)
{
	int q = pos + !!c;

	if (lextable_terms[q >> 3] & (1 << (q & 7))) /* terminal */
		return lextable[q] | 0x8000;

	return pos + (lextable[q] << 1);
}

static int lws_hpack_update_table_size(struct lws *wsi, int idx)
{
	lwsl_info("hpack set table size %d\n", idx);
	return 0;
}

static int lws_frag_start(struct lws *wsi, int hdr_token_idx)
{
	struct allocated_headers * ah = wsi->u.http2.http.ah;

	if (!hdr_token_idx) {
		lwsl_err("%s: zero hdr_token_idx\n", __func__);
		return 1;
	}

	if (ah->nfrag >= ARRAY_SIZE(ah->frag_index)) {
		lwsl_err("%s: frag index %d too big\n", __func__, ah->nfrag);
		return 1;
	}

	ah->frags[ah->nfrag].offset = ah->pos;
	ah->frags[ah->nfrag].len = 0;
	ah->frags[ah->nfrag].nfrag = 0;

	ah->frag_index[hdr_token_idx] = ah->nfrag;

	return 0;
}

static int lws_frag_append(struct lws *wsi, unsigned char c)
{
	struct allocated_headers * ah = wsi->u.http2.http.ah;

	ah->data[ah->pos++] = c;
	ah->frags[ah->nfrag].len++;

	return ah->pos >= wsi->context->max_http_header_data;
}

static int lws_frag_end(struct lws *wsi)
{
	if (lws_frag_append(wsi, 0))
		return 1;

	wsi->u.http2.http.ah->nfrag++;
	return 0;
}

static void lws_dump_header(struct lws *wsi, int hdr)
{
	char s[200];
	int len = lws_hdr_copy(wsi, s, sizeof(s) - 1, hdr);
	s[len] = '\0';
	lwsl_info("  hdr tok %d (%s) = '%s'\n", hdr, lws_token_to_string(hdr), s);
}

static int
lws_token_from_index(struct lws *wsi, int index, char **arg, int *len)
{
	struct hpack_dynamic_table *dyn;

	/* dynamic table only belongs to network wsi */

	wsi = lws_http2_get_network_wsi(wsi);

	dyn = wsi->u.http2.hpack_dyn_table;

	if (index < ARRAY_SIZE(static_token))
		return static_token[index];

	if (!dyn)
		return 0;

	index -= ARRAY_SIZE(static_token);
	if (index >= dyn->num_entries)
		return 0;

	if (arg && len) {
		*arg = dyn->args + dyn->entries[index].arg_offset;
		*len = dyn->entries[index].arg_len;
	}

	return dyn->entries[index].token;
}

static int
lws_hpack_add_dynamic_header(struct lws *wsi, int token, char *arg, int len)
{
	struct hpack_dynamic_table *dyn;
	int ret = 1;

	wsi = lws_http2_get_network_wsi(wsi);
	dyn = wsi->u.http2.hpack_dyn_table;

	if (!dyn) {
		dyn = lws_zalloc(sizeof(*dyn));
		if (!dyn)
			return 1;
		wsi->u.http2.hpack_dyn_table = dyn;

		dyn->args = lws_malloc(1024);
		if (!dyn->args)
			goto bail1;
		dyn->args_length = 1024;
		dyn->entries = lws_malloc(sizeof(dyn->entries[0]) * 20);
		if (!dyn->entries)
			goto bail2;
		dyn->num_entries = 20;
	}

	if (dyn->next == dyn->num_entries)
		return 1;

	if (dyn->args_length - dyn->pos < len)
		return 1;

	dyn->entries[dyn->next].token = token;
	dyn->entries[dyn->next].arg_offset = dyn->pos;
	if (len)
		memcpy(dyn->args + dyn->pos, arg, len);
	dyn->entries[dyn->next].arg_len = len;

	lwsl_info("%s: added dynamic hdr %d, token %d (%s), len %d\n",
		  __func__, dyn->next, token, lws_token_to_string(token), len);

	dyn->pos += len;
	dyn->next++;

	return 0;

bail2:
	lws_free(dyn->args);
bail1:
	lws_free(dyn);
	wsi->u.http2.hpack_dyn_table = NULL;

	return ret;
}

static int lws_write_indexed_hdr(struct lws *wsi, int idx)
{
	const char *p;
	int tok = lws_token_from_index(wsi, idx, NULL, 0);

	lwsl_info("writing indexed hdr %d (tok %d '%s')\n", idx, tok,
		  lws_token_to_string(tok));

	if (lws_frag_start(wsi, tok))
		return 1;

	if (idx < ARRAY_SIZE(http2_canned)) {
		p = http2_canned[idx];
		while (*p)
			if (lws_frag_append(wsi, *p++))
				return 1;
	}
	if (lws_frag_end(wsi))
		return 1;

	lws_dump_header(wsi, tok);

	return 0;
}

int lws_hpack_interpret(struct lws *wsi, unsigned char c)
{
	unsigned int prev;
	unsigned char c1;
	int n;

	lwsl_debug("   state %d\n", wsi->u.http2.hpack);

	switch (wsi->u.http2.hpack) {
	case HPKS_OPT_PADDING:
		wsi->u.http2.padding = c;
		lwsl_info("padding %d\n", c);
		if (wsi->u.http2.flags & LWS_HTTP2_FLAG_PRIORITY) {
			wsi->u.http2.hpack = HKPS_OPT_E_DEPENDENCY;
			wsi->u.http2.hpack_m = 4;
		} else
			wsi->u.http2.hpack = HPKS_TYPE;
		break;
	case HKPS_OPT_E_DEPENDENCY:
		wsi->u.http2.hpack_e_dep <<= 8;
		wsi->u.http2.hpack_e_dep |= c;
		if (! --wsi->u.http2.hpack_m) {
			lwsl_info("hpack_e_dep = 0x%x\n", wsi->u.http2.hpack_e_dep);
			wsi->u.http2.hpack = HKPS_OPT_WEIGHT;
		}
		break;
	case HKPS_OPT_WEIGHT:
		/* weight */
		wsi->u.http2.hpack = HPKS_TYPE;
		break;

	case HPKS_TYPE:

		if (wsi->u.http2.count > (wsi->u.http2.length - wsi->u.http2.padding)) {
			lwsl_info("padding eat\n");
			break;
		}

		if (c & 0x80) { /* indexed header field only */
			/* just a possibly-extended integer */
			wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_7;
			lwsl_debug("HKPS_TYPE setting header_index %d\n", c & 0x7f);
			wsi->u.http2.header_index = c & 0x7f;
			if ((c & 0x7f) == 0x7f) {
				wsi->u.http2.hpack_len = c & 0x7f;
				wsi->u.http2.hpack_m = 0;
				wsi->u.http2.hpack = HPKS_IDX_EXT;
				break;
			}
			lwsl_debug("HKPS_TYPE: %d\n", c & 0x7f);
			if (lws_write_indexed_hdr(wsi, c & 0x7f))
				return 1;
			/* stay at same state */
			break;
		}
		if (c & 0x40) { /* literal header incr idx */
			/*
			 * [possibly-extended hdr idx (6) | new literal hdr name]
			 * H + possibly-extended value length
			 * literal value
			 */
			lwsl_debug("HKPS_TYPE 2 setting header_index %d\n", 0);
			wsi->u.http2.header_index = 0;
			if (c == 0x40) { /* literal name */
				wsi->u.http2.hpack_type = HPKT_LITERAL_HDR_VALUE_INCR;
				wsi->u.http2.value = 0;
				wsi->u.http2.hpack = HPKS_HLEN;
				break;
			}
			/* indexed name */
			wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_6_VALUE_INCR;
			if ((c & 0x3f) == 0x3f) {
				wsi->u.http2.hpack_len = c & 0x3f;
				wsi->u.http2.hpack_m = 0;
				wsi->u.http2.hpack = HPKS_IDX_EXT;
				break;
			}
			lwsl_debug("HKPS_TYPE 3 setting header_index %d\n", c & 0x3f);
			wsi->u.http2.header_index = c & 0x3f;
			wsi->u.http2.value = 1;
			wsi->u.http2.hpack = HPKS_HLEN;
			break;
		}
		switch(c & 0xf0) {
		case 0x10: /* literal header never index */
		case 0: /* literal header without indexing */
			/*
			 * follows 0x40 except 4-bit hdr idx
			 * and don't add to index
			 */
			if (c == 0) { /* literal name */
				wsi->u.http2.hpack_type = HPKT_LITERAL_HDR_VALUE;
				wsi->u.http2.hpack = HPKS_HLEN;
				wsi->u.http2.value = 0;
				break;
			}
			//lwsl_debug("indexed\n");
			/* indexed name */
			wsi->u.http2.hpack_type = HPKT_INDEXED_HDR_4_VALUE;
			wsi->u.http2.header_index = 0;
			if ((c & 0xf) == 0xf) {
				wsi->u.http2.hpack_len = c & 0xf;
				wsi->u.http2.hpack_m = 0;
				wsi->u.http2.hpack = HPKS_IDX_EXT;
				break;
			}
			//lwsl_err("HKPS_TYPE 5 setting header_index %d\n", c & 0xf);
			wsi->u.http2.header_index = c & 0xf;
			wsi->u.http2.value = 1;
			wsi->u.http2.hpack = HPKS_HLEN;
			break;

		case 0x20:
		case 0x30: /* header table size update */
			/* possibly-extended size value (5) */
			wsi->u.http2.hpack_type = HPKT_SIZE_5;
			if ((c & 0x1f) == 0x1f) {
				wsi->u.http2.hpack_len = c & 0x1f;
				wsi->u.http2.hpack_m = 0;
				wsi->u.http2.hpack = HPKS_IDX_EXT;
				break;
			}
			lws_hpack_update_table_size(wsi, c & 0x1f);
			/* stay at HPKS_TYPE state */
			break;
		}
		break;

	case HPKS_IDX_EXT:
		wsi->u.http2.hpack_len += (c & 0x7f) << wsi->u.http2.hpack_m;
		wsi->u.http2.hpack_m += 7;
		if (!(c & 0x80)) {
			switch (wsi->u.http2.hpack_type) {
			case HPKT_INDEXED_HDR_7:
				//lwsl_err("HKPS_IDX_EXT hdr idx %d\n", wsi->u.http2.hpack_len);
				if (lws_write_indexed_hdr(wsi, wsi->u.http2.hpack_len))
					return 1;
				wsi->u.http2.hpack = HPKS_TYPE;
				break;
			default:
				// lwsl_err("HKPS_IDX_EXT setting header_index %d\n",
				//		wsi->u.http2.hpack_len);
				wsi->u.http2.header_index = wsi->u.http2.hpack_len;
				wsi->u.http2.value = 1;
				wsi->u.http2.hpack = HPKS_HLEN;
				break;
			}
		}
		break;

	case HPKS_HLEN: /* [ H | 7+ ] */
		wsi->u.http2.huff = !!(c & 0x80);
		wsi->u.http2.hpack_pos = 0;
		wsi->u.http2.hpack_len = c & 0x7f;
		if (wsi->u.http2.hpack_len < 0x7f) {
pre_data:
			if (wsi->u.http2.value) {
				if (wsi->u.http2.header_index)
				if (lws_frag_start(wsi, lws_token_from_index(wsi,
						   wsi->u.http2.header_index,
						   NULL, NULL))) {
				//	lwsl_notice("%s: hlen failed\n", __func__);
					return 1;
				}
			} else
				wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
			wsi->u.http2.hpack = HPKS_DATA;
			break;
		}
		wsi->u.http2.hpack_m = 0;
		wsi->u.http2.hpack = HPKS_HLEN_EXT;
		break;

	case HPKS_HLEN_EXT:
		wsi->u.http2.hpack_len += (c & 0x7f) <<
					wsi->u.http2.hpack_m;
		wsi->u.http2.hpack_m += 7;
		if (!(c & 0x80))
			goto pre_data;

		break;

	case HPKS_DATA:
		for (n = 0; n < 8; n++) {
			if (wsi->u.http2.huff) {
				prev = wsi->u.http2.hpack_pos;
				wsi->u.http2.hpack_pos = huftable_decode(
						wsi->u.http2.hpack_pos,
		     				(c >> 7) & 1);
				c <<= 1;
				if (wsi->u.http2.hpack_pos == 0xffff)
					return 1;
				if (!(wsi->u.http2.hpack_pos & 0x8000))
					continue;
				c1 = wsi->u.http2.hpack_pos & 0x7fff;
				wsi->u.http2.hpack_pos = 0;

				if (!c1 && prev == HUFTABLE_0x100_PREV)
					; /* EOT */
			} else {
				n = 8;
				c1 = c;
			}
			if (wsi->u.http2.value) { /* value */
				if (wsi->u.http2.header_index)
					if (lws_frag_append(wsi, c1))
						return 1;
			} else { /* name */
				if (lws_parse(wsi, c1))
					return 1;

			}
		}
		if (--wsi->u.http2.hpack_len == 0) {

			switch (wsi->u.http2.hpack_type) {
			case HPKT_LITERAL_HDR_VALUE_INCR:
			case HPKT_INDEXED_HDR_6_VALUE_INCR: // !!!
				if (lws_hpack_add_dynamic_header(wsi,
				     lws_token_from_index(wsi,
						 wsi->u.http2.header_index,
						 	 NULL, NULL), NULL, 0))
					return 1;
				break;
			default:
				break;
			}

			n = 8;
			if (wsi->u.http2.value) {
				if (lws_frag_end(wsi))
					return 1;
				// lwsl_err("data\n");
				lws_dump_header(wsi, lws_token_from_index(
						wsi, wsi->u.http2.header_index,
						NULL, NULL));
				if (wsi->u.http2.count + wsi->u.http2.padding ==
				    wsi->u.http2.length)
					wsi->u.http2.hpack = HKPS_OPT_DISCARD_PADDING;
				else
					wsi->u.http2.hpack = HPKS_TYPE;
			} else { /* name */
				//if (wsi->u.hdr.parser_state < WSI_TOKEN_COUNT)

				wsi->u.http2.value = 1;
				wsi->u.http2.hpack = HPKS_HLEN;
			}
		}
		break;
	case HKPS_OPT_DISCARD_PADDING:
		lwsl_info("eating padding %x\n", c);
		if (! --wsi->u.http2.padding)
			wsi->u.http2.hpack = HPKS_TYPE;
		break;
	}

	return 0;
}

static int lws_http2_num(int starting_bits, unsigned long num,
			 unsigned char **p, unsigned char *end)
{
	int mask = (1 << starting_bits) - 1;

	if (num < mask) {
		*((*p)++) |= num;
		return *p >= end;
	}

	*((*p)++) |= mask;
	if (*p >= end)
		return 1;

	num -= mask;
	while (num >= 128) {
		*((*p)++) = 0x80 | (num & 0x7f);
		if (*p >= end)
			return 1;
		num >>= 7;
	}

	return 0;
}

int lws_add_http2_header_by_name(struct lws *wsi,
				 const unsigned char *name,
				 const unsigned char *value, int length,
				 unsigned char **p, unsigned char *end)
{
	int len;

	lwsl_info("%s: %p  %s:%s\n", __func__, *p, name, value);

	len = strlen((char *)name);
	if (len)
		if (name[len - 1] == ':')
			len--;

	if (end - *p < len + length + 8)
		return 1;

	*((*p)++) = 0; /* not indexed, literal name */

	**p = 0; /* non-HUF */
	if (lws_http2_num(7, len, p, end))
		return 1;
	memcpy(*p, name, len);
	*p += len;

	*(*p) = 0; /* non-HUF */
	if (lws_http2_num(7, length, p, end))
		return 1;

	memcpy(*p, value, length);
	*p += length;

	return 0;
}

int lws_add_http2_header_by_token(struct lws *wsi, enum lws_token_indexes token,
				  const unsigned char *value, int length,
				  unsigned char **p, unsigned char *end)
{
	const unsigned char *name;

	name = lws_token_to_string(token);
	if (!name)
		return 1;

	return lws_add_http2_header_by_name(wsi, name, value, length, p, end);
}

int lws_add_http2_header_status(struct lws *wsi,
			        unsigned int code, unsigned char **p,
				unsigned char *end)
{
	unsigned char status[10];
	int n;

	wsi->u.http2.send_END_STREAM = !!(code >= 400);

	n = sprintf((char *)status, "%u", code);
	if (lws_add_http2_header_by_token(wsi, WSI_TOKEN_HTTP_COLON_STATUS,
					  status, n, p, end))

		return 1;

	return 0;
}

Added undroid/libwebsockets/lib/http2.c.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
/*
 * libwebsockets - small server side websockets and web server implementation
 *
 * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation:
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */


#include "private-libwebsockets.h"

const struct http2_settings lws_http2_default_settings = { {
	0,
	/* LWS_HTTP2_SETTINGS__HEADER_TABLE_SIZE */		4096,
	/* LWS_HTTP2_SETTINGS__ENABLE_PUSH */			   1,
	/* LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS */	 100,
	/* LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE */	       65535,
	/* LWS_HTTP2_SETTINGS__MAX_FRAME_SIZE */	       16384,
	/* LWS_HTTP2_SETTINGS__MAX_HEADER_LIST_SIZE */		  ~0,
}};


void lws_http2_init(struct http2_settings *settings)
{
	memcpy(settings, lws_http2_default_settings.setting, sizeof(*settings));
}

struct lws *
lws_http2_wsi_from_id(struct lws *wsi, unsigned int sid)
{
	do {
		if (wsi->u.http2.my_stream_id == sid)
			return wsi;

		wsi = wsi->u.http2.next_child_wsi;
	} while (wsi);

	return NULL;
}

struct lws *
lws_create_server_child_wsi(struct lws_vhost *vhost, struct lws *parent_wsi,
			    unsigned int sid)
{
	struct lws *wsi = lws_create_new_server_wsi(vhost);

	if (!wsi)
		return NULL;

	/* no more children allowed by parent */
	if (parent_wsi->u.http2.child_count + 1 ==
	    parent_wsi->u.http2.peer_settings.setting[
			LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS])
		goto bail;
	lws_http2_init(&wsi->u.http2.peer_settings);
	lws_http2_init(&wsi->u.http2.my_settings);
	wsi->u.http2.stream_id = sid;
	wsi->u.http2.my_stream_id = sid;

	wsi->u.http2.parent_wsi = parent_wsi;
	wsi->u.http2.next_child_wsi = parent_wsi->u.http2.next_child_wsi;
	parent_wsi->u.http2.next_child_wsi = wsi;
	parent_wsi->u.http2.child_count++;

	wsi->u.http2.my_priority = 16;
	wsi->u.http2.tx_credit = 65535;

	wsi->state = LWSS_HTTP2_ESTABLISHED;
	wsi->mode = parent_wsi->mode;

	wsi->protocol = &vhost->protocols[0];
	if (lws_ensure_user_space(wsi))
		goto bail;

	lwsl_info("%s: %p new child %p, sid %d, user_space=%p\n", __func__,
		  parent_wsi, wsi, sid, wsi->user_space);

	return wsi;

bail:
	vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY,
			       NULL, NULL, 0);
	lws_free(wsi);

	return NULL;
}

int lws_remove_server_child_wsi(struct lws_context *context, struct lws *wsi)
{
	struct lws **w = &wsi->u.http2.parent_wsi;
	do {
		if (*w == wsi) {
			*w = wsi->u.http2.next_child_wsi;
			(wsi->u.http2.parent_wsi)->u.http2.child_count--;
			return 0;
		}

		w = &((*w)->u.http2.next_child_wsi);
	} while (*w);

	lwsl_err("%s: can't find %p\n", __func__, wsi);
	return 1;
}

int
lws_http2_interpret_settings_payload(struct http2_settings *settings,
				     unsigned char *buf, int len)
{
	unsigned int a, b;

	if (!len)
		return 0;

	if (len < LWS_HTTP2_SETTINGS_LENGTH)
		return 1;

	while (len >= LWS_HTTP2_SETTINGS_LENGTH) {
		a = (buf[0] << 8) | buf[1];
		if (a < LWS_HTTP2_SETTINGS__COUNT) {
			b = buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5];
			settings->setting[a] = b;
			lwsl_info("http2 settings %d <- 0x%x\n", a, b);
		}
		len -= LWS_HTTP2_SETTINGS_LENGTH;
		buf += LWS_HTTP2_SETTINGS_LENGTH;
	}

	if (len)
		return 1;

	return 0;
}

struct lws *lws_http2_get_network_wsi(struct lws *wsi)
{
	while (wsi->u.http2.parent_wsi)
		wsi = wsi->u.http2.parent_wsi;

	return wsi;
}

int lws_http2_frame_write(struct lws *wsi, int type, int flags,
			  unsigned int sid, unsigned int len, unsigned char *buf)
{
	struct lws *wsi_eff = lws_http2_get_network_wsi(wsi);
	unsigned char *p = &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH];
	int n;

	*p++ = len >> 16;
	*p++ = len >> 8;
	*p++ = len;
	*p++ = type;
	*p++ = flags;
	*p++ = sid >> 24;
	*p++ = sid >> 16;
	*p++ = sid >> 8;
	*p++ = sid;

	lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d\n",
		  __func__, wsi, wsi_eff, type, flags, sid, len,
		  wsi->u.http2.tx_credit);

	if (type == LWS_HTTP2_FRAME_TYPE_DATA) {
		if (wsi->u.http2.tx_credit < len)
			lwsl_err("%s: %p: sending payload len %d"
				 " but tx_credit only %d!\n", len,
				 wsi->u.http2.tx_credit);
		wsi->u.http2.tx_credit -= len;
	}

	n = lws_issue_raw(wsi_eff, &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH],
			  len + LWS_HTTP2_FRAME_HEADER_LENGTH);
	if (n >= LWS_HTTP2_FRAME_HEADER_LENGTH)
		return n - LWS_HTTP2_FRAME_HEADER_LENGTH;

	return n;
}

static void lws_http2_settings_write(struct lws *wsi, int n, unsigned char *buf)
{
	*buf++ = n >> 8;
	*buf++ = n;
	*buf++ = wsi->u.http2.my_settings.setting[n] >> 24;
	*buf++ = wsi->u.http2.my_settings.setting[n] >> 16;
	*buf++ = wsi->u.http2.my_settings.setting[n] >> 8;
	*buf = wsi->u.http2.my_settings.setting[n];
}

static const char * https_client_preface =
	"PRI * HTTP/2.0\x0d\x0a\x0d\x0aSM\x0d\x0a\x0d\x0a";

int
lws_http2_parser(struct lws *wsi, unsigned char c)
{
	struct lws *swsi;
	int n;

	switch (wsi->state) {
	case LWSS_HTTP2_AWAIT_CLIENT_PREFACE:
		if (https_client_preface[wsi->u.http2.count++] != c)
			return 1;

		if (!https_client_preface[wsi->u.http2.count]) {
			lwsl_info("http2: %p: established\n", wsi);
			wsi->state = LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS;
			wsi->u.http2.count = 0;
			wsi->u.http2.tx_credit = 65535;

			/*
			 * we must send a settings frame -- empty one is OK...
			 * that must be the first thing sent by server
			 * and the peer must send a SETTINGS with ACK flag...
			 */

			lws_set_protocol_write_pending(wsi,
						       LWS_PPS_HTTP2_MY_SETTINGS);
		}
		break;

	case LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS:
	case LWSS_HTTP2_ESTABLISHED:
		if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { // payload
			wsi->u.http2.count++;
			wsi->u.http2.stream_wsi->u.http2.count = wsi->u.http2.count;
			/* applies to wsi->u.http2.stream_wsi which may be wsi*/
			switch(wsi->u.http2.type) {
			case LWS_HTTP2_FRAME_TYPE_SETTINGS:
				wsi->u.http2.stream_wsi->u.http2.one_setting[wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH] = c;
				if (wsi->u.http2.count % LWS_HTTP2_SETTINGS_LENGTH == LWS_HTTP2_SETTINGS_LENGTH - 1)
					if (lws_http2_interpret_settings_payload(
					     &wsi->u.http2.stream_wsi->u.http2.peer_settings,
					     wsi->u.http2.one_setting,
					     LWS_HTTP2_SETTINGS_LENGTH))
						return 1;
				break;
			case LWS_HTTP2_FRAME_TYPE_CONTINUATION:
			case LWS_HTTP2_FRAME_TYPE_HEADERS:
				lwsl_info(" %02X\n", c);
				if (!wsi->u.http2.stream_wsi->u.hdr.ah)
					if (lws_header_table_attach(wsi->u.http2.stream_wsi, 0)) {
						lwsl_err("%s: Failed to get ah\n", __func__);
						return 1;
					}
				if (lws_hpack_interpret(wsi->u.http2.stream_wsi, c)) {
					lwsl_notice("%s: lws_hpack_interpret failed\n", __func__);
					return 1;
				}
				break;
			case LWS_HTTP2_FRAME_TYPE_GOAWAY:
				if (wsi->u.http2.count >= 5 && wsi->u.http2.count <= 8) {
					wsi->u.http2.hpack_e_dep <<= 8;
					wsi->u.http2.hpack_e_dep |= c;
					if (wsi->u.http2.count == 8) {
						lwsl_info("goaway err 0x%x\n", wsi->u.http2.hpack_e_dep);
					}
				}
				wsi->u.http2.GOING_AWAY = 1;
				break;
			case LWS_HTTP2_FRAME_TYPE_DATA:
				break;
			case LWS_HTTP2_FRAME_TYPE_PRIORITY:
				break;
			case LWS_HTTP2_FRAME_TYPE_RST_STREAM:
				break;
			case LWS_HTTP2_FRAME_TYPE_PUSH_PROMISE:
				break;
			case LWS_HTTP2_FRAME_TYPE_PING:
				if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
				} else { /* they're sending us a ping request */
					if (wsi->u.http2.count > 8)
						return 1;
					wsi->u.http2.ping_payload[wsi->u.http2.count - 1] = c;
				}
				break;
			case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
				wsi->u.http2.hpack_e_dep <<= 8;
				wsi->u.http2.hpack_e_dep |= c;
				break;
			}
			if (wsi->u.http2.count != wsi->u.http2.length)
				break;

			/* end of frame */

			wsi->u.http2.frame_state = 0;
			wsi->u.http2.count = 0;
			swsi = wsi->u.http2.stream_wsi;
			/* set our initial window size */
			if (!wsi->u.http2.initialized) {
				wsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE];
				lwsl_info("initial tx credit on master conn %p: %d\n", wsi, wsi->u.http2.tx_credit);
				wsi->u.http2.initialized = 1;
			}
			switch (wsi->u.http2.type) {
			case LWS_HTTP2_FRAME_TYPE_HEADERS:
				/* service the http request itself */
				lwsl_info("servicing initial http request, wsi=%p, stream wsi=%p\n", wsi, wsi->u.http2.stream_wsi);
				n = lws_http_action(swsi);
				(void)n;
				lwsl_info("  action result %d\n", n);
				break;
			case LWS_HTTP2_FRAME_TYPE_PING:
				if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
				} else { /* they're sending us a ping request */
					lws_set_protocol_write_pending(wsi, LWS_PPS_HTTP2_PONG);
				}
				break;
			case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
				wsi->u.http2.hpack_e_dep &= ~(1 << 31);
				if ((long long)swsi->u.http2.tx_credit + (unsigned long long)wsi->u.http2.hpack_e_dep > (~(1 << 31)))
					return 1; /* actually need to close swsi not the whole show */
				swsi->u.http2.tx_credit += wsi->u.http2.hpack_e_dep;
				if (swsi->u.http2.waiting_tx_credit && swsi->u.http2.tx_credit > 0) {
					lwsl_info("%s: %p: waiting_tx_credit -> wait on writeable\n", __func__, wsi);
					swsi->u.http2.waiting_tx_credit = 0;
					lws_callback_on_writable(swsi);
				}
				break;
			}
			break;
		}
		switch (wsi->u.http2.frame_state++) {
		case 0:
			wsi->u.http2.length = c;
			break;
		case 1:
		case 2:
			wsi->u.http2.length <<= 8;
			wsi->u.http2.length |= c;
			break;
		case 3:
			wsi->u.http2.type = c;
			break;
		case 4:
			wsi->u.http2.flags = c;
			break;
		case 5:
		case 6:
		case 7:
		case 8:
			wsi->u.http2.stream_id <<= 8;
			wsi->u.http2.stream_id |= c;
			break;
		}
		if (wsi->u.http2.frame_state == LWS_HTTP2_FRAME_HEADER_LENGTH) { /* frame header complete */
			lwsl_info("frame: type 0x%x, flags 0x%x, sid 0x%x, len 0x%x\n",
				  wsi->u.http2.type, wsi->u.http2.flags, wsi->u.http2.stream_id, wsi->u.http2.length);
			wsi->u.http2.count = 0;

			wsi->u.http2.stream_wsi = wsi;
			if (wsi->u.http2.stream_id)
				wsi->u.http2.stream_wsi = lws_http2_wsi_from_id(wsi, wsi->u.http2.stream_id);

			switch (wsi->u.http2.type) {
			case LWS_HTTP2_FRAME_TYPE_SETTINGS:
				/* nonzero sid on settings is illegal */
				if (wsi->u.http2.stream_id)
					return 1;

				if (wsi->u.http2.flags & LWS_HTTP2_FLAG_SETTINGS_ACK) { // ack
				} else
					/* non-ACK coming in means we must ACK it */
					lws_set_protocol_write_pending(wsi, LWS_PPS_HTTP2_ACK_SETTINGS);
				break;
			case LWS_HTTP2_FRAME_TYPE_PING:
				if (wsi->u.http2.stream_id)
					return 1;
				if (wsi->u.http2.length != 8)
					return 1;
				break;
			case LWS_HTTP2_FRAME_TYPE_CONTINUATION:
				if (wsi->u.http2.END_HEADERS)
					return 1;
				goto update_end_headers;

			case LWS_HTTP2_FRAME_TYPE_HEADERS:
				lwsl_info("LWS_HTTP2_FRAME_TYPE_HEADERS: stream_id = %d\n", wsi->u.http2.stream_id);
				if (!wsi->u.http2.stream_id)
					return 1;
				if (!wsi->u.http2.stream_wsi) {
					wsi->u.http2.stream_wsi =
						lws_create_server_child_wsi(wsi->vhost, wsi, wsi->u.http2.stream_id);
					wsi->u.http2.stream_wsi->http2_substream = 1;
				}

				/* END_STREAM means after servicing this, close the stream */
				wsi->u.http2.END_STREAM = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_STREAM);
				lwsl_info("%s: headers END_STREAM = %d\n",__func__, wsi->u.http2.END_STREAM);
update_end_headers:
				/* no END_HEADERS means CONTINUATION must come */
				wsi->u.http2.END_HEADERS = !!(wsi->u.http2.flags & LWS_HTTP2_FLAG_END_HEADERS);

				swsi = wsi->u.http2.stream_wsi;
				if (!swsi)
					return 1;


				/* prepare the hpack parser at the right start */

				swsi->u.http2.flags = wsi->u.http2.flags;
				swsi->u.http2.length = wsi->u.http2.length;
				swsi->u.http2.END_STREAM = wsi->u.http2.END_STREAM;

				if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PADDED)
					swsi->u.http2.hpack = HPKS_OPT_PADDING;
				else
					if (swsi->u.http2.flags & LWS_HTTP2_FLAG_PRIORITY) {
						swsi->u.http2.hpack = HKPS_OPT_E_DEPENDENCY;
						swsi->u.http2.hpack_m = 4;
					} else
						swsi->u.http2.hpack = HPKS_TYPE;
				lwsl_info("initial hpack state %d\n", swsi->u.http2.hpack);
				break;
			case LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE:
				if (wsi->u.http2.length != 4)
					return 1;
				break;
			}
			if (wsi->u.http2.length == 0)
				wsi->u.http2.frame_state = 0;

		}
		break;
	}

	return 0;
}

int lws_http2_do_pps_send(struct lws_context *context, struct lws *wsi)
{
	unsigned char settings[LWS_PRE + 6 * LWS_HTTP2_SETTINGS__COUNT];
	struct lws *swsi;
	int n, m = 0;

	lwsl_debug("%s: %p: %d\n", __func__, wsi, wsi->pps);

	switch (wsi->pps) {
	case LWS_PPS_HTTP2_MY_SETTINGS:
		for (n = 1; n < LWS_HTTP2_SETTINGS__COUNT; n++)
			if (wsi->u.http2.my_settings.setting[n] != lws_http2_default_settings.setting[n]) {
				lws_http2_settings_write(wsi, n,
							 &settings[LWS_PRE + m]);
				m += sizeof(wsi->u.http2.one_setting);
			}
		n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS,
		     			  0, LWS_HTTP2_STREAM_ID_MASTER, m,
		     			  &settings[LWS_PRE]);
		if (n != m) {
			lwsl_info("send %d %d\n", n, m);
			return 1;
		}
		break;
	case LWS_PPS_HTTP2_ACK_SETTINGS:
		/* send ack ... always empty */
		n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_SETTINGS,
			1, LWS_HTTP2_STREAM_ID_MASTER, 0,
			&settings[LWS_PRE]);
		if (n) {
			lwsl_err("ack tells %d\n", n);
			return 1;
		}
		/* this is the end of the preface dance then? */
		if (wsi->state == LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS) {
			wsi->state = LWSS_HTTP2_ESTABLISHED;

			wsi->u.http.fd = LWS_INVALID_FILE;

			if (lws_is_ssl(lws_http2_get_network_wsi(wsi))) {
				lwsl_info("skipping nonexistant ssl upgrade headers\n");
				break;
			}

			/*
			 * we need to treat the headers from this upgrade
			 * as the first job.  These need to get
			 * shifted to stream ID 1
			 */
			lwsl_info("%s: setting up sid 1\n", __func__);

			swsi = wsi->u.http2.stream_wsi =
					lws_create_server_child_wsi(wsi->vhost, wsi, 1);
			/* pass on the initial headers to SID 1 */
			swsi->u.http.ah = wsi->u.http.ah;
			wsi->u.http.ah = NULL;

			lwsl_info("%s: inherited headers %p\n", __func__, swsi->u.http.ah);
			swsi->u.http2.tx_credit = wsi->u.http2.peer_settings.setting[LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE];
			lwsl_info("initial tx credit on conn %p: %d\n", swsi, swsi->u.http2.tx_credit);
			swsi->u.http2.initialized = 1;
			/* demanded by HTTP2 */
			swsi->u.http2.END_STREAM = 1;
			lwsl_info("servicing initial http request\n");
			return lws_http_action(swsi);
		}
		break;
	case LWS_PPS_HTTP2_PONG:
		memcpy(&settings[LWS_PRE], wsi->u.http2.ping_payload, 8);
		n = lws_http2_frame_write(wsi, LWS_HTTP2_FRAME_TYPE_PING,
		     			  LWS_HTTP2_FLAG_SETTINGS_ACK,
			    		  LWS_HTTP2_STREAM_ID_MASTER, 8,
		     			  &settings[LWS_PRE]);
		if (n != 8) {
			lwsl_info("send %d %d\n", n, m);
			return 1;
		}
		break;
	default:
		break;
	}

	return 0;
}

struct lws * lws_http2_get_nth_child(struct lws *wsi, int n)
{
	do {
		wsi = wsi->u.http2.next_child_wsi;
		if (!wsi)
			return NULL;
	} while (n--);

	return wsi;
}

Added undroid/libwebsockets/lib/huftable.h.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
static unsigned char lextable[] = {
/* pos 0000:   0 */    /* 0 */ 0x42  /* (to 0x0084 state  98) */,
                       /* 1 */ 0x01  /* (to 0x0002 state   1) */,
/* pos 0002:   1 */    /* 0 */ 0x5C  /* (to 0x00BA state 151) */,
                       /* 1 */ 0x01  /* (to 0x0004 state   2) */,
/* pos 0004:   2 */    /* 0 */ 0x66  /* (to 0x00D0 state 173) */,
                       /* 1 */ 0x01  /* (to 0x0006 state   3) */,
/* pos 0006:   3 */    /* 0 */ 0x74  /* (to 0x00EE state 204) */,
                       /* 1 */ 0x01  /* (to 0x0008 state   4) */,
/* pos 0008:   4 */    /* 0 */ 0x8C  /* (to 0x0120 state 263) */,
                       /* 1 */ 0x01  /* (to 0x000A state   5) */,
/* pos 000a:   5 */    /* 0 */ 0x46  /* (to 0x0096 state 113) */,
                       /* 1 */ 0x01  /* (to 0x000C state   6) */,
/* pos 000c:   6 */    /* 0 */ 0x75  /* (to 0x00F6 state 211) */,
                       /* 1 */ 0x01  /* (to 0x000E state   7) */,
/* pos 000e:   7 */    /* 0 */ 0x40  /* (to 0x008E state 104) */,
                       /* 1 */ 0x01  /* (to 0x0010 state   8) */,
/* pos 0010:   8 */    /* 0 */ 0x45  /* (to 0x009A state 116) */,
                       /* 1 */ 0x01  /* (to 0x0012 state   9) */,
/* pos 0012:   9 */    /* 0 */ 0x40  /* (to 0x0092 state 108) */,
                       /* 1 */ 0x01  /* (to 0x0014 state  10) */,
/* pos 0014:  10 */    /* 0 */ 0x01  /* (to 0x0016 state  11) */,
                       /* 1 */ 0x03  /* (to 0x001A state  14) */,
/* pos 0016:  11 */    /* 0 */ 0x01  /* (to 0x0018 state  12) */,
                       /* 1 */ 0x5B  /* (to 0x00CC state 166) */,
/* pos 0018:  12 */     /* terminal 0 */ 0x00,
                        /* terminal 36 */ 0x24,
/* pos 001a:  14 */    /* 0 */ 0x72  /* (to 0x00FE state 220) */,
                       /* 1 */ 0x01  /* (to 0x001C state  15) */,
/* pos 001c:  15 */    /* 0 */ 0x72  /* (to 0x0100 state 222) */,
                       /* 1 */ 0x01  /* (to 0x001E state  16) */,
/* pos 001e:  16 */    /* 0 */ 0x53  /* (to 0x00C4 state 158) */,
                       /* 1 */ 0x01  /* (to 0x0020 state  17) */,
/* pos 0020:  17 */     /* terminal 123 */ 0x7B,
                       /* 1 */ 0x01  /* (to 0x0022 state  18) */,
/* pos 0022:  18 */    /* 0 */ 0x6B  /* (to 0x00F8 state 216) */,
                       /* 1 */ 0x01  /* (to 0x0024 state  19) */,
/* pos 0024:  19 */    /* 0 */ 0x84  /* (to 0x012C state 279) */,
                       /* 1 */ 0x01  /* (to 0x0026 state  20) */,
/* pos 0026:  20 */    /* 0 */ 0x01  /* (to 0x0028 state  21) */,
                       /* 1 */ 0x06  /* (to 0x0032 state  27) */,
/* pos 0028:  21 */    /* 0 */ 0xB3  /* (to 0x018E state 377) */,
                       /* 1 */ 0x01  /* (to 0x002A state  22) */,
/* pos 002a:  22 */    /* 0 */ 0xC3  /* (to 0x01B0 state 414) */,
                       /* 1 */ 0x01  /* (to 0x002C state  23) */,
/* pos 002c:  23 */    /* 0 */ 0x01  /* (to 0x002E state  24) */,
                       /* 1 */ 0x8C  /* (to 0x0144 state 301) */,
/* pos 002e:  24 */    /* 0 */ 0x01  /* (to 0x0030 state  25) */,
                       /* 1 */ 0x8A  /* (to 0x0142 state 298) */,
/* pos 0030:  25 */     /* terminal 1 */ 0x01,
                        /* terminal 135 */ 0x87,
/* pos 0032:  27 */    /* 0 */ 0x8E  /* (to 0x014E state 314) */,
                       /* 1 */ 0x01  /* (to 0x0034 state  28) */,
/* pos 0034:  28 */    /* 0 */ 0x0F  /* (to 0x0052 state  50) */,
                       /* 1 */ 0x01  /* (to 0x0036 state  29) */,
/* pos 0036:  29 */    /* 0 */ 0xA4  /* (to 0x017E state 362) */,
                       /* 1 */ 0x01  /* (to 0x0038 state  30) */,
/* pos 0038:  30 */    /* 0 */ 0xB7  /* (to 0x01A6 state 403) */,
                       /* 1 */ 0x01  /* (to 0x003A state  31) */,
/* pos 003a:  31 */    /* 0 */ 0xC8  /* (to 0x01CA state 440) */,
                       /* 1 */ 0x01  /* (to 0x003C state  32) */,
/* pos 003c:  32 */    /* 0 */ 0x01  /* (to 0x003E state  33) */,
                       /* 1 */ 0x0F  /* (to 0x005A state  55) */,
/* pos 003e:  33 */    /* 0 */ 0x01  /* (to 0x0040 state  34) */,
                       /* 1 */ 0x07  /* (to 0x004C state  46) */,
/* pos 0040:  34 */    /* 0 */ 0x01  /* (to 0x0042 state  35) */,
                       /* 1 */ 0x03  /* (to 0x0046 state  39) */,
/* pos 0042:  35 */     /* terminal 254 */ 0xFE,
                       /* 1 */ 0x01  /* (to 0x0044 state  36) */,
/* pos 0044:  36 */     /* terminal 2 */ 0x02,
                        /* terminal 3 */ 0x03,
/* pos 0046:  39 */    /* 0 */ 0x01  /* (to 0x0048 state  40) */,
                       /* 1 */ 0x02  /* (to 0x004A state  43) */,
/* pos 0048:  40 */     /* terminal 4 */ 0x04,
                        /* terminal 5 */ 0x05,
/* pos 004a:  43 */     /* terminal 6 */ 0x06,
                        /* terminal 7 */ 0x07,
/* pos 004c:  46 */    /* 0 */ 0x01  /* (to 0x004E state  47) */,
                       /* 1 */ 0x0E  /* (to 0x0068 state  67) */,
/* pos 004e:  47 */    /* 0 */ 0x01  /* (to 0x0050 state  48) */,
                       /* 1 */ 0x0C  /* (to 0x0066 state  63) */,
/* pos 0050:  48 */     /* terminal 8 */ 0x08,
                        /* terminal 11 */ 0x0B,
/* pos 0052:  50 */    /* 0 */ 0xA7  /* (to 0x01A0 state 396) */,
                       /* 1 */ 0x01  /* (to 0x0054 state  51) */,
/* pos 0054:  51 */    /* 0 */ 0x01  /* (to 0x0056 state  52) */,
                       /* 1 */ 0x7B  /* (to 0x014A state 309) */,
/* pos 0056:  52 */     /* terminal 239 */ 0xEF,
                       /* 1 */ 0x01  /* (to 0x0058 state  53) */,
/* pos 0058:  53 */     /* terminal 9 */ 0x09,
                        /* terminal 142 */ 0x8E,
/* pos 005a:  55 */    /* 0 */ 0x0A  /* (to 0x006E state  74) */,
                       /* 1 */ 0x01  /* (to 0x005C state  56) */,
/* pos 005c:  56 */    /* 0 */ 0x11  /* (to 0x007E state  91) */,
                       /* 1 */ 0x01  /* (to 0x005E state  57) */,
/* pos 005e:  57 */    /* 0 */ 0x64  /* (to 0x0126 state 274) */,
                       /* 1 */ 0x01  /* (to 0x0060 state  58) */,
/* pos 0060:  58 */     /* terminal 249 */ 0xF9,
                       /* 1 */ 0x01  /* (to 0x0062 state  59) */,
/* pos 0062:  59 */    /* 0 */ 0x01  /* (to 0x0064 state  60) */,
                       /* 1 */ 0x0A  /* (to 0x0076 state  81) */,
/* pos 0064:  60 */     /* terminal 10 */ 0x0A,
                        /* terminal 13 */ 0x0D,
/* pos 0066:  63 */     /* terminal 12 */ 0x0C,
                        /* terminal 14 */ 0x0E,
/* pos 0068:  67 */    /* 0 */ 0x01  /* (to 0x006A state  68) */,
                       /* 1 */ 0x02  /* (to 0x006C state  71) */,
/* pos 006a:  68 */     /* terminal 15 */ 0x0F,
                        /* terminal 16 */ 0x10,
/* pos 006c:  71 */     /* terminal 17 */ 0x11,
                        /* terminal 18 */ 0x12,
/* pos 006e:  74 */    /* 0 */ 0x01  /* (to 0x0070 state  75) */,
                       /* 1 */ 0x05  /* (to 0x0078 state  84) */,
/* pos 0070:  75 */    /* 0 */ 0x01  /* (to 0x0072 state  76) */,
                       /* 1 */ 0x02  /* (to 0x0074 state  79) */,
/* pos 0072:  76 */     /* terminal 19 */ 0x13,
                        /* terminal 20 */ 0x14,
/* pos 0074:  79 */     /* terminal 21 */ 0x15,
                        /* terminal 23 */ 0x17,
/* pos 0076:  81 */     /* terminal 22 */ 0x16,
                        /* terminal 256 */ 0x00,
/* pos 0078:  84 */    /* 0 */ 0x01  /* (to 0x007A state  85) */,
                       /* 1 */ 0x02  /* (to 0x007C state  88) */,
/* pos 007a:  85 */     /* terminal 24 */ 0x18,
                        /* terminal 25 */ 0x19,
/* pos 007c:  88 */     /* terminal 26 */ 0x1A,
                        /* terminal 27 */ 0x1B,
/* pos 007e:  91 */    /* 0 */ 0x01  /* (to 0x0080 state  92) */,
                       /* 1 */ 0x02  /* (to 0x0082 state  95) */,
/* pos 0080:  92 */     /* terminal 28 */ 0x1C,
                        /* terminal 29 */ 0x1D,
/* pos 0082:  95 */     /* terminal 30 */ 0x1E,
                        /* terminal 31 */ 0x1F,
/* pos 0084:  98 */    /* 0 */ 0x13  /* (to 0x00AA state 133) */,
                       /* 1 */ 0x01  /* (to 0x0086 state  99) */,
/* pos 0086:  99 */    /* 0 */ 0x01  /* (to 0x0088 state 100) */,
                       /* 1 */ 0x0F  /* (to 0x00A4 state 129) */,
/* pos 0088: 100 */    /* 0 */ 0x4B  /* (to 0x011E state 258) */,
                       /* 1 */ 0x01  /* (to 0x008A state 101) */,
/* pos 008a: 101 */    /* 0 */ 0x01  /* (to 0x008C state 102) */,
                       /* 1 */ 0x0C  /* (to 0x00A2 state 126) */,
/* pos 008c: 102 */     /* terminal 32 */ 0x20,
                        /* terminal 37 */ 0x25,
/* pos 008e: 104 */    /* 0 */ 0x01  /* (to 0x0090 state 105) */,
                       /* 1 */ 0x08  /* (to 0x009E state 119) */,
/* pos 0090: 105 */     /* terminal 33 */ 0x21,
                        /* terminal 34 */ 0x22,
/* pos 0092: 108 */     /* terminal 124 */ 0x7C,
                       /* 1 */ 0x01  /* (to 0x0094 state 109) */,
/* pos 0094: 109 */     /* terminal 35 */ 0x23,
                        /* terminal 62 */ 0x3E,
/* pos 0096: 113 */    /* 0 */ 0x01  /* (to 0x0098 state 114) */,
                       /* 1 */ 0x05  /* (to 0x00A0 state 124) */,
/* pos 0098: 114 */     /* terminal 38 */ 0x26,
                        /* terminal 42 */ 0x2A,
/* pos 009a: 116 */     /* terminal 63 */ 0x3F,
                       /* 1 */ 0x01  /* (to 0x009C state 117) */,
/* pos 009c: 117 */     /* terminal 39 */ 0x27,
                        /* terminal 43 */ 0x2B,
/* pos 009e: 119 */     /* terminal 40 */ 0x28,
                        /* terminal 41 */ 0x29,
/* pos 00a0: 124 */     /* terminal 44 */ 0x2C,
                        /* terminal 59 */ 0x3B,
/* pos 00a2: 126 */     /* terminal 45 */ 0x2D,
                        /* terminal 46 */ 0x2E,
/* pos 00a4: 129 */    /* 0 */ 0x01  /* (to 0x00A6 state 130) */,
                       /* 1 */ 0x08  /* (to 0x00B4 state 144) */,
/* pos 00a6: 130 */    /* 0 */ 0x01  /* (to 0x00A8 state 131) */,
                       /* 1 */ 0x06  /* (to 0x00B2 state 141) */,
/* pos 00a8: 131 */     /* terminal 47 */ 0x2F,
                        /* terminal 51 */ 0x33,
/* pos 00aa: 133 */    /* 0 */ 0x01  /* (to 0x00AC state 134) */,
                       /* 1 */ 0x2D  /* (to 0x0104 state 229) */,
/* pos 00ac: 134 */    /* 0 */ 0x01  /* (to 0x00AE state 135) */,
                       /* 1 */ 0x02  /* (to 0x00B0 state 138) */,
/* pos 00ae: 135 */     /* terminal 48 */ 0x30,
                        /* terminal 49 */ 0x31,
/* pos 00b0: 138 */     /* terminal 50 */ 0x32,
                        /* terminal 97 */ 0x61,
/* pos 00b2: 141 */     /* terminal 52 */ 0x34,
                        /* terminal 53 */ 0x35,
/* pos 00b4: 144 */    /* 0 */ 0x01  /* (to 0x00B6 state 145) */,
                       /* 1 */ 0x02  /* (to 0x00B8 state 148) */,
/* pos 00b6: 145 */     /* terminal 54 */ 0x36,
                        /* terminal 55 */ 0x37,
/* pos 00b8: 148 */     /* terminal 56 */ 0x38,
                        /* terminal 57 */ 0x39,
/* pos 00ba: 151 */    /* 0 */ 0x06  /* (to 0x00C6 state 160) */,
                       /* 1 */ 0x01  /* (to 0x00BC state 152) */,
/* pos 00bc: 152 */    /* 0 */ 0x2C  /* (to 0x0114 state 246) */,
                       /* 1 */ 0x01  /* (to 0x00BE state 153) */,
/* pos 00be: 153 */    /* 0 */ 0x2F  /* (to 0x011C state 256) */,
                       /* 1 */ 0x01  /* (to 0x00C0 state 154) */,
/* pos 00c0: 154 */    /* 0 */ 0x01  /* (to 0x00C2 state 155) */,
                       /* 1 */ 0x07  /* (to 0x00CE state 170) */,
/* pos 00c2: 155 */     /* terminal 58 */ 0x3A,
                        /* terminal 66 */ 0x42,
/* pos 00c4: 158 */     /* terminal 60 */ 0x3C,
                        /* terminal 96 */ 0x60,
/* pos 00c6: 160 */    /* 0 */ 0x01  /* (to 0x00C8 state 161) */,
                       /* 1 */ 0x21  /* (to 0x0108 state 232) */,
/* pos 00c8: 161 */    /* 0 */ 0x01  /* (to 0x00CA state 162) */,
                       /* 1 */ 0x1D  /* (to 0x0102 state 224) */,
/* pos 00ca: 162 */     /* terminal 61 */ 0x3D,
                        /* terminal 65 */ 0x41,
/* pos 00cc: 166 */     /* terminal 64 */ 0x40,
                        /* terminal 91 */ 0x5B,
/* pos 00ce: 170 */     /* terminal 67 */ 0x43,
                        /* terminal 68 */ 0x44,
/* pos 00d0: 173 */    /* 0 */ 0x01  /* (to 0x00D2 state 174) */,
                       /* 1 */ 0x08  /* (to 0x00E0 state 189) */,
/* pos 00d2: 174 */    /* 0 */ 0x01  /* (to 0x00D4 state 175) */,
                       /* 1 */ 0x04  /* (to 0x00DA state 182) */,
/* pos 00d4: 175 */    /* 0 */ 0x01  /* (to 0x00D6 state 176) */,
                       /* 1 */ 0x02  /* (to 0x00D8 state 179) */,
/* pos 00d6: 176 */     /* terminal 69 */ 0x45,
                        /* terminal 70 */ 0x46,
/* pos 00d8: 179 */     /* terminal 71 */ 0x47,
                        /* terminal 72 */ 0x48,
/* pos 00da: 182 */    /* 0 */ 0x01  /* (to 0x00DC state 183) */,
                       /* 1 */ 0x02  /* (to 0x00DE state 186) */,
/* pos 00dc: 183 */     /* terminal 73 */ 0x49,
                        /* terminal 74 */ 0x4A,
/* pos 00de: 186 */     /* terminal 75 */ 0x4B,
                        /* terminal 76 */ 0x4C,
/* pos 00e0: 189 */    /* 0 */ 0x01  /* (to 0x00E2 state 190) */,
                       /* 1 */ 0x04  /* (to 0x00E8 state 197) */,
/* pos 00e2: 190 */    /* 0 */ 0x01  /* (to 0x00E4 state 191) */,
                       /* 1 */ 0x02  /* (to 0x00E6 state 194) */,
/* pos 00e4: 191 */     /* terminal 77 */ 0x4D,
                        /* terminal 78 */ 0x4E,
/* pos 00e6: 194 */     /* terminal 79 */ 0x4F,
                        /* terminal 80 */ 0x50,
/* pos 00e8: 197 */    /* 0 */ 0x01  /* (to 0x00EA state 198) */,
                       /* 1 */ 0x02  /* (to 0x00EC state 201) */,
/* pos 00ea: 198 */     /* terminal 81 */ 0x51,
                        /* terminal 82 */ 0x52,
/* pos 00ec: 201 */     /* terminal 83 */ 0x53,
                        /* terminal 84 */ 0x54,
/* pos 00ee: 204 */    /* 0 */ 0x01  /* (to 0x00F0 state 205) */,
                       /* 1 */ 0x11  /* (to 0x0110 state 242) */,
/* pos 00f0: 205 */    /* 0 */ 0x01  /* (to 0x00F2 state 206) */,
                       /* 1 */ 0x02  /* (to 0x00F4 state 209) */,
/* pos 00f2: 206 */     /* terminal 85 */ 0x55,
                        /* terminal 86 */ 0x56,
/* pos 00f4: 209 */     /* terminal 87 */ 0x57,
                        /* terminal 89 */ 0x59,
/* pos 00f6: 211 */     /* terminal 88 */ 0x58,
                        /* terminal 90 */ 0x5A,
/* pos 00f8: 216 */    /* 0 */ 0x01  /* (to 0x00FA state 217) */,
                       /* 1 */ 0x1F  /* (to 0x0136 state 286) */,
/* pos 00fa: 217 */    /* 0 */ 0x01  /* (to 0x00FC state 218) */,
                       /* 1 */ 0x17  /* (to 0x0128 state 276) */,
/* pos 00fc: 218 */     /* terminal 92 */ 0x5C,
                        /* terminal 195 */ 0xC3,
/* pos 00fe: 220 */     /* terminal 93 */ 0x5D,
                        /* terminal 126 */ 0x7E,
/* pos 0100: 222 */     /* terminal 94 */ 0x5E,
                        /* terminal 125 */ 0x7D,
/* pos 0102: 224 */     /* terminal 95 */ 0x5F,
                        /* terminal 98 */ 0x62,
/* pos 0104: 229 */    /* 0 */ 0x01  /* (to 0x0106 state 230) */,
                       /* 1 */ 0x05  /* (to 0x010E state 240) */,
/* pos 0106: 230 */     /* terminal 99 */ 0x63,
                        /* terminal 101 */ 0x65,
/* pos 0108: 232 */    /* 0 */ 0x01  /* (to 0x010A state 233) */,
                       /* 1 */ 0x02  /* (to 0x010C state 237) */,
/* pos 010a: 233 */     /* terminal 100 */ 0x64,
                        /* terminal 102 */ 0x66,
/* pos 010c: 237 */     /* terminal 103 */ 0x67,
                        /* terminal 104 */ 0x68,
/* pos 010e: 240 */     /* terminal 105 */ 0x69,
                        /* terminal 111 */ 0x6F,
/* pos 0110: 242 */    /* 0 */ 0x01  /* (to 0x0112 state 243) */,
                       /* 1 */ 0x05  /* (to 0x011A state 254) */,
/* pos 0112: 243 */     /* terminal 106 */ 0x6A,
                        /* terminal 107 */ 0x6B,
/* pos 0114: 246 */    /* 0 */ 0x01  /* (to 0x0116 state 247) */,
                       /* 1 */ 0x02  /* (to 0x0118 state 250) */,
/* pos 0116: 247 */     /* terminal 108 */ 0x6C,
                        /* terminal 109 */ 0x6D,
/* pos 0118: 250 */     /* terminal 110 */ 0x6E,
                        /* terminal 112 */ 0x70,
/* pos 011a: 254 */     /* terminal 113 */ 0x71,
                        /* terminal 118 */ 0x76,
/* pos 011c: 256 */     /* terminal 114 */ 0x72,
                        /* terminal 117 */ 0x75,
/* pos 011e: 258 */     /* terminal 115 */ 0x73,
                        /* terminal 116 */ 0x74,
/* pos 0120: 263 */    /* 0 */ 0x01  /* (to 0x0122 state 264) */,
                       /* 1 */ 0x02  /* (to 0x0124 state 267) */,
/* pos 0122: 264 */     /* terminal 119 */ 0x77,
                        /* terminal 120 */ 0x78,
/* pos 0124: 267 */     /* terminal 121 */ 0x79,
                        /* terminal 122 */ 0x7A,
/* pos 0126: 274 */     /* terminal 127 */ 0x7F,
                        /* terminal 220 */ 0xDC,
/* pos 0128: 276 */     /* terminal 208 */ 0xD0,
                       /* 1 */ 0x01  /* (to 0x012A state 277) */,
/* pos 012a: 277 */     /* terminal 128 */ 0x80,
                        /* terminal 130 */ 0x82,
/* pos 012c: 279 */    /* 0 */ 0x2E  /* (to 0x0188 state 372) */,
                       /* 1 */ 0x01  /* (to 0x012E state 280) */,
/* pos 012e: 280 */    /* 0 */ 0x01  /* (to 0x0130 state 281) */,
                       /* 1 */ 0x1B  /* (to 0x0164 state 332) */,
/* pos 0130: 281 */    /* 0 */ 0x01  /* (to 0x0132 state 282) */,
                       /* 1 */ 0x06  /* (to 0x013C state 291) */,
/* pos 0132: 282 */     /* terminal 230 */ 0xE6,
                       /* 1 */ 0x01  /* (to 0x0134 state 283) */,
/* pos 0134: 283 */     /* terminal 129 */ 0x81,
                        /* terminal 132 */ 0x84,
/* pos 0136: 286 */    /* 0 */ 0x01  /* (to 0x0138 state 287) */,
                       /* 1 */ 0x14  /* (to 0x015E state 328) */,
/* pos 0138: 287 */    /* 0 */ 0x01  /* (to 0x013A state 288) */,
                       /* 1 */ 0x30  /* (to 0x0198 state 388) */,
/* pos 013a: 288 */     /* terminal 131 */ 0x83,
                        /* terminal 162 */ 0xA2,
/* pos 013c: 291 */    /* 0 */ 0x01  /* (to 0x013E state 292) */,
                       /* 1 */ 0x02  /* (to 0x0140 state 296) */,
/* pos 013e: 292 */     /* terminal 133 */ 0x85,
                        /* terminal 134 */ 0x86,
/* pos 0140: 296 */     /* terminal 136 */ 0x88,
                        /* terminal 146 */ 0x92,
/* pos 0142: 298 */     /* terminal 137 */ 0x89,
                        /* terminal 138 */ 0x8A,
/* pos 0144: 301 */    /* 0 */ 0x01  /* (to 0x0146 state 302) */,
                       /* 1 */ 0x02  /* (to 0x0148 state 305) */,
/* pos 0146: 302 */     /* terminal 139 */ 0x8B,
                        /* terminal 140 */ 0x8C,
/* pos 0148: 305 */     /* terminal 141 */ 0x8D,
                        /* terminal 143 */ 0x8F,
/* pos 014a: 309 */    /* 0 */ 0x01  /* (to 0x014C state 310) */,
                       /* 1 */ 0x06  /* (to 0x0156 state 319) */,
/* pos 014c: 310 */     /* terminal 144 */ 0x90,
                        /* terminal 145 */ 0x91,
/* pos 014e: 314 */    /* 0 */ 0x01  /* (to 0x0150 state 315) */,
                       /* 1 */ 0x12  /* (to 0x0172 state 350) */,
/* pos 0150: 315 */    /* 0 */ 0x01  /* (to 0x0152 state 316) */,
                       /* 1 */ 0x05  /* (to 0x015A state 325) */,
/* pos 0152: 316 */    /* 0 */ 0x01  /* (to 0x0154 state 317) */,
                       /* 1 */ 0x03  /* (to 0x0158 state 322) */,
/* pos 0154: 317 */     /* terminal 147 */ 0x93,
                        /* terminal 149 */ 0x95,
/* pos 0156: 319 */     /* terminal 148 */ 0x94,
                        /* terminal 159 */ 0x9F,
/* pos 0158: 322 */     /* terminal 150 */ 0x96,
                        /* terminal 151 */ 0x97,
/* pos 015a: 325 */    /* 0 */ 0x01  /* (to 0x015C state 326) */,
                       /* 1 */ 0x08  /* (to 0x016A state 338) */,
/* pos 015c: 326 */     /* terminal 152 */ 0x98,
                        /* terminal 155 */ 0x9B,
/* pos 015e: 328 */    /* 0 */ 0x42  /* (to 0x01E2 state 465) */,
                       /* 1 */ 0x01  /* (to 0x0160 state 329) */,
/* pos 0160: 329 */    /* 0 */ 0x01  /* (to 0x0162 state 330) */,
                       /* 1 */ 0x0C  /* (to 0x0178 state 355) */,
/* pos 0162: 330 */     /* terminal 153 */ 0x99,
                        /* terminal 161 */ 0xA1,
/* pos 0164: 332 */    /* 0 */ 0x01  /* (to 0x0166 state 333) */,
                       /* 1 */ 0x05  /* (to 0x016E state 347) */,
/* pos 0166: 333 */    /* 0 */ 0x01  /* (to 0x0168 state 334) */,
                       /* 1 */ 0x03  /* (to 0x016C state 342) */,
/* pos 0168: 334 */     /* terminal 154 */ 0x9A,
                        /* terminal 156 */ 0x9C,
/* pos 016a: 338 */     /* terminal 157 */ 0x9D,
                        /* terminal 158 */ 0x9E,
/* pos 016c: 342 */     /* terminal 160 */ 0xA0,
                        /* terminal 163 */ 0xA3,
/* pos 016e: 347 */    /* 0 */ 0x01  /* (to 0x0170 state 348) */,
                       /* 1 */ 0x07  /* (to 0x017C state 360) */,
/* pos 0170: 348 */     /* terminal 164 */ 0xA4,
                        /* terminal 169 */ 0xA9,
/* pos 0172: 350 */    /* 0 */ 0x01  /* (to 0x0174 state 351) */,
                       /* 1 */ 0x09  /* (to 0x0184 state 369) */,
/* pos 0174: 351 */    /* 0 */ 0x01  /* (to 0x0176 state 352) */,
                       /* 1 */ 0x03  /* (to 0x017A state 357) */,
/* pos 0176: 352 */     /* terminal 165 */ 0xA5,
                        /* terminal 166 */ 0xA6,
/* pos 0178: 355 */     /* terminal 167 */ 0xA7,
                        /* terminal 172 */ 0xAC,
/* pos 017a: 357 */     /* terminal 168 */ 0xA8,
                        /* terminal 174 */ 0xAE,
/* pos 017c: 360 */     /* terminal 170 */ 0xAA,
                        /* terminal 173 */ 0xAD,
/* pos 017e: 362 */    /* 0 */ 0x01  /* (to 0x0180 state 363) */,
                       /* 1 */ 0x1B  /* (to 0x01B4 state 417) */,
/* pos 0180: 363 */    /* 0 */ 0x01  /* (to 0x0182 state 364) */,
                       /* 1 */ 0x2A  /* (to 0x01D4 state 449) */,
/* pos 0182: 364 */     /* terminal 171 */ 0xAB,
                        /* terminal 206 */ 0xCE,
/* pos 0184: 369 */    /* 0 */ 0x01  /* (to 0x0186 state 370) */,
                       /* 1 */ 0x09  /* (to 0x0196 state 385) */,
/* pos 0186: 370 */     /* terminal 175 */ 0xAF,
                        /* terminal 180 */ 0xB4,
/* pos 0188: 372 */    /* 0 */ 0x01  /* (to 0x018A state 373) */,
                       /* 1 */ 0x27  /* (to 0x01D6 state 451) */,
/* pos 018a: 373 */    /* 0 */ 0x01  /* (to 0x018C state 374) */,
                       /* 1 */ 0x05  /* (to 0x0194 state 381) */,
/* pos 018c: 374 */     /* terminal 176 */ 0xB0,
                        /* terminal 177 */ 0xB1,
/* pos 018e: 377 */    /* 0 */ 0x01  /* (to 0x0190 state 378) */,
                       /* 1 */ 0x07  /* (to 0x019C state 393) */,
/* pos 0190: 378 */    /* 0 */ 0x01  /* (to 0x0192 state 379) */,
                       /* 1 */ 0x05  /* (to 0x019A state 390) */,
/* pos 0192: 379 */     /* terminal 178 */ 0xB2,
                        /* terminal 181 */ 0xB5,
/* pos 0194: 381 */     /* terminal 179 */ 0xB3,
                        /* terminal 209 */ 0xD1,
/* pos 0196: 385 */     /* terminal 182 */ 0xB6,
                        /* terminal 183 */ 0xB7,
/* pos 0198: 388 */     /* terminal 184 */ 0xB8,
                        /* terminal 194 */ 0xC2,
/* pos 019a: 390 */     /* terminal 185 */ 0xB9,
                        /* terminal 186 */ 0xBA,
/* pos 019c: 393 */    /* 0 */ 0x01  /* (to 0x019E state 394) */,
                       /* 1 */ 0x04  /* (to 0x01A4 state 400) */,
/* pos 019e: 394 */     /* terminal 187 */ 0xBB,
                        /* terminal 189 */ 0xBD,
/* pos 01a0: 396 */    /* 0 */ 0x01  /* (to 0x01A2 state 397) */,
                       /* 1 */ 0x07  /* (to 0x01AE state 412) */,
/* pos 01a2: 397 */     /* terminal 188 */ 0xBC,
                        /* terminal 191 */ 0xBF,
/* pos 01a4: 400 */     /* terminal 190 */ 0xBE,
                        /* terminal 196 */ 0xC4,
/* pos 01a6: 403 */    /* 0 */ 0x01  /* (to 0x01A8 state 404) */,
                       /* 1 */ 0x0D  /* (to 0x01C0 state 427) */,
/* pos 01a8: 404 */    /* 0 */ 0x01  /* (to 0x01AA state 405) */,
                       /* 1 */ 0x0A  /* (to 0x01BC state 424) */,
/* pos 01aa: 405 */    /* 0 */ 0x01  /* (to 0x01AC state 406) */,
                       /* 1 */ 0x08  /* (to 0x01BA state 421) */,
/* pos 01ac: 406 */     /* terminal 192 */ 0xC0,
                        /* terminal 193 */ 0xC1,
/* pos 01ae: 412 */     /* terminal 197 */ 0xC5,
                        /* terminal 231 */ 0xE7,
/* pos 01b0: 414 */    /* 0 */ 0x01  /* (to 0x01B2 state 415) */,
                       /* 1 */ 0x1B  /* (to 0x01E6 state 475) */,
/* pos 01b2: 415 */     /* terminal 198 */ 0xC6,
                        /* terminal 228 */ 0xE4,
/* pos 01b4: 417 */    /* 0 */ 0x1B  /* (to 0x01EA state 481) */,
                       /* 1 */ 0x01  /* (to 0x01B6 state 418) */,
/* pos 01b6: 418 */    /* 0 */ 0x01  /* (to 0x01B8 state 419) */,
                       /* 1 */ 0x19  /* (to 0x01E8 state 478) */,
/* pos 01b8: 419 */     /* terminal 199 */ 0xC7,
                        /* terminal 207 */ 0xCF,
/* pos 01ba: 421 */     /* terminal 200 */ 0xC8,
                        /* terminal 201 */ 0xC9,
/* pos 01bc: 424 */    /* 0 */ 0x01  /* (to 0x01BE state 425) */,
                       /* 1 */ 0x06  /* (to 0x01C8 state 438) */,
/* pos 01be: 425 */     /* terminal 202 */ 0xCA,
                        /* terminal 205 */ 0xCD,
/* pos 01c0: 427 */    /* 0 */ 0x0D  /* (to 0x01DA state 455) */,
                       /* 1 */ 0x01  /* (to 0x01C2 state 428) */,
/* pos 01c2: 428 */    /* 0 */ 0x17  /* (to 0x01F0 state 490) */,
                       /* 1 */ 0x01  /* (to 0x01C4 state 429) */,
/* pos 01c4: 429 */     /* terminal 255 */ 0xFF,
                       /* 1 */ 0x01  /* (to 0x01C6 state 430) */,
/* pos 01c6: 430 */     /* terminal 203 */ 0xCB,
                        /* terminal 204 */ 0xCC,
/* pos 01c8: 438 */     /* terminal 210 */ 0xD2,
                        /* terminal 213 */ 0xD5,
/* pos 01ca: 440 */    /* 0 */ 0x01  /* (to 0x01CC state 441) */,
                       /* 1 */ 0x14  /* (to 0x01F2 state 494) */,
/* pos 01cc: 441 */    /* 0 */ 0x01  /* (to 0x01CE state 442) */,
                       /* 1 */ 0x09  /* (to 0x01DE state 461) */,
/* pos 01ce: 442 */    /* 0 */ 0x01  /* (to 0x01D0 state 443) */,
                       /* 1 */ 0x02  /* (to 0x01D2 state 447) */,
/* pos 01d0: 443 */     /* terminal 211 */ 0xD3,
                        /* terminal 212 */ 0xD4,
/* pos 01d2: 447 */     /* terminal 214 */ 0xD6,
                        /* terminal 221 */ 0xDD,
/* pos 01d4: 449 */     /* terminal 215 */ 0xD7,
                        /* terminal 225 */ 0xE1,
/* pos 01d6: 451 */    /* 0 */ 0x01  /* (to 0x01D8 state 452) */,
                       /* 1 */ 0x07  /* (to 0x01E4 state 469) */,
/* pos 01d8: 452 */     /* terminal 216 */ 0xD8,
                        /* terminal 217 */ 0xD9,
/* pos 01da: 455 */    /* 0 */ 0x01  /* (to 0x01DC state 456) */,
                       /* 1 */ 0x09  /* (to 0x01EC state 484) */,
/* pos 01dc: 456 */     /* terminal 218 */ 0xDA,
                        /* terminal 219 */ 0xDB,
/* pos 01de: 461 */    /* 0 */ 0x01  /* (to 0x01E0 state 462) */,
                       /* 1 */ 0x08  /* (to 0x01EE state 488) */,
/* pos 01e0: 462 */     /* terminal 222 */ 0xDE,
                        /* terminal 223 */ 0xDF,
/* pos 01e2: 465 */     /* terminal 224 */ 0xE0,
                        /* terminal 226 */ 0xE2,
/* pos 01e4: 469 */     /* terminal 227 */ 0xE3,
                        /* terminal 229 */ 0xE5,
/* pos 01e6: 475 */     /* terminal 232 */ 0xE8,
                        /* terminal 233 */ 0xE9,
/* pos 01e8: 478 */     /* terminal 234 */ 0xEA,
                        /* terminal 235 */ 0xEB,
/* pos 01ea: 481 */     /* terminal 236 */ 0xEC,
                        /* terminal 237 */ 0xED,
/* pos 01ec: 484 */     /* terminal 238 */ 0xEE,
                        /* terminal 240 */ 0xF0,
/* pos 01ee: 488 */     /* terminal 241 */ 0xF1,
                        /* terminal 244 */ 0xF4,
/* pos 01f0: 490 */     /* terminal 242 */ 0xF2,
                        /* terminal 243 */ 0xF3,
/* pos 01f2: 494 */    /* 0 */ 0x01  /* (to 0x01F4 state 495) */,
                       /* 1 */ 0x04  /* (to 0x01FA state 503) */,
/* pos 01f4: 495 */    /* 0 */ 0x01  /* (to 0x01F6 state 496) */,
                       /* 1 */ 0x02  /* (to 0x01F8 state 499) */,
/* pos 01f6: 496 */     /* terminal 245 */ 0xF5,
                        /* terminal 246 */ 0xF6,
/* pos 01f8: 499 */     /* terminal 247 */ 0xF7,
                        /* terminal 248 */ 0xF8,
/* pos 01fa: 503 */    /* 0 */ 0x01  /* (to 0x01FC state 504) */,
                       /* 1 */ 0x02  /* (to 0x01FE state 507) */,
/* pos 01fc: 504 */     /* terminal 250 */ 0xFA,
                        /* terminal 251 */ 0xFB,
/* pos 01fe: 507 */     /* terminal 252 */ 0xFC,
                        /* terminal 253 */ 0xFD,
/* total size 512 bytes, biggest jump 200/256, fails=0 */
};

 static unsigned char lextable_terms[] = {

	0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 
	0x34, 0x0f, 0x43, 0x03, 0xf1, 0x3c, 0xfc, 0x3c, 
	0x0f, 0x30, 0x37, 0xf7, 0x0f, 0xc3, 0xcf, 0x03, 
	0x3c, 0xfc, 0xc0, 0xf3, 0xf0, 0x3c, 0xfc, 0xf0, 
	0xcf, 0xfc, 0xcc, 0xff, 0xfc, 0x0d, 0x34, 0xcc, 
	0xcf, 0x33, 0xf0, 0x33, 0x0c, 0x3f, 0xc3, 0x3f, 
	0xcc, 0x30, 0xfc, 0xcf, 0x3c, 0xf0, 0x0c, 0xcf, 
	0xd0, 0x03, 0x3f, 0x33, 0xff, 0xff, 0xc3, 0xf3, 
};

/* state that points to 0x100 for disambiguation with 0x0 */
#define HUFTABLE_0x100_PREV 118

Added undroid/libwebsockets/lib/lextable-strings.h.































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/* set of parsable strings -- ALL LOWER CASE */

static const char *set[] = {
	"get ",
	"post ",
	"options ",
	"host:",
	"connection:",
	"upgrade:",
	"origin:",
	"sec-websocket-draft:",
	"\x0d\x0a",

	"sec-websocket-extensions:",
	"sec-websocket-key1:",
	"sec-websocket-key2:",
	"sec-websocket-protocol:",

	"sec-websocket-accept:",
	"sec-websocket-nonce:",
	"http/1.1 ",
	"http2-settings:",

	"accept:",
	"access-control-request-headers:",
	"if-modified-since:",
	"if-none-match:",
	"accept-encoding:",
	"accept-language:",
	"pragma:",
	"cache-control:",
	"authorization:",
	"cookie:",
	"content-length:",
	"content-type:",
	"date:",
	"range:",
	"referer:",
	"sec-websocket-key:",
	"sec-websocket-version:",
	"sec-websocket-origin:",

	":authority",
	":method",
	":path",
	":scheme",
	":status",

	"accept-charset:",
	"accept-ranges:",
	"access-control-allow-origin:",
	"age:",
	"allow:",
	"content-disposition:",
	"content-encoding:",
	"content-language:",
	"content-location:",
	"content-range:",
	"etag:",
	"expect:",
	"expires:",
	"from:",
	"if-match:",
	"if-range:",
	"if-unmodified-since:",
	"last-modified:",
	"link:",
	"location:",
	"max-forwards:",
	"proxy-authenticate:",
	"proxy-authorization:",
	"refresh:",
	"retry-after:",
	"server:",
	"set-cookie:",
	"strict-transport-security:",
	"transfer-encoding:",
	"user-agent:",
	"vary:",
	"via:",
	"www-authenticate:",

	"patch",
	"put",
	"delete",

	"uri-args", /* fake header used for uri-only storage */

	"proxy ",
	"x-real-ip:",
	"http/1.0 ",

	"", /* not matchable */

};

Added undroid/libwebsockets/lib/lextable.h.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
/* pos 0000:   0 */    0x67 /* 'g' */, 0x40, 0x00  /* (to 0x0040 state   1) */,
                       0x70 /* 'p' */, 0x42, 0x00  /* (to 0x0045 state   5) */,
                       0x6F /* 'o' */, 0x51, 0x00  /* (to 0x0057 state  10) */,
                       0x68 /* 'h' */, 0x5D, 0x00  /* (to 0x0066 state  18) */,
                       0x63 /* 'c' */, 0x66, 0x00  /* (to 0x0072 state  23) */,
                       0x75 /* 'u' */, 0x81, 0x00  /* (to 0x0090 state  34) */,
                       0x73 /* 's' */, 0x97, 0x00  /* (to 0x00A9 state  48) */,
                       0x0D /* '.' */, 0xD0, 0x00  /* (to 0x00E5 state  68) */,
                       0x61 /* 'a' */, 0x28, 0x01  /* (to 0x0140 state 129) */,
                       0x69 /* 'i' */, 0x67, 0x01  /* (to 0x0182 state 163) */,
                       0x64 /* 'd' */, 0x10, 0x02  /* (to 0x022E state 265) */,
                       0x72 /* 'r' */, 0x19, 0x02  /* (to 0x023A state 270) */,
                       0x3A /* ':' */, 0x4A, 0x02  /* (to 0x026E state 299) */,
                       0x65 /* 'e' */, 0xD6, 0x02  /* (to 0x02FD state 409) */,
                       0x66 /* 'f' */, 0xF2, 0x02  /* (to 0x031C state 425) */,
                       0x6C /* 'l' */, 0x14, 0x03  /* (to 0x0341 state 458) */,
                       0x6D /* 'm' */, 0x37, 0x03  /* (to 0x0367 state 484) */,
                       0x74 /* 't' */, 0xA6, 0x03  /* (to 0x03D9 state 578) */,
                       0x76 /* 'v' */, 0xC1, 0x03  /* (to 0x03F7 state 606) */,
                       0x77 /* 'w' */, 0xCE, 0x03  /* (to 0x0407 state 614) */,
                       0x78 /* 'x' */, 0xF5, 0x03  /* (to 0x0431 state 650) */,
                       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' */, 0x8C, 0x01  /* (to 0x01D4 state 211) */,
                       0x61 /* 'a' */, 0xCE, 0x03  /* (to 0x0419 state 631) */,
                       0x75 /* 'u' */, 0xD0, 0x03  /* (to 0x041E state 635) */,
                       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 */    0x70 /* 'p' */, 0x07, 0x00  /* (to 0x005E state  11) */,
                       0x72 /* 'r' */, 0x48, 0x00  /* (to 0x00A2 state  42) */,
                       0x08, /* fail */
/* pos 005e:  11 */    0xF4 /* 't' -> */,
/* pos 005f:  12 */    0xE9 /* 'i' -> */,
/* pos 0060:  13 */    0xEF /* 'o' -> */,
/* pos 0061:  14 */    0xEE /* 'n' -> */,
/* pos 0062:  15 */    0xF3 /* 's' -> */,
/* pos 0063:  16 */    0xA0 /* ' ' -> */,
/* pos 0064:  17 */    0x00, 0x02                  /* - terminal marker  2 - */,
/* pos 0066:  18 */    0x6F /* 'o' */, 0x07, 0x00  /* (to 0x006D state  19) */,
                       0x74 /* 't' */, 0xB6, 0x00  /* (to 0x011F state 110) */,
                       0x08, /* fail */
/* pos 006d:  19 */    0xF3 /* 's' -> */,
/* pos 006e:  20 */    0xF4 /* 't' -> */,
/* pos 006f:  21 */    0xBA /* ':' -> */,
/* pos 0070:  22 */    0x00, 0x03                  /* - terminal marker  3 - */,
/* pos 0072:  23 */    0x6F /* 'o' */, 0x07, 0x00  /* (to 0x0079 state  24) */,
                       0x61 /* 'a' */, 0x6C, 0x01  /* (to 0x01E1 state 217) */,
                       0x08, /* fail */
/* pos 0079:  24 */    0x6E /* 'n' */, 0x07, 0x00  /* (to 0x0080 state  25) */,
                       0x6F /* 'o' */, 0x81, 0x01  /* (to 0x01FD state 243) */,
                       0x08, /* fail */
/* pos 0080:  25 */    0x6E /* 'n' */, 0x07, 0x00  /* (to 0x0087 state  26) */,
                       0x74 /* 't' */, 0x80, 0x01  /* (to 0x0203 state 248) */,
                       0x08, /* fail */
/* pos 0087:  26 */    0xE5 /* 'e' -> */,
/* pos 0088:  27 */    0xE3 /* 'c' -> */,
/* pos 0089:  28 */    0xF4 /* 't' -> */,
/* pos 008a:  29 */    0xE9 /* 'i' -> */,
/* pos 008b:  30 */    0xEF /* 'o' -> */,
/* pos 008c:  31 */    0xEE /* 'n' -> */,
/* pos 008d:  32 */    0xBA /* ':' -> */,
/* pos 008e:  33 */    0x00, 0x04                  /* - terminal marker  4 - */,
/* pos 0090:  34 */    0x70 /* 'p' */, 0x0A, 0x00  /* (to 0x009A state  35) */,
                       0x73 /* 's' */, 0x59, 0x03  /* (to 0x03EC state 596) */,
                       0x72 /* 'r' */, 0x91, 0x03  /* (to 0x0427 state 642) */,
                       0x08, /* fail */
/* pos 009a:  35 */    0xE7 /* 'g' -> */,
/* pos 009b:  36 */    0xF2 /* 'r' -> */,
/* pos 009c:  37 */    0xE1 /* 'a' -> */,
/* pos 009d:  38 */    0xE4 /* 'd' -> */,
/* pos 009e:  39 */    0xE5 /* 'e' -> */,
/* pos 009f:  40 */    0xBA /* ':' -> */,
/* pos 00a0:  41 */    0x00, 0x05                  /* - terminal marker  5 - */,
/* pos 00a2:  42 */    0xE9 /* 'i' -> */,
/* pos 00a3:  43 */    0xE7 /* 'g' -> */,
/* pos 00a4:  44 */    0xE9 /* 'i' -> */,
/* pos 00a5:  45 */    0xEE /* 'n' -> */,
/* pos 00a6:  46 */    0xBA /* ':' -> */,
/* pos 00a7:  47 */    0x00, 0x06                  /* - terminal marker  6 - */,
/* pos 00a9:  48 */    0x65 /* 'e' */, 0x07, 0x00  /* (to 0x00B0 state  49) */,
                       0x74 /* 't' */, 0x13, 0x03  /* (to 0x03BF state 553) */,
                       0x08, /* fail */
/* pos 00b0:  49 */    0x63 /* 'c' */, 0x0A, 0x00  /* (to 0x00BA state  50) */,
                       0x72 /* 'r' */, 0xFC, 0x02  /* (to 0x03AF state 539) */,
                       0x74 /* 't' */, 0xFF, 0x02  /* (to 0x03B5 state 544) */,
                       0x08, /* fail */
/* pos 00ba:  50 */    0xAD /* '-' -> */,
/* pos 00bb:  51 */    0xF7 /* 'w' -> */,
/* pos 00bc:  52 */    0xE5 /* 'e' -> */,
/* pos 00bd:  53 */    0xE2 /* 'b' -> */,
/* pos 00be:  54 */    0xF3 /* 's' -> */,
/* pos 00bf:  55 */    0xEF /* 'o' -> */,
/* pos 00c0:  56 */    0xE3 /* 'c' -> */,
/* pos 00c1:  57 */    0xEB /* 'k' -> */,
/* pos 00c2:  58 */    0xE5 /* 'e' -> */,
/* pos 00c3:  59 */    0xF4 /* 't' -> */,
/* pos 00c4:  60 */    0xAD /* '-' -> */,
/* pos 00c5:  61 */    0x64 /* 'd' */, 0x19, 0x00  /* (to 0x00DE state  62) */,
                       0x65 /* 'e' */, 0x20, 0x00  /* (to 0x00E8 state  70) */,
                       0x6B /* 'k' */, 0x29, 0x00  /* (to 0x00F4 state  81) */,
                       0x70 /* 'p' */, 0x38, 0x00  /* (to 0x0106 state  88) */,
                       0x61 /* 'a' */, 0x3F, 0x00  /* (to 0x0110 state  97) */,
                       0x6E /* 'n' */, 0x44, 0x00  /* (to 0x0118 state 104) */,
                       0x76 /* 'v' */, 0x86, 0x01  /* (to 0x025D state 284) */,
                       0x6F /* 'o' */, 0x8C, 0x01  /* (to 0x0266 state 292) */,
                       0x08, /* fail */
/* pos 00de:  62 */    0xF2 /* 'r' -> */,
/* pos 00df:  63 */    0xE1 /* 'a' -> */,
/* pos 00e0:  64 */    0xE6 /* 'f' -> */,
/* pos 00e1:  65 */    0xF4 /* 't' -> */,
/* pos 00e2:  66 */    0xBA /* ':' -> */,
/* pos 00e3:  67 */    0x00, 0x07                  /* - terminal marker  7 - */,
/* pos 00e5:  68 */    0x8A /* '.' -> */,
/* pos 00e6:  69 */    0x00, 0x08                  /* - terminal marker  8 - */,
/* pos 00e8:  70 */    0xF8 /* 'x' -> */,
/* pos 00e9:  71 */    0xF4 /* 't' -> */,
/* pos 00ea:  72 */    0xE5 /* 'e' -> */,
/* pos 00eb:  73 */    0xEE /* 'n' -> */,
/* pos 00ec:  74 */    0xF3 /* 's' -> */,
/* pos 00ed:  75 */    0xE9 /* 'i' -> */,
/* pos 00ee:  76 */    0xEF /* 'o' -> */,
/* pos 00ef:  77 */    0xEE /* 'n' -> */,
/* pos 00f0:  78 */    0xF3 /* 's' -> */,
/* pos 00f1:  79 */    0xBA /* ':' -> */,
/* pos 00f2:  80 */    0x00, 0x09                  /* - terminal marker  9 - */,
/* pos 00f4:  81 */    0xE5 /* 'e' -> */,
/* pos 00f5:  82 */    0xF9 /* 'y' -> */,
/* pos 00f6:  83 */    0x31 /* '1' */, 0x0A, 0x00  /* (to 0x0100 state  84) */,
                       0x32 /* '2' */, 0x0A, 0x00  /* (to 0x0103 state  86) */,
                       0x3A /* ':' */, 0x5F, 0x01  /* (to 0x025B state 283) */,
                       0x08, /* fail */
/* pos 0100:  84 */    0xBA /* ':' -> */,
/* pos 0101:  85 */    0x00, 0x0A                  /* - terminal marker 10 - */,
/* pos 0103:  86 */    0xBA /* ':' -> */,
/* pos 0104:  87 */    0x00, 0x0B                  /* - terminal marker 11 - */,
/* pos 0106:  88 */    0xF2 /* 'r' -> */,
/* pos 0107:  89 */    0xEF /* 'o' -> */,
/* pos 0108:  90 */    0xF4 /* 't' -> */,
/* pos 0109:  91 */    0xEF /* 'o' -> */,
/* pos 010a:  92 */    0xE3 /* 'c' -> */,
/* pos 010b:  93 */    0xEF /* 'o' -> */,
/* pos 010c:  94 */    0xEC /* 'l' -> */,
/* pos 010d:  95 */    0xBA /* ':' -> */,
/* pos 010e:  96 */    0x00, 0x0C                  /* - terminal marker 12 - */,
/* pos 0110:  97 */    0xE3 /* 'c' -> */,
/* pos 0111:  98 */    0xE3 /* 'c' -> */,
/* pos 0112:  99 */    0xE5 /* 'e' -> */,
/* pos 0113: 100 */    0xF0 /* 'p' -> */,
/* pos 0114: 101 */    0xF4 /* 't' -> */,
/* pos 0115: 102 */    0xBA /* ':' -> */,
/* pos 0116: 103 */    0x00, 0x0D                  /* - terminal marker 13 - */,
/* pos 0118: 104 */    0xEF /* 'o' -> */,
/* pos 0119: 105 */    0xEE /* 'n' -> */,
/* pos 011a: 106 */    0xE3 /* 'c' -> */,
/* pos 011b: 107 */    0xE5 /* 'e' -> */,
/* pos 011c: 108 */    0xBA /* ':' -> */,
/* pos 011d: 109 */    0x00, 0x0E                  /* - terminal marker 14 - */,
/* pos 011f: 110 */    0xF4 /* 't' -> */,
/* pos 0120: 111 */    0xF0 /* 'p' -> */,
/* pos 0121: 112 */    0x2F /* '/' */, 0x07, 0x00  /* (to 0x0128 state 113) */,
                       0x32 /* '2' */, 0x10, 0x00  /* (to 0x0134 state 118) */,
                       0x08, /* fail */
/* pos 0128: 113 */    0xB1 /* '1' -> */,
/* pos 0129: 114 */    0xAE /* '.' -> */,
/* pos 012a: 115 */    0x31 /* '1' */, 0x07, 0x00  /* (to 0x0131 state 116) */,
                       0x30 /* '0' */, 0x0F, 0x03  /* (to 0x043C state 660) */,
                       0x08, /* fail */
/* pos 0131: 116 */    0xA0 /* ' ' -> */,
/* pos 0132: 117 */    0x00, 0x0F                  /* - terminal marker 15 - */,
/* pos 0134: 118 */    0xAD /* '-' -> */,
/* pos 0135: 119 */    0xF3 /* 's' -> */,
/* pos 0136: 120 */    0xE5 /* 'e' -> */,
/* pos 0137: 121 */    0xF4 /* 't' -> */,
/* pos 0138: 122 */    0xF4 /* 't' -> */,
/* pos 0139: 123 */    0xE9 /* 'i' -> */,
/* pos 013a: 124 */    0xEE /* 'n' -> */,
/* pos 013b: 125 */    0xE7 /* 'g' -> */,
/* pos 013c: 126 */    0xF3 /* 's' -> */,
/* pos 013d: 127 */    0xBA /* ':' -> */,
/* pos 013e: 128 */    0x00, 0x10                  /* - terminal marker 16 - */,
/* pos 0140: 129 */    0x63 /* 'c' */, 0x0D, 0x00  /* (to 0x014D state 130) */,
                       0x75 /* 'u' */, 0xAC, 0x00  /* (to 0x01EF state 230) */,
                       0x67 /* 'g' */, 0x7D, 0x01  /* (to 0x02C3 state 358) */,
                       0x6C /* 'l' */, 0x7E, 0x01  /* (to 0x02C7 state 361) */,
                       0x08, /* fail */
/* pos 014d: 130 */    0xE3 /* 'c' -> */,
/* pos 014e: 131 */    0xE5 /* 'e' -> */,
/* pos 014f: 132 */    0x70 /* 'p' */, 0x07, 0x00  /* (to 0x0156 state 133) */,
                       0x73 /* 's' */, 0x0E, 0x00  /* (to 0x0160 state 136) */,
                       0x08, /* fail */
/* pos 0156: 133 */    0xF4 /* 't' -> */,
/* pos 0157: 134 */    0x3A /* ':' */, 0x07, 0x00  /* (to 0x015E state 135) */,
                       0x2D /* '-' */, 0x59, 0x00  /* (to 0x01B3 state 192) */,
                       0x08, /* fail */
/* pos 015e: 135 */    0x00, 0x11                  /* - terminal marker 17 - */,
/* pos 0160: 136 */    0xF3 /* 's' -> */,
/* pos 0161: 137 */    0xAD /* '-' -> */,
/* pos 0162: 138 */    0xE3 /* 'c' -> */,
/* pos 0163: 139 */    0xEF /* 'o' -> */,
/* pos 0164: 140 */    0xEE /* 'n' -> */,
/* pos 0165: 141 */    0xF4 /* 't' -> */,
/* pos 0166: 142 */    0xF2 /* 'r' -> */,
/* pos 0167: 143 */    0xEF /* 'o' -> */,
/* pos 0168: 144 */    0xEC /* 'l' -> */,
/* pos 0169: 145 */    0xAD /* '-' -> */,
/* pos 016a: 146 */    0x72 /* 'r' */, 0x07, 0x00  /* (to 0x0171 state 147) */,
                       0x61 /* 'a' */, 0x48, 0x01  /* (to 0x02B5 state 345) */,
                       0x08, /* fail */
/* pos 0171: 147 */    0xE5 /* 'e' -> */,
/* pos 0172: 148 */    0xF1 /* 'q' -> */,
/* pos 0173: 149 */    0xF5 /* 'u' -> */,
/* pos 0174: 150 */    0xE5 /* 'e' -> */,
/* pos 0175: 151 */    0xF3 /* 's' -> */,
/* pos 0176: 152 */    0xF4 /* 't' -> */,
/* pos 0177: 153 */    0xAD /* '-' -> */,
/* pos 0178: 154 */    0xE8 /* 'h' -> */,
/* pos 0179: 155 */    0xE5 /* 'e' -> */,
/* pos 017a: 156 */    0xE1 /* 'a' -> */,
/* pos 017b: 157 */    0xE4 /* 'd' -> */,
/* pos 017c: 158 */    0xE5 /* 'e' -> */,
/* pos 017d: 159 */    0xF2 /* 'r' -> */,
/* pos 017e: 160 */    0xF3 /* 's' -> */,
/* pos 017f: 161 */    0xBA /* ':' -> */,
/* pos 0180: 162 */    0x00, 0x12                  /* - terminal marker 18 - */,
/* pos 0182: 163 */    0xE6 /* 'f' -> */,
/* pos 0183: 164 */    0xAD /* '-' -> */,
/* pos 0184: 165 */    0x6D /* 'm' */, 0x0D, 0x00  /* (to 0x0191 state 166) */,
                       0x6E /* 'n' */, 0x20, 0x00  /* (to 0x01A7 state 181) */,
                       0x72 /* 'r' */, 0x9E, 0x01  /* (to 0x0328 state 435) */,
                       0x75 /* 'u' */, 0xA2, 0x01  /* (to 0x032F state 441) */,
                       0x08, /* fail */
/* pos 0191: 166 */    0x6F /* 'o' */, 0x07, 0x00  /* (to 0x0198 state 167) */,
                       0x61 /* 'a' */, 0x8E, 0x01  /* (to 0x0322 state 430) */,
                       0x08, /* fail */
/* pos 0198: 167 */    0xE4 /* 'd' -> */,
/* pos 0199: 168 */    0xE9 /* 'i' -> */,
/* pos 019a: 169 */    0xE6 /* 'f' -> */,
/* pos 019b: 170 */    0xE9 /* 'i' -> */,
/* pos 019c: 171 */    0xE5 /* 'e' -> */,
/* pos 019d: 172 */    0xE4 /* 'd' -> */,
/* pos 019e: 173 */    0xAD /* '-' -> */,
/* pos 019f: 174 */    0xF3 /* 's' -> */,
/* pos 01a0: 175 */    0xE9 /* 'i' -> */,
/* pos 01a1: 176 */    0xEE /* 'n' -> */,
/* pos 01a2: 177 */    0xE3 /* 'c' -> */,
/* pos 01a3: 178 */    0xE5 /* 'e' -> */,
/* pos 01a4: 179 */    0xBA /* ':' -> */,
/* pos 01a5: 180 */    0x00, 0x13                  /* - terminal marker 19 - */,
/* pos 01a7: 181 */    0xEF /* 'o' -> */,
/* pos 01a8: 182 */    0xEE /* 'n' -> */,
/* pos 01a9: 183 */    0xE5 /* 'e' -> */,
/* pos 01aa: 184 */    0xAD /* '-' -> */,
/* pos 01ab: 185 */    0xED /* 'm' -> */,
/* pos 01ac: 186 */    0xE1 /* 'a' -> */,
/* pos 01ad: 187 */    0xF4 /* 't' -> */,
/* pos 01ae: 188 */    0xE3 /* 'c' -> */,
/* pos 01af: 189 */    0xE8 /* 'h' -> */,
/* pos 01b0: 190 */    0xBA /* ':' -> */,
/* pos 01b1: 191 */    0x00, 0x14                  /* - terminal marker 20 - */,
/* pos 01b3: 192 */    0x65 /* 'e' */, 0x0D, 0x00  /* (to 0x01C0 state 193) */,
                       0x6C /* 'l' */, 0x14, 0x00  /* (to 0x01CA state 202) */,
                       0x63 /* 'c' */, 0xEB, 0x00  /* (to 0x02A4 state 330) */,
                       0x72 /* 'r' */, 0xF1, 0x00  /* (to 0x02AD state 338) */,
                       0x08, /* fail */
/* pos 01c0: 193 */    0xEE /* 'n' -> */,
/* pos 01c1: 194 */    0xE3 /* 'c' -> */,
/* pos 01c2: 195 */    0xEF /* 'o' -> */,
/* pos 01c3: 196 */    0xE4 /* 'd' -> */,
/* pos 01c4: 197 */    0xE9 /* 'i' -> */,
/* pos 01c5: 198 */    0xEE /* 'n' -> */,
/* pos 01c6: 199 */    0xE7 /* 'g' -> */,
/* pos 01c7: 200 */    0xBA /* ':' -> */,
/* pos 01c8: 201 */    0x00, 0x15                  /* - terminal marker 21 - */,
/* pos 01ca: 202 */    0xE1 /* 'a' -> */,
/* pos 01cb: 203 */    0xEE /* 'n' -> */,
/* pos 01cc: 204 */    0xE7 /* 'g' -> */,
/* pos 01cd: 205 */    0xF5 /* 'u' -> */,
/* pos 01ce: 206 */    0xE1 /* 'a' -> */,
/* pos 01cf: 207 */    0xE7 /* 'g' -> */,
/* pos 01d0: 208 */    0xE5 /* 'e' -> */,
/* pos 01d1: 209 */    0xBA /* ':' -> */,
/* pos 01d2: 210 */    0x00, 0x16                  /* - terminal marker 22 - */,
/* pos 01d4: 211 */    0x61 /* 'a' */, 0x07, 0x00  /* (to 0x01DB state 212) */,
                       0x6F /* 'o' */, 0x9E, 0x01  /* (to 0x0375 state 497) */,
                       0x08, /* fail */
/* pos 01db: 212 */    0xE7 /* 'g' -> */,
/* pos 01dc: 213 */    0xED /* 'm' -> */,
/* pos 01dd: 214 */    0xE1 /* 'a' -> */,
/* pos 01de: 215 */    0xBA /* ':' -> */,
/* pos 01df: 216 */    0x00, 0x17                  /* - terminal marker 23 - */,
/* pos 01e1: 217 */    0xE3 /* 'c' -> */,
/* pos 01e2: 218 */    0xE8 /* 'h' -> */,
/* pos 01e3: 219 */    0xE5 /* 'e' -> */,
/* pos 01e4: 220 */    0xAD /* '-' -> */,
/* pos 01e5: 221 */    0xE3 /* 'c' -> */,
/* pos 01e6: 222 */    0xEF /* 'o' -> */,
/* pos 01e7: 223 */    0xEE /* 'n' -> */,
/* pos 01e8: 224 */    0xF4 /* 't' -> */,
/* pos 01e9: 225 */    0xF2 /* 'r' -> */,
/* pos 01ea: 226 */    0xEF /* 'o' -> */,
/* pos 01eb: 227 */    0xEC /* 'l' -> */,
/* pos 01ec: 228 */    0xBA /* ':' -> */,
/* pos 01ed: 229 */    0x00, 0x18                  /* - terminal marker 24 - */,
/* pos 01ef: 230 */    0xF4 /* 't' -> */,
/* pos 01f0: 231 */    0xE8 /* 'h' -> */,
/* pos 01f1: 232 */    0xEF /* 'o' -> */,
/* pos 01f2: 233 */    0xF2 /* 'r' -> */,
/* pos 01f3: 234 */    0xE9 /* 'i' -> */,
/* pos 01f4: 235 */    0xFA /* 'z' -> */,
/* pos 01f5: 236 */    0xE1 /* 'a' -> */,
/* pos 01f6: 237 */    0xF4 /* 't' -> */,
/* pos 01f7: 238 */    0xE9 /* 'i' -> */,
/* pos 01f8: 239 */    0xEF /* 'o' -> */,
/* pos 01f9: 240 */    0xEE /* 'n' -> */,
/* pos 01fa: 241 */    0xBA /* ':' -> */,
/* pos 01fb: 242 */    0x00, 0x19                  /* - terminal marker 25 - */,
/* pos 01fd: 243 */    0xEB /* 'k' -> */,
/* pos 01fe: 244 */    0xE9 /* 'i' -> */,
/* pos 01ff: 245 */    0xE5 /* 'e' -> */,
/* pos 0200: 246 */    0xBA /* ':' -> */,
/* pos 0201: 247 */    0x00, 0x1A                  /* - terminal marker 26 - */,
/* pos 0203: 248 */    0xE5 /* 'e' -> */,
/* pos 0204: 249 */    0xEE /* 'n' -> */,
/* pos 0205: 250 */    0xF4 /* 't' -> */,
/* pos 0206: 251 */    0xAD /* '-' -> */,
/* pos 0207: 252 */    0x6C /* 'l' */, 0x10, 0x00  /* (to 0x0217 state 253) */,
                       0x74 /* 't' */, 0x1E, 0x00  /* (to 0x0228 state 260) */,
                       0x64 /* 'd' */, 0xC0, 0x00  /* (to 0x02CD state 366) */,
                       0x65 /* 'e' */, 0xCA, 0x00  /* (to 0x02DA state 378) */,
                       0x72 /* 'r' */, 0xE3, 0x00  /* (to 0x02F6 state 403) */,
                       0x08, /* fail */
/* pos 0217: 253 */    0x65 /* 'e' */, 0x0A, 0x00  /* (to 0x0221 state 254) */,
                       0x61 /* 'a' */, 0xCA, 0x00  /* (to 0x02E4 state 387) */,
                       0x6F /* 'o' */, 0xD0, 0x00  /* (to 0x02ED state 395) */,
                       0x08, /* fail */
/* pos 0221: 254 */    0xEE /* 'n' -> */,
/* pos 0222: 255 */    0xE7 /* 'g' -> */,
/* pos 0223: 256 */    0xF4 /* 't' -> */,
/* pos 0224: 257 */    0xE8 /* 'h' -> */,
/* pos 0225: 258 */    0xBA /* ':' -> */,
/* pos 0226: 259 */    0x00, 0x1B                  /* - terminal marker 27 - */,
/* pos 0228: 260 */    0xF9 /* 'y' -> */,
/* pos 0229: 261 */    0xF0 /* 'p' -> */,
/* pos 022a: 262 */    0xE5 /* 'e' -> */,
/* pos 022b: 263 */    0xBA /* ':' -> */,
/* pos 022c: 264 */    0x00, 0x1C                  /* - terminal marker 28 - */,
/* pos 022e: 265 */    0x61 /* 'a' */, 0x07, 0x00  /* (to 0x0235 state 266) */,
                       0x65 /* 'e' */, 0xF0, 0x01  /* (to 0x0421 state 637) */,
                       0x08, /* fail */
/* pos 0235: 266 */    0xF4 /* 't' -> */,
/* pos 0236: 267 */    0xE5 /* 'e' -> */,
/* pos 0237: 268 */    0xBA /* ':' -> */,
/* pos 0238: 269 */    0x00, 0x1D                  /* - terminal marker 29 - */,
/* pos 023a: 270 */    0x61 /* 'a' */, 0x07, 0x00  /* (to 0x0241 state 271) */,
                       0x65 /* 'e' */, 0x0A, 0x00  /* (to 0x0247 state 276) */,
                       0x08, /* fail */
/* pos 0241: 271 */    0xEE /* 'n' -> */,
/* pos 0242: 272 */    0xE7 /* 'g' -> */,
/* pos 0243: 273 */    0xE5 /* 'e' -> */,
/* pos 0244: 274 */    0xBA /* ':' -> */,
/* pos 0245: 275 */    0x00, 0x1E                  /* - terminal marker 30 - */,
/* pos 0247: 276 */    0x66 /* 'f' */, 0x07, 0x00  /* (to 0x024E state 277) */,
                       0x74 /* 't' */, 0x5A, 0x01  /* (to 0x03A4 state 529) */,
                       0x08, /* fail */
/* pos 024e: 277 */    0x65 /* 'e' */, 0x07, 0x00  /* (to 0x0255 state 278) */,
                       0x72 /* 'r' */, 0x4D, 0x01  /* (to 0x039E state 524) */,
                       0x08, /* fail */
/* pos 0255: 278 */    0xF2 /* 'r' -> */,
/* pos 0256: 279 */    0xE5 /* 'e' -> */,
/* pos 0257: 280 */    0xF2 /* 'r' -> */,
/* pos 0258: 281 */    0xBA /* ':' -> */,
/* pos 0259: 282 */    0x00, 0x1F                  /* - terminal marker 31 - */,
/* pos 025b: 283 */    0x00, 0x20                  /* - terminal marker 32 - */,
/* pos 025d: 284 */    0xE5 /* 'e' -> */,
/* pos 025e: 285 */    0xF2 /* 'r' -> */,
/* pos 025f: 286 */    0xF3 /* 's' -> */,
/* pos 0260: 287 */    0xE9 /* 'i' -> */,
/* pos 0261: 288 */    0xEF /* 'o' -> */,
/* pos 0262: 289 */    0xEE /* 'n' -> */,
/* pos 0263: 290 */    0xBA /* ':' -> */,
/* pos 0264: 291 */    0x00, 0x21                  /* - terminal marker 33 - */,
/* pos 0266: 292 */    0xF2 /* 'r' -> */,
/* pos 0267: 293 */    0xE9 /* 'i' -> */,
/* pos 0268: 294 */    0xE7 /* 'g' -> */,
/* pos 0269: 295 */    0xE9 /* 'i' -> */,
/* pos 026a: 296 */    0xEE /* 'n' -> */,
/* pos 026b: 297 */    0xBA /* ':' -> */,
/* pos 026c: 298 */    0x00, 0x22                  /* - terminal marker 34 - */,
/* pos 026e: 299 */    0x61 /* 'a' */, 0x0D, 0x00  /* (to 0x027B state 300) */,
                       0x6D /* 'm' */, 0x14, 0x00  /* (to 0x0285 state 309) */,
                       0x70 /* 'p' */, 0x18, 0x00  /* (to 0x028C state 315) */,
                       0x73 /* 's' */, 0x1A, 0x00  /* (to 0x0291 state 319) */,
                       0x08, /* fail */
/* pos 027b: 300 */    0xF5 /* 'u' -> */,
/* pos 027c: 301 */    0xF4 /* 't' -> */,
/* pos 027d: 302 */    0xE8 /* 'h' -> */,
/* pos 027e: 303 */    0xEF /* 'o' -> */,
/* pos 027f: 304 */    0xF2 /* 'r' -> */,
/* pos 0280: 305 */    0xE9 /* 'i' -> */,
/* pos 0281: 306 */    0xF4 /* 't' -> */,
/* pos 0282: 307 */    0xF9 /* 'y' -> */,
/* pos 0283: 308 */    0x00, 0x23                  /* - terminal marker 35 - */,
/* pos 0285: 309 */    0xE5 /* 'e' -> */,
/* pos 0286: 310 */    0xF4 /* 't' -> */,
/* pos 0287: 311 */    0xE8 /* 'h' -> */,
/* pos 0288: 312 */    0xEF /* 'o' -> */,
/* pos 0289: 313 */    0xE4 /* 'd' -> */,
/* pos 028a: 314 */    0x00, 0x24                  /* - terminal marker 36 - */,
/* pos 028c: 315 */    0xE1 /* 'a' -> */,
/* pos 028d: 316 */    0xF4 /* 't' -> */,
/* pos 028e: 317 */    0xE8 /* 'h' -> */,
/* pos 028f: 318 */    0x00, 0x25                  /* - terminal marker 37 - */,
/* pos 0291: 319 */    0x63 /* 'c' */, 0x07, 0x00  /* (to 0x0298 state 320) */,
                       0x74 /* 't' */, 0x0A, 0x00  /* (to 0x029E state 325) */,
                       0x08, /* fail */
/* pos 0298: 320 */    0xE8 /* 'h' -> */,
/* pos 0299: 321 */    0xE5 /* 'e' -> */,
/* pos 029a: 322 */    0xED /* 'm' -> */,
/* pos 029b: 323 */    0xE5 /* 'e' -> */,
/* pos 029c: 324 */    0x00, 0x26                  /* - terminal marker 38 - */,
/* pos 029e: 325 */    0xE1 /* 'a' -> */,
/* pos 029f: 326 */    0xF4 /* 't' -> */,
/* pos 02a0: 327 */    0xF5 /* 'u' -> */,
/* pos 02a1: 328 */    0xF3 /* 's' -> */,
/* pos 02a2: 329 */    0x00, 0x27                  /* - terminal marker 39 - */,
/* pos 02a4: 330 */    0xE8 /* 'h' -> */,
/* pos 02a5: 331 */    0xE1 /* 'a' -> */,
/* pos 02a6: 332 */    0xF2 /* 'r' -> */,
/* pos 02a7: 333 */    0xF3 /* 's' -> */,
/* pos 02a8: 334 */    0xE5 /* 'e' -> */,
/* pos 02a9: 335 */    0xF4 /* 't' -> */,
/* pos 02aa: 336 */    0xBA /* ':' -> */,
/* pos 02ab: 337 */    0x00, 0x28                  /* - terminal marker 40 - */,
/* pos 02ad: 338 */    0xE1 /* 'a' -> */,
/* pos 02ae: 339 */    0xEE /* 'n' -> */,
/* pos 02af: 340 */    0xE7 /* 'g' -> */,
/* pos 02b0: 341 */    0xE5 /* 'e' -> */,
/* pos 02b1: 342 */    0xF3 /* 's' -> */,
/* pos 02b2: 343 */    0xBA /* ':' -> */,
/* pos 02b3: 344 */    0x00, 0x29                  /* - terminal marker 41 - */,
/* pos 02b5: 345 */    0xEC /* 'l' -> */,
/* pos 02b6: 346 */    0xEC /* 'l' -> */,
/* pos 02b7: 347 */    0xEF /* 'o' -> */,
/* pos 02b8: 348 */    0xF7 /* 'w' -> */,
/* pos 02b9: 349 */    0xAD /* '-' -> */,
/* pos 02ba: 350 */    0xEF /* 'o' -> */,
/* pos 02bb: 351 */    0xF2 /* 'r' -> */,
/* pos 02bc: 352 */    0xE9 /* 'i' -> */,
/* pos 02bd: 353 */    0xE7 /* 'g' -> */,
/* pos 02be: 354 */    0xE9 /* 'i' -> */,
/* pos 02bf: 355 */    0xEE /* 'n' -> */,
/* pos 02c0: 356 */    0xBA /* ':' -> */,
/* pos 02c1: 357 */    0x00, 0x2A                  /* - terminal marker 42 - */,
/* pos 02c3: 358 */    0xE5 /* 'e' -> */,
/* pos 02c4: 359 */    0xBA /* ':' -> */,
/* pos 02c5: 360 */    0x00, 0x2B                  /* - terminal marker 43 - */,
/* pos 02c7: 361 */    0xEC /* 'l' -> */,
/* pos 02c8: 362 */    0xEF /* 'o' -> */,
/* pos 02c9: 363 */    0xF7 /* 'w' -> */,
/* pos 02ca: 364 */    0xBA /* ':' -> */,
/* pos 02cb: 365 */    0x00, 0x2C                  /* - terminal marker 44 - */,
/* pos 02cd: 366 */    0xE9 /* 'i' -> */,
/* pos 02ce: 367 */    0xF3 /* 's' -> */,
/* pos 02cf: 368 */    0xF0 /* 'p' -> */,
/* pos 02d0: 369 */    0xEF /* 'o' -> */,
/* pos 02d1: 370 */    0xF3 /* 's' -> */,
/* pos 02d2: 371 */    0xE9 /* 'i' -> */,
/* pos 02d3: 372 */    0xF4 /* 't' -> */,
/* pos 02d4: 373 */    0xE9 /* 'i' -> */,
/* pos 02d5: 374 */    0xEF /* 'o' -> */,
/* pos 02d6: 375 */    0xEE /* 'n' -> */,
/* pos 02d7: 376 */    0xBA /* ':' -> */,
/* pos 02d8: 377 */    0x00, 0x2D                  /* - terminal marker 45 - */,
/* pos 02da: 378 */    0xEE /* 'n' -> */,
/* pos 02db: 379 */    0xE3 /* 'c' -> */,
/* pos 02dc: 380 */    0xEF /* 'o' -> */,
/* pos 02dd: 381 */    0xE4 /* 'd' -> */,
/* pos 02de: 382 */    0xE9 /* 'i' -> */,
/* pos 02df: 383 */    0xEE /* 'n' -> */,
/* pos 02e0: 384 */    0xE7 /* 'g' -> */,
/* pos 02e1: 385 */    0xBA /* ':' -> */,
/* pos 02e2: 386 */    0x00, 0x2E                  /* - terminal marker 46 - */,
/* pos 02e4: 387 */    0xEE /* 'n' -> */,
/* pos 02e5: 388 */    0xE7 /* 'g' -> */,
/* pos 02e6: 389 */    0xF5 /* 'u' -> */,
/* pos 02e7: 390 */    0xE1 /* 'a' -> */,
/* pos 02e8: 391 */    0xE7 /* 'g' -> */,
/* pos 02e9: 392 */    0xE5 /* 'e' -> */,
/* pos 02ea: 393 */    0xBA /* ':' -> */,
/* pos 02eb: 394 */    0x00, 0x2F                  /* - terminal marker 47 - */,
/* pos 02ed: 395 */    0xE3 /* 'c' -> */,
/* pos 02ee: 396 */    0xE1 /* 'a' -> */,
/* pos 02ef: 397 */    0xF4 /* 't' -> */,
/* pos 02f0: 398 */    0xE9 /* 'i' -> */,
/* pos 02f1: 399 */    0xEF /* 'o' -> */,
/* pos 02f2: 400 */    0xEE /* 'n' -> */,
/* pos 02f3: 401 */    0xBA /* ':' -> */,
/* pos 02f4: 402 */    0x00, 0x30                  /* - terminal marker 48 - */,
/* pos 02f6: 403 */    0xE1 /* 'a' -> */,
/* pos 02f7: 404 */    0xEE /* 'n' -> */,
/* pos 02f8: 405 */    0xE7 /* 'g' -> */,
/* pos 02f9: 406 */    0xE5 /* 'e' -> */,
/* pos 02fa: 407 */    0xBA /* ':' -> */,
/* pos 02fb: 408 */    0x00, 0x31                  /* - terminal marker 49 - */,
/* pos 02fd: 409 */    0x74 /* 't' */, 0x07, 0x00  /* (to 0x0304 state 410) */,
                       0x78 /* 'x' */, 0x09, 0x00  /* (to 0x0309 state 414) */,
                       0x08, /* fail */
/* pos 0304: 410 */    0xE1 /* 'a' -> */,
/* pos 0305: 411 */    0xE7 /* 'g' -> */,
/* pos 0306: 412 */    0xBA /* ':' -> */,
/* pos 0307: 413 */    0x00, 0x32                  /* - terminal marker 50 - */,
/* pos 0309: 414 */    0xF0 /* 'p' -> */,
/* pos 030a: 415 */    0x65 /* 'e' */, 0x07, 0x00  /* (to 0x0311 state 416) */,
                       0x69 /* 'i' */, 0x09, 0x00  /* (to 0x0316 state 420) */,
                       0x08, /* fail */
/* pos 0311: 416 */    0xE3 /* 'c' -> */,
/* pos 0312: 417 */    0xF4 /* 't' -> */,
/* pos 0313: 418 */    0xBA /* ':' -> */,
/* pos 0314: 419 */    0x00, 0x33                  /* - terminal marker 51 - */,
/* pos 0316: 420 */    0xF2 /* 'r' -> */,
/* pos 0317: 421 */    0xE5 /* 'e' -> */,
/* pos 0318: 422 */    0xF3 /* 's' -> */,
/* pos 0319: 423 */    0xBA /* ':' -> */,
/* pos 031a: 424 */    0x00, 0x34                  /* - terminal marker 52 - */,
/* pos 031c: 425 */    0xF2 /* 'r' -> */,
/* pos 031d: 426 */    0xEF /* 'o' -> */,
/* pos 031e: 427 */    0xED /* 'm' -> */,
/* pos 031f: 428 */    0xBA /* ':' -> */,
/* pos 0320: 429 */    0x00, 0x35                  /* - terminal marker 53 - */,
/* pos 0322: 430 */    0xF4 /* 't' -> */,
/* pos 0323: 431 */    0xE3 /* 'c' -> */,
/* pos 0324: 432 */    0xE8 /* 'h' -> */,
/* pos 0325: 433 */    0xBA /* ':' -> */,
/* pos 0326: 434 */    0x00, 0x36                  /* - terminal marker 54 - */,
/* pos 0328: 435 */    0xE1 /* 'a' -> */,
/* pos 0329: 436 */    0xEE /* 'n' -> */,
/* pos 032a: 437 */    0xE7 /* 'g' -> */,
/* pos 032b: 438 */    0xE5 /* 'e' -> */,
/* pos 032c: 439 */    0xBA /* ':' -> */,
/* pos 032d: 440 */    0x00, 0x37                  /* - terminal marker 55 - */,
/* pos 032f: 441 */    0xEE /* 'n' -> */,
/* pos 0330: 442 */    0xED /* 'm' -> */,
/* pos 0331: 443 */    0xEF /* 'o' -> */,
/* pos 0332: 444 */    0xE4 /* 'd' -> */,
/* pos 0333: 445 */    0xE9 /* 'i' -> */,
/* pos 0334: 446 */    0xE6 /* 'f' -> */,
/* pos 0335: 447 */    0xE9 /* 'i' -> */,
/* pos 0336: 448 */    0xE5 /* 'e' -> */,
/* pos 0337: 449 */    0xE4 /* 'd' -> */,
/* pos 0338: 450 */    0xAD /* '-' -> */,
/* pos 0339: 451 */    0xF3 /* 's' -> */,
/* pos 033a: 452 */    0xE9 /* 'i' -> */,
/* pos 033b: 453 */    0xEE /* 'n' -> */,
/* pos 033c: 454 */    0xE3 /* 'c' -> */,
/* pos 033d: 455 */    0xE5 /* 'e' -> */,
/* pos 033e: 456 */    0xBA /* ':' -> */,
/* pos 033f: 457 */    0x00, 0x38                  /* - terminal marker 56 - */,
/* pos 0341: 458 */    0x61 /* 'a' */, 0x0A, 0x00  /* (to 0x034B state 459) */,
                       0x69 /* 'i' */, 0x15, 0x00  /* (to 0x0359 state 472) */,
                       0x6F /* 'o' */, 0x17, 0x00  /* (to 0x035E state 476) */,
                       0x08, /* fail */
/* pos 034b: 459 */    0xF3 /* 's' -> */,
/* pos 034c: 460 */    0xF4 /* 't' -> */,
/* pos 034d: 461 */    0xAD /* '-' -> */,
/* pos 034e: 462 */    0xED /* 'm' -> */,
/* pos 034f: 463 */    0xEF /* 'o' -> */,
/* pos 0350: 464 */    0xE4 /* 'd' -> */,
/* pos 0351: 465 */    0xE9 /* 'i' -> */,
/* pos 0352: 466 */    0xE6 /* 'f' -> */,
/* pos 0353: 467 */    0xE9 /* 'i' -> */,
/* pos 0354: 468 */    0xE5 /* 'e' -> */,
/* pos 0355: 469 */    0xE4 /* 'd' -> */,
/* pos 0356: 470 */    0xBA /* ':' -> */,
/* pos 0357: 471 */    0x00, 0x39                  /* - terminal marker 57 - */,
/* pos 0359: 472 */    0xEE /* 'n' -> */,
/* pos 035a: 473 */    0xEB /* 'k' -> */,
/* pos 035b: 474 */    0xBA /* ':' -> */,
/* pos 035c: 475 */    0x00, 0x3A                  /* - terminal marker 58 - */,
/* pos 035e: 476 */    0xE3 /* 'c' -> */,
/* pos 035f: 477 */    0xE1 /* 'a' -> */,
/* pos 0360: 478 */    0xF4 /* 't' -> */,
/* pos 0361: 479 */    0xE9 /* 'i' -> */,
/* pos 0362: 480 */    0xEF /* 'o' -> */,
/* pos 0363: 481 */    0xEE /* 'n' -> */,
/* pos 0364: 482 */    0xBA /* ':' -> */,
/* pos 0365: 483 */    0x00, 0x3B                  /* - terminal marker 59 - */,
/* pos 0367: 484 */    0xE1 /* 'a' -> */,
/* pos 0368: 485 */    0xF8 /* 'x' -> */,
/* pos 0369: 486 */    0xAD /* '-' -> */,
/* pos 036a: 487 */    0xE6 /* 'f' -> */,
/* pos 036b: 488 */    0xEF /* 'o' -> */,
/* pos 036c: 489 */    0xF2 /* 'r' -> */,
/* pos 036d: 490 */    0xF7 /* 'w' -> */,
/* pos 036e: 491 */    0xE1 /* 'a' -> */,
/* pos 036f: 492 */    0xF2 /* 'r' -> */,
/* pos 0370: 493 */    0xE4 /* 'd' -> */,
/* pos 0371: 494 */    0xF3 /* 's' -> */,
/* pos 0372: 495 */    0xBA /* ':' -> */,
/* pos 0373: 496 */    0x00, 0x3C                  /* - terminal marker 60 - */,
/* pos 0375: 497 */    0xF8 /* 'x' -> */,
/* pos 0376: 498 */    0xF9 /* 'y' -> */,
/* pos 0377: 499 */    0x2D /* '-' */, 0x07, 0x00  /* (to 0x037E state 500) */,
                       0x20 /* ' ' */, 0xB5, 0x00  /* (to 0x042F state 649) */,
                       0x08, /* fail */
/* pos 037e: 500 */    0xE1 /* 'a' -> */,
/* pos 037f: 501 */    0xF5 /* 'u' -> */,
/* pos 0380: 502 */    0xF4 /* 't' -> */,
/* pos 0381: 503 */    0xE8 /* 'h' -> */,
/* pos 0382: 504 */    0x65 /* 'e' */, 0x07, 0x00  /* (to 0x0389 state 505) */,
                       0x6F /* 'o' */, 0x0E, 0x00  /* (to 0x0393 state 514) */,
                       0x08, /* fail */
/* pos 0389: 505 */    0xEE /* 'n' -> */,
/* pos 038a: 506 */    0xF4 /* 't' -> */,
/* pos 038b: 507 */    0xE9 /* 'i' -> */,
/* pos 038c: 508 */    0xE3 /* 'c' -> */,
/* pos 038d: 509 */    0xE1 /* 'a' -> */,
/* pos 038e: 510 */    0xF4 /* 't' -> */,
/* pos 038f: 511 */    0xE5 /* 'e' -> */,
/* pos 0390: 512 */    0xBA /* ':' -> */,
/* pos 0391: 513 */    0x00, 0x3D                  /* - terminal marker 61 - */,
/* pos 0393: 514 */    0xF2 /* 'r' -> */,
/* pos 0394: 515 */    0xE9 /* 'i' -> */,
/* pos 0395: 516 */    0xFA /* 'z' -> */,
/* pos 0396: 517 */    0xE1 /* 'a' -> */,
/* pos 0397: 518 */    0xF4 /* 't' -> */,
/* pos 0398: 519 */    0xE9 /* 'i' -> */,
/* pos 0399: 520 */    0xEF /* 'o' -> */,
/* pos 039a: 521 */    0xEE /* 'n' -> */,
/* pos 039b: 522 */    0xBA /* ':' -> */,
/* pos 039c: 523 */    0x00, 0x3E                  /* - terminal marker 62 - */,
/* pos 039e: 524 */    0xE5 /* 'e' -> */,
/* pos 039f: 525 */    0xF3 /* 's' -> */,
/* pos 03a0: 526 */    0xE8 /* 'h' -> */,
/* pos 03a1: 527 */    0xBA /* ':' -> */,
/* pos 03a2: 528 */    0x00, 0x3F                  /* - terminal marker 63 - */,
/* pos 03a4: 529 */    0xF2 /* 'r' -> */,
/* pos 03a5: 530 */    0xF9 /* 'y' -> */,
/* pos 03a6: 531 */    0xAD /* '-' -> */,
/* pos 03a7: 532 */    0xE1 /* 'a' -> */,
/* pos 03a8: 533 */    0xE6 /* 'f' -> */,
/* pos 03a9: 534 */    0xF4 /* 't' -> */,
/* pos 03aa: 535 */    0xE5 /* 'e' -> */,
/* pos 03ab: 536 */    0xF2 /* 'r' -> */,
/* pos 03ac: 537 */    0xBA /* ':' -> */,
/* pos 03ad: 538 */    0x00, 0x40                  /* - terminal marker 64 - */,
/* pos 03af: 539 */    0xF6 /* 'v' -> */,
/* pos 03b0: 540 */    0xE5 /* 'e' -> */,
/* pos 03b1: 541 */    0xF2 /* 'r' -> */,
/* pos 03b2: 542 */    0xBA /* ':' -> */,
/* pos 03b3: 543 */    0x00, 0x41                  /* - terminal marker 65 - */,
/* pos 03b5: 544 */    0xAD /* '-' -> */,
/* pos 03b6: 545 */    0xE3 /* 'c' -> */,
/* pos 03b7: 546 */    0xEF /* 'o' -> */,
/* pos 03b8: 547 */    0xEF /* 'o' -> */,
/* pos 03b9: 548 */    0xEB /* 'k' -> */,
/* pos 03ba: 549 */    0xE9 /* 'i' -> */,
/* pos 03bb: 550 */    0xE5 /* 'e' -> */,
/* pos 03bc: 551 */    0xBA /* ':' -> */,
/* pos 03bd: 552 */    0x00, 0x42                  /* - terminal marker 66 - */,
/* pos 03bf: 553 */    0xF2 /* 'r' -> */,
/* pos 03c0: 554 */    0xE9 /* 'i' -> */,
/* pos 03c1: 555 */    0xE3 /* 'c' -> */,
/* pos 03c2: 556 */    0xF4 /* 't' -> */,
/* pos 03c3: 557 */    0xAD /* '-' -> */,
/* pos 03c4: 558 */    0xF4 /* 't' -> */,
/* pos 03c5: 559 */    0xF2 /* 'r' -> */,
/* pos 03c6: 560 */    0xE1 /* 'a' -> */,
/* pos 03c7: 561 */    0xEE /* 'n' -> */,
/* pos 03c8: 562 */    0xF3 /* 's' -> */,
/* pos 03c9: 563 */    0xF0 /* 'p' -> */,
/* pos 03ca: 564 */    0xEF /* 'o' -> */,
/* pos 03cb: 565 */    0xF2 /* 'r' -> */,
/* pos 03cc: 566 */    0xF4 /* 't' -> */,
/* pos 03cd: 567 */    0xAD /* '-' -> */,
/* pos 03ce: 568 */    0xF3 /* 's' -> */,
/* pos 03cf: 569 */    0xE5 /* 'e' -> */,
/* pos 03d0: 570 */    0xE3 /* 'c' -> */,
/* pos 03d1: 571 */    0xF5 /* 'u' -> */,
/* pos 03d2: 572 */    0xF2 /* 'r' -> */,
/* pos 03d3: 573 */    0xE9 /* 'i' -> */,
/* pos 03d4: 574 */    0xF4 /* 't' -> */,
/* pos 03d5: 575 */    0xF9 /* 'y' -> */,
/* pos 03d6: 576 */    0xBA /* ':' -> */,
/* pos 03d7: 577 */    0x00, 0x43                  /* - terminal marker 67 - */,
/* pos 03d9: 578 */    0xF2 /* 'r' -> */,
/* pos 03da: 579 */    0xE1 /* 'a' -> */,
/* pos 03db: 580 */    0xEE /* 'n' -> */,
/* pos 03dc: 581 */    0xF3 /* 's' -> */,
/* pos 03dd: 582 */    0xE6 /* 'f' -> */,
/* pos 03de: 583 */    0xE5 /* 'e' -> */,
/* pos 03df: 584 */    0xF2 /* 'r' -> */,
/* pos 03e0: 585 */    0xAD /* '-' -> */,
/* pos 03e1: 586 */    0xE5 /* 'e' -> */,
/* pos 03e2: 587 */    0xEE /* 'n' -> */,
/* pos 03e3: 588 */    0xE3 /* 'c' -> */,
/* pos 03e4: 589 */    0xEF /* 'o' -> */,
/* pos 03e5: 590 */    0xE4 /* 'd' -> */,
/* pos 03e6: 591 */    0xE9 /* 'i' -> */,
/* pos 03e7: 592 */    0xEE /* 'n' -> */,
/* pos 03e8: 593 */    0xE7 /* 'g' -> */,
/* pos 03e9: 594 */    0xBA /* ':' -> */,
/* pos 03ea: 595 */    0x00, 0x44                  /* - terminal marker 68 - */,
/* pos 03ec: 596 */    0xE5 /* 'e' -> */,
/* pos 03ed: 597 */    0xF2 /* 'r' -> */,
/* pos 03ee: 598 */    0xAD /* '-' -> */,
/* pos 03ef: 599 */    0xE1 /* 'a' -> */,
/* pos 03f0: 600 */    0xE7 /* 'g' -> */,
/* pos 03f1: 601 */    0xE5 /* 'e' -> */,
/* pos 03f2: 602 */    0xEE /* 'n' -> */,
/* pos 03f3: 603 */    0xF4 /* 't' -> */,
/* pos 03f4: 604 */    0xBA /* ':' -> */,
/* pos 03f5: 605 */    0x00, 0x45                  /* - terminal marker 69 - */,
/* pos 03f7: 606 */    0x61 /* 'a' */, 0x07, 0x00  /* (to 0x03FE state 607) */,
                       0x69 /* 'i' */, 0x09, 0x00  /* (to 0x0403 state 611) */,
                       0x08, /* fail */
/* pos 03fe: 607 */    0xF2 /* 'r' -> */,
/* pos 03ff: 608 */    0xF9 /* 'y' -> */,
/* pos 0400: 609 */    0xBA /* ':' -> */,
/* pos 0401: 610 */    0x00, 0x46                  /* - terminal marker 70 - */,
/* pos 0403: 611 */    0xE1 /* 'a' -> */,
/* pos 0404: 612 */    0xBA /* ':' -> */,
/* pos 0405: 613 */    0x00, 0x47                  /* - terminal marker 71 - */,
/* pos 0407: 614 */    0xF7 /* 'w' -> */,
/* pos 0408: 615 */    0xF7 /* 'w' -> */,
/* pos 0409: 616 */    0xAD /* '-' -> */,
/* pos 040a: 617 */    0xE1 /* 'a' -> */,
/* pos 040b: 618 */    0xF5 /* 'u' -> */,
/* pos 040c: 619 */    0xF4 /* 't' -> */,
/* pos 040d: 620 */    0xE8 /* 'h' -> */,
/* pos 040e: 621 */    0xE5 /* 'e' -> */,
/* pos 040f: 622 */    0xEE /* 'n' -> */,
/* pos 0410: 623 */    0xF4 /* 't' -> */,
/* pos 0411: 624 */    0xE9 /* 'i' -> */,
/* pos 0412: 625 */    0xE3 /* 'c' -> */,
/* pos 0413: 626 */    0xE1 /* 'a' -> */,
/* pos 0414: 627 */    0xF4 /* 't' -> */,
/* pos 0415: 628 */    0xE5 /* 'e' -> */,
/* pos 0416: 629 */    0xBA /* ':' -> */,
/* pos 0417: 630 */    0x00, 0x48                  /* - terminal marker 72 - */,
/* pos 0419: 631 */    0xF4 /* 't' -> */,
/* pos 041a: 632 */    0xE3 /* 'c' -> */,
/* pos 041b: 633 */    0xE8 /* 'h' -> */,
/* pos 041c: 634 */    0x00, 0x49                  /* - terminal marker 73 - */,
/* pos 041e: 635 */    0xF4 /* 't' -> */,
/* pos 041f: 636 */    0x00, 0x4A                  /* - terminal marker 74 - */,
/* pos 0421: 637 */    0xEC /* 'l' -> */,
/* pos 0422: 638 */    0xE5 /* 'e' -> */,
/* pos 0423: 639 */    0xF4 /* 't' -> */,
/* pos 0424: 640 */    0xE5 /* 'e' -> */,
/* pos 0425: 641 */    0x00, 0x4B                  /* - terminal marker 75