aboutsummaryrefslogtreecommitdiff
path: root/src/microspdy/structures.h
blob: ff4c47ffd820857291919d88d2a50aed25f71862 (plain) (blame)
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
/*
    This file is part of libmicrospdy
    Copyright (C) 2012 Andrey Uzunov

    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 structures.h
 * @brief  internal and public structures -- most of the structs used by
 * 			the library are defined here
 * @author Andrey Uzunov
 */

#ifndef STRUCTURES_H
#define STRUCTURES_H

#include "platform.h"
#include "microspdy.h"
#include "io.h"


/**
 * All possible SPDY control frame types. The number is used in the header
 * of the control frame.
 */
enum SPDY_CONTROL_FRAME_TYPES
{
	/**
	 * The SYN_STREAM control frame allows the sender to asynchronously
	 * create a stream between the endpoints.
	 */
	SPDY_CONTROL_FRAME_TYPES_SYN_STREAM = 1,
	
	/**
	 * SYN_REPLY indicates the acceptance of a stream creation by
	 * the recipient of a SYN_STREAM frame.
	 */
	SPDY_CONTROL_FRAME_TYPES_SYN_REPLY = 2,
	
	/**
	 * The RST_STREAM frame allows for abnormal termination of a stream.
	 * When sent by the creator of a stream, it indicates the creator
	 * wishes to cancel the stream. When sent by the recipient of a
	 * stream, it indicates an error or that the recipient did not want
	 * to accept the stream, so the stream should be closed.
	 */
	SPDY_CONTROL_FRAME_TYPES_RST_STREAM = 3,
	
	/**
	 * A SETTINGS frame contains a set of id/value pairs for
	 * communicating configuration data about how the two endpoints may
	 * communicate. SETTINGS frames can be sent at any time by either
	 * endpoint, are optionally sent, and are fully asynchronous. When
	 * the server is the sender, the sender can request that
	 * configuration data be persisted by the client across SPDY
	 * sessions and returned to the server in future communications.
	 */
	SPDY_CONTROL_FRAME_TYPES_SETTINGS = 4,
	
	/**
	 * The PING control frame is a mechanism for measuring a minimal
	 * round-trip time from the sender. It can be sent from the client
	 * or the server. Recipients of a PING frame should send an
	 * identical frame to the sender as soon as possible (if there is
	 * other pending data waiting to be sent, PING should take highest
	 * priority). Each ping sent by a sender should use a unique ID.
	 */
	SPDY_CONTROL_FRAME_TYPES_PING = 6,
	
	/**
	 * The GOAWAY control frame is a mechanism to tell the remote side
	 * of the connection to stop creating streams on this session. It
	 * can be sent from the client or the server.
	 */
	SPDY_CONTROL_FRAME_TYPES_GOAWAY = 7,
	
	/**
	 * The HEADERS frame augments a stream with additional headers. It
	 * may be optionally sent on an existing stream at any time.
	 * Specific application of the headers in this frame is
	 * application-dependent. The name/value header block within this
	 * frame is compressed.
	 */
	SPDY_CONTROL_FRAME_TYPES_HEADERS = 8,
	
	/**
	 * The WINDOW_UPDATE control frame is used to implement per stream
	 * flow control in SPDY. Flow control in SPDY is per hop, that is,
	 * only between the two endpoints of a SPDY connection. If there are
	 * one or more intermediaries between the client and the origin
	 * server, flow control signals are not explicitly forwarded by the
	 * intermediaries.
	 */
	SPDY_CONTROL_FRAME_TYPES_WINDOW_UPDATE = 9,
	
	/**
	 * The CREDENTIAL control frame is used by the client to send
	 * additional client certificates to the server. A SPDY client may
	 * decide to send requests for resources from different origins on
	 * the same SPDY session if it decides that that server handles both
	 * origins. For example if the IP address associated with both
	 * hostnames matches and the SSL server certificate presented in the
	 * initial handshake is valid for both hostnames. However, because
	 * the SSL connection can contain at most one client certificate,
	 * the client needs a mechanism to send additional client
	 * certificates to the server.
	 */
	SPDY_CONTROL_FRAME_TYPES_CREDENTIAL = 11
};


