1 /*
2
3 uWSGI SPDY3 router
4
5 */
6
7 #include "common.h"
8
9 #ifdef UWSGI_SPDY
10
11 extern struct uwsgi_http uhttp;
12
13 #include "spdy3.h"
14
spdy_h_read_control(uint8_t * header)15 static uint8_t spdy_h_read_control(uint8_t *header) {
16 return header[0] >> 7;
17 }
18
spdy_h_read_version(uint8_t * header)19 static uint16_t spdy_h_read_version(uint8_t *header) {
20 uint16_t ret = 0;
21 uint8_t *ptr = (uint8_t *) &ret;
22 ptr[0] = header[0] & 0x7f;
23 ptr[1] = header[1];
24 return ntohs(ret);
25 }
26
spdy_h_read_type(uint8_t * header)27 static uint16_t spdy_h_read_type(uint8_t *header) {
28 uint16_t ret = 0;
29 uint8_t *ptr = (uint8_t *) &ret;
30 ptr[0] = header[2];
31 ptr[1] = header[3];
32 return ntohs(ret);
33 }
34
35
spdy_h_read_flags(uint8_t * header)36 static uint8_t spdy_h_read_flags(uint8_t *header) {
37 return header[4];
38 }
39
spdy_h_read_length(uint8_t * header)40 static uint32_t spdy_h_read_length(uint8_t *header) {
41 uint32_t ret = 0;
42 uint8_t *ptr = (uint8_t *) &ret;
43 ptr[1] = header[5];
44 ptr[2] = header[6];
45 ptr[3] = header[7];
46 return ntohl(ret);
47 }
48
spdy_stream_id(uint8_t * body)49 static uint32_t spdy_stream_id(uint8_t *body) {
50 uint32_t ret = 0;
51 uint8_t *ptr = (uint8_t *) &ret;
52 ptr[0] = body[0] & 0x7f;
53 ptr[1] = body[1];
54 ptr[2] = body[2];
55 ptr[3] = body[3];
56 return ntohl(ret);
57 }
58
59 /*
60 static uint32_t spdy_associated_stream_id(uint8_t *body) {
61 uint32_t ret = 0;
62 uint8_t *ptr = (uint8_t *) &ret;
63 ptr[0] = body[4] & 0x7f;
64 ptr[1] = body[5];
65 ptr[2] = body[6];
66 ptr[3] = body[7];
67 return ntohl(ret);
68 }
69 */
70
spdy_translate(char * buf,uint32_t len,uint16_t * d_len)71 static char *spdy_translate(char *buf, uint32_t len, uint16_t *d_len) {
72 uint32_t i;
73 if (len == 0) return NULL;
74
75 if (buf[0] == ':') {
76
77 if (!uwsgi_strncmp(buf+1, len-1, "method", 6)) {
78 *d_len = 14;
79 return uwsgi_str("REQUEST_METHOD");
80 }
81
82 if (!uwsgi_strncmp(buf+1, len-1, "path", 4)) {
83 *d_len = 11;
84 return uwsgi_str("REQUEST_URI");
85 }
86
87 if (!uwsgi_strncmp(buf+1, len-1, "version", 7)) {
88 *d_len = 15;
89 return uwsgi_str("SERVER_PROTOCOL");
90 }
91
92 if (!uwsgi_strncmp(buf+1, len-1, "host", 4)) {
93 *d_len = 9;
94 return uwsgi_str("HTTP_HOST");
95 }
96
97 if (!uwsgi_strncmp(buf+1, len-1, "scheme", 6)) {
98 *d_len = 12;
99 return uwsgi_str("UWSGI_SCHEME");
100 }
101
102 return NULL;
103 }
104
105 if (!uwsgi_strncmp(buf, len, "content-length", 14)) {
106 *d_len = 14;
107 return uwsgi_str("CONTENT_LENGTH");
108 }
109
110 if (!uwsgi_strncmp(buf, len, "content-type", 12)) {
111 *d_len = 12;
112 return uwsgi_str("CONTENT_TYPE");
113 }
114
115 char *buf2 = uwsgi_malloc(len + 5);
116 memcpy(buf2, "HTTP_", 5);
117 char *ptr = buf2+5;
118 for(i=0;i<len;i++) {
119 if (buf[i] == '-') {
120 *ptr++= '_';
121 }
122 else {
123 *ptr++= toupper((int) buf[i]);
124 }
125 }
126
127 *d_len = len+5;
128 return buf2;
129
130 }
131
spdy_http_to_spdy(char * buf,size_t len,uint32_t * hh)132 struct uwsgi_buffer *spdy_http_to_spdy(char *buf, size_t len, uint32_t *hh) {
133 size_t i;
134 size_t next = 0;
135 struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
136 // leave space for the number of items
137 ub->pos+=4;
138
139 int found = 0;
140 // :version
141 for(i=0;i<len;i++) {
142 if (buf[i] == ' ') {
143 if (uwsgi_buffer_append_keyval32(ub, ":version", 8, buf, i)) goto end;
144 if (i+1 >= len) goto end;
145 next = i+1;
146 found = 1;
147 break;
148 }
149 }
150
151 if (!found) goto end;
152
153 // :status
154 found = 0;
155 for(i=next;i<len;i++) {
156 if (buf[i] == '\r' || buf[i] == '\n') {
157 if (uwsgi_buffer_append_keyval32(ub, ":status", 7, buf + next, i-next)) goto end;
158 if (i+1 >= len) goto end;
159 next = i + 1;
160 found = 1;
161 break;
162 }
163 }
164
165 if (!found) goto end;
166
167 *hh = 2;
168
169 char *key = NULL;
170
171 // find first header position
172 for(i=next;i<len;i++) {
173 if (buf[i] != '\r' && buf[i] != '\n') {
174 key = buf + i;
175 next = i;
176 break;
177 }
178 }
179
180 if (!key) return ub;
181
182 uint32_t h_len = 0;
183 // merge header values and ensure keys are all lowercase
184 struct uwsgi_string_list *hr=NULL, *usl=NULL;
185 char *line_value;
186 size_t line_key_len, line_value_len;
187 for(i=next;i<len;i++) {
188 if (key) {
189 if (buf[i] == '\r' || buf[i] == '\n') {
190 char *colon = memchr(key, ':', h_len);
191 if (!colon) goto end;
192 // security check
193 if (colon+2 >= buf+len) goto end;
194 // tolower !!!
195 size_t j;
196 for(j=0;j<h_len;j++) {
197 // don't lowercase values, only keys
198 if (key[j] == ':') break;
199 key[j] = tolower((int) key[j]);
200 }
201 line_key_len = colon - key;
202 key[line_key_len] = 0;
203 line_value_len = h_len - 2 - line_key_len;
204 line_value = uwsgi_strncopy(colon+2, line_value_len);
205 if (hr) {
206 // check if we already store values for this key
207 usl = uwsgi_string_list_has_item(hr, key, line_key_len);
208 if (usl) {
209 // we have this key, append new value
210 char *oldval = usl->custom_ptr;
211 usl->custom_ptr = uwsgi_concat3n(usl->custom_ptr, usl->custom, "\0", 1, line_value, line_value_len);
212 usl->custom = usl->custom + 1 + line_value_len;
213 free(oldval);
214 }
215 else {
216 // this key is new
217 usl = uwsgi_string_new_list(&hr, key);
218 usl->custom_ptr = line_value;
219 usl->custom = line_value_len;
220 }
221 }
222 else {
223 // this is first key
224 usl = uwsgi_string_new_list(&hr, key);
225 usl->custom_ptr = line_value;
226 usl->custom = line_value_len;
227 }
228 key = NULL;
229 h_len = 0;
230 }
231 else {
232 h_len++;
233 }
234 }
235 else {
236 if (buf[i] != '\r' && buf[i] != '\n') {
237 key = buf+i;
238 h_len = 1;
239 }
240 }
241 }
242
243 // append all merged header lines to buffer and free memory
244 struct uwsgi_string_list *ohr;
245 while (hr) {
246 if (uwsgi_buffer_append_keyval32(ub, hr->value, hr->len, hr->custom_ptr, hr->custom)) goto end;
247 *hh+=1;
248 ohr = hr;
249 hr = hr->next;
250 free(ohr->custom_ptr);
251 free(ohr);
252 }
253
254 return ub;
255
256 end:
257 uwsgi_buffer_destroy(ub);
258 return NULL;
259 }
260
261 char *spdy_deflate_http_headers(struct http_session *, struct uwsgi_buffer *, size_t *);
262
263 // be sure to have at least 8 free bytes
spdy_data_header(char * buf,uint32_t len,uint32_t stream_id)264 static void spdy_data_header(char *buf, uint32_t len, uint32_t stream_id) {
265 // stream id
266 buf[3] = (uint8_t) (stream_id & 0xff);
267 buf[2] = (uint8_t) ((stream_id >> 8) & 0xff);
268 buf[1] = (uint8_t) ((stream_id >> 16) & 0xff);
269 buf[0] = (uint8_t) ((stream_id >> 24) & 0xff);
270
271 // FIN
272 if (len == 0) {
273 buf[4] = 1;
274 }
275
276 // length
277 buf[7] = (uint8_t) (len & 0xff);
278 buf[6] = (uint8_t) ((len >> 8) & 0xff);
279 buf[5] = (uint8_t) ((len >> 16) & 0xff);
280
281 }
282
283
284 // be sure to have at least 12 free bytes
spdy_reply_header(char * buf,uint32_t len,uint32_t stream_id)285 static void spdy_reply_header(char *buf, uint32_t len, uint32_t stream_id) {
286 buf[0] = 0x80;
287 buf[1] = 0x03;
288 buf[2] = 0;
289 buf[3] = 0x02;
290
291 // flags
292 buf[4] = 0;
293
294 // length
295 buf[7] = (uint8_t) (len & 0xff);
296 buf[6] = (uint8_t) ((len >> 8) & 0xff);
297 buf[5] = (uint8_t) ((len >> 16) & 0xff);
298
299 // stream id
300 buf[11] = (uint8_t) (stream_id & 0xff);
301 buf[10] = (uint8_t) ((stream_id >> 8) & 0xff);
302 buf[9] = (uint8_t) ((stream_id >> 16) & 0xff);
303 buf[8] = (uint8_t) ((stream_id >> 24) & 0xff);
304
305 }
306
307 // be sure to have at least 16 free bytes
spdy_window_update(char * buf,uint32_t stream_id,uint32_t wsize)308 void spdy_window_update(char *buf, uint32_t stream_id, uint32_t wsize) {
309 buf[0] = 0x80;
310 buf[1] = 0x03;
311 buf[2] = 0;
312 buf[3] = 0x09;
313
314 // flags
315 buf[4] = 0;
316
317 uint32_t len = 8;
318
319 // length
320 buf[7] = (uint8_t) (len & 0xff);
321 buf[6] = (uint8_t) ((len >> 8) & 0xff);
322 buf[5] = (uint8_t) ((len >> 16) & 0xff);
323
324 // stream id
325 buf[11] = (uint8_t) (stream_id & 0xff);
326 buf[10] = (uint8_t) ((stream_id >> 8) & 0xff);
327 buf[9] = (uint8_t) ((stream_id >> 16) & 0xff);
328 buf[8] = (uint8_t) ((stream_id >> 24) & 0xff);
329
330 buf[15] = (uint8_t) (wsize & 0xff);
331 buf[14] = (uint8_t) ((wsize >> 8) & 0xff);
332 buf[13] = (uint8_t) ((wsize >> 16) & 0xff);
333 buf[12] = (uint8_t) ((wsize >> 24) & 0xff);
334
335 }
336
337
http_parse_to_spdy(struct corerouter_peer * peer)338 static ssize_t http_parse_to_spdy(struct corerouter_peer *peer) {
339 size_t i;
340 struct uwsgi_buffer *ub = peer->in;
341 struct uwsgi_buffer *out = peer->out;
342
343 // reset the out buf (it will hold the spdy frame)
344 out->pos = 0;
345 peer->session->main_peer->out_pos = 0;
346
347 // end of the stream
348 if (peer->r_parser_status == 5) {
349 return -1;
350 }
351
352 // send DATA frame
353 if (peer->r_parser_status == 4) {
354 spdy_data_header(out->buf, ub->pos, peer->sid);
355 out->pos = 8;
356 // no need to call append on empty values
357 if (ub->pos > 0) {
358 if (uwsgi_buffer_append(out, ub->buf, ub->pos)) return -1;
359 }
360 else {
361 peer->r_parser_status = 5;
362 }
363 // reset the input buffer
364 ub->pos = 0;
365 return 1;
366 }
367
368 // try to send REPLY frame
369 for(i=0;i<ub->pos;i++) {
370 char c = ub->buf[i];
371 if (c == '\r' && (peer->r_parser_status == 0 || peer->r_parser_status == 2)) {
372 peer->r_parser_status++;
373 }
374 else if (c == '\r') {
375 peer->r_parser_status = 1;
376 }
377 else if (c == '\n' && peer->r_parser_status == 1) {
378 peer->r_parser_status = 2;
379 }
380 // parsing done
381 else if (c == '\n' && peer->r_parser_status == 3) {
382 peer->r_parser_status = 4;
383 uint32_t hh = 0;
384 struct uwsgi_buffer *h_buf = spdy_http_to_spdy(ub->buf, i, &hh);
385 if (!h_buf) return -1;
386 // put the number of headers on front of the buffer
387 h_buf->buf[3] = (uint8_t) (hh & 0xff);
388 h_buf->buf[2] = (uint8_t) ((hh >> 8) & 0xff);
389 h_buf->buf[1] = (uint8_t) ((hh >> 16) & 0xff);
390 h_buf->buf[0] = (uint8_t) ((hh >> 24) & 0xff);
391
392 // ok now we need to deflate the buffer
393 size_t cb_len = 0;
394 char *compressed_buf = spdy_deflate_http_headers((struct http_session *) peer->session, h_buf, &cb_len);
395 uwsgi_buffer_destroy(h_buf);
396 if (!compressed_buf) {
397 return -1;
398 }
399 // ok now we need an additional buffer
400 spdy_reply_header(out->buf, 4+cb_len, peer->sid);
401 out->pos = 12;
402 if (uwsgi_buffer_append(out, compressed_buf, cb_len)) {
403 free(compressed_buf);
404 return -1;
405 }
406 free(compressed_buf);
407
408 // any push request ???
409 // after all of the pushed requests are sent, we have to come back here...
410 // remains ?
411 if (ub->pos-i > 1) {
412 uint32_t remains = ub->pos-(i+1);
413 if (uwsgi_buffer_append(out, "\0\0\0\0\0\0\0\0", 8)) {
414 return -1;
415 }
416 spdy_data_header(out->buf + (out->pos - 8), remains, peer->sid);
417 if (uwsgi_buffer_append(out, ub->buf+i+1, remains)) {
418 return -1;
419 }
420 }
421 // reset the input buffer
422 ub->pos = 0;
423 return 1;
424 }
425 else {
426 peer->r_parser_status = 0;
427 }
428 }
429
430 return 0;
431
432 }
433
hr_instance_read_to_spdy(struct corerouter_peer * peer)434 ssize_t hr_instance_read_to_spdy(struct corerouter_peer *peer) {
435 ssize_t len = cr_read(peer, "hr_instance_read_to_spdy()");
436
437 // do not check for empty packet, as 0 will trigger a data frame
438 len = http_parse_to_spdy(peer);
439 if (len > 0) goto parsed;
440 if (len < 0) {
441 if (peer->r_parser_status == 5) return 0;
442 return -1;
443 }
444 // need more data
445 return 1;
446
447 parsed:
448 peer->session->main_peer->out = peer->out;
449 peer->session->main_peer->out_pos = 0;
450 cr_write_to_main(peer, hr_ssl_write);
451 return 1;
452 }
453
spdy_deflate_http_headers(struct http_session * hr,struct uwsgi_buffer * h_buf,size_t * dlen)454 char *spdy_deflate_http_headers(struct http_session *hr, struct uwsgi_buffer *h_buf, size_t *dlen) {
455 // calculate the amount of bytes needed for output (+30 should be enough)
456 Bytef *dbuf = uwsgi_malloc(h_buf->pos+30);
457 z_stream *z = &hr->spdy_z_out;
458 z->avail_in = h_buf->pos; z->next_in = (Bytef *) h_buf->buf; z->avail_out = h_buf->pos+30; z->next_out = dbuf;
459 if (deflate(z, Z_SYNC_FLUSH) != Z_OK) {
460 free(dbuf);
461 return NULL;
462 }
463
464 *dlen = z->next_out - dbuf;
465 return (char *) dbuf;
466 }
467
spdy_inflate_http_headers(struct http_session * hr)468 static ssize_t spdy_inflate_http_headers(struct http_session *hr) {
469
470 Bytef zbuf[4096];
471
472 uint8_t *src = (uint8_t *) hr->session.main_peer->in->buf;
473
474 hr->spdy_z_in.avail_in = hr->spdy_control_length - 10;
475 hr->spdy_z_in.next_in = src + 10;
476
477 struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
478
479 while(hr->spdy_z_in.avail_in > 0) {
480 hr->spdy_z_in.avail_out = 4096;
481 hr->spdy_z_in.next_out = zbuf;
482
483 int ret = inflate(&hr->spdy_z_in, Z_NO_FLUSH);
484 if (ret == Z_NEED_DICT) {
485 inflateSetDictionary(&hr->spdy_z_in, (Bytef *) SPDY_dictionary_txt, sizeof(SPDY_dictionary_txt));
486 ret = inflate(&hr->spdy_z_in, Z_NO_FLUSH);
487 }
488 if (ret != Z_OK) {
489 uwsgi_buffer_destroy(ub);
490 return -1;
491 }
492 size_t zlen = hr->spdy_z_in.next_out-zbuf;
493 if (uwsgi_buffer_append(ub, (char *) zbuf, zlen)) {
494 uwsgi_buffer_destroy(ub);
495 return -1;
496 }
497 }
498
499 if (ub->pos < 4) {
500 uwsgi_buffer_destroy(ub);
501 return -1;
502 }
503
504 uint32_t headers_num = uwsgi_be32(ub->buf);
505 uint32_t i, watermark = ub->pos, pos = 4;
506
507 struct corerouter_peer *new_peer = uwsgi_cr_peer_add(&hr->session);
508 new_peer->last_hook_read = hr_instance_read_to_spdy;
509 new_peer->out = uwsgi_buffer_new(uwsgi.page_size);
510 // this will avoid the buffer being destroyed on the first instance write
511 new_peer->out_need_free = 2;
512 // leave space for uwsgi header
513 new_peer->out->pos = 4;
514 new_peer->sid = hr->spdy_data_stream_id;
515
516 // leave space for header
517 for(i=0;i<headers_num;i++) {
518 // key
519 if (pos + 4 > watermark) {
520 uwsgi_buffer_destroy(ub);
521 return -1;
522 }
523 uint32_t k_len = uwsgi_be32( ub->buf + pos);
524 pos += 4;
525 if (pos + k_len > watermark) {
526 uwsgi_buffer_destroy(ub);
527 return -1;
528 }
529 char *k = ub->buf + pos;
530 pos += k_len;
531
532 // value
533 if (pos + 4 > watermark) {
534 uwsgi_buffer_destroy(ub);
535 return -1;
536 }
537 uint32_t v_len = uwsgi_be32( ub->buf + pos);
538 pos += 4;
539 if (pos + v_len > watermark) {
540 uwsgi_buffer_destroy(ub);
541 return -1;
542 }
543 char *v = ub->buf + pos;
544 pos += v_len;
545
546 uint16_t nk_len = 0;
547 char *cgi_name = spdy_translate(k, k_len, &nk_len);
548 if (!cgi_name) {
549 uwsgi_buffer_destroy(ub);
550 return -1;
551 }
552
553 if (uwsgi_buffer_append_keyval(new_peer->out, cgi_name, nk_len, v, v_len)) {
554 uwsgi_buffer_destroy(ub);
555 return -1;
556 }
557
558 if (!uwsgi_strncmp(cgi_name, nk_len, "HTTP_HOST", 9)) {
559 if (v_len <= 0xff) {
560 memcpy(new_peer->key, new_peer->out->buf + (new_peer->out->pos - v_len), v_len);
561 new_peer->key_len = v_len;
562 }
563 }
564 else if (!uwsgi_strncmp(cgi_name, nk_len, "REQUEST_URI", 11)) {
565 char *path_info = new_peer->out->buf + (new_peer->out->pos - v_len);
566 uint16_t path_info_len = v_len;
567 char *query_string = memchr(path_info, '?', v_len);
568 if (query_string) {
569 query_string++;
570 path_info_len = (query_string - path_info) -1;
571 uint16_t query_string_len = v_len - (path_info_len + 1);
572 if (uwsgi_buffer_append_keyval(new_peer->out, "QUERY_STRING", 12, query_string, query_string_len)) {
573 free(cgi_name);
574 uwsgi_buffer_destroy(ub);
575 return -1;
576 }
577 }
578 if (uwsgi_buffer_append_keyval(new_peer->out, "PATH_INFO", 9, path_info, path_info_len)) {
579 free(cgi_name);
580 uwsgi_buffer_destroy(ub);
581 return -1;
582 }
583 }
584 free(cgi_name);
585 }
586 uwsgi_buffer_destroy(ub);
587
588 // find the backend node
589 if (new_peer->key_len == 0) return -1;
590
591 if (uwsgi_buffer_append_keyval(new_peer->out, "HTTPS", 5, "on", 2)) return -1;
592 if (uwsgi_buffer_append_keyval(new_peer->out, "SPDY", 4, "on", 2)) return -1;
593 if (uwsgi_buffer_append_keynum(new_peer->out, "SPDY.version", 12, 3)) return -1;
594 if (uwsgi_buffer_append_keynum(new_peer->out, "SPDY.stream", 11, new_peer->sid)) return -1;
595
596
597 struct uwsgi_corerouter *ucr = hr->session.corerouter;
598
599 // get instance name
600 if (ucr->mapper(ucr, new_peer )) return -1;
601
602 if (new_peer->instance_address_len == 0) {
603 return -1;
604 }
605
606 uint16_t pktsize = new_peer->out->pos-4;
607 // fix modifiers
608 new_peer->out->buf[0] = new_peer->session->main_peer->modifier1;
609 new_peer->out->buf[3] = new_peer->session->main_peer->modifier2;
610 // fix pktsize
611 new_peer->out->buf[1] = (uint8_t) (pktsize & 0xff);
612 new_peer->out->buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
613
614 new_peer->can_retry = 1;
615
616 cr_connect(new_peer, hr_instance_connected);
617
618 return 1;
619 }
620
spdy_manage_settings(struct http_session * hs)621 ssize_t spdy_manage_settings(struct http_session *hs) {
622 uwsgi_log("settings received !!!\n");
623 return 1;
624 }
625
spdy_manage_syn_stream(struct http_session * hr)626 ssize_t spdy_manage_syn_stream(struct http_session *hr) {
627 uint8_t *buf = (uint8_t *) hr->session.main_peer->in->buf;
628 hr->spdy_data_stream_id = spdy_stream_id(buf);
629 //uwsgi_log("SYN_STREAM received %u !!!\n", hr->spdy_data_stream_id) ;
630 //uwsgi_log("associated stream %u\n", spdy_associated_stream_id(buf));
631 return spdy_inflate_http_headers(hr);
632 }
633
spdy_manage_rst_stream(struct http_session * hr)634 ssize_t spdy_manage_rst_stream(struct http_session *hr) {
635 uint8_t *buf = (uint8_t *) hr->session.main_peer->in->buf;
636 hr->spdy_data_stream_id = spdy_stream_id(buf);
637 //uwsgi_log("RST_STREAM received %u !!!\n", hr->spdy_data_stream_id) ;
638 struct corerouter_peer *peer = uwsgi_cr_peer_find_by_sid(&hr->session, hr->spdy_data_stream_id);
639 if (peer) {
640 corerouter_close_peer(hr->session.corerouter, peer);
641 }
642 return 0;
643 }
644
spdy_manage_ping(struct http_session * hr)645 ssize_t spdy_manage_ping(struct http_session *hr) {
646 if (!hr->spdy_ping) {
647 hr->spdy_ping = uwsgi_buffer_new(12);
648 }
649 hr->spdy_ping->pos = 0;
650 if (uwsgi_buffer_append(hr->spdy_ping, hr->session.main_peer->in->buf, 12)) return -1;
651 hr->session.main_peer->out = hr->spdy_ping;
652 hr->session.main_peer->out_pos = 0;
653 cr_write_to_main(hr->session.main_peer, hr_ssl_write);
654 //uwsgi_log("PONG\n");
655 return 1;
656 }
657
658
659 /*
660
661 read from ssl peer.
662
663 This must be able to efficiently manage both http and spdy packets
664
665 when the first chunk is received the spdy field of the session is checked.
666
667 If it is a spdy packet, the SPDY parser will run...
668
669 */
670
671
672
673 #define UWSGI_SPDY_PHASE_HEADER 0
674 #define UWSGI_SPDY_PHASE_CONTROL 1
675 #define UWSGI_SPDY_PHASE_DATA 2
676
spdy_parse(struct corerouter_peer * main_peer)677 ssize_t spdy_parse(struct corerouter_peer *main_peer) {
678 struct corerouter_session *cs = main_peer->session;
679 struct http_session *hr = (struct http_session *) cs;
680
681 ssize_t ret = -1;
682
683 if (!hr->spdy_initialized) {
684 hr->spdy_z_in.zalloc = Z_NULL;
685 hr->spdy_z_in.zfree = Z_NULL;
686 hr->spdy_z_in.opaque = Z_NULL;
687 if (inflateInit(&hr->spdy_z_in) != Z_OK) {
688 return -1;
689 }
690 hr->spdy_z_out.zalloc = Z_NULL;
691 hr->spdy_z_out.zfree = Z_NULL;
692 hr->spdy_z_out.opaque = Z_NULL;
693 if (deflateInit(&hr->spdy_z_out, Z_DEFAULT_COMPRESSION) != Z_OK) {
694 return -1;
695 }
696 if (deflateSetDictionary(&hr->spdy_z_out, (Bytef *) SPDY_dictionary_txt, sizeof(SPDY_dictionary_txt)) != Z_OK) {
697 return -1;
698 }
699 cs->can_keepalive = 1;
700 hr->spdy_initialized = 1;
701
702 hr->spdy_phase = UWSGI_SPDY_PHASE_HEADER;
703 hr->spdy_need = 8;
704
705 main_peer->out = uhttp.spdy3_settings;
706 main_peer->out->pos = uhttp.spdy3_settings_size;
707 main_peer->out_pos = 0;
708 cr_write_to_main(main_peer, hr_ssl_write);
709 return 1;
710 }
711
712 for(;;) {
713 size_t len = main_peer->in->pos;
714 if (len == 0) {
715 return 1;
716 }
717 uint8_t *buf = (uint8_t *) main_peer->in->buf;
718 //uwsgi_log("%d bytes available\n", len);
719 switch(hr->spdy_phase) {
720 case UWSGI_SPDY_PHASE_HEADER:
721 if (len >= hr->spdy_need) {
722 hr->spdy_frame_type = spdy_h_read_control(buf);
723 if (hr->spdy_frame_type) {
724 hr->spdy_control_version = spdy_h_read_version(buf);
725 hr->spdy_control_type = spdy_h_read_type(buf);
726 hr->spdy_control_flags = spdy_h_read_flags(buf);
727 hr->spdy_control_length = spdy_h_read_length(buf);
728 hr->spdy_phase = UWSGI_SPDY_PHASE_CONTROL;
729 hr->spdy_need = hr->spdy_control_length;
730 //uwsgi_log("now i need %llu bytes for type %u\n", (unsigned long long) hr->spdy_need, hr->spdy_control_type);
731 }
732 else {
733 hr->spdy_phase = UWSGI_SPDY_PHASE_DATA;
734 hr->spdy_data_stream_id = spdy_stream_id(buf);
735 hr->spdy_control_length = spdy_h_read_length(buf);
736 hr->spdy_need = hr->spdy_control_length;
737 //uwsgi_log("need %llu bytes for stream_id %lu\n", (unsigned long long) hr->spdy_need, hr->spdy_data_stream_id);
738 }
739 if (uwsgi_buffer_decapitate(main_peer->in, 8)) return -1;
740 continue;
741 }
742 return 1;
743 case UWSGI_SPDY_PHASE_CONTROL:
744 if (len >= hr->spdy_need) {
745 switch(hr->spdy_control_type) {
746 // SYN_STREAM
747 case 1:
748 ret = spdy_manage_syn_stream(hr);
749 if (ret == 0) goto goon;
750 if (ret < 0) return -1;
751 goto newframe;
752 // RST_STREAM
753 case 3:
754 ret = spdy_manage_rst_stream(hr);
755 if (ret == 0) goto goon;
756 if (ret < 0) return -1;
757 goto newframe;
758 case 4:
759 //uwsgi_log("settings request...\n");
760 break;
761 case 6:
762 ret = spdy_manage_ping(hr);
763 if (ret == 0) goto goon;
764 if (ret < 0) return -1;
765 goto newframe;
766 break;
767 case 7:
768 // uwsgi_log("GO AWAY...\n");
769 break;
770 case 9:
771 // uwsgi_log("window update...\n");
772 break;
773 default:
774 uwsgi_log("i do not know how to manage type %u\n", hr->spdy_control_type);
775 break;
776 }
777 goon:
778 hr->spdy_phase = UWSGI_SPDY_PHASE_HEADER;
779 hr->spdy_need = 8;
780 if (uwsgi_buffer_decapitate(main_peer->in, hr->spdy_control_length)) return -1;
781 continue;
782 }
783 return 1;
784 case UWSGI_SPDY_PHASE_DATA:
785 if (len >= hr->spdy_need) {
786 struct corerouter_peer *peer = uwsgi_cr_peer_find_by_sid(&hr->session, hr->spdy_data_stream_id);
787 if (!peer) {
788 return -1;
789 }
790
791 peer->out->pos = 0;
792 if (uwsgi_buffer_append(peer->out, main_peer->in->buf, hr->spdy_need)) return -1;
793 peer->out_pos = 0;
794 hr->spdy_update_window = hr->spdy_data_stream_id;
795 cr_write_to_backend(peer, hr_instance_write);
796 ret = 1;
797 goto newframe;
798 }
799 return 1;
800 default:
801 return -1;
802 }
803 }
804
805 return -1;
806
807 newframe:
808 hr->spdy_phase = UWSGI_SPDY_PHASE_HEADER;
809 hr->spdy_need = 8;
810 if (uwsgi_buffer_decapitate(main_peer->in, hr->spdy_control_length)) return -1;
811 return ret;
812
813 }
814
815
uwsgi_spdy_npn(SSL * ssl,const unsigned char ** data,unsigned int * len,void * arg)816 int uwsgi_spdy_npn(SSL *ssl, const unsigned char **data, unsigned int *len, void *arg) {
817 //*data = (const unsigned char *) "\x06spdy/3\x06spdy/2\x08http/1.1\x08http/1.0";
818 *data = (const unsigned char *) "\x06spdy/3\x08http/1.1\x08http/1.0";
819 *len = strlen((const char *) *data);
820 return SSL_TLSEXT_ERR_OK;
821 }
822
uwsgi_spdy_info_cb(SSL const * ssl,int where,int ret)823 void uwsgi_spdy_info_cb(SSL const *ssl, int where, int ret) {
824 if (where & SSL_CB_HANDSHAKE_DONE) {
825 const unsigned char * proto = NULL;
826 unsigned len = 0;
827 SSL_get0_next_proto_negotiated(ssl, &proto, &len);
828 if (len == 6) {
829 if (!memcmp(proto, "spdy/3", 6)) {
830 //uwsgi_log("SPDY 3 !!!\n");
831 struct http_session *hr = SSL_get_ex_data(ssl, uhttp.spdy_index);
832 hr->spdy = 3;
833 //hr->spdy_hook = hr_recv_spdy_control_frame;
834 }
835 else if (!memcmp(proto, "spdy/2", 6)) {
836 //uwsgi_log("SPDY 2 !!!\n");
837 struct http_session *hr = SSL_get_ex_data(ssl, uhttp.spdy_index);
838 hr->spdy = 2;
839 //uwsgi_log("SPDY/2\n");
840 //hr->spdy_hook = hr_recv_spdy_control_frame;
841 }
842 }
843 #if OPENSSL_VERSION_NUMBER < 0x10100000L
844 if (ssl->s3) {
845 ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
846 }
847 #endif
848 }
849 }
850
851 #endif
852