ssize_t hr_ssl_read(struct corerouter_peer *main_peer) { struct corerouter_session *cs = main_peer->session; struct http_session *hr = (struct http_session *) cs; hr_ssl_clear_errors(); // try to always leave 4k available if (uwsgi_buffer_ensure(main_peer->in, uwsgi.page_size)) return -1; int ret = SSL_read(hr->ssl, main_peer->in->buf + main_peer->in->pos, main_peer->in->len - main_peer->in->pos); if (ret > 0) { // fix the buffer main_peer->in->pos += ret; // check for pending data int ret2 = SSL_pending(hr->ssl); if (ret2 > 0) { if (uwsgi_buffer_fix(main_peer->in, main_peer->in->len + ret2 )) { uwsgi_cr_log(main_peer, "cannot fix the buffer to %d\n", main_peer->in->len + ret2); return -1; } if (SSL_read(hr->ssl, main_peer->in->buf + main_peer->in->pos, ret2) != ret2) { uwsgi_cr_log(main_peer, "SSL_read() on %d bytes of pending data failed\n", ret2); return -1; } // fix the buffer main_peer->in->pos += ret2; } #ifdef UWSGI_SPDY if (hr->spdy) { //uwsgi_log("RUNNING THE SPDY PARSER FOR %d bytes\n", main_peer->in->pos); return spdy_parse(main_peer); } #endif return http_parse(main_peer); } int err = SSL_get_error(hr->ssl, ret); if (err == SSL_ERROR_ZERO_RETURN || err == 0) return 0; if (err == SSL_ERROR_WANT_READ) { cr_reset_hooks_and_read(main_peer, hr_ssl_read); return 1; } else if (err == SSL_ERROR_WANT_WRITE) { cr_write_to_main(main_peer, hr_ssl_read); return 1; } else if (err == SSL_ERROR_SYSCALL) { if (errno != 0) uwsgi_cr_error(main_peer, "hr_ssl_read()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { ERR_print_errors_fp(stderr); } return -1; }
static struct uwsgi_buffer *uwsgi_websocket_recv_do(struct wsgi_request *wsgi_req, int nb) { if (!wsgi_req->websocket_buf) { // this buffer will be destroyed on connection close wsgi_req->websocket_buf = uwsgi_buffer_new(uwsgi.page_size); // need 2 byte header wsgi_req->websocket_need = 2; } for(;;) { size_t remains = wsgi_req->websocket_buf->pos; // i have data; if (remains >= wsgi_req->websocket_need) { switch(wsgi_req->websocket_phase) { // header case 0: uwsgi_websocket_parse_header(wsgi_req); wsgi_req->websocket_pktsize = 2 + (wsgi_req->websocket_has_mask*4); if (wsgi_req->websocket_size == 126) { wsgi_req->websocket_need += 2; wsgi_req->websocket_phase = 1; wsgi_req->websocket_pktsize += 2; } else if (wsgi_req->websocket_size == 127) { wsgi_req->websocket_need += 8; wsgi_req->websocket_phase = 1; wsgi_req->websocket_pktsize += 8; } else { wsgi_req->websocket_phase = 2; } break; // size case 1: if (wsgi_req->websocket_size == 126) { wsgi_req->websocket_size = uwsgi_be16(wsgi_req->websocket_buf->buf+2); } else if (wsgi_req->websocket_size == 127) { wsgi_req->websocket_size = uwsgi_be64(wsgi_req->websocket_buf->buf+2); } else { uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n"); return NULL; } if (wsgi_req->websocket_size > (uwsgi.websockets_max_size*1024)) { uwsgi_log("[uwsgi-websocket] invalid packet size received: %llu, max allowed: %llu\n", wsgi_req->websocket_size, uwsgi.websockets_max_size * 1024); return NULL; } wsgi_req->websocket_phase = 2; break; // mask check case 2: if (wsgi_req->websocket_has_mask) { wsgi_req->websocket_need += 4; wsgi_req->websocket_phase = 3; } else { wsgi_req->websocket_need += wsgi_req->websocket_size; wsgi_req->websocket_phase = 4; } break; // mask case 3: wsgi_req->websocket_pktsize += wsgi_req->websocket_size; wsgi_req->websocket_need += wsgi_req->websocket_size; wsgi_req->websocket_phase = 4; break; // message case 4: switch (wsgi_req->websocket_opcode) { // message case 0: case 1: case 2: return uwsgi_websockets_parse(wsgi_req); // close case 0x8: return NULL; // ping case 0x9: if (uwsgi_websockets_pong(wsgi_req)) { return NULL; } break; // pong case 0xA: wsgi_req->websocket_last_pong = uwsgi_now(); break; default: break; } // reset the status wsgi_req->websocket_phase = 0; wsgi_req->websocket_need = 2; // decapitate the buffer if (uwsgi_buffer_decapitate(wsgi_req->websocket_buf, wsgi_req->websocket_pktsize)) return NULL; break; // oops default: uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n"); return NULL; } } // need more data else { if (uwsgi_buffer_ensure(wsgi_req->websocket_buf, uwsgi.page_size)) return NULL; ssize_t len = uwsgi_websockets_recv_pkt(wsgi_req, nb); if (len <= 0) { if (nb == 1 && len == 0) { // return an empty buffer to signal blocking event return uwsgi_buffer_new(0); } return NULL; } // update buffer size wsgi_req->websocket_buf->pos+=len; } } return NULL; }