/**
 * SPDY_SESSION_STATUS is used to show the current receiving state 
 * of each session, i.e. what is expected to come now, and how it should
 * be handled.
 */
enum SPDY_SESSION_STATUS
{
	/**
	 * The session is in closing state, do not read read anything from
	 * it. Do not write anything to it.
	 */
	SPDY_SESSION_STATUS_CLOSING = 0,
	
	/**
	 * Wait for new SPDY frame to come.
	 */
	SPDY_SESSION_STATUS_WAIT_FOR_HEADER = 1,
	
	/**
	 * The standard 8 byte header of the SPDY frame was received and
	 * handled. Wait for the specific (sub)headers according to the
	 * frame type.
	 */
	SPDY_SESSION_STATUS_WAIT_FOR_SUBHEADER = 2,
	
	/**
	 * The specific (sub)headers were received and handled. Wait for the
	 * "body", i.e. wait for the name/value pairs compressed by zlib.
	 */
	SPDY_SESSION_STATUS_WAIT_FOR_BODY = 3,
	
	/**
	 * Ignore all the bytes read from the socket, e.g. larger frames.
	 */
	SPDY_SESSION_STATUS_IGNORE_BYTES= 4,
	
	/**
	 * The session is in pre-closing state, do not read read anything
	 * from it. In this state the output queue will be written to the
	 * socket.
	 */
	SPDY_SESSION_STATUS_FLUSHING = 5,
};


/**
 * Specific flags for the SYN_STREAM control frame.
 */
enum SPDY_SYN_STREAM_FLAG
{
	/**
	 * The sender won't send any more frames on this stream.
	 */
	SPDY_SYN_STREAM_FLAG_FIN = 1,
	
	/**
	 * The sender creates this stream as unidirectional.
	 */
	SPDY_SYN_STREAM_FLAG_UNIDIRECTIONAL = 2
};


/**
 * Specific flags for the SYN_REPLY control frame.
 */
enum SPDY_SYN_REPLY_FLAG
{
	/**
	 * The sender won't send any more frames on this stream.
	 */
	SPDY_SYN_REPLY_FLAG_FIN = 1
};


/**
 * Specific flags for the data frame.
 */
enum SPDY_DATA_FLAG
{
	/**
	 * The sender won't send any more frames on this stream.
	 */
	SPDY_DATA_FLAG_FIN = 1,
	
	/**
	 * The data in the frame is compressed. 
	 * This flag appears only in the draft on ietf.org but not on
	 * chromium.org.
	 */
	SPDY_DATA_FLAG_COMPRESS = 2
};

/**
 * Status code within RST_STREAM control frame.
 */
enum SPDY_RST_STREAM_STATUS
{
	/**
	 * This is a generic error, and should only be used if a more
	 * specific error is not available.
	 */
	SPDY_RST_STREAM_STATUS_PROTOCOL_ERROR = 1,
	
	/**
	 * This is returned when a frame is received for a stream which is
	 * not active.
	 */
	SPDY_RST_STREAM_STATUS_INVALID_STREAM = 2,
	
	/**
	 * Indicates that the stream was refused before any processing has
	 * been done on the stream.
	 */
	SPDY_RST_STREAM_STATUS_REFUSED_STREAM = 3,
	
	/**
	 * Indicates that the recipient of a stream does not support the
	 * SPDY version requested.
	 */
	SPDY_RST_STREAM_STATUS_UNSUPPORTED_VERSION = 4,
	
	/**
	 * Used by the creator of a stream to indicate that the stream is
	 * no longer needed.
	 */
	SPDY_RST_STREAM_STATUS_CANCEL = 5,
	
	/**
	 * This is a generic error which can be used when the implementation
	 * has internally failed, not due to anything in the protocol.
	 */
	SPDY_RST_STREAM_STATUS_INTERNAL_ERROR = 6,
	
