// 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; }
// allocate a new session static int rawrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) { // set default read hook cs->main_peer->last_hook_read = rr_read; // set close hook cs->close = rr_session_close; // set retry hook cs->retry = rr_retry; if (sa && sa->sa_family == AF_INET) { if (urr.xclient) { struct rawrouter_session *rr = (struct rawrouter_session *) cs; rr->xclient = uwsgi_buffer_new(13+sizeof(cs->client_address)+2); if (uwsgi_buffer_append(rr->xclient, "XCLIENT ADDR=", 13)) return -1; if (uwsgi_buffer_append(rr->xclient, cs->client_address, strlen(cs->client_address))) return -1; if (uwsgi_buffer_append(rr->xclient, "\r\n", 2)) return -1; } } // add a new peer struct corerouter_peer *peer = uwsgi_cr_peer_add(cs); // set default peer hook peer->last_hook_read = rr_instance_read; // use the address as hostname memcpy(peer->key, cs->ugs->name, cs->ugs->name_len); peer->key_len = cs->ugs->name_len; // the mapper hook if (ucr->mapper(ucr, peer)) { return -1; } if (peer->instance_address_len == 0) { return -1; } peer->can_retry = 1; cr_connect(peer, rr_instance_connected); return 0; }
// 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; }