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; }
// called after receaving the uwsgi header (read vars) static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) { struct uwsgi_header *uh = (struct uwsgi_header *) main_peer->in->buf; // better to store it as the original buf address could change uint16_t pktsize = uh->_pktsize; // increase buffer if needed if (uwsgi_buffer_fix(main_peer->in, pktsize+4)) return -1; ssize_t len = cr_read_exact(main_peer, pktsize+4, "fr_recv_uwsgi_vars()"); if (!len) return 0; // headers received, ready to choose the instance if (main_peer->in->pos == (size_t)(pktsize+4)) { struct uwsgi_corerouter *ucr = main_peer->session->corerouter; struct corerouter_peer *new_peer = uwsgi_cr_peer_add(main_peer->session); new_peer->last_hook_read = fr_instance_read; if (!ufr.force_key) { // find the hostname if (uwsgi_hooked_parse(main_peer->in->buf+4, pktsize, fr_get_hostname, (void *) new_peer)) { return -1; } } else { new_peer->key_len = strlen(ufr.force_key); memcpy(new_peer->key, ufr.force_key, new_peer->key_len); } // check the hostname; if (new_peer->key_len == 0) return -1; // find an instance using the key if (ucr->mapper(ucr, new_peer)) return -1; // check instance if (new_peer->instance_address_len == 0) { if (ufr.cr.fallback_on_no_key) { new_peer->failed = 1; new_peer->can_retry = 1; corerouter_close_peer(&ufr.cr, new_peer); return len; } return -1; } new_peer->can_retry = 1; cr_connect(new_peer, fr_instance_connected); } return len; }
// called after receaving the uwsgi header (read vars) ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) { struct uwsgi_header *uh = (struct uwsgi_header *) main_peer->in->buf; // increase buffer if needed if (uwsgi_buffer_fix(main_peer->in, uh->pktsize+4)) return -1; ssize_t len = cr_read_exact(main_peer, uh->pktsize+4, "fr_recv_uwsgi_vars()"); if (!len) return 0; // headers received, ready to choose the instance if (main_peer->in->pos == (size_t)(uh->pktsize+4)) { struct uwsgi_corerouter *ucr = main_peer->session->corerouter; struct corerouter_peer *new_peer = uwsgi_cr_peer_add(main_peer->session); new_peer->last_hook_read = fr_instance_read; // find the hostname if (uwsgi_hooked_parse(main_peer->in->buf+4, uh->pktsize, fr_get_hostname, (void *) new_peer)) { return -1; } // check the hostname; if (new_peer->key_len == 0) return -1; // find an instance using the key if (ucr->mapper(ucr, new_peer)) return -1; // check instance if (new_peer->instance_address_len == 0) return -1; cr_connect(new_peer, fr_instance_connected); } return len; }
static ssize_t sr_read(struct corerouter_peer *main_peer) { struct corerouter_session *cs = main_peer->session; struct sslrouter_session *sr = (struct sslrouter_session *) cs; int ret = SSL_read(sr->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(sr->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(sr->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; } if (!main_peer->session->peers) { // add a new peer struct corerouter_peer *peer = uwsgi_cr_peer_add(cs); // set default peer hook peer->last_hook_read = sr_instance_read; // use the address as hostname peer->key = cs->ugs->name; peer->key_len = cs->ugs->name_len; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if (usr.sni) { const char *servername = SSL_get_servername(sr->ssl, TLSEXT_NAMETYPE_host_name); if (servername) { peer->key = (char *) servername; peer->key_len = strlen(servername); } } #endif // the mapper hook if (cs->corerouter->mapper(cs->corerouter, peer)) { return -1; } if (peer->instance_address_len == 0) { return -1; } peer->can_retry = 1; cr_connect(peer, sr_instance_connected); return 1; } main_peer->session->peers->out = main_peer->in; main_peer->session->peers->out_pos = 0; cr_write_to_backend(main_peer, sr_instance_write); return ret; } if (ret == 0) return 0; int err = SSL_get_error(sr->ssl, ret); if (err == SSL_ERROR_WANT_READ) { cr_reset_hooks_and_read(main_peer, sr_read); return 1; } else if (err == SSL_ERROR_WANT_WRITE) { cr_write_to_main(main_peer, sr_read); return 1; } else if (err == SSL_ERROR_SYSCALL) { uwsgi_cr_error(main_peer, "sr_ssl_read()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { ERR_print_errors_fp(stderr); } return -1; }