	/**
	 * The endpoint detected that its peer violated the flow control
	 * protocol.
	 */
	SPDY_RST_STREAM_STATUS_FLOW_CONTROL_ERROR = 7,
	
	/**
	 * The endpoint received a SYN_REPLY for a stream already open.
	 */
	SPDY_RST_STREAM_STATUS_STREAM_IN_USE = 8,
	
	/**
	 * The endpoint received a data or SYN_REPLY frame for a stream
	 * which is half closed.
	 */
	SPDY_RST_STREAM_STATUS_STREAM_ALREADY_CLOSED = 9,
	
	/**
	 * The server received a request for a resource whose origin does
	 * not have valid credentials in the client certificate vector.
	 */
	SPDY_RST_STREAM_STATUS_INVALID_CREDENTIALS = 10,
	
	/**
	 * The endpoint received a frame which this implementation could not
	 * support. If FRAME_TOO_LARGE is sent for a SYN_STREAM, HEADERS,
	 * or SYN_REPLY frame without fully processing the compressed
	 * portion of those frames, then the compression state will be
	 * out-of-sync with the other endpoint. In this case, senders of
	 * FRAME_TOO_LARGE MUST close the session.
	 */
	SPDY_RST_STREAM_STATUS_FRAME_TOO_LARGE = 11
};


/**
 * Status code within GOAWAY control frame.
 */
enum SPDY_GOAWAY_STATUS
{
	/**
	 * This is a normal session teardown.
	 */
	SPDY_GOAWAY_STATUS_OK = 0,
	
	/**
	 * This is a generic error, and should only be used if a more
	 * specific error is not available.
	 */
	SPDY_GOAWAY_STATUS_PROTOCOL_ERROR = 1,
	
	/**
	 * This is a generic error which can be used when the implementation
	 * has internally failed, not due to anything in the protocol.
	 */
	SPDY_GOAWAY_STATUS_INTERNAL_ERROR = 11
};


struct SPDYF_Stream;

struct SPDYF_Response_Queue;

/**
 * Callback for new stream. To be used in the application layer of the
 * lib.
 *
 * @param cls
 * @param stream the new stream
 * @return SPDY_YES on success,
 *         SPDY_NO if error occurs
 */
typedef int
(*SPDYF_NewStreamCallback) (void *cls,
						struct SPDYF_Stream * stream);


/**
 * Callback to be called when the response queue object was handled and 
 * the data was already sent. 
 *
 * @param cls
 * @param response_queue the SPDYF_Response_Queue structure which will
 * 			be cleaned very soon
 * @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 part of the response (in one
 * 			or several frames) was sent to the client.
 */
typedef void
(*SPDYF_ResponseQueueResultCallback) (void * cls,
								struct SPDYF_Response_Queue *response_queue,
								enum SPDY_RESPONSE_RESULT status);


/**
 * Representation of the control frame's headers, which are common for
 * all types.
 */
struct __attribute__((__packed__)) SPDYF_Control_Frame
{
	uint16_t version : 15;
	uint16_t control_bit : 1; /* always 1 for control frames */
	uint16_t type;
	uint32_t flags : 8;
	uint32_t length : 24;
};


/**
 * Representation of the data frame's headers.
 */
struct __attribute__((__packed__)) SPDYF_Data_Frame
{
	uint32_t stream_id : 31;
	uint32_t control_bit : 1; /* always 0 for data frames */
	uint32_t flags : 8;
	uint32_t length : 24;
};


/**
 * Queue of the responses, to be handled (e.g. compressed) and sent later.
 */
struct SPDYF_Response_Queue
{
	/**
	 * This is a doubly-linked list.
	 */
	struct SPDYF_Response_Queue *next;

	/**
	 * This is a doubly-linked list.
	 */
	struct SPDYF_Response_Queue *prev;

	/**
	 * Stream (Request) for which is the response.
	 */
	struct SPDYF_Stream *stream;

	/**
	 * Response structure with all the data (uncompressed headers) to be sent.
	 */
	struct SPDY_Response *response;

