updated spec enabled ssl
[profile/ivi/libwebsockets.git] / lib / extension-deflate-stream.c
1 #include "private-libwebsockets.h"
2 #include "extension-deflate-stream.h"
3 #include <stdio.h>
4 #include <string.h>
5 #include <assert.h>
6
7 #define LWS_ZLIB_WINDOW_BITS 15
8 #define LWS_ZLIB_MEMLEVEL 8
9
10 int lws_extension_callback_deflate_stream(
11                 struct libwebsocket_context *context,
12                 struct libwebsocket_extension *ext,
13                 struct libwebsocket *wsi,
14                         enum libwebsocket_extension_callback_reasons reason,
15                                                void *user, void *in, size_t len)
16 {
17         struct lws_ext_deflate_stream_conn *conn =
18                                      (struct lws_ext_deflate_stream_conn *)user;
19         int n;
20         struct lws_tokens *eff_buf = (struct lws_tokens *)in;
21
22         switch (reason) {
23
24         /*
25          * for deflate-stream, both client and server sides act the same
26          */
27
28         case LWS_EXT_CALLBACK_CLIENT_CONSTRUCT:
29         case LWS_EXT_CALLBACK_CONSTRUCT:
30                 conn->zs_in.zalloc = conn->zs_out.zalloc = Z_NULL;
31                 conn->zs_in.zfree = conn->zs_out.zfree = Z_NULL;
32                 conn->zs_in.opaque = conn->zs_out.opaque = Z_NULL;
33                 n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
34                 if (n != Z_OK) {
35                         lwsl_err("deflateInit returned %d\n", n);
36                         return 1;
37                 }
38                 n = deflateInit2(&conn->zs_out,
39                                  DEFLATE_STREAM_COMPRESSION_LEVEL, Z_DEFLATED,
40                                  -LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
41                                                             Z_DEFAULT_STRATEGY);
42                 if (n != Z_OK) {
43                         lwsl_err("deflateInit returned %d\n", n);
44                         return 1;
45                 }
46                 lwsl_ext("zlibs constructed\n");
47                 conn->remaining_in = 0;
48                 break;
49
50         case LWS_EXT_CALLBACK_DESTROY:
51                 (void)inflateEnd(&conn->zs_in);
52                 (void)deflateEnd(&conn->zs_out);
53                 lwsl_ext("zlibs destructed\n");
54                 break;
55
56         case LWS_EXT_CALLBACK_PACKET_RX_PREPARSE:
57
58                 /*
59                  * inflate the incoming compressed data
60                  * Notice, length may be 0 and pointer NULL
61                  * in the case we are flushing with nothing new coming in
62                  */
63                 if (conn->remaining_in) {
64                         conn->zs_in.next_in = conn->buf_in;
65                         conn->zs_in.avail_in = conn->remaining_in;
66                         conn->remaining_in = 0;
67                 } else {
68                         conn->zs_in.next_in = (unsigned char *)eff_buf->token;
69                         conn->zs_in.avail_in = eff_buf->token_len;
70                 }
71
72                 conn->zs_in.next_out = conn->buf_out;
73                 conn->zs_in.avail_out = sizeof(conn->buf_out);
74
75                 n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
76                 switch (n) {
77                 case Z_NEED_DICT:
78                 case Z_DATA_ERROR:
79                 case Z_MEM_ERROR:
80                         /*
81                          * screwed.. close the connection... we will get a
82                          * destroy callback to take care of closing nicely
83                          */
84                         lwsl_err("zlib error inflate %d\n", n);
85                         return -1;
86                 }
87
88                 /* rewrite the buffer pointers and length */
89
90                 eff_buf->token = (char *)conn->buf_out;
91                 eff_buf->token_len =
92                         sizeof(conn->buf_out) - conn->zs_in.avail_out;
93
94                 /* copy avail data if not consumed */
95                 if (conn->zs_in.avail_in > 0) {
96                         conn->remaining_in = conn->zs_in.avail_in;
97                         memcpy(conn->buf_in, conn->zs_in.next_in,
98                                                         conn->zs_in.avail_in);
99                         return 1;
100                 }
101
102                 /*
103                  * if we filled the output buffer, signal that we likely have
104                  * more and need to be called again
105                  */
106
107                 if (eff_buf->token_len == sizeof(conn->buf_out))
108                         return 1;
109
110                 /* we don't need calling again until new input data comes */
111
112                 return 0;
113
114         case LWS_EXT_CALLBACK_FLUSH_PENDING_TX:
115         case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
116
117                 /*
118                  * deflate the outgoing compressed data
119                  */
120
121                 conn->zs_out.next_in = (unsigned char *)eff_buf->token;
122                 conn->zs_out.avail_in = eff_buf->token_len;
123
124                 conn->zs_out.next_out = conn->buf_out;
125                 conn->zs_out.avail_out = sizeof(conn->buf_out);
126
127                 n = Z_PARTIAL_FLUSH;
128                 if (reason == LWS_EXT_CALLBACK_FLUSH_PENDING_TX)
129                         n = Z_FULL_FLUSH;
130
131                 n = deflate(&conn->zs_out, n);
132                 if (n == Z_STREAM_ERROR) {
133                         /*
134                          * screwed.. close the connection... we will get a
135                          * destroy callback to take care of closing nicely
136                          */
137                         lwsl_ext("zlib error deflate\n");
138
139                         return -1;
140                 }
141
142                 /* rewrite the buffer pointers and length */
143
144                 eff_buf->token = (char *)conn->buf_out;
145                 eff_buf->token_len =
146                                 sizeof(conn->buf_out) - conn->zs_out.avail_out;
147
148                 /*
149                  * if we filled the output buffer, signal that we likely have
150                  * more and need to be called again... even in deflate case
151                  * we might sometimes need to spill more than came in
152                  */
153
154                 if (eff_buf->token_len == sizeof(conn->buf_out))
155                         return 1;
156
157                 /* we don't need calling again until new input data comes */
158
159                 return 0;
160
161         default:
162                 break;
163         }
164
165         return 0;
166 }