...
This commit is contained in:
parent
e108022ccc
commit
116bd967d6
@ -147,6 +147,22 @@ Marc Lehmann has written <a
|
|||||||
portable version in libeio</a>.
|
portable version in libeio</a>.
|
||||||
</dd>
|
</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
|
The following are nearly same in Windows overlapped and UNIX
|
||||||
non-blocking sockets. The only difference is that the UNIX variants
|
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>
|
<li><a href="http://msdn.microsoft.com/en-us/library/aa365146(v=VS.85).aspx"><code>ConnectNamedPipe</code></a>
|
||||||
</ul>
|
</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>
|
</body></html>
|
||||||
|
|||||||
51
ol.h
51
ol.h
@ -8,6 +8,16 @@
|
|||||||
# include "ol_win.h"
|
# include "ol_win.h"
|
||||||
#endif
|
#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.
|
* Do not make assumptions about the order of the elements in this sturct.
|
||||||
@ -17,10 +27,19 @@
|
|||||||
struct ol_buf;
|
struct ol_buf;
|
||||||
|
|
||||||
|
|
||||||
typedef ol_read_cb void(*)(ol_buf *bufs, int bufcnt);
|
typedef enum {
|
||||||
typedef ol_close_cb void(*)(int read, int write);
|
OL_TCP,
|
||||||
typedef ol_connect_cb void(*)();
|
OL_TCP6,
|
||||||
typedef ol_accept_cb void(*)(ol_handle *peer);
|
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);
|
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);
|
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.
|
* Send data to h. User responsible for bufs until callback is made.
|
||||||
* Multiple ol_handle_write() calls may be issued before the previous ones
|
* 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);
|
int ol_listen(ol_handle* h, int backlog, ol_accept_cb cb);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes EOF or sends a FIN packet.
|
* 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);
|
int ol_close(ol_handle* h);
|
||||||
|
|
||||||
|
|
||||||
@ -121,7 +154,7 @@ int ol_free(ol_handle* h);
|
|||||||
ol_loop* ol_loop_new();
|
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);
|
void ol_loop_free(ol_loop* loop);
|
||||||
|
|||||||
69
ol_unix.c
69
ol_unix.c
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
ol_loop* ol_loop_new() {
|
ol_loop* ol_loop_new() {
|
||||||
ol_loop* loop = malloc(sizeof(ol_loop));
|
ol_loop* loop = calloc(sizeof(ol_loop), 1);
|
||||||
if (!loop) {
|
if (!loop) {
|
||||||
return NULL;
|
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* 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) {
|
if (!handle) {
|
||||||
return NULL;
|
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->read_cb = read_cb;
|
||||||
handle->close_cb = close_cb;
|
handle->close_cb = close_cb;
|
||||||
|
|
||||||
|
handle->type = v4 ? OL_TCP : OL_TCP6;
|
||||||
|
|
||||||
int domain = v4 ? AF_INET : AF_INET6;
|
int domain = v4 ? AF_INET : AF_INET6;
|
||||||
handle->fd = socket(domain, SOCK_STREAM, 0);
|
handle->fd = socket(domain, SOCK_STREAM, 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@ -46,32 +50,42 @@ 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) {
|
static void tcp_check_connect_status(ol_handle* h) {
|
||||||
int r = connect(h->fd, h->connect_addr, h->connect_addrlen);
|
assert(h->connecting);
|
||||||
|
|
||||||
if (r != 0) {
|
int error;
|
||||||
if (errno == EINPROGRESS) {
|
socklen_t len = sizeof(int);
|
||||||
/* Wait for fd to become writable. */
|
getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &error, &len);
|
||||||
h->connecting = 1;
|
|
||||||
ev_io_init(&h->write_watcher, handle_tcp_io, h->fd, EV_WRITE);
|
if (error == 0) {
|
||||||
ev_io_start(h->loop, &h->write_watcher);
|
tcp_connected(h);
|
||||||
}
|
} else if (errno != EINPROGRESS) {
|
||||||
return got_error("connect", errno);
|
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) {
|
if (h->connect_cb) {
|
||||||
h->connect_cb(h);
|
h->connect_cb(h);
|
||||||
h->connecting = 0;
|
|
||||||
h->connect_cb = NULL;
|
|
||||||
}
|
}
|
||||||
|
h->connecting = 0;
|
||||||
return 0;
|
h->connect_cb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -86,12 +100,27 @@ int ol_connect(ol_handle* h, sockaddr* addr, sockaddr_len addrlen,
|
|||||||
h->connect_addrlen = addrlen;
|
h->connect_addrlen = addrlen;
|
||||||
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
|
/* We're allowed to ol_write before the socket becomes connected. */
|
||||||
ol_write(h, buf, 1, bytes_sent, cb);
|
ol_write(h, buf, 1, bytes_sent, cb);
|
||||||
} else {
|
} else {
|
||||||
h->connect_cb = cb;
|
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.
|
* Note can be cast to io_vec.
|
||||||
*/
|
*/
|
||||||
typedef struct _ol_buf {
|
typedef struct {
|
||||||
char* buf;
|
char* buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
ngx_queue_s write_queue;
|
ngx_queue_s write_queue;
|
||||||
@ -11,11 +9,16 @@ typedef struct _ol_buf {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _ol_handle {
|
typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
|
ol_handle_type type;
|
||||||
|
|
||||||
ol_read_cb read_cb;
|
ol_read_cb read_cb;
|
||||||
ol_close_cb close_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 write_queue;
|
||||||
ngx_queue_s all_handles;
|
ngx_queue_s all_handles;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user