	/**
	 * Control frame. The length field should be set after compressing
	 * the headers!
	 */
	struct SPDYF_Control_Frame *control_frame;

	/**
	 * Data frame. The length field should be set after compressing
	 * the body!
	 */
	struct SPDYF_Data_Frame *data_frame;

	/**
	 * Data to be sent: name/value pairs in control frames or body in data frames.
	 */
	void *data;

	/**
	 * Specific handler for different frame types.
	 */
	int (* process_response_handler)(struct SPDY_Session *session);

	/**
	 * Callback to be called when the last bytes from the response was sent
	 * to the client.
	 */
	SPDYF_ResponseQueueResultCallback frqcb;
	
	/**
	 * Closure for frqcb.
	 */
	void *frqcb_cls;

	/**
	 * Callback to be used by the application layer.
	 */
	SPDY_ResponseResultCallback rrcb;
	
	/**
	 * Closure for rcb.
	 */
	void *rrcb_cls;

	/**
	 * Data size.
	 */
	size_t data_size;

	/**
	 * True if data frame should be sent. False if control frame should
	 * be sent.
	 */
	bool is_data;
};



/**
 * Collection of HTTP headers used in requests and responses.
 */
struct SPDY_NameValue
{
	/**
	* This is a doubly-linked list.
	*/
	struct SPDY_NameValue *next;

	/**
	* This is a doubly-linked list.
	*/
	struct SPDY_NameValue *prev;

	/**
	* Null terminated string for name.
	*/
    char *name;

	/**
	* Array of Null terminated strings for value. num_values is the
	* length of the array.
	*/
	char **value;

	/**
	* Number of values, this is >= 0.
	*/
	unsigned int num_values;
};


/**
 * Represents a SPDY stream
 */ 
struct SPDYF_Stream
{
	/**
	 * This is a doubly-linked list.
	 */
	struct SPDYF_Stream *next;

	/**
	 * This is a doubly-linked list.
	 */
	struct SPDYF_Stream *prev;

	/**
	 * Reference to the SPDY_Session struct.
	 */
	struct SPDY_Session *session;
	
	/**
	 * Name value pairs, sent within the frame which created the stream.
	 */
	struct SPDY_NameValue *headers;
  
	/**
	 * This stream's ID.
	 */
	uint32_t stream_id;
	
	/**
	 * Stream to which this one is associated.
	 */
	uint32_t assoc_stream_id;
	
	/**
	 * Stream priority. 0 is the highest, 7 is the lowest.
	 */
	uint8_t priority;
	
	/**
	 * Integer specifying the index in the server's CREDENTIAL vector of
	 * the client certificate to be used for this request The value 0
	 * means no client certificate should be associated with this stream.
	 */
	uint8_t slot;
	
	/**
	 * If initially the stream was created as unidirectional.
	 */
	bool flag_unidirectional;
	
	/**
	 * If the stream won't be used for receiving frames anymore. The 
	 * client has sent FLAG_FIN or the stream was terminated with
	 * RST_STREAM.
	 */
	bool is_in_closed;
	
	/**
	 * If the stream won't be used for sending out frames anymore. The 
	 * server has sent FLAG_FIN or the stream was terminated with
	 * RST_STREAM.
	 */
	bool is_out_closed;
	
	/**
	 * Which entity (server/client) has created the stream.
	 */
	bool is_server_initiator;
};


/**
 * Represents a SPDY session which is just a TCP connection
 */ 
struct SPDY_Session
{
	/**
	 * zlib stream for decompressing all the name/pair values from the
	 * received frames. All the received compressed data must be
	 * decompressed within one context: this stream. Thus, it should be
	 * unique for the session and initialized at its creation.
	 */
	z_stream zlib_recv_stream;

	/**
	 * zlib stream for compressing all the name/pair values from the
	 * frames to be sent. All the sent compressed data must be
	 * compressed within one context: this stream. Thus, it should be
	 * unique for the session and initialized at its creation.
	 */
	z_stream zlib_send_stream;
	
