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