# HG changeset patch # User Tero Marttila # Date 1235835577 -7200 # Node ID 14e79683c48cbaf7e4b9d215fabd1c310f1b9acb # Parent 9fe218576d13ea665f24fa60520d04a51d50dc33 working event-based operation for sock_tcp diff -r 9fe218576d13 -r 14e79683c48c src/error.h --- a/src/error.h Sun Feb 22 10:16:28 2009 +0200 +++ b/src/error.h Sat Feb 28 17:39:37 2009 +0200 @@ -64,6 +64,7 @@ /* Libevent errors */ _ERROR_CODE( ERR_EVENT_NEW, 0x010201, NONE ), + _ERROR_CODE( ERR_EVENT_ADD, 0x010202, NONE ), // mask of bits used for the error_code value _ERROR_CODE_MASK = 0xffffff, diff -r 9fe218576d13 -r 14e79683c48c src/line_proto.c --- a/src/line_proto.c Sun Feb 22 10:16:28 2009 +0200 +++ b/src/line_proto.c Sat Feb 28 17:39:37 2009 +0200 @@ -56,7 +56,7 @@ // got a line? if (line) - lp->cb_read(lp, line, lp->cb_arg); + lp->cb_read(line, lp->cb_arg); } while (line); @@ -104,6 +104,7 @@ // initialize event-based stuff sock_stream_event_init(sock, &line_proto_sock_stream_callbacks, lp); + line_proto_schedule_events(lp, EV_READ); // return *lp_ptr = lp; diff -r 9fe218576d13 -r 14e79683c48c src/line_proto.h --- a/src/line_proto.h Sun Feb 22 10:16:28 2009 +0200 +++ b/src/line_proto.h Sat Feb 28 17:39:37 2009 +0200 @@ -15,7 +15,7 @@ /* * The callback for receiving lines */ -typedef void (*line_proto_read_cb)(struct line_proto *lp, const char *line, void *arg); +typedef void (*line_proto_read_cb)(const char *line, void *arg); /* * Create a new line_proto off the the given sock_stream. The newly allocated line_proto will be returned via *lp_ptr. @@ -28,10 +28,9 @@ line_proto_read_cb cb_func, void *cb_arg, struct error_info *err); /* - * Receive one line into the given buffer. The line will be terminated with '\r\n', and said terminator will be - * NUL'd out, so the buffer is safe for use as a C-string after succesfull return. - * - * Note: currently this uses the buffer to store intermediate state, so always pass the same buffer (for now). + * Runs the socket recv() into our internal buffer. If a full line was received, a pointer to our internal bufffer is + * returned via *line_ptr, and we return SUCCESS. If we don't yet have a full line, and receiving more would block, + * NULL is returned via *line_ptr instead. Otherwise, nonzero error return code. */ err_t line_proto_read (struct line_proto *lp, const char **line_ptr); diff -r 9fe218576d13 -r 14e79683c48c src/nexus.c --- a/src/nexus.c Sun Feb 22 10:16:28 2009 +0200 +++ b/src/nexus.c Sat Feb 28 17:39:37 2009 +0200 @@ -13,14 +13,17 @@ #include "line_proto.h" #define CONNECT_HOST "irc.fixme.fi" -#define CONNECT_SERV "6697" +#define CONNECT_SERV "6667" #define LINE_LENGTH 512 +void on_line (const char *line, void *arg) { + printf("<<< %s\n", line); +} + int main (int argc, char **argv) { struct event_base *ev_base; struct sock_stream *sock; struct line_proto *lp; - char *line; struct error_info _err; // initialize libevent @@ -32,25 +35,18 @@ errx(1, "sock_init: %s", error_msg(&_err)); // over-simplified connect - if (sock_gnutls_connect(&sock, CONNECT_HOST, CONNECT_SERV, &_err)) + if (sock_tcp_connect(&sock, CONNECT_HOST, CONNECT_SERV, &_err)) errx(1, "sock_gnutls_connect: %s", error_msg(&_err)); // line protocol - if (line_proto_create(&lp, sock, LINE_LENGTH, NULL, NULL, &_err)) + if (line_proto_create(&lp, sock, LINE_LENGTH, on_line, NULL, &_err)) errx(1, "line_proto_create: %s", error_msg(&_err)); - // read lines and dump them out - do { - // recv - if (line_proto_read(lp, &line)) - errx(1, "line_proto_read: %s", error_msg(line_proto_error(lp))); - - // printf - printf("<<< %s\n", line); - - } while (1); + // run event loop + if (event_base_dispatch(ev_base)) + errx(1, "event_base_dispatch"); - // ok + // ok, no cleanup return 0; } diff -r 9fe218576d13 -r 14e79683c48c src/sock.c --- a/src/sock.c Sun Feb 22 10:16:28 2009 +0200 +++ b/src/sock.c Sat Feb 28 17:39:37 2009 +0200 @@ -35,7 +35,7 @@ // proxy off to method handler if ((err = sock->type->methods.read(sock, buf, &len))) - return err; + return -err; // return updated bytes-read len return len; @@ -47,7 +47,7 @@ // proxy off to method handler if ((err = sock->type->methods.write(sock, buf, &len))) - return err; + return -err; // return updated bytes-written len return len; diff -r 9fe218576d13 -r 14e79683c48c src/sock_tcp.c --- a/src/sock_tcp.c Sun Feb 22 10:16:28 2009 +0200 +++ b/src/sock_tcp.c Sat Feb 28 17:39:37 2009 +0200 @@ -11,6 +11,21 @@ #include /* + * Our basic socket event handler for driving our callbacks + */ +static void sock_tcp_event_handler (evutil_socket_t fd, short what, void *arg) +{ + struct sock_tcp *sock = arg; + + // invoke appropriate callback + if (what & EV_READ && SOCK_TCP_BASE(sock)->cb_info->on_read) + SOCK_TCP_BASE(sock)->cb_info->on_read(SOCK_TCP_BASE(sock), SOCK_TCP_BASE(sock)->cb_arg); + + if (what & EV_WRITE && SOCK_TCP_BASE(sock)->cb_info->on_write) + SOCK_TCP_BASE(sock)->cb_info->on_read(SOCK_TCP_BASE(sock), SOCK_TCP_BASE(sock)->cb_arg); +} + +/* * Our sock_stream_methods.read method */ static err_t sock_tcp_read (struct sock_stream *base_sock, void *buf, size_t *len) @@ -51,14 +66,32 @@ static err_t sock_tcp_event_init (struct sock_stream *base_sock) { struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp); + err_t err; + + // set nonblocking + if ((err = sock_tcp_set_nonblock(sock, 1))) + return err; + + // add ourselves as the event handler + if ((err = sock_tcp_init_ev(sock, &sock_tcp_event_handler, sock))) + return err; + // done return SUCCESS; } static err_t sock_tcp_event_enable (struct sock_stream *base_sock, short mask) { struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp); + + // just add the appropraite events + if (mask & EV_READ && event_add(sock->ev_read, NULL)) + return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD); + + if (mask & EV_WRITE && event_add(sock->ev_write, NULL)) + return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD); + // done return SUCCESS; } @@ -72,21 +105,6 @@ .methods.event_enable = &sock_tcp_event_enable, }; -/* - * Our basic socket event handler for driving our callbacks - */ -static void sock_tcp_event (evutil_socket_t fd, short what, void *arg) -{ - struct sock_tcp *sock = arg; - - // invoke appropriate callback - if (what & EV_READ && SOCK_TCP_BASE(sock)->cb_info->on_read) - SOCK_TCP_BASE(sock)->cb_info->on_read(SOCK_TCP_BASE(sock), SOCK_TCP_BASE(sock)->cb_arg); - - if (what & EV_WRITE && SOCK_TCP_BASE(sock)->cb_info->on_write) - SOCK_TCP_BASE(sock)->cb_info->on_read(SOCK_TCP_BASE(sock), SOCK_TCP_BASE(sock)->cb_arg); -} - err_t sock_tcp_alloc (struct sock_tcp **sock_ptr) { // alloc @@ -116,9 +134,15 @@ { // require valid fd assert(sock->fd >= 0); + + // this is initialization + assert(sock->ev_read == NULL && sock->ev_write == NULL); // create new event - if ((sock->ev = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_READ, ev_cb, cb_arg)) == NULL) + if ((sock->ev_read = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_READ, ev_cb, cb_arg)) == NULL) + return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_NEW); + + if ((sock->ev_write = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_WRITE, ev_cb, cb_arg)) == NULL) return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_NEW); // ok diff -r 9fe218576d13 -r 14e79683c48c src/sock_tcp.h --- a/src/sock_tcp.h Sun Feb 22 10:16:28 2009 +0200 +++ b/src/sock_tcp.h Sat Feb 28 17:39:37 2009 +0200 @@ -16,8 +16,8 @@ /* The OS file descriptor */ int fd; - /* The libevent struct */ - struct event *ev; + /* The IO events */ + struct event *ev_read, *ev_write; }; #define SOCK_TCP_BASE(sock_ptr) (&(sock_ptr)->base) @@ -34,8 +34,7 @@ err_t sock_tcp_init_fd (struct sock_tcp *sock, int fd); /* - * Initialize sock_tcp.ev to use the socket's fd with the given callback. By default, this is created with EV_READ - * flags, but is not added. + * Initialize sock_tcp.ev_* to use the socket's fd with the given callback. The ev's are not activated yet. */ err_t sock_tcp_init_ev (struct sock_tcp *sock, void (*ev_cb) (evutil_socket_t, short, void *), void *arg);