	/**
	 * This is a doubly-linked list.
	 */
	struct SPDY_Session *next;

	/**
	 * This is a doubly-linked list.
	 */
	struct SPDY_Session *prev;

	/**
	 * Reference to the SPDY_Daemon struct.
	 */
	struct SPDY_Daemon *daemon;

	/**
	 * Foreign address (of length addr_len).
	 */
	struct sockaddr *addr;

	/**
	 * Head of doubly-linked list of the SPDY streams belonging to the
	 * session.
	 */
	struct SPDYF_Stream *streams_head;

	/**
	 * Tail of doubly-linked list of the streams.
	 */
	struct SPDYF_Stream *streams_tail;

	/**
	 * Unique IO context for the session. Initialized on each creation
	 * (actually when the TCP connection is established).
	 */
	void *io_context;
	
	/**
	 * Head of doubly-linked list of the responses.
	 */
	struct SPDYF_Response_Queue *response_queue_head;
	
	/**
	 * Tail of doubly-linked list of the responses.
	 */
	struct SPDYF_Response_Queue *response_queue_tail;

	/**
	 * Buffer for reading requests.
	 */
	void *read_buffer;

	/**
	 * Buffer for writing responses.
	 */
	void *write_buffer;

	/**
	 * Specific handler for the frame that is currently being received.
	 */
	void (*frame_handler) (struct SPDY_Session * session);

	/**
	 * Closure for frame_handler.
	 */
	void *frame_handler_cls;

	/**
	 * Extra field to be used by the user with set/get func for whatever
	 * purpose he wants.
	 */
	void *user_cls;

	/**
	 * Function to initialize the IO context for a new session.
	 */
	SPDYF_IONewSession fio_new_session;

	/**
	 * Function to deinitialize the IO context for a session.
	 */
	SPDYF_IOCloseSession fio_close_session;

	/**
	 * Function to read data from socket.
	 */
	SPDYF_IORecv fio_recv;

	/**
	 * Function to write data to socket.
	 */
	SPDYF_IOSend fio_send;

	/**
	 * Function to check for pending data in IO buffers.
	 */
	SPDYF_IOIsPending fio_is_pending;

	/**
	 * Function to call before writing set of frames.
	 */
	SPDYF_IOBeforeWrite fio_before_write;

	/**
	 * Function to call after writing set of frames.
	 */
	SPDYF_IOAfterWrite fio_after_write;

	/**
	 * Number of bytes that the lib must ignore immediately after they 
	 * are read from the TLS socket without adding them to the read buf.
	 * This is needed, for instance, when receiving frame bigger than
	 * the buffer to avoid deadlock situations.
	 */
	size_t read_ignore_bytes;

	/**
	 * Size of read_buffer (in bytes).  This value indicates
	 * how many bytes we're willing to read into the buffer;
	 * the real buffer is one byte longer to allow for
	 * adding zero-termination (when needed).
	 */
	size_t read_buffer_size;

	/**
	 * Position where we currently append data in
	 * read_buffer (last valid position).
	 */
	size_t read_buffer_offset;

	/**
	 * Position until where everything was already read
	 */
	size_t read_buffer_beginning;

	/**
	 * Size of write_buffer (in bytes).  This value indicates
	 * how many bytes we're willing to prepare for writing.
	 */
	size_t write_buffer_size;

	/**
	 * Position where we currently append data in
	 * write_buffer (last valid position).
	 */
	size_t write_buffer_offset;

	/**
	 * Position until where everything was already written to the socket
	 */
	size_t write_buffer_beginning;
	
	/**
	 * Last time this connection had any activity
	 * (reading or writing). In milliseconds.
	 */
	unsigned long long last_activity;

	/**
	 * Socket for this connection.  Set to -1 if
	 * this connection has died (daemon should clean
	 * up in that case).
	 */
	int socket_fd;

	/**
	 * Length of the foreign address.
	 */
	socklen_t addr_len;
	
	/**
	 * The biggest stream ID for this session for streams initiated
	 * by the client.
	 */
	uint32_t last_in_stream_id;
	
