void net_send_stream(struct connection *c, void *data, u_int32_t len, int (*cb)(struct netbuf *), struct netbuf **out) { struct netbuf *nb; kore_debug("net_send_stream(%p, %p, %d)", c, data, len); nb = kore_pool_get(&nb_pool); nb->cb = cb; nb->owner = c; nb->s_off = 0; nb->buf = data; nb->b_len = len; nb->m_len = nb->b_len; nb->type = NETBUF_SEND; nb->flags = NETBUF_IS_STREAM; TAILQ_INSERT_TAIL(&(c->send_queue), nb, list); if (out != NULL) *out = nb; }
int net_write_ssl(struct connection *c, int len, int *written) { int r; r = SSL_write(c->ssl, (c->snb->buf + c->snb->s_off), len); if (c->tls_reneg > 1) return (KORE_RESULT_ERROR); if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: c->snb->flags |= NETBUF_MUST_RESEND; c->flags &= ~CONN_WRITE_POSSIBLE; return (KORE_RESULT_OK); case SSL_ERROR_SYSCALL: switch (errno) { case EINTR: *written = 0; return (KORE_RESULT_OK); case EAGAIN: c->snb->flags |= NETBUF_MUST_RESEND; c->flags &= ~CONN_WRITE_POSSIBLE; return (KORE_RESULT_OK); default: break; } /* FALLTHROUGH */ default: kore_debug("SSL_write(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } } *written = r; return (KORE_RESULT_OK); }
int net_read(struct connection *c, int *bytes) { int r; r = read(c->fd, (c->rnb->buf + c->rnb->s_off), (c->rnb->b_len - c->rnb->s_off)); if (r <= 0) { switch (errno) { case EINTR: case EAGAIN: c->flags &= ~CONN_READ_POSSIBLE; return (KORE_RESULT_OK); default: kore_debug("read(): %s", errno_s); return (KORE_RESULT_ERROR); } } *bytes = r; return (KORE_RESULT_OK); }
int net_read_ssl(struct connection *c, int *bytes) { int r; r = SSL_read(c->ssl, (c->rnb->buf + c->rnb->s_off), (c->rnb->b_len - c->rnb->s_off)); if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: c->flags &= ~CONN_READ_POSSIBLE; return (KORE_RESULT_OK); default: kore_debug("SSL_read(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } } *bytes = r; return (KORE_RESULT_OK); }
int net_write_ssl(struct connection *c, int len, int *written) { int r; r = SSL_write(c->ssl, (c->snb->buf + c->snb->s_off), len); if (r <= 0) { r = SSL_get_error(c->ssl, r); switch (r) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: c->snb->flags |= NETBUF_MUST_RESEND; c->flags &= ~CONN_WRITE_POSSIBLE; return (KORE_RESULT_OK); default: kore_debug("SSL_write(): %s", ssl_errno_s); return (KORE_RESULT_ERROR); } } *written = r; return (KORE_RESULT_OK); }
int net_write(struct connection *c, int len, int *written) { int r; r = write(c->fd, (c->snb->buf + c->snb->s_off), len); if (r <= -1) { switch (errno) { case EINTR: *written = 0; return (KORE_RESULT_OK); case EAGAIN: c->flags &= ~CONN_WRITE_POSSIBLE; return (KORE_RESULT_OK); default: kore_debug("write: %s", errno_s); return (KORE_RESULT_ERROR); } } *written = r; return (KORE_RESULT_OK); }
void kore_platform_proctitle(char *title) { if (prctl(PR_SET_NAME, title) == -1) kore_debug("prctl(): %s", errno_s); }
int kore_platform_event_wait(void) { struct connection *c; struct timespec timeo; int n, i, *fd; timeo.tv_sec = 0; timeo.tv_nsec = 100000000; n = kevent(kfd, changelist, nchanges, events, event_count, &timeo); if (n == -1) { if (errno == EINTR) return (0); fatal("kevent(): %s", errno_s); } nchanges = 0; if (n > 0) kore_debug("main(): %d sockets available", n); for (i = 0; i < n; i++) { fd = (int *)events[i].udata; if (events[i].flags & EV_EOF || events[i].flags & EV_ERROR) { if (*fd == server.fd) fatal("error on server socket"); c = (struct connection *)events[i].udata; kore_connection_disconnect(c); continue; } if (*fd == server.fd) { while (worker->accepted < worker->accept_treshold) { kore_connection_accept(&server, &c); if (c == NULL) continue; worker->accepted++; kore_platform_event_schedule(c->fd, EVFILT_READ, EV_ADD, c); kore_platform_event_schedule(c->fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, c); } } else { c = (struct connection *)events[i].udata; if (events[i].filter == EVFILT_READ) c->flags |= CONN_READ_POSSIBLE; if (events[i].filter == EVFILT_WRITE) c->flags |= CONN_WRITE_POSSIBLE; if (!kore_connection_handle(c)) { kore_connection_disconnect(c); } else { if (!TAILQ_EMPTY(&(c->send_queue))) { kore_platform_event_schedule(c->fd, EVFILT_WRITE, EV_ADD | EV_ONESHOT, c); } } } } return (count); }
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); }
void kore_task_finish(struct kore_task *t) { kore_debug("kore_task_finished: %p (%d)", t, t->result); close(t->fds[1]); }