int kore_connection_accept(struct listener *l, struct connection **out) { socklen_t len; struct connection *c; kore_debug("kore_connection_accept(%p)", l); *out = NULL; len = sizeof(struct sockaddr_in); c = kore_pool_get(&connection_pool); if ((c->fd = accept(l->fd, (struct sockaddr *)&(c->sin), &len)) == -1) { kore_pool_put(&connection_pool, c); kore_debug("accept(): %s", errno_s); return (KORE_RESULT_ERROR); } if (!kore_connection_nonblock(c->fd)) { close(c->fd); kore_pool_put(&connection_pool, c); return (KORE_RESULT_ERROR); } c->owner = l; c->ssl = NULL; c->flags = 0; c->inflate_started = 0; c->deflate_started = 0; c->client_stream_id = 0; c->proto = CONN_PROTO_UNKNOWN; c->state = CONN_STATE_SSL_SHAKE; c->wsize_initial = SPDY_INIT_WSIZE; c->idle_timer.start = 0; c->idle_timer.length = KORE_IDLE_TIMER_MAX; TAILQ_INIT(&(c->send_queue)); TAILQ_INIT(&(c->recv_queue)); TAILQ_INIT(&(c->spdy_streams)); kore_worker_connection_add(c); kore_connection_start_idletimer(c); *out = c; return (KORE_RESULT_OK); }
/* * Connect to our target host:port and attach it to a struct connection that * Kore understands. We set the disconnect method so we get a callback * whenever either of the connections will go away so we can cleanup the * one it is attached to. */ static int ktunnel_pipe_create(struct connection *c, const char *host, const char *port) { struct sockaddr_in sin; struct connection *cpipe; u_int16_t nport; int fd, err; nport = kore_strtonum(port, 10, 1, SHRT_MAX, &err); if (err == KORE_RESULT_ERROR) { kore_log(LOG_ERR, "invalid port given %s", port); return (KORE_RESULT_ERROR); } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { kore_log(LOG_ERR, "socket(): %s", errno_s); return (KORE_RESULT_ERROR); } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(nport); sin.sin_addr.s_addr = inet_addr(host); kore_log(LOG_NOTICE, "Attempting to connect to %s:%s", host, port); if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { close(fd); kore_log(LOG_ERR, "connect(): %s", errno_s); return (KORE_RESULT_ERROR); } if (!kore_connection_nonblock(fd)) { close(fd); return (KORE_RESULT_ERROR); } cpipe = kore_connection_new(c); cpipe->fd = fd; cpipe->addr.ipv4 = sin; cpipe->read = net_read; cpipe->write = net_write; cpipe->addrtype = AF_INET; cpipe->proto = CONN_PROTO_UNKNOWN; cpipe->state = CONN_STATE_ESTABLISHED; /* Don't let these connections timeout any time soon. */ cpipe->idle_timer.length = 10000000000; c->idle_timer.length = 10000000000; c->hdlr_extra = cpipe; cpipe->hdlr_extra = c; c->disconnect = ktunnel_pipe_disconnect; cpipe->disconnect = ktunnel_pipe_disconnect; kore_worker_connection_add(cpipe); kore_connection_start_idletimer(cpipe); kore_platform_event_all(cpipe->fd, cpipe); net_recv_reset(c, NETBUF_SEND_PAYLOAD_MAX, ktunnel_pipe_data); net_recv_queue(cpipe, NETBUF_SEND_PAYLOAD_MAX, NETBUF_CALL_CB_ALWAYS, ktunnel_pipe_data); printf("connection started to %s (%p -> %p)\n", host, c, cpipe); return (KORE_RESULT_OK); }