	/**
	 * The biggest stream ID for this session for streams initiated
	 * by the server.
	 */
	uint32_t last_out_stream_id;
	
	/**
	 * This value is updated whenever SYN_REPLY or RST_STREAM are sent
	 * and is used later in GOAWAY frame.
	 * TODO it is not clear in the draft what happens when streams are
	 * not answered in the order of their IDs. Moreover, why should we
	 * send GOAWAY with the ID of received bogus SYN_STREAM with huge ID?
	 */
	uint32_t last_replied_to_stream_id;
	
	/**
	 * Shows the stream id of the currently handled frame. This value is
	 * to be used when sending RST_STREAM in answer to a problematic
	 * frame, e.g. larger than supported.
	 */
	uint32_t current_stream_id;
	
	/**
	 * 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.
	 */
	uint32_t max_num_frames;

	/**
	 * Shows the current receiving state the session, i.e. what is
	 * expected to come now, and how it shold be handled.
	 */
	enum SPDY_SESSION_STATUS status;

	/**
	 * Has this socket been closed for reading (i.e.
	 * other side closed the connection)?  If so,
	 * we must completely close the connection once
	 * we are done sending our response (and stop
	 * trying to read from this socket).
	 */
	bool read_closed;

	/**
	 * If the server sends GOAWAY, it must ignore all SYN_STREAMS for
	 * this session. Normally the server will soon close the TCP session.
	 */
	bool is_goaway_sent;

	/**
	 * If the server receives GOAWAY, it must not send new SYN_STREAMS 
	 * on this session. Normally the client will soon close the TCP
	 * session.
	 */
	bool is_goaway_received;
};


/**
 * State and settings kept for each SPDY daemon.
 */
struct SPDY_Daemon
{

	/**
	 * Tail of doubly-linked list of our current, active sessions.
	 */
	struct SPDY_Session *sessions_head;

	/**
	 * Tail of doubly-linked list of our current, active sessions.
	 */
	struct SPDY_Session *sessions_tail;
	
	/**
	 * Tail of doubly-linked list of connections to clean up.
	 */
	struct SPDY_Session *cleanup_head;

	/**
	 * Tail of doubly-linked list of connections to clean up.
	 */
	struct SPDY_Session *cleanup_tail;

	/**
	 * Unique IO context for the daemon. Initialized on daemon start.
	 */
	void *io_context;

	/**
	 * Certificate file of the server. File path is kept here.
	 */
	char *certfile;

	/**
	 * Key file for the certificate of the server. File path is
	 * kept here.
	 */
	char *keyfile;
	

	/**
	 * The address to which the listening socket is bound.
	 */
	struct sockaddr *address;
	
	/**
	 * Callback called when a new SPDY session is
	 * established by a client
	 */
	SPDY_NewSessionCallback new_session_cb;

	/**
	 * Callback called when a client closes the session
	 */
	SPDY_SessionClosedCallback session_closed_cb;

	/**
	 * Callback called when a client sends request
	 */
	SPDY_NewRequestCallback new_request_cb;

	/**
	* Callback called when HTTP POST params are received
	* after request
	*/
	SPDY_NewPOSTDataCallback new_post_data_cb;

	/**
	 * Closure argument for all the callbacks that can be used by the client.
	 */
	void *cls;

	/**
	 * Callback called when new stream is created.
	 */
	SPDYF_NewStreamCallback fnew_stream_cb;

	/**
	 * Closure argument for all the callbacks defined in the framing layer.
	 */
	void *fcls;

	/**
	 * Function to initialize the IO context for the daemon.
	 */
	SPDYF_IOInit fio_init;

	/**
	 * Function to deinitialize the IO context for the daemon.
	 */
	SPDYF_IODeinit fio_deinit;

	/**
	 * After how many milliseconds of inactivity should
	 * connections time out? Zero for no timeout.
	 */
	unsigned long long session_timeout;

	/**
	 * Listen socket.
	 */
	int socket_fd;
	
