188 lines
3.6 KiB
C
188 lines
3.6 KiB
C
/**
|
|
* 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);
|
|
|
|
|
|
|
|
|