int hr_force_https(struct corerouter_peer *peer) { struct corerouter_session *cs = peer->session; struct http_session *hr = (struct http_session *) cs; if (uwsgi_buffer_append(peer->in, "HTTP/1.1 301 Moved Permanently\r\nLocation: https://", 50)) return -1; char *colon = memchr(peer->key, ':', peer->key_len); if (colon) { if (uwsgi_buffer_append(peer->in, peer->key, colon-peer->key)) return -1; } else { if (uwsgi_buffer_append(peer->in, peer->key, peer->key_len)) return -1; } if (cs->ugs->ctx) { if (uwsgi_buffer_append(peer->in, ":", 1)) return -1; if (uwsgi_buffer_append(peer->in,cs->ugs->ctx, strlen(cs->ugs->ctx))) return -1; } if (uwsgi_buffer_append(peer->in, hr->request_uri, hr->request_uri_len)) return -1; if (uwsgi_buffer_append(peer->in, "\r\n\r\n", 4)) return -1; hr->session.wait_full_write = 1; peer->session->main_peer->out = peer->in; peer->session->main_peer->out_pos = 0; cr_write_to_main(peer, hr->func_write); return 0; }
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; }
ssize_t hr_ssl_write(struct corerouter_peer *main_peer) { struct corerouter_session *cs = main_peer->session; struct http_session *hr = (struct http_session *) cs; hr_ssl_clear_errors(); int ret = SSL_write(hr->ssl, main_peer->out->buf + main_peer->out_pos, main_peer->out->pos - main_peer->out_pos); if (ret > 0) { main_peer->out_pos += ret; if (main_peer->out->pos == main_peer->out_pos) { // reset the buffer (if needed) main_peer->out->pos = 0; if (main_peer->session->wait_full_write) { main_peer->session->wait_full_write = 0; return 0; } if (main_peer->session->connect_peer_after_write) { cr_connect(main_peer->session->connect_peer_after_write, hr_instance_connected); main_peer->session->connect_peer_after_write = NULL; return ret; } cr_reset_hooks(main_peer); #ifdef UWSGI_SPDY if (hr->spdy) { return spdy_parse(main_peer); } #endif } return ret; } 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_write); return 1; } else if (err == SSL_ERROR_WANT_WRITE) { cr_write_to_main(main_peer, hr_ssl_write); return 1; } else if (err == SSL_ERROR_SYSCALL) { if (errno != 0) uwsgi_cr_error(main_peer, "hr_ssl_write()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { ERR_print_errors_fp(stderr); } return -1; }
// read from backend static ssize_t rr_instance_read(struct corerouter_peer *peer) { ssize_t len = cr_read(peer, "rr_instance_read()"); if (!len) return 0; // set the input buffer as the main output one peer->session->main_peer->out = peer->in; peer->session->main_peer->out_pos = 0; cr_write_to_main(peer, rr_write); return len; }
// write the xclient banner static ssize_t rr_xclient_write(struct corerouter_peer *peer) { struct corerouter_session *cs = peer->session; struct rawrouter_session *rr = (struct rawrouter_session *) cs; ssize_t len = cr_write_buf(peer, rr->xclient, "rr_xclient_write()"); if (!len) return 0; if (cr_write_complete_buf(peer, rr->xclient)) { if (peer->session->main_peer->out_pos > 0) { // (eventually) send previous data peer->last_hook_read = rr_instance_read; cr_write_to_main(peer, rr_write); } else { // reset to standard behaviour peer->in->pos = 0; cr_reset_hooks_and_read(peer, rr_instance_read); } } return len; }
ssize_t hr_ssl_write(struct corerouter_peer *main_peer) { struct corerouter_session *cs = main_peer->session; struct http_session *hr = (struct http_session *) cs; int ret = SSL_write(hr->ssl, main_peer->out->buf + main_peer->out_pos, main_peer->out->pos - main_peer->out_pos); if (ret > 0) { main_peer->out_pos += ret; if (main_peer->out->pos == main_peer->out_pos) { // reset the buffer (if needed) main_peer->out->pos = 0; cr_reset_hooks(main_peer); } return ret; } if (ret == 0) return 0; int err = SSL_get_error(hr->ssl, ret); if (err == SSL_ERROR_WANT_READ) { cr_reset_hooks_and_read(main_peer, hr_ssl_write); return 1; } else if (err == SSL_ERROR_WANT_WRITE) { cr_write_to_main(main_peer, hr_ssl_write); return 1; } else if (err == SSL_ERROR_SYSCALL) { uwsgi_error("hr_ssl_write()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { ERR_print_errors_fp(stderr); } return -1; }
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; }