/* * This function is called for backends while they are connecting. * In here we check for write events and attempt to connect() to the * backend. * * Once a connection is established we set the backend handle function * pointer to the backend_handle_default() callback and setup the reads * for both the backend and the client connection we received. */ int backend_handle_connect(struct connection *c) { int ret; struct connection *src; /* We will get a write notification when we can progress. */ if (!(c->flags & CONN_WRITE_POSSIBLE)) return (KORE_RESULT_OK); kore_connection_stop_idletimer(c); /* Attempt connecting. */ ret = connect(c->fd, (struct sockaddr *)&c->addr.ipv4, sizeof(c->addr.ipv4)); /* If we failed check why, we are non blocking. */ if (ret == -1) { /* If we got a real error, disconnect. */ if (errno != EALREADY && errno != EINPROGRESS && errno != EISCONN) { kore_log(LOG_ERR, "connect(): %s", errno_s); return (KORE_RESULT_ERROR); } /* Clean the write flag, we'll be called later. */ if (errno != EISCONN) { c->flags &= ~CONN_WRITE_POSSIBLE; kore_connection_start_idletimer(c); return (KORE_RESULT_OK); } } /* The connection to the backend succeeded. */ c->handle = backend_handle_default; /* Setup read calls for both backend and its client. */ net_recv_queue(c, NETBUF_SEND_PAYLOAD_MAX, NETBUF_CALL_CB_ALWAYS, pipe_data); net_recv_queue(c->hdlr_extra, NETBUF_SEND_PAYLOAD_MAX, NETBUF_CALL_CB_ALWAYS, pipe_data); /* Allow for all events now. */ kore_connection_start_idletimer(c); kore_platform_event_all(c->fd, c); /* Allow events from source now. */ src = c->hdlr_extra; kore_platform_event_all(src->fd, src); /* Now lets start. */ return (c->handle(c)); }
int kore_connection_handle(struct connection *c) { int r; u_int32_t len; const u_char *data; kore_debug("kore_connection_handle(%p)", c); if (c->proto != CONN_PROTO_SPDY) kore_connection_stop_idletimer(c); switch (c->state) { case CONN_STATE_SSL_SHAKE: if (c->ssl == NULL) { c->ssl = SSL_new(primary_dom->ssl_ctx); if (c->ssl == NULL) { kore_debug("SSL_new(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } SSL_set_fd(c->ssl, c->fd); SSL_set_accept_state(c->ssl); } r = SSL_accept(c->ssl); if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: return (KORE_RESULT_OK); default: kore_debug("SSL_accept(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } } r = SSL_get_verify_result(c->ssl); if (r != X509_V_OK) { kore_debug("SSL_get_verify_result(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } SSL_get0_next_proto_negotiated(c->ssl, &data, &len); if (data) { if (!memcmp(data, "spdy/3", MIN(6, len))) { c->proto = CONN_PROTO_SPDY; net_recv_queue(c, SPDY_FRAME_SIZE, 0, NULL, spdy_frame_recv); } else if (!memcmp(data, "http/1.1", MIN(8, len))) { c->proto = CONN_PROTO_HTTP; net_recv_queue(c, HTTP_HEADER_MAX_LEN, NETBUF_CALL_CB_ALWAYS, NULL, http_header_recv); } else { kore_debug("npn: received unknown protocol"); } } else { c->proto = CONN_PROTO_HTTP; net_recv_queue(c, HTTP_HEADER_MAX_LEN, NETBUF_CALL_CB_ALWAYS, NULL, http_header_recv); } c->state = CONN_STATE_ESTABLISHED; /* FALLTHROUGH */ case CONN_STATE_ESTABLISHED: if (c->flags & CONN_READ_POSSIBLE) { if (!net_recv_flush(c)) return (KORE_RESULT_ERROR); } if (c->flags & CONN_WRITE_POSSIBLE) { if (!net_send_flush(c)) return (KORE_RESULT_ERROR); } break; case CONN_STATE_DISCONNECTING: break; default: kore_debug("unknown state on %d (%d)", c->fd, c->state); break; } if (c->proto != CONN_PROTO_SPDY) kore_connection_start_idletimer(c); return (KORE_RESULT_OK); }