libuv/ol_unix.c
Ryan Dahl 116bd967d6 ...
2011-03-23 20:40:55 -07:00

130 lines
2.4 KiB
C

#include "ol.h"
ol_loop* ol_loop_new() {
ol_loop* loop = calloc(sizeof(ol_loop), 1);
if (!loop) {
return NULL;
}
loop.evloop = ev_loop_new(0);
if (!loop.evloop) {
return NULL;
}
return loop;
}
void ol_associate(ol_loop* loop, ol_handle* handle) {
assert(!handle->loop);
handle->loop = loop;
}
void ol_run(ol_loop *loop) {
ev_run(loop, 0);
}
ol_handle* ol_tcp_new(int v4, ol_read_cb read_cb, ol_close_cb close_cb) {
ol_handle *handle = calloc(sizeof(ol_handle), 1);
if (!handle) {
return NULL;
}
handle->read_cb = read_cb;
handle->close_cb = close_cb;
handle->type = v4 ? OL_TCP : OL_TCP6;
int domain = v4 ? AF_INET : AF_INET6;
handle->fd = socket(domain, SOCK_STREAM, 0);
if (fd == -1) {
free(handle);
got_error("socket", errno);
return NULL;
}
return handle;
}
static void tcp_io(EV_P_ ev_io *w, int revents) {
ol_handle* h = (ol_handle*)w->data;
if (h->connecting) {
tcp_check_connect_status(h);
} else {
}
}
static void tcp_check_connect_status(ol_handle* h) {
assert(h->connecting);
int error;
socklen_t len = sizeof(int);
getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &error, &len);
if (error == 0) {
tcp_connected(h);
} else if (errno != EINPROGRESS) {
close(h->fd);
got_error("connect", errno);
}
/* EINPROGRESS - unlikely. What to do? */
}
static void tcp_connected(ol_handle* h) {
assert(h->connecting);
if (h->connect_cb) {
h->connect_cb(h);
}
h->connecting = 0;
h->connect_cb = NULL;
}
int ol_connect(ol_handle* h, sockaddr* addr, sockaddr_len addrlen,
ol_buf* buf, size_t* bytes_sent, ol_connect_cb cb) {
if (h->connecting) {
return got_error("connect", EALREADY);
}
h->connecting = 1;
h->connect_addr = addr;
h->connect_addrlen = addrlen;
if (buf) {
/* We're allowed to ol_write before the socket becomes connected. */
ol_write(h, buf, 1, bytes_sent, cb);
} else {
h->connect_cb = cb;
}
int r = connect(h->fd, h->connect_addr, h->connect_addrlen);
if (r != 0) {
if (errno == EINPROGRESS) {
/* Wait for fd to become writable. */
h->connecting = 1;
ev_io_init(&h->write_watcher, tcp_io, h->fd, EV_WRITE);
ev_io_start(h->loop, &h->write_watcher);
}
return got_error("connect", errno);
}
/* Connected */
tcp_connected(h);
return 0;
}
int ol_get_fd(ol_handle* h) {
return h->fd;
}