...
This commit is contained in:
parent
e108022ccc
commit
116bd967d6
@ -147,6 +147,22 @@ Marc Lehmann has written <a
|
||||
portable version in libeio</a>.
|
||||
</dd>
|
||||
|
||||
<dt><code>shutdown(2)</code>, graceful close, half-duplex connections</dt>
|
||||
<dd>
|
||||
<a
|
||||
href="http://msdn.microsoft.com/en-us/library/ms738547(v=VS.85).aspx">Graceful
|
||||
Shutdown, Linger Options, and Socket Closure</a>
|
||||
<br/>
|
||||
<a
|
||||
href="http://msdn.microsoft.com/en-us/library/ms737757(VS.85).aspx"><code>DisconnectEx()</code></a>
|
||||
|
||||
</dd>
|
||||
|
||||
<dt><code>close(2)</code></dt>
|
||||
<dd>
|
||||
<a href="http://msdn.microsoft.com/en-us/library/ms737582(v=VS.85).aspx"><code>closesocket()</code></a>
|
||||
</dd>
|
||||
|
||||
|
||||
The following are nearly same in Windows overlapped and UNIX
|
||||
non-blocking sockets. The only difference is that the UNIX variants
|
||||
@ -351,4 +367,10 @@ Pipes:
|
||||
<li><a href="http://msdn.microsoft.com/en-us/library/aa365146(v=VS.85).aspx"><code>ConnectNamedPipe</code></a>
|
||||
</ul>
|
||||
|
||||
|
||||
Also useful:
|
||||
<a
|
||||
href="http://msdn.microsoft.com/en-us/library/xw1ew2f8(v=vs.80).aspx">Introduction
|
||||
to Visual C++ for UNIX Users</a>
|
||||
|
||||
</body></html>
|
||||
|
||||
51
ol.h
51
ol.h
@ -8,6 +8,16 @@
|
||||
# include "ol_win.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Error codes are not cross-platform, so we have our own.
|
||||
*/
|
||||
typedef enum {
|
||||
OL_SUCCESS = 0,
|
||||
OL_EAGAIN = -1,
|
||||
OL_EPIPE = -2,
|
||||
OL_EMEM = -3,
|
||||
} ol_errno;
|
||||
|
||||
|
||||
/**
|
||||
* Do not make assumptions about the order of the elements in this sturct.
|
||||
@ -17,10 +27,19 @@
|
||||
struct ol_buf;
|
||||
|
||||
|
||||
typedef ol_read_cb void(*)(ol_buf *bufs, int bufcnt);
|
||||
typedef ol_close_cb void(*)(int read, int write);
|
||||
typedef ol_connect_cb void(*)();
|
||||
typedef ol_accept_cb void(*)(ol_handle *peer);
|
||||
typedef enum {
|
||||
OL_TCP,
|
||||
OL_TCP6,
|
||||
OL_NAMED_PIPE,
|
||||
OL_FILE,
|
||||
OL_TTY
|
||||
} ol_handle_type;
|
||||
|
||||
|
||||
typedef ol_read_cb void(*)(ol_handle* h, ol_buf *bufs, int bufcnt);
|
||||
typedef ol_close_cb void(*)(ol_handle* h, int read, int write, ol_errno err);
|
||||
typedef ol_connect_cb void(*)(ol_handle* h);
|
||||
typedef ol_accept_cb void(*)(ol_handle* h, ol_handle *peer);
|
||||
|
||||
|
||||
/**
|
||||
@ -70,10 +89,10 @@ int ol_bind(ol_handle* h, sockaddr* addr, sockaddr_len len);
|
||||
size_t ol_buffer_size(ol_handle* h);
|
||||
|
||||
|
||||
int ol_pause(ol_handle* h);
|
||||
int ol_read_stop(ol_handle* h);
|
||||
|
||||
|
||||
int ol_resume(ol_handle* h);
|
||||
int ol_read_start(ol_handle* h);
|
||||
|
||||
|
||||
/**
|
||||
@ -85,6 +104,12 @@ int ol_resume(ol_handle* h);
|
||||
int ol_get_fd(ol_handle* h);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the type of the handle.
|
||||
*/
|
||||
ol_handle_type ol_get_type(ol_handle* h);
|
||||
|
||||
|
||||
/**
|
||||
* Send data to h. User responsible for bufs until callback is made.
|
||||
* Multiple ol_handle_write() calls may be issued before the previous ones
|
||||
@ -95,17 +120,25 @@ int ol_write(ol_handle* h, ol_buf* bufs, int bufcnt,
|
||||
|
||||
|
||||
/**
|
||||
* Note: works on both named pipes and TCP handles.
|
||||
* Works on both named pipes and TCP handles.
|
||||
*/
|
||||
int ol_listen(ol_handle* h, int backlog, ol_accept_cb cb);
|
||||
|
||||
|
||||
/**
|
||||
* Writes EOF or sends a FIN packet.
|
||||
* Further calls to ol_write() result in OI_EPIPE error. When the send
|
||||
* buffer is drained and the other side also terminates their writes, the
|
||||
* handle is finally closed and ol_close_cb() made. There is no need to call
|
||||
* ol_close() after this.
|
||||
*/
|
||||
int ol_end(ol_handle* h);
|
||||
int ol_graceful_close(ol_handle* h);
|
||||
|
||||
|
||||
/**
|
||||
* Immediately closes the handle. If there is data in the send buffer
|
||||
* it will not be sent.
|
||||
*/
|
||||
int ol_close(ol_handle* h);
|
||||
|
||||
|
||||
@ -121,7 +154,7 @@ int ol_free(ol_handle* h);
|
||||
ol_loop* ol_loop_new();
|
||||
|
||||
|
||||
ol_loop* ol_associate(ol_handle* handle);
|
||||
void ol_associate(ol_loop* loop, ol_handle* handle);
|
||||
|
||||
|
||||
void ol_loop_free(ol_loop* loop);
|
||||
|
||||
67
ol_unix.c
67
ol_unix.c
@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
ol_loop* ol_loop_new() {
|
||||
ol_loop* loop = malloc(sizeof(ol_loop));
|
||||
ol_loop* loop = calloc(sizeof(ol_loop), 1);
|
||||
if (!loop) {
|
||||
return NULL;
|
||||
}
|
||||
@ -16,7 +16,9 @@ ol_loop* ol_loop_new() {
|
||||
}
|
||||
|
||||
|
||||
ol_loop* ol_associate(ol_handle* handle) {
|
||||
void ol_associate(ol_loop* loop, ol_handle* handle) {
|
||||
assert(!handle->loop);
|
||||
handle->loop = loop;
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +28,7 @@ void ol_run(ol_loop *loop) {
|
||||
|
||||
|
||||
ol_handle* ol_tcp_new(int v4, ol_read_cb read_cb, ol_close_cb close_cb) {
|
||||
ol_handle *handle = malloc(sizeof(ol_handle));
|
||||
ol_handle *handle = calloc(sizeof(ol_handle), 1);
|
||||
if (!handle) {
|
||||
return NULL;
|
||||
}
|
||||
@ -34,6 +36,8 @@ ol_handle* ol_tcp_new(int v4, ol_read_cb read_cb, ol_close_cb close_cb) {
|
||||
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) {
|
||||
@ -46,34 +50,44 @@ ol_handle* ol_tcp_new(int v4, ol_read_cb read_cb, ol_close_cb close_cb) {
|
||||
}
|
||||
|
||||
|
||||
void handle_tcp_io() {
|
||||
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 {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int try_connect(ol_handle* h) {
|
||||
int r = connect(h->fd, h->connect_addr, h->connect_addrlen);
|
||||
static void tcp_check_connect_status(ol_handle* h) {
|
||||
assert(h->connecting);
|
||||
|
||||
if (r != 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
/* Wait for fd to become writable. */
|
||||
h->connecting = 1;
|
||||
ev_io_init(&h->write_watcher, handle_tcp_io, h->fd, EV_WRITE);
|
||||
ev_io_start(h->loop, &h->write_watcher);
|
||||
}
|
||||
return got_error("connect", errno);
|
||||
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);
|
||||
}
|
||||
|
||||
/* Connected */
|
||||
/* 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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ol_connect(ol_handle* h, sockaddr* addr, sockaddr_len addrlen,
|
||||
ol_buf* buf, size_t* bytes_sent, ol_connect_cb cb) {
|
||||
@ -86,12 +100,27 @@ int ol_connect(ol_handle* h, sockaddr* addr, sockaddr_len addrlen,
|
||||
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;
|
||||
}
|
||||
|
||||
return try_connect(h);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
11
ol_unix.h
11
ol_unix.h
@ -1,9 +1,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* Note can be cast to io_vec.
|
||||
*/
|
||||
typedef struct _ol_buf {
|
||||
typedef struct {
|
||||
char* buf;
|
||||
size_t len;
|
||||
ngx_queue_s write_queue;
|
||||
@ -11,11 +9,16 @@ typedef struct _ol_buf {
|
||||
|
||||
|
||||
|
||||
typedef struct _ol_handle {
|
||||
typedef struct {
|
||||
int fd;
|
||||
ol_handle_type type;
|
||||
|
||||
ol_read_cb read_cb;
|
||||
ol_close_cb close_cb;
|
||||
ol_connect_cb connect_cb;
|
||||
|
||||
ev_io read_watcher;
|
||||
ev_io write_watcher;
|
||||
|
||||
ngx_queue_s write_queue;
|
||||
ngx_queue_s all_handles;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user