	/**
   * This value is inherited by all sessions of the daemon.
	 * 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.
	 */
	uint32_t max_num_frames;

	/**
	 * Daemon's options.
	 */
	enum SPDY_DAEMON_OPTION options;

	/**
	 * Daemon's flags.
	 */
	enum SPDY_DAEMON_FLAG flags;

	/**
	 * IO subsystem type used by daemon and all its sessions.
	 */
	enum SPDY_IO_SUBSYSTEM io_subsystem;

	/**
	 * Listen port.
	 */
	uint16_t port;
};


/**
 * Represents a SPDY response.
 */
struct SPDY_Response
{
	/**
	 * Raw uncompressed stream of the name/value pairs in SPDY frame
	 * used for the HTTP headers.
	 */
    void *headers;
	
	/**
	 * Raw stream of the data to be sent. Equivalent to the body in HTTP
	 * response.
	 */
	void *data;
	
	/**
	 * Callback function to be used when the response data is provided
	 * with callbacks. In this case data must be NULL and data_size must
	 * be 0.
	 */
	SPDY_ResponseCallback rcb;
	
	/**
	 * Extra argument to rcb.
	 */
	void *rcb_cls;
	
	/**
	 * Length of headers.
	 */
	size_t headers_size;
	
	/**
	 * Length of data.
	 */
	size_t data_size;
	
	/**
	 * The callback func will be called to get that amount of bytes to
	 * put them into a DATA frame. It is either user preffered or
	 * the maximum supported by the lib value.
	 */
	uint32_t rcb_block_size;
};


/* Macros for handling data and structures */


/**
 * Insert an element at the head of a DLL. Assumes that head, tail and
 * element are structs with prev and next fields.
 *
 * @param head pointer to the head of the DLL (struct ? *)
 * @param tail pointer to the tail of the DLL (struct ? *)
 * @param element element to insert (struct ? *)
 */
#define DLL_insert(head,tail,element) do { \
	(element)->next = (head); \
	(element)->prev = NULL; \
	if ((tail) == NULL) \
		(tail) = element; \
	else \
		(head)->prev = element; \
	(head) = (element); } while (0)


/**
 * Remove an element from a DLL. Assumes
 * that head, tail and element are structs
 * with prev and next fields.
 *
 * @param head pointer to the head of the DLL (struct ? *)
 * @param tail pointer to the tail of the DLL (struct ? *)
 * @param element element to remove (struct ? *)
 */
#define DLL_remove(head,tail,element) do { \
	if ((element)->prev == NULL) \
		(head) = (element)->next;  \
	else \
		(element)->prev->next = (element)->next; \
	if ((element)->next == NULL) \
		(tail) = (element)->prev;  \
	else \
		(element)->next->prev = (element)->prev; \
	(element)->next = NULL; \
	(element)->prev = NULL; } while (0)


/**
 * Convert all integers in a SPDY control frame headers structure from
 * host byte order to network byte order.
 *
 * @param frame input and output structure (struct SPDY_Control_Frame *)
 */
#if HAVE_BIG_ENDIAN
#define SPDYF_CONTROL_FRAME_HTON(frame)
#else
#define SPDYF_CONTROL_FRAME_HTON(frame) do { \
	(*((uint16_t *) frame  )) = (*((uint8_t *) (frame) +1 )) | ((*((uint8_t *) frame  ))<<8);\
	(frame)->type = htons((frame)->type); \
	(frame)->length = HTON24((frame)->length); \
	} while (0)
#endif


/**
 * Convert all integers in a SPDY control frame headers structure from
 * network byte order to host byte order.
 *
 * @param frame input and output structure (struct SPDY_Control_Frame *)
 */	
#if HAVE_BIG_ENDIAN
#define SPDYF_CONTROL_FRAME_NTOH(frame)
#else
#define SPDYF_CONTROL_FRAME_NTOH(frame) do { \
	(*((uint16_t *) frame  )) = (*((uint8_t *) (frame) +1 )) | ((*((uint8_t *) frame  ))<<8);\
	(frame)->type = ntohs((frame)->type); \
	(frame)->length = NTOH24((frame)->length); \
	} while (0)
