diff --git a/ol-old.h b/ol-old.h deleted file mode 100644 index 58adcd1c..00000000 --- a/ol-old.h +++ /dev/null @@ -1,187 +0,0 @@ -/** - * Overlapped I/O for every operating system. - */ - -#ifdef __POSIX__ -# include "ol-unix.h" -#else -# include "ol-win.h" -#endif - -typedef struct { - int code; - const char* msg; -} ol_err; - -/** - * Error codes are not cross-platform, so we have our own. - */ -typedef enum { - OL_SUCCESS = 0, - OL_EPENDING = -1, - OL_EPIPE = -2, - OL_EMEM = -3 -} ol_err; - - -inline const char* ol_err_string(int errorno) { - switch (errorno) { - case OL_SUCCESS: - case OL_EPENDING: - return ""; - - case OL_EPIPE: - return "EPIPE: Write to non-writable handle"; - - case OL_EMEM: - return "EMEM: Out of memory!"; - - default: - assert(0); - return "Unknown error code. Bug."; - } -} - - -/** - * Do not make assumptions about the order of the elements in this sturct. - * Always use offsetof because the order is platform dependent. Has a char* - * buf and size_t len. That's all you need to know. - */ -struct ol_buf; - - -typedef enum { - OL_TCP, - OL_TCP6, - OL_NAMED_PIPE, - OL_FILE, - OL_TTY -} ol_handle_type; - - -typedef void(*)(ol_handle* h, ol_buf *bufs, int bufcnt) ol_read_cb; -typedef void(*)(ol_handle* h) ol_connect_cb; -typedef void(*)(ol_handle* h, ol_handle *peer) ol_accept_cb; -typedef void(*)(ol_handle* h) ol_write_cb; - - -typedef enum { - OL_READ, - OL_WRITE, - OL_CONNECT, - OL_ACCEPT, - OL_DESTROY -} ol_req_type; - - -typedef struct { - ol_req_type type; - ol_req_private _; - /* following are rw */ - union { - ol_write_cb write_cb; - ol_connect_cb connect_cb; - }; - void* data; /* rw */ -} ol_req; - - -ol_handle* ol_handle_new(); - - -ol_handle* ol_open_file(ol_handle* h, ol_req* req, char *filename); -ol_handle* ol_open_named_pipe(ol_handle* h, ol_req* req, char *filename); -ol_handle* ol_open_tty(ol_handle* h, ol_req* req); - - -struct sockaddr oi_ip4_addr(char*, int port); - -/** - * Depth of write buffer in bytes. - */ -size_t ol_buffer_size(ol_handle* h); - - -/** - * Returns file descriptor associated with the handle. There may be only - * limited numbers of file descriptors allowed by the operating system. On - * Windows this limit is 2048 (see - * _setmaxstdio[http://msdn.microsoft.com/en-us/library/6e3b887c.aspx]) - */ -int ol_get_fd(ol_handle* h); - - -/** - * Returns the type of the handle. - */ -ol_handle_type ol_get_type(ol_handle* h); - - -/** - * Only works with named pipes and TCP sockets. - */ -int ol_connect(ol_handle* h, ol_req* req, sockaddr* addr, ol_buf* initial_buf); - - -int ol_accept(ol_handle* h, ol_req* req); - - -/** - * Send data to handle. User responsible for bufs until callback is made. - * Multiple ol_handle_write() calls may be issued before the previous ones - * complete - data will sent in the correct order. - * - * Returns zero on succuessful write and bytes_sent is filled with the - * number of bytes successfully written. If an asyncrhonous write was - * successfully initiated then OL_EAGAIN is returned. - */ -int ol_write(ol_handle* h, ol_req* req, ol_buf* bufs, int bufcnt); -int ol_write2(ol_handle* h, ol_req* req, const char *string); - - -int ol_read(ol_handle* h, ol_req* req, ol_buf* bufs, int bufcnt); - - -/** - * Works on both named pipes and TCP handles. Synchronous. - */ -int ol_listen(ol_handle* h, int backlog); - - -/** - * See http://msdn.microsoft.com/en-us/library/ms737757(v=VS.85).aspx - */ -int ol_disconnect(ol_handle* h, ol_req* req); - - -/** - * Immediately closes the handle. If there is data in the send buffer - * it will not be sent. - */ -int ol_close(ol_handle* h); - - -/** - * Releases memory associated with handle. You MUST call this after - * is made with both 0 arguments. - */ -int ol_free(ol_handle* h); - - - - -ol_loop* ol_loop_new(); - - -void ol_associate(ol_loop* loop, ol_handle* handle); - - -void ol_loop_free(ol_loop* loop); - - -void ol_run(ol_loop* loop); - - - - diff --git a/ol-unix-old.c b/ol-unix-old.c deleted file mode 100644 index 7cbd2a83..00000000 --- a/ol-unix-old.c +++ /dev/null @@ -1,300 +0,0 @@ -#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, sockaddr* addr, sockaddr_len len, - 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 (handle->fd == -1) { - free(handle); - got_error("socket", err); - return NULL; - } - - /* Lose the pesky "Address already in use" error message */ - int yes = 1; - int r = setsockopt(handle->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); - if (r == -1) { - close(handle->fd); - free(handle); - unhandled_error("setsockopt", r); - return NULL; - } - - /* We auto-bind the specified address */ - if (addr) { - int r = bind(handle->fd, addr, v4 ? sizeof(sockaddr_in) : - sizeof(sockaddr_in6)); - - if (r < 0) { - got_error("bind", errno); - close(handle->fd); - free(handle); - 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 (err != EINPROGRESS) { - close(h->fd); - got_error("connect", err); - } - - /* EINPROGRESS - unlikely. What to do? */ -} - - -ol_bucket* ol_handle_first_bucket(ol_handle* h) { - ngx_queue_t* element = ngx_queue_head(h); - if (!element) { - return NULL; - } - return ngx_queue_data(element, ol_bucket, write_queue); -} - - -static void tcp_flush(oi_loop* loop, ol_handle* h) { - ol_bucket* bucket = ol_handle_first_bucket(h); - - for (; bucket; bucket = ol_handle_first_bucket(h)) { - io_vec* vec = (io_vec*) bucket->bufs[bucket->current_index]; - int remaining_bufcnt = bucket->bufcnt - bucket->current_index; - ssize_t written = writev(h->fd, vec, remaining_bufcnt); - - if (written < 0) { - if (err == EAGAIN) { - ev_io_start(loop, &h->write_watcher); - } else { - got_error("writev", err); - } - - } else { - /* See how much was written, increase current_index, and update bufs. */ - oi_buf current = bucket->bufs[bucket->current_index]; - - while (bucket->current_index < bucket->bufcnt) { - if (current.len >= written) { - current = bucket->bufs[++bucket->current_index]; - } else { - bucket->bufs[bucket->current_index].buf += written; - break; - } - } - } - } -} - - -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; - - ev_io_init(&h->read_watcher, tcp_io, h->fd, EV_READ); - ev_io_start(h->loop, &h->read_watcher); - - if (ngx_queue_empty(&h->write_queue)) { - ev_io_stop(h->loop, &h->write_watcher); - } else { - /* Now that we're connected let's try to flush. */ - tcp_flush(h); - } -} - - -int ol_connect(ol_handle* h, sockaddr* addr, sockaddr_len addrlen, - ol_buf* buf, ol_connect_cb connect_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, connect_cb); - } else { - /* Nothing to write. Don't call the callback until we're connected. */ - h->connect_cb = connect_cb; - } - - int r = connect(h->fd, h->connect_addr, h->connect_addrlen); - - if (r != 0) { - if (err == 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", err); - } - - /* Connected */ - tcp_connected(h); - return 0; -} - - -int ol_get_fd(ol_handle* h) { - return h->fd; -} - - -ol_bucket* bucket_new(oi_handle* h, oi_buf* bufs, int bufcnt, ol_write_cb cb) { - ol_bucket* bucket = malloc(sizeof(ol_bucket)); - if (!bucket) { - got_error("malloc", OL_EMEM); - return NULL; - } - - bucket->bufs = bufs; - bucket->bufcnt = bufcnt; - bucket->write_cb = write_cb; - bucket->handle = handle; - ngx_queue_init(&bucket->write_queue); - - return bucket; -} - - -int ol_write(ol_handle* h, ol_buf* bufs, int bufcnt, ol_write_cb cb) { - if (!h->connecting && !h->writable) { - return got_error("write", OL_EPIPE); - } - - if (!h->writable) { - /* This happens when writing to a socket which is not connected yet. */ - bucket* b = bucket_new(h, buf, bufcnt, cb); - bucket_append(h, b); - return got_error("write", OL_EPENDING); - } - - ssize_t written; - - /* If the write queue is empty, attempt to write now. */ - if (ngx_queue_empty(&h->write_queue)) { - /* The queue is empty. Attempt the writev immediately. */ - written = writev(h->fd, (io_vec*)bufs, bufcnt); - - if (written >= 0) { - size_t seen = 0; - - /* Figure out what's left to be written */ - for (int i = 0; i < bufcnt; i++) { - seen += bufs[i].len; - - if (seen == written) { - /* We wrote the entire thing. */ - return 0; - } - - if (seen > written) { - break; - } - } - - assert(seen > written); - - /* We've made a partial write of the bufs. bufs[i] is the first buf - * that wasn't totally flushed. We must now add - * bufs[i], bufs[i + 1], ..., bufs[bufcnt - 1] - * to the write queue. - */ - } - } - - -} - - -int ol_write2(ol_handle* h, char *base, size_t len) { - ol_buf buf; - buf.base = base; - buf.len = len; - - return ol_write(h, &buf, 1, NULL); -} - - -int ol_write3(ol_handle* h, const char *string) { - /* You're doing it wrong if strlen(string) > 1mb. */ - return ol_write2(h, string, strnlen(string, 1024 * 1024)); -} - - -struct sockaddr oi_ip4_addr(char *ip, int port) { - sockaddr_in addr; - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(ip); - - return addr; -}