void db_state_change(struct kore_pgsql *pgsql, void *arg) { struct connection *c = arg; printf("%p: state change on pgsql %d\n", arg, pgsql->state); switch (pgsql->state) { case KORE_PGSQL_STATE_INIT: db_init(c, pgsql); break; case KORE_PGSQL_STATE_WAIT: break; case KORE_PGSQL_STATE_COMPLETE: kore_connection_disconnect(c); break; case KORE_PGSQL_STATE_ERROR: kore_pgsql_logerror(pgsql); kore_connection_disconnect(c); break; case KORE_PGSQL_STATE_RESULT: db_results(pgsql, c); break; default: kore_pgsql_continue(pgsql); break; } }
void kore_platform_event_wait(void) { struct connection *c; int n, i, *fd; n = epoll_wait(efd, events, event_count, 100); if (n == -1) { if (errno == EINTR) return; fatal("epoll_wait(): %s", errno_s); } if (n > 0) kore_debug("main(): %d sockets available", n); for (i = 0; i < n; i++) { fd = (int *)events[i].data.ptr; if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP) { if (*fd == server.fd) fatal("error on server socket"); c = (struct connection *)events[i].data.ptr; kore_connection_disconnect(c); continue; } if (*fd == server.fd) { while (worker->accepted < worker->accept_treshold) { kore_connection_accept(&server, &c); if (c == NULL) break; worker->accepted++; kore_platform_event_schedule(c->fd, EPOLLIN | EPOLLOUT | EPOLLET, 0, c); } } else { c = (struct connection *)events[i].data.ptr; if (events[i].events & EPOLLIN) c->flags |= CONN_READ_POSSIBLE; if (events[i].events & EPOLLOUT && !(c->flags & CONN_WRITE_BLOCK)) c->flags |= CONN_WRITE_POSSIBLE; if (!kore_connection_handle(c)) kore_connection_disconnect(c); } } }
void kore_connection_check_idletimer(u_int64_t now, struct connection *c) { u_int64_t d; d = now - c->idle_timer.start; if (d >= c->idle_timer.length) { kore_debug("%p idle for %d ms, expiring", c, d); kore_connection_disconnect(c); } }
/* * Called whenever a client or its backend have disconnected. * This will disconnect the matching paired connection as well. */ void disconnect(struct connection *c) { struct connection *pair = c->hdlr_extra; c->hdlr_extra = NULL; if (pair != NULL) { pair->hdlr_extra = NULL; kore_connection_disconnect(pair); } }
/* * Called when either part of the pipe disconnects. */ static void ktunnel_pipe_disconnect(struct connection *c) { struct connection *cpipe = c->hdlr_extra; printf("ktunnel_pipe_disconnect(%p)->%p\n", c, cpipe); if (cpipe != NULL) { /* Prevent Kore from calling kore_mem_free() on hdlr_extra. */ c->hdlr_extra = NULL; kore_connection_disconnect(cpipe); } }
void db_init(struct connection *c, struct kore_pgsql *pgsql) { if (!kore_pgsql_setup(pgsql, "db", KORE_PGSQL_ASYNC)) { if (pgsql->state == KORE_PGSQL_STATE_INIT) { printf("\twaiting for available pgsql connection\n"); return; } kore_pgsql_logerror(pgsql); kore_connection_disconnect(c); return; } printf("\tgot pgsql connection\n"); if (!kore_pgsql_query(pgsql, "SELECT * FROM coders, pg_sleep(5)")) { kore_pgsql_logerror(pgsql); kore_connection_disconnect(c); return; } printf("\tquery fired off!\n"); }
void kore_connection_check_idletimer(u_int64_t now, struct connection *c) { u_int64_t d; d = now - c->idle_timer.start; if (d >= c->idle_timer.length) { kore_debug("%p idle for %d ms, expiring", c, d); if (c->proto == CONN_PROTO_SPDY) spdy_session_teardown(c, SPDY_SESSION_ERROR_OK); else kore_connection_disconnect(c); } }
int net_send_flush(struct connection *c) { kore_debug("net_send_flush(%p)", c); while (!TAILQ_EMPTY(&(c->send_queue)) && (c->flags & CONN_WRITE_POSSIBLE)) { if (!net_send(c)) return (KORE_RESULT_ERROR); } if ((c->flags & CONN_CLOSE_EMPTY) && TAILQ_EMPTY(&(c->send_queue))) kore_connection_disconnect(c); return (KORE_RESULT_OK); }
/* * Called for every new connection on a certain ip/port. Which one is * configured in the TLS proxy its configuration file. */ void client_setup(struct connection *c) { int i, fd; struct connection *backend; /* Paranoia. */ if (c->ssl->session == NULL || c->ssl->session->tlsext_hostname == NULL) { kore_connection_disconnect(c); return; } /* Figure out what backend to use. */ for (i = 0; backends[i].name != NULL; i++) { if (!strcasecmp(backends[i].name, c->ssl->session->tlsext_hostname)) break; } /* If we don't have any backends, we just disconnect the client. */ if (backends[i].name == NULL) { kore_connection_disconnect(c); return; } /* Create new socket for the backend connection. */ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { kore_log(LOG_ERR, "socket(): %s", errno_s); kore_connection_disconnect(c); return; } /* Set it to non blocking as well. */ if (!kore_connection_nonblock(fd, 1)) { close(fd); kore_connection_disconnect(c); return; } /* Grab a new connection from Kore to hook backend into. */ backend = kore_connection_new(NULL); /* Prepare our connection. */ backend->addrtype = AF_INET; backend->addr.ipv4.sin_family = AF_INET; backend->addr.ipv4.sin_port = htons(backends[i].port); backend->addr.ipv4.sin_addr.s_addr = inet_addr(backends[i].ip); /* Set the file descriptor for the backend. */ backend->fd = fd; /* Default write/read callbacks for backend. */ backend->read = net_read; backend->write = net_write; /* Connection type (unknown to Kore). */ backend->proto = CONN_PROTO_UNKNOWN; backend->state = CONN_STATE_ESTABLISHED; /* The backend idle timer is set first to connection timeout. */ backend->idle_timer.length = PROXY_CONNECT_TIMEOUT; /* The client idle timer is set to default idle time. */ c->idle_timer.length = PROXY_TIMEOUT; /* Now link both the client and the backend connection together. */ c->hdlr_extra = backend; backend->hdlr_extra = c; /* * The handle function pointer for the backend is set to the * backend_handle_connect() while connecting. */ c->handle = client_handle; backend->handle = backend_handle_connect; /* Set the disconnect method for both connections. */ c->disconnect = disconnect; backend->disconnect = disconnect; /* Queue write events for the backend connection for now. */ kore_platform_schedule_write(backend->fd, backend); /* Start idle timer for the backend. */ kore_connection_start_idletimer(backend); /* Set our client connection to established. */ c->state = CONN_STATE_ESTABLISHED; /* Insert the backend into the list of Kore connections. */ TAILQ_INSERT_TAIL(&connections, backend, list); /* Kick off connecting. */ backend->flags |= CONN_WRITE_POSSIBLE; backend->handle(backend); }
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); }