#endif


/**
 * Convert all integers in a SPDY data frame headers structure from
 * host byte order to network byte order.
 *
 * @param frame input and output structure (struct SPDY_Data_Frame *)
 */
#if HAVE_BIG_ENDIAN
#define SPDYF_DATA_FRAME_HTON(frame)
#else
#define SPDYF_DATA_FRAME_HTON(frame) do { \
	*((uint32_t *) frame  ) = htonl(*((uint32_t *) frame  ));\
	(frame)->length = HTON24((frame)->length); \
	} while (0)
#endif


/**
 * Convert all integers in a SPDY data frame headers structure from
 * network byte order to host byte order.
 *
 * @param frame input and output structure (struct SPDY_Data_Frame *)
 */	
#if HAVE_BIG_ENDIAN
#define SPDYF_DATA_FRAME_NTOH(frame)
#else
#define SPDYF_DATA_FRAME_NTOH(frame) do { \
	*((uint32_t *) frame  ) = ntohl(*((uint32_t *) frame  ));\
	(frame)->length = NTOH24((frame)->length); \
	} while (0)
#endif


/**
 * Creates one or more new SPDYF_Response_Queue object to be put on the
 * response queue.
 *
 * @param is_data whether new data frame or new control frame will be
 *                crerated
 * @param data the row stream which will be used as the body of the frame
 * @param data_size length of data
 * @param response object, part of which is the frame
 * @param stream on which data is to be sent 
 * @param closestream TRUE if the frame must close the stream (with flag) 
 * @param frqcb callback to notify application layer when the frame
 *              has been sent or discarded 
 * @param frqcb_cls closure for frqcb
 * @param rrcb callback used by the application layer to notify the
 *             application when the frame has been sent or discarded.
 *             frqcb will call it 
 * @param rrcb_cls closure for rrcb
 * @return double linked list of SPDYF_Response_Queue structures: one or
 *         more frames are returned based on the size of the data
 */
struct SPDYF_Response_Queue *
SPDYF_response_queue_create(bool is_data,
						void *data,
						size_t data_size,
						struct SPDY_Response *response,
						struct SPDYF_Stream *stream,
						bool closestream,
						SPDYF_ResponseQueueResultCallback frqcb,
						void *frqcb_cls,
						SPDY_ResponseResultCallback rrcb,
						void *rrcb_cls);


/**
 * Destroys SPDYF_Response_Queue structure and whatever is in it.
 *
 * @param response_queue to destroy
 */
void
SPDYF_response_queue_destroy(struct SPDYF_Response_Queue *response_queue);


/**
 * Checks if the container is empty, i.e. created but no values were
 * added to it.
 *
 * @param container
 * @return SPDY_YES if empty
 *         SPDY_NO if not
 */
int
SPDYF_name_value_is_empty(struct SPDY_NameValue *container);


/**
 * Transforms raw binary decomressed stream of headers
 * into SPDY_NameValue, containing all of the headers and values.
 *
 * @param stream that is to be transformed
 * @param size length of the stream
 * @param container will contain the newly created SPDY_NameValue
 *        container. Should point to NULL.
 * @return SPDY_YES on success
 *         SPDY_NO on memory error
 *         SPDY_INPUT_ERROR if the provided stream is not valid
 */
int
SPDYF_name_value_from_stream(void *stream,
							size_t size,
							struct SPDY_NameValue ** container);


/**
 * Transforms array of objects of name/values tuples, containing HTTP
 * headers, into raw binary stream. The resulting stream is ready to
 * be compressed and sent.
 *
 * @param container one or more SPDY_NameValue objects. Each object
 *        contains multiple number of name/value tuples.
 * @param num_containers length of the array
 * @param stream will contain the resulting stream. Should point to NULL.
 * @return length of stream or value less than 0 indicating error
 */
ssize_t
SPDYF_name_value_to_stream(struct SPDY_NameValue * container[],
							int num_containers,
							void **stream);

#endif