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
|
/*
This file is part of libmicrospdy
Copyright (C) 2012, 2013 Christian Grothoff
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file microspdy.h
* @brief public interface to libmicrospdy
* @author Andrey Uzunov
* @author Christian Grothoff
*
* All symbols defined in this header start with SPDY_. libmisrospdy is a small
* SPDY daemon library. The application can start multiple daemons
* and they are independent.<p>
*
* The header file defines various constants used by the SPDY and the HTTP protocol.
* This does not mean that the lib actually interprets all of these
* values. Not everything is implemented. The provided constants are exported as a convenience
* for users of the library. The lib does not verify that provided
* HTTP headers and if their values conform to the SPDY protocol,
* it only checks if the required headers for the SPDY requests and
* responses are provided.<p>
*
* The library uses just a single thread.<p>
*
* Before including "microspdy.h" you should add the necessary
* includes to define the types used in this file (which headers are needed may
* depend on your platform; for possible suggestions consult
* "platform.h" in the libmicrospdy distribution).<p>
*
* All of the functions returning SPDY_YES/SPDY_NO return
* SPDY_INPUT_ERROR when any of the parameters are invalid, e.g.,
* required parameter is NULL.
*/
#ifndef SPDY_MICROSPDY_H
#define SPDY_MICROSPDY_H
#include <zlib.h>
#include <stdbool.h>
/* While we generally would like users to use a configure-driven
build process which detects which headers are present and
hence works on any platform, we use "standard" includes here
to build out-of-the-box for beginning users on common systems.
Once you have a proper build system and go for more exotic
platforms, you should define MHD_PLATFORM_H in some header that
you always include *before* "microhttpd.h". Then the following
"standard" includes won't be used (which might be a good
idea, especially on platforms where they do not exist). */
#ifndef MHD_PLATFORM_H
#include <unistd.h>
#include <stdarg.h>
#include <stdint.h>
#ifdef __MINGW32__
#include <ws2tcpip.h>
#else
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif
#endif
/**
* return code for "YES".
*/
#define SPDY_YES 1
/**
* return code for "NO".
*/
#define SPDY_NO 0
/**
* return code for error when input parameters are wrong. To be returned
* only by functions which return int. The others will return NULL on
* input error.
*/
#define SPDY_INPUT_ERROR -1
/**
* SPDY version supported by the lib.
*/
#define SPDY_VERSION 3
/**
* The maximum allowed size (without 8 byte headers) of
* SPDY frames (value length) is 8192. The lib will accept and
* send frames with length at most this value here.
*/
#define SPDY_MAX_SUPPORTED_FRAME_SIZE 8192
/**
* HTTP response codes.
*/
#define SPDY_HTTP_CONTINUE 100
#define SPDY_HTTP_SWITCHING_PROTOCOLS 101
#define SPDY_HTTP_PROCESSING 102
#define SPDY_HTTP_OK 200
#define SPDY_HTTP_CREATED 201
#define SPDY_HTTP_ACCEPTED 202
#define SPDY_HTTP_NON_AUTHORITATIVE_INFORMATION 203
#define SPDY_HTTP_NO_CONTENT 204
#define SPDY_HTTP_RESET_CONTENT 205
#define SPDY_HTTP_PARTIAL_CONTENT 206
#define SPDY_HTTP_MULTI_STATUS 207
#define SPDY_HTTP_MULTIPLE_CHOICES 300
#define SPDY_HTTP_MOVED_PERMANENTLY 301
#define SPDY_HTTP_FOUND 302
#define SPDY_HTTP_SEE_OTHER 303
#define SPDY_HTTP_NOT_MODIFIED 304
#define SPDY_HTTP_USE_PROXY 305
#define SPDY_HTTP_SWITCH_PROXY 306
#define SPDY_HTTP_TEMPORARY_REDIRECT 307
#define SPDY_HTTP_BAD_REQUEST 400
#define SPDY_HTTP_UNAUTHORIZED 401
#define SPDY_HTTP_PAYMENT_REQUIRED 402
#define SPDY_HTTP_FORBIDDEN 403
#define SPDY_HTTP_NOT_FOUND 404
#define SPDY_HTTP_METHOD_NOT_ALLOWED 405
#define SPDY_HTTP_METHOD_NOT_ACCEPTABLE 406
#define SPDY_HTTP_PROXY_AUTHENTICATION_REQUIRED 407
#define SPDY_HTTP_REQUEST_TIMEOUT 408
#define SPDY_HTTP_CONFLICT 409
#define SPDY_HTTP_GONE 410
#define SPDY_HTTP_LENGTH_REQUIRED 411
#define SPDY_HTTP_PRECONDITION_FAILED 412
#define SPDY_HTTP_REQUEST_ENTITY_TOO_LARGE 413
#define SPDY_HTTP_REQUEST_URI_TOO_LONG 414
#define SPDY_HTTP_UNSUPPORTED_MEDIA_TYPE 415
#define SPDY_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE 416
#define SPDY_HTTP_EXPECTATION_FAILED 417
#define SPDY_HTTP_UNPROCESSABLE_ENTITY 422
#define SPDY_HTTP_LOCKED 423
#define SPDY_HTTP_FAILED_DEPENDENCY 424
#define SPDY_HTTP_UNORDERED_COLLECTION 425
#define SPDY_HTTP_UPGRADE_REQUIRED 426
#define SPDY_HTTP_NO_RESPONSE 444
#define SPDY_HTTP_RETRY_WITH 449
#define SPDY_HTTP_BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS 450
#define SPDY_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS 451
#define SPDY_HTTP_INTERNAL_SERVER_ERROR 500
#define SPDY_HTTP_NOT_IMPLEMENTED 501
#define SPDY_HTTP_BAD_GATEWAY 502
#define SPDY_HTTP_SERVICE_UNAVAILABLE 503
#define SPDY_HTTP_GATEWAY_TIMEOUT 504
#define SPDY_HTTP_HTTP_VERSION_NOT_SUPPORTED 505
#define SPDY_HTTP_VARIANT_ALSO_NEGOTIATES 506
#define SPDY_HTTP_INSUFFICIENT_STORAGE 507
#define SPDY_HTTP_BANDWIDTH_LIMIT_EXCEEDED 509
#define SPDY_HTTP_NOT_EXTENDED 510
/**
* HTTP headers are used in SPDY, but all of them MUST be lowercase.
* Some are not valid in SPDY and MUST not be used
*/
#define SPDY_HTTP_HEADER_ACCEPT "accept"
#define SPDY_HTTP_HEADER_ACCEPT_CHARSET "accept-charset"
#define SPDY_HTTP_HEADER_ACCEPT_ENCODING "accept-encoding"
#define SPDY_HTTP_HEADER_ACCEPT_LANGUAGE "accept-language"
#define SPDY_HTTP_HEADER_ACCEPT_RANGES "accept-ranges"
#define SPDY_HTTP_HEADER_AGE "age"
#define SPDY_HTTP_HEADER_ALLOW "allow"
#define SPDY_HTTP_HEADER_AUTHORIZATION "authorization"
#define SPDY_HTTP_HEADER_CACHE_CONTROL "cache-control"
/* Connection header is forbidden in SPDY */
#define SPDY_HTTP_HEADER_CONNECTION "connection"
#define SPDY_HTTP_HEADER_CONTENT_ENCODING "content-encoding"
#define SPDY_HTTP_HEADER_CONTENT_LANGUAGE "content-language"
#define SPDY_HTTP_HEADER_CONTENT_LENGTH "content-length"
#define SPDY_HTTP_HEADER_CONTENT_LOCATION "content-location"
#define SPDY_HTTP_HEADER_CONTENT_MD5 "content-md5"
#define SPDY_HTTP_HEADER_CONTENT_RANGE "content-range"
#define SPDY_HTTP_HEADER_CONTENT_TYPE "content-type"
#define SPDY_HTTP_HEADER_COOKIE "cookie"
#define SPDY_HTTP_HEADER_DATE "date"
#define SPDY_HTTP_HEADER_ETAG "etag"
#define SPDY_HTTP_HEADER_EXPECT "expect"
#define SPDY_HTTP_HEADER_EXPIRES "expires"
#define SPDY_HTTP_HEADER_FROM "from"
/* Host header is forbidden in SPDY */
#define SPDY_HTTP_HEADER_HOST "host"
#define SPDY_HTTP_HEADER_IF_MATCH "if-match"
#define SPDY_HTTP_HEADER_IF_MODIFIED_SINCE "if-modified-since"
#define SPDY_HTTP_HEADER_IF_NONE_MATCH "if-none-match"
#define SPDY_HTTP_HEADER_IF_RANGE "if-range"
#define SPDY_HTTP_HEADER_IF_UNMODIFIED_SINCE "if-unmodified-since"
/* Keep-Alive header is forbidden in SPDY */
#define SPDY_HTTP_HEADER_KEEP_ALIVE "keep-alive"
#define SPDY_HTTP_HEADER_LAST_MODIFIED "last-modified"
#define SPDY_HTTP_HEADER_LOCATION "location"
#define SPDY_HTTP_HEADER_MAX_FORWARDS "max-forwards"
#define SPDY_HTTP_HEADER_PRAGMA "pragma"
#define SPDY_HTTP_HEADER_PROXY_AUTHENTICATE "proxy-authenticate"
#define SPDY_HTTP_HEADER_PROXY_AUTHORIZATION "proxy-authorization"
/* Proxy-Connection header is forbidden in SPDY */
#define SPDY_HTTP_HEADER_PROXY_CONNECTION "proxy-connection"
#define SPDY_HTTP_HEADER_RANGE "range"
#define SPDY_HTTP_HEADER_REFERER "referer"
#define SPDY_HTTP_HEADER_RETRY_AFTER "retry-after"
#define SPDY_HTTP_HEADER_SERVER "server"
#define SPDY_HTTP_HEADER_SET_COOKIE "set-cookie"
#define SPDY_HTTP_HEADER_SET_COOKIE2 "set-cookie2"
#define SPDY_HTTP_HEADER_TE "te"
#define SPDY_HTTP_HEADER_TRAILER "trailer"
/* Transfer-Encoding header is forbidden in SPDY */
#define SPDY_HTTP_HEADER_TRANSFER_ENCODING "transfer-encoding"
#define SPDY_HTTP_HEADER_UPGRADE "upgrade"
#define SPDY_HTTP_HEADER_USER_AGENT "user-agent"
#define SPDY_HTTP_HEADER_VARY "vary"
#define SPDY_HTTP_HEADER_VIA "via"
#define SPDY_HTTP_HEADER_WARNING "warning"
#define SPDY_HTTP_HEADER_WWW_AUTHENTICATE "www-authenticate"
/**
* HTTP versions (a value must be provided in SPDY requests/responses).
*/
#define SPDY_HTTP_VERSION_1_0 "HTTP/1.0"
#define SPDY_HTTP_VERSION_1_1 "HTTP/1.1"
/**
* HTTP methods
*/
#define SPDY_HTTP_METHOD_CONNECT "CONNECT"
#define SPDY_HTTP_METHOD_DELETE "DELETE"
#define SPDY_HTTP_METHOD_GET "GET"
#define SPDY_HTTP_METHOD_HEAD "HEAD"
#define SPDY_HTTP_METHOD_OPTIONS "OPTIONS"
#define SPDY_HTTP_METHOD_POST "POST"
#define SPDY_HTTP_METHOD_PUT "PUT"
#define SPDY_HTTP_METHOD_TRACE "TRACE"
/**
* HTTP POST encodings, see also
* http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4
*/
#define SPDY_HTTP_POST_ENCODING_FORM_URLENCODED "application/x-www-form-urlencoded"
#define SPDY_HTTP_POST_ENCODING_MULTIPART_FORMDATA "multipart/form-data"
/**
* Handle for the daemon (listening on a socket).
*/
struct SPDY_Daemon;
/**
* Handle for a SPDY session/connection.
*/
struct SPDY_Session;
/**
* Handle for a SPDY request sent by a client. The structure has pointer
* to the session's handler
*/
struct SPDY_Request;
/**
* Handle for a response containing HTTP headers and data to be sent.
* The structure has pointer to the session's handler
* for this response.
*/
struct SPDY_Response;
/**
* Collection of tuples of an HTTP header and values used in requests
* and responses.
*/
struct SPDY_NameValue;
/**
* Collection of tuples of a SPDY setting ID, value
* and flags used to control the sessions.
*/
struct SPDY_Settings;
/**
* SPDY IO sybsystem flags used by SPDY_init() and SPDY_deinit().<p>
*
* The values are used internally as flags, that is why they must be
* powers of 2.
*/
enum SPDY_IO_SUBSYSTEM
{
/**
* No subsystem. For internal use.
*/
SPDY_IO_SUBSYSTEM_NONE = 0,
/**
* Default TLS implementation provided by openSSL/libssl.
*/
SPDY_IO_SUBSYSTEM_OPENSSL = 1,
/**
* No TLS is used.
*/
SPDY_IO_SUBSYSTEM_RAW = 2,
};
/**
* SPDY daemon options. Passed in the varargs portion of
* SPDY_start_daemon to customize the daemon. Each option must
* be followed by a value of a specific type.<p>
*
* The values are used internally as flags, that is why they must be
* powers of 2.
*/
enum SPDY_DAEMON_OPTION
{
/**
* No more options / last option. This is used
* to terminate the VARARGs list.
*/
SPDY_DAEMON_OPTION_END = 0,
/**
* Set a custom timeout for all connections. Must be followed by
* a number of seconds, given as an 'unsigned int'. Use
* zero for no timeout.
*/
SPDY_DAEMON_OPTION_SESSION_TIMEOUT = 1,
/**
* Bind daemon to the supplied sockaddr. This option must be
* followed by a 'struct sockaddr *'. The 'struct sockaddr*'
* should point to a 'struct sockaddr_in6' or to a
* 'struct sockaddr_in'.
*/
SPDY_DAEMON_OPTION_SOCK_ADDR = 2,
/**
* Flags for the daemon. Must be followed by a SPDY_DAEMON_FLAG value
* which is the result of bitwise OR of desired flags.
*/
SPDY_DAEMON_OPTION_FLAGS = 4,
/**
* IO subsystem type used by daemon and all its sessions. If not set,
* TLS provided by openssl is used. Must be followed by a
* SPDY_IO_SUBSYSTEM value.
*/
SPDY_DAEMON_OPTION_IO_SUBSYSTEM = 8,
/**
* Maximum number of frames to be written to the socket at once. The
* library tries to send max_num_frames in a single call to SPDY_run
* for a single session. This means no requests can be received nor
* other sessions can send data as long the current one has enough
* frames to send and there is no error on writing. Thus, a big value
* will affect the performance. Small value gives fairnes for sessions.
* Must be followed by a positive integer (uin32_t). If not set, the
* default value 10 will be used.
*/
SPDY_DAEMON_OPTION_MAX_NUM_FRAMES = 16,
};
/**
* Flags for starting SPDY daemon. They are used to set some settings
* for the daemon, which do not require values.
*/
enum SPDY_DAEMON_FLAG
{
/**
* No flags selected.
*/
SPDY_DAEMON_FLAG_NO = 0,
/**
* The server will bind only on IPv6 addresses. If the flag is set and
* the daemon is provided with IPv4 address or IPv6 is not supported,
* starting daemon will fail.
*/
SPDY_DAEMON_FLAG_ONLY_IPV6 = 1,
/**
* All sessions' sockets will be set with TCP_NODELAY if the flag is
* used. Option considered only by SPDY_IO_SUBSYSTEM_RAW.
*/
SPDY_DAEMON_FLAG_NO_DELAY = 2,
};
/**
* SPDY settings IDs sent by both client and server in SPDY SETTINGS frame.
* They affect the whole SPDY session. Defined in SPDY Protocol - Draft 3.
*/
enum SPDY_SETTINGS
{
/**
* Allows the sender to send its expected upload bandwidth on this
* channel. This number is an estimate. The value should be the
* integral number of kilobytes per second that the sender predicts
* as an expected maximum upload channel capacity.
*/
SPDY_SETTINGS_UPLOAD_BANDWIDTH = 1,
/**
* Allows the sender to send its expected download bandwidth on this
* channel. This number is an estimate. The value should be the
* integral number of kilobytes per second that the sender predicts as
* an expected maximum download channel capacity.
*/
SPDY_SETTINGS_DOWNLOAD_BANDWIDTH = 2,
/**
* Allows the sender to send its expected round-trip-time on this
* channel. The round trip time is defined as the minimum amount of
* time to send a control frame from this client to the remote and
* receive a response. The value is represented in milliseconds.
*/
SPDY_SETTINGS_ROUND_TRIP_TIME = 3,
/**
* Allows the sender to inform the remote endpoint the maximum number
* of concurrent streams which it will allow. By default there is no
* limit. For implementors it is recommended that this value be no
* smaller than 100.
*/
SPDY_SETTINGS_MAX_CONCURRENT_STREAMS = 4,
/**
* Allows the sender to inform the remote endpoint of the current TCP
* CWND value.
*/
SPDY_SETTINGS_CURRENT_CWND = 5,
/**
* Allows the sender to inform the remote endpoint the retransmission
* rate (bytes retransmitted / total bytes transmitted).
*/
SPDY_SETTINGS_DOWNLOAD_RETRANS_RATE = 6,
/**
* Allows the sender to inform the remote endpoint the initial window
* size (in bytes) for new streams.
*/
SPDY_SETTINGS_INITIAL_WINDOW_SIZE = 7,
/**
* Allows the server to inform the client if the new size of the
* client certificate vector.
*/
SPDY_SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8,
};
/**
* Flags for each individual SPDY setting in the SPDY SETTINGS frame.
* They affect only one setting to which they are set.
* Defined in SPDY Protocol - Draft 3.
*/
enum SPDY_FLAG_SETTINGS{
/**
* When set, the sender of this SETTINGS frame is requesting that the
* recipient persist the ID/Value and return it in future SETTINGS
* frames sent from the sender to this recipient. Because persistence
* is only implemented on the client, this flag is only sent by the
* server.
*/
SPDY_FLAG_SETTINGS_PERSIST_VALUE = 1,
/**
* When set, the sender is notifying the recipient that this ID/Value
* pair was previously sent to the sender by the recipient with the
* SPDY_FLAG_SETTINGS_PERSIST_VALUE, and the sender is returning it.
* Because persistence is only implemented on the client, this flag is
* only sent by the client.
*/
SPDY_FLAG_SETTINGS_PERSISTED = 2,
};
/**
* Flag associated with a whole SPDY SETTINGS frame. Affect all the
* settings in the frame. Defined in SPDY Protocol - Draft 3.
*/
enum SPDY_FLAG_SETTINGS_FRAME
{
/**
* When set, the client should clear any previously persisted SETTINGS
* ID/Value pairs. If this frame contains ID/Value pairs with the
* SPDY_FLAG_SETTINGS_PERSIST_VALUE set, then the client will first
* clear its existing, persisted settings, and then persist the values
* with the flag set which are contained within this frame. Because
* persistence is only implemented on the client, this flag can only
* be used when the sender is the server.
*/
SPDY_FLAG_SETTINGS_CLEAR_SETTINGS = 1,
};
/**
* SPDY settings function options. Passed in the varargs portion of
* SPDY_SettingsReceivedCallback and SPDY_send_settings to customize
* more the settings handling. Each option must
* be followed by a value of a specific type.<p>
*
* The values are used internally as flags, that is why they must be
* powers of 2.
*/
enum SPDY_SETTINGS_OPTION
{
/**
* No more options / last option. This is used
* to terminate the VARARGs list.
*/
SPDY_SETTINGS_OPTION_END = 0,
};
/**
* Used as a parameter for SPDY_ResponseResultCallback and shows if the
* response was actually written to the TLS socket or discarded by the
* lib for any reason (and respectively the reason).
*/
enum SPDY_RESPONSE_RESULT
{
/**
* The lib has written the full response to the TLS socket.
*/
SPDY_RESPONSE_RESULT_SUCCESS = 0,
/**
* The session is being closed, so the data is being discarded
*/
SPDY_RESPONSE_RESULT_SESSION_CLOSED = 1,
/**
* The stream for this response has been closed. May happen when the
* sender had sent first SYN_STREAM and after that RST_STREAM.
*/
SPDY_RESPONSE_RESULT_STREAM_CLOSED = 2,
};
/**
* Callback for serious error condition. The default action is to print
* an error message and abort().
*
* @param cls user specified value
* @param file where the error occured
* @param line where the error occured
* @param reason error details message, may be NULL
*/
typedef void
(*SPDY_PanicCallback) (void * cls,
const char * file,
unsigned int line,
const char * reason);
/**
* Callback for new SPDY session established by a client. Called
* immediately after the TCP connection was established.
*
* @param cls client-defined closure
* @param session handler for the new SPDY session
*/
typedef void
(*SPDY_NewSessionCallback) (void * cls,
struct SPDY_Session * session);
/**
* Callback for closed session. Called after the TCP connection was
* closed. In this callback function the user has the last
* chance to access the SPDY_Session structure. After that the latter
* will be cleaned!
*
* @param cls client-defined closure
* @param session handler for the closed SPDY session
* @param by_client SPDY_YES if the session close was initiated by the
* client;
* SPDY_NO if closed by the server
*/
typedef void
(*SPDY_SessionClosedCallback) (void * cls,
struct SPDY_Session * session,
int by_client);
/**
* Iterator over name-value pairs.
*
* @param cls client-defined closure
* @param name of the pair
* @param value of the pair
* @return SPDY_YES to continue iterating,
* SPDY_NO to abort the iteration
*/
typedef int
(*SPDY_NameValueIterator) (void * cls,
const char * name,
const char * const * value,
int num_values);
/**
* Callback for received SPDY request.
*
* @param cls client-defined closure
* @param request handler. The request object is required for
* sending responses.
* @param priority of the SPDY stream which the request was
* sent over
* @param method HTTP method
* @param path HTTP path
* @param version HTTP version just like in HTTP request/response:
* "HTTP/1.0" or "HTTP/1.1" currently
* @param host called host as in HTTP
* @param scheme used ("http" or "https"). In SPDY 3 it is only "https".
* @param headers other HTTP headers from the request
*/
typedef void (*SPDY_NewRequestCallback) (void * cls,
struct SPDY_Request * request,
uint8_t priority,
const char * method,
const char * path,
const char * version,
const char * host,
const char * scheme,
struct SPDY_NameValue * headers);
/**
* Callback for received new data chunk from the POST data of a given
* request.
*
* @param cls client-defined closure
* @param request handler
* @param buf data chunk from the POST data
* @param size the size of the data chunk 'buf' in bytes
* @param more false if this is the last chunk from the POST data. Note:
* true does not mean that more data will come, exceptional
* situation is possible
* @return SPDY_YES to continue calling the function,
* SPDY_NO to stop calling the function for this request
*/
typedef int (*SPDY_NewPOSTDataCallback) (void * cls,
struct SPDY_Request *request,
const void * buf,
size_t size,
bool more);
// How about passing POST encoding information
// here as well?
//TODO
/**
* Callback to be used with SPDY_build_response_with_callback. The
* callback will be called when the lib wants to write to the TLS socket.
* The application should provide the data to be sent.
*
* @param cls client-defined closure
* @param max maximum number of bytes that are allowed to be written
* to the buffer.
* @param more true if more data will be sent (i.e. the function must
* be calleed again),
* false if this is the last chunk, the lib will close
* the stream
* @return number of bytes written to buffer. On error the call MUST
* return value less than 0 to indicate the library.
*/
typedef ssize_t (*SPDY_ResponseCallback) (void * cls,
void * buffer,
size_t max,
bool * more);
/**
* Callback to be called when the last bytes from the response was sent
* to the client or when the response was discarded from the lib. This
* callback is a very good place to discard the request and the response
* objects, if they will not be reused (e.g., sending the same response
* again). If the stream is closed it is safe to discard the request
* object.
*
* @param cls client-defined closure
* @param response handler to the response that was just sent
* @param request handler to the request for which the response was sent
* @param status shows if actually the response was sent or it was
* discarded by the lib for any reason (e.g., closing session,
* closing stream, stopping daemon, etc.). It is possible that
* status indicates an error but parts of the response headers
* and/or body (in one
* or several frames) were already sent to the client.
* @param streamopened indicates if the the stream for this request/
* response pair is still opened. If yes, the server may want
* to use SPDY push to send something additional to the client
* and/or close the stream.
*/
typedef void
(*SPDY_ResponseResultCallback) (void * cls,
struct SPDY_Response * response,
struct SPDY_Request * request,
enum SPDY_RESPONSE_RESULT status,
bool streamopened);
/**
* Callback to notify when SPDY ping response is received.
*
* @param session handler for which the ping request was sent
* @param rtt the timespan between sending ping request and receiving it
* from the library
*/
typedef void
(*SPDY_PingCallback) (void * cls,
struct SPDY_Session * session,
struct timeval * rtt);
/**
* Iterator over settings ID/Value/Flags tuples.
*
* @param cls client-defined closure
* @param id SPDY settings ID
* @param value value for this setting
* @param flags flags for this tuple; use
* enum SPDY_FLAG_SETTINGS
* @return SPDY_YES to continue iterating,
* SPDY_NO to abort the iteration
*/
typedef int
(*SPDY_SettingsIterator) (void * cls,
enum SPDY_SETTINGS id,
int32_t value,
uint8_t flags);
/**
* Callback to notify when SPDY SETTINGS are received from the client.
*
* @param session handler for which settings are received
* @param settings ID/value/flags tuples of the settings
* @param flags for the whole settings frame; use
* enum SPDY_FLAG_SETTINGS_FRAME
* @param ... list of options (type-value pairs,
* terminated with SPDY_SETTINGS_OPTION_END).
*/
typedef void
(*SPDY_SettingsReceivedCallback) (struct SPDY_Session * session,
struct SPDY_Settings * settings,
uint8_t flags,
...);
/* Global functions for the library */
/**
* Init function for the whole library. It MUST be called before any
* other function of the library to initialize things like TLS context
* and possibly other stuff needed by the lib. Currently the call
* always returns SPDY_YES.
*
* @param enum SPDY_IO_SUBSYSTEM io_subsystem the IO subsystem that will
* be initialized. Several can be used with bitwise OR. If no
* parameter is set, the default openssl subsystem will be used.
* @return SPDY_YES if the library was correctly initialized and its
* functions can be used now;
* SPDY_NO on error
*/
int
(SPDY_init) (enum SPDY_IO_SUBSYSTEM io_subsystem, ...);
#define SPDY_init() SPDY_init(SPDY_IO_SUBSYSTEM_OPENSSL)
/**
* Deinit function for the whole lib. It can be called after finishing
* using the library. It frees and cleans up resources allocated in
* SPDY_init. Currently the function does not do anything.
*/
void
SPDY_deinit ();
/**
* Sets the global error handler to a different implementation. "cb"
* will only be called in the case of typically fatal, serious
* internal consistency issues. These issues should only arise in the
* case of serious memory corruption or similar problems with the
* architecture as well as failed assertions. While "cb" is allowed to
* return and the lib will then try to continue, this is never safe.
*
* The default implementation that is used if no panic function is set
* simply prints an error message and calls "abort". Alternative
* implementations might call "exit" or other similar functions.
*
* @param cb new error handler
* @param cls passed to error handler
*/
void
SPDY_set_panic_func (SPDY_PanicCallback cb,
void *cls);
/* Daemon functions */
/**
* Start a SPDY webserver on the given port.
*
* @param port to bind to. The value is ignored if address structure
* is passed as daemon option
* @param certfile path to the certificate that will be used by server
* @param keyfile path to the keyfile for the certificate
* @param nscb callback called when a new SPDY session is
* established by a client
* @param sccb callback called when a session is closed
* @param nrcb callback called when a client sends request
* @param npdcb callback called when HTTP POST params are received
* after request
* @param cls common extra argument to all of the callbacks
* @param ... list of options (type-value pairs,
* terminated with SPDY_DAEMON_OPTION_END).
* @return NULL on error, handle to daemon on success
*/
struct SPDY_Daemon *
SPDY_start_daemon (uint16_t port,
const char * certfile,
const char * keyfile,
SPDY_NewSessionCallback nscb,
SPDY_SessionClosedCallback sccb,
SPDY_NewRequestCallback nrcb,
SPDY_NewPOSTDataCallback npdcb,
void * cls,
...);
/**
* Shutdown the daemon. First all sessions are closed. It is NOT safe
* to call this function in user callbacks.
*
* @param daemon to stop
*/
void
SPDY_stop_daemon (struct SPDY_Daemon *daemon);
/**
* Obtain the select sets for this daemon. Only those are retrieved,
* which some processing should be done for, i.e. not all sockets are
* added to write_fd_set.<p>
*
* It is possible that there is
* nothing to be read from a socket but there is data either in the
* TLS subsystem's read buffers or in libmicrospdy's read buffers, which
* waits for being processed. In such case the file descriptor will be
* added to write_fd_set. Since it is very likely for the socket to be
* ready for writing, the select used in the application's event loop
* will return with success, SPDY_run will be called, the data will be
* processed and maybe something will be written to the socket. Without
* this behaviour, considering a proper event loop, data may stay in the
* buffers, but run is never called.
*
* @param daemon to get sets from
* @param read_fd_set read set
* @param write_fd_set write set
* @param except_fd_set except set
* @return largest FD added to any of the sets
*/
int
SPDY_get_fdset (struct SPDY_Daemon * daemon,
fd_set * read_fd_set,
fd_set * write_fd_set,
fd_set * except_fd_set);
/**
* Obtain timeout value for select for this daemon. The returned value
* is how long select
* should at most block, not the timeout value set for connections.
*
* @param daemon to query for timeout
* @param timeout will be set to the timeout value (in milliseconds)
* @return SPDY_YES on success
* SPDY_NO if no connections exist that
* would necessiate the use of a timeout right now
*/
int
SPDY_get_timeout (struct SPDY_Daemon * daemon,
unsigned long long * timeout);
/**
* Run webserver operations. This method must be called in
* the client event loop.
*
* @param daemon to run
*/
void
SPDY_run (struct SPDY_Daemon *daemon);
/* SPDY Session handling functions */
/**
* Closes a SPDY session. SPDY clients and servers are expected to keep
* sessions opened as long as possible. However, the server may want to
* close some connections, e.g. if there are too many, to free some
* resources. The function can also be used to close a specific session
* if the client is not desired.
*
* @param session handler to be closed
*/
void
SPDY_close_session(struct SPDY_Session * session);
/**
* Associate a void pointer with a session. The data accessible by the
* pointer can later be used wherever the session handler is available.
*
* @param session handler
* @param cls any data pointed by a pointer to be accessible later
*/
void
SPDY_set_cls_to_session(struct SPDY_Session * session,
void * cls);
/**
* Retrieves the pointer associated with SPDY_set_cls_to_session().
*
* @param session handler to get its cls
* @return same pointer added by SPDY_set_cls_to_session() or
* NULL when nothing was associated
*/
void *
SPDY_get_cls_from_session(struct SPDY_Session * session);
/**
* Retrieves the remote address of a given session.
*
* @param session handler to get its remote address
* @param addr out parameter; pointing to remote address
* @return length of the address structure
*/
socklen_t
SPDY_get_remote_addr(struct SPDY_Session * session,
struct sockaddr ** addr);
/* SPDY name/value data structure handling functions */
/**
* Create a new NameValue structure. It is needed for putting inside the
* HTTP headers and their values for a response. The user should later
* destroy alone the structure.
*
* @return hendler to the new empty structure or NULL on error
*/
struct SPDY_NameValue *
SPDY_name_value_create ();
/**
* Add name/value pair to a NameValue structure. SPDY_NO will be returned
* if the name/value pair is already in the structure. It is legal to
* add different values for the same name.
*
* @param container structure to which the new pair is added
* @param name for the value. Null-terminated string.
* @param value the value itself. Null-terminated string.
* @return SPDY_NO on error or SPDY_YES on success
*/
int
SPDY_name_value_add (struct SPDY_NameValue * container,
const char * name,
const char * value);
/**
* Lookup value for a name in a name/value structure.
*
* @param container structure in which to lookup
* @param name the name to look for
* @param num_values length of the returned array with values
* @return NULL if no such item was found, or an array containing the
* values
*/
const char * const *
SPDY_name_value_lookup (struct SPDY_NameValue *container,
const char *name,
int * num_values);
/**
* Iterate over name/value structure.
*
* @param container structure which to iterate over
* @param iterator callback to call on each name/value pair;
* maybe NULL (then just count headers)
* @param iterator_cls extra argument to iterator
* @return number of entries iterated over
*/
int
SPDY_name_value_iterate (struct SPDY_NameValue *container,
SPDY_NameValueIterator iterator,
void *iterator_cls);
/**
* Destroy a NameValue structure. Use this function to destroy only
* objects which, after passed to, will not be destroied by other
* functions.
*
*/
void
SPDY_name_value_destroy (struct SPDY_NameValue * container);
/* SPDY request handling functions */
/**
* Gets the session responsible for the given
* request.
*
* @param request for which the session is wanted
* @return session handler for the request
*/
struct SPDY_Session *
SPDY_get_session_for_request(const struct SPDY_Request * request);
/**
* Associate a void pointer with a request. The data accessible by the
* pointer can later be used wherever the request handler is available.
*
* @param request with which to associate a pointer
* @param cls any data pointed by a pointer to be accessible later
*/
void
SPDY_set_cls_to_request(struct SPDY_Request * request,
void * cls);
/**
* Retrieves the pointer associated with the request by
* SPDY_set_cls_to_request().
*
* @param request to get its cls
* @return same pointer added by SPDY_set_cls_to_request() or
* NULL when nothing was associated
*/
void *
SPDY_get_cls_from_request(struct SPDY_Request * request);
/* SPDY response handling functions */
/**
* Create response object containing all needed headers and data. The
* response object is not bound to a request, so it can be used multiple
* times with SPDY_queue_response() and schould be
* destroied by calling the SPDY_destroy_response().<p>
*
* Currently the library does not provide compression of the body data.
* It is up to the user to pass already compressed data and the
* appropriate headers to this function when desired.
*
* @param status HTTP status code for the response (e.g. 404)
* @param statustext HTTP status message for the response, which will
* be appended to the status code (e.g. "OK"). Can be NULL
* @param version HTTP version for the response (e.g. "http/1.1")
* @param headers name/value structure containing additional HTTP headers.
* Can be NULL. Can be used multiple times, it is up to
* the user to destoy the object when not needed anymore.
* @param data the body of the response. The lib will make a copy of it,
* so it is up to the user to take care of the memory
* pointed by data
* @param size length of data. It can be 0, then the lib will send only
* headers
* @return NULL on error, handle to response object on success
*/
struct SPDY_Response *
SPDY_build_response(int status,
const char * statustext,
const char * version,
struct SPDY_NameValue * headers,
const void * data,
size_t size);
/**
* Create response object containing all needed headers. The data will
* be provided later when the lib calls the callback function (just
* before writing it to the TLS socket). The
* response object is not bound to a request, so it can be used multiple
* times with SPDY_queue_response() and schould be
* destroied by calling the SPDY_destroy_response().<p>
*
* Currently the library does not provide compression of the body data.
* It is up to the user to pass already compressed data and the
* appropriate headers to this function and the callback when desired.
*
* @param status HTTP status code for the response (e.g. 404)
* @param statustext HTTP status message for the response, which will
* be appended to the status code (e.g. "OK"). Can be NULL
* @param version HTTP version for the response (e.g. "http/1.1")
* @param headers name/value structure containing additional HTTP headers.
* Can be NULL. Can be used multiple times, it is up to
* the user to destoy the object when not needed anymore.
* @param rcb callback to use to obtain response data
* @param rcb_cls extra argument to rcb
* @param block_size preferred block size for querying rcb (advisory only,
* the lib will call rcb specifying the block size); clients
* should pick a value that is appropriate for IO and
* memory performance requirements. The function will
* fail if the value is bigger than the maximum
* supported value (SPDY_MAX_SUPPORTED_FRAME_SIZE).
* Can be 0, then the lib will use
* SPDY_MAX_SUPPORTED_FRAME_SIZE instead.
* @return NULL on error, handle to response object on success
*/
struct SPDY_Response *
SPDY_build_response_with_callback(int status,
const char * statustext,
const char * version,
struct SPDY_NameValue * headers,
SPDY_ResponseCallback rcb,
void *rcb_cls,
uint32_t block_size);
/**
* Queue response object to be sent to the client. A successfully queued
* response may never be sent, e.g. when the stream gets closed. The
* data will be added to the output queue. The call will fail, if the
* output for this session
* is closed (i.e. the session is closed, half or full) or the output
* channel for the stream, on which the request was received, is closed
* (i.e. the stream is closed, half or full).
*
* @param request object identifying the request to which the
* response is returned
* @param response object containg headers and data to be sent
* @param closestream TRUE if the server does NOT intend to PUSH
* something more associated to this request/response later,
* FALSE otherwise
* @param consider_priority if FALSE, the response will be added to the
* end of the queue. If TRUE, the response will be added after
* the last previously added response with priority of the
* request grater or equal to that of the current one. This
* means that the function should be called with TRUE each time
* if one wants to be sure that the output queue behaves like
* a priority queue
* @param rrcb callback called when all the data was sent (last frame
* from response) or when that frame was discarded (e.g. the
* stream has been closed meanwhile)
* @param rrcb_cls extra argument to rcb
* @return SPDY_NO on error or SPDY_YES on success
*/
int
SPDY_queue_response (struct SPDY_Request * request,
struct SPDY_Response *response,
bool closestream,
bool consider_priority,
SPDY_ResponseResultCallback rrcb,
void * rrcb_cls);
/**
* Destroy a response structure. It should be called for all objects
* returned by SPDY_build_response*() functions to free the memory
* associated with the prepared response. It is safe to call this
* function not before being sure that the response will not be used by
* the lib anymore, this means after SPDY_ResponseResultCallback
* callbacks were called for all calls to SPDY_queue_response() passing
* this response.
*
* @param response to destroy
*/
void
SPDY_destroy_response (struct SPDY_Response *response);
/* SPDY settings ID/value data structure handling functions */
/**
* Create a new SettingsIDValue structure. It is needed for putting
* inside tuples of SPDY option, flags and value for sending to the
* client.
*
* @return hendler to the new empty structure or NULL on error
*/
const struct SPDY_Settings *
SPDY_settings_create ();
/**
* Add or update a tuple to a SettingsIDValue structure.
*
* @param container structure to which the new tuple is added
* @param id SPDY settings ID that will be sent. If this ID already in
* container, the tupple for it will be updated (value and/or
* flags). If it is not in the container, a new tupple will be
* added.
* @param flags SPDY settings flags applied only to this setting
* @param value of the setting
* @return SPDY_NO on error
* or SPDY_YES if a new setting was added
*/
int
SPDY_settings_add (struct SPDY_Settings *container,
enum SPDY_SETTINGS id,
enum SPDY_FLAG_SETTINGS flags,
int32_t value);
/**
* Lookup value and flags for an ID in a settings ID/value structure.
*
* @param container structure in which to lookup
* @param id SPDY settings ID to search for
* @param flags out param for SPDY settings flags for this setting;
* check it against the flags in enum SPDY_FLAG_SETTINGS
* @param value out param for the value of this setting
* @return SPDY_NO if the setting is not into the structure
* or SPDY_YES if it is into it
*/
int
SPDY_settings_lookup (const struct SPDY_Settings * container,
enum SPDY_SETTINGS id,
enum SPDY_FLAG_SETTINGS * flags,
int32_t * value);
/**
* Iterate over settings ID/value structure.
*
* @param container structure which to iterate over
* @param iterator callback to call on each ID/value pair;
* maybe NULL (then just count number of settings)
* @param iterator_cls extra argument to iterator
* @return number of entries iterated over
*/
int
SPDY_settings_iterate (const struct SPDY_Settings * container,
SPDY_SettingsIterator iterator,
void * iterator_cls);
/**
* Destroy a settings ID/value structure. Use this function to destroy
* only objects which, after passed to, will not be destroied by other
* functions.
*
* @param container structure which to detroy
*/
void
SPDY_settings_destroy (struct SPDY_Settings * container);
/* SPDY SETTINGS handling functions */
/**
* Send SPDY SETTINGS to the client. The call will return fail if there
* in invald setting into the settings container (e.g. invalid setting
* ID).
*
* @param session SPDY_Session handler for which settings are being sent
* @param settings ID/value pairs of the settings to be sent.
* Can be used multiple times, it is up to the user to destoy
* the object when not needed anymore.
* @param flags for the whole settings frame. They are valid for all tuples
* @param ... list of options (type-value pairs,
* terminated with SPDY_SETTINGS_OPTION_END).
* @return SPDY_NO on error or SPDY_YES on
* success
*/
int
SPDY_send_settings (struct SPDY_Session * session,
struct SPDY_Settings * settings,
enum SPDY_FLAG_SETTINGS_FRAME flags,
...);
/* SPDY misc functions */
/**
* Destroy a request structure. It should be called for all objects
* received as a parameter in SPDY_NewRequestCallback to free the memory
* associated with the request. It is safe to call this
* function not before being sure that the request will not be used by
* the lib anymore, this means after the stream, on which this request
* had been sent, was closed and all SPDY_ResponseResultCallback
* callbacks were called for all calls to SPDY_queue_response() passing
* this request object.
*
* @param request to destroy
*/
void
SPDY_destroy_request (struct SPDY_Request * request);
/**
* Send SPDY ping to the client
*
* @param session handler for which the ping request is sent
* @param rttcb callback called when ping response to the request is
* received
* @param rttcb_cls extra argument to rttcb
* @return SPDY_NO on error or SPDY_YES on success
*/
int
SPDY_send_ping(struct SPDY_Session * session,
SPDY_PingCallback rttcb,
void * rttcb_cls);
#endif
|