src/sock_fd.c
branchnew-transport
changeset 154 f4472119de3b
parent 153 d35e7cb3a489
child 155 c59d3eaff0fb
equal deleted inserted replaced
153:d35e7cb3a489 154:f4472119de3b
     1 #include "sock_fd.h"
       
     2 
       
     3 #include <fcntl.h>
       
     4 #include <unistd.h>
       
     5 #include <assert.h>
       
     6 
       
     7 void sock_fd_event_handler (evutil_socket_t fd, short what, void *arg) 
       
     8 {
       
     9     struct sock_fd *sock = arg;
       
    10 
       
    11     (void) fd;
       
    12 
       
    13     // invoke appropriate callback
       
    14     sock_stream_invoke_callbacks(SOCK_FD_BASE(sock), what);
       
    15 }
       
    16 
       
    17 err_t sock_fd_read (struct sock_stream *base_sock, void *buf, size_t *len, struct error_info *err)
       
    18 {
       
    19     struct sock_fd *sock = SOCK_FROM_BASE(base_sock, struct sock_fd);
       
    20     int ret;
       
    21     
       
    22     // read(), and detect non-EAGAIN or EOF
       
    23     if ((ret = read(sock->fd, buf, *len)) < 0 && errno != EAGAIN)
       
    24         // unexpected error
       
    25         RETURN_SET_ERROR_ERRNO(err, ERR_READ);
       
    26     
       
    27     else if (ret == 0)
       
    28         // EOF
       
    29         return SET_ERROR(err, ERR_READ_EOF);
       
    30 
       
    31 
       
    32     if (ret < 0) {
       
    33         // EAGAIN -> zero bytes
       
    34         *len = 0;
       
    35 
       
    36     } else {
       
    37         // normal -> bytes read
       
    38         *len = ret;
       
    39     }
       
    40 
       
    41     // ok
       
    42     return SUCCESS;
       
    43 }
       
    44 
       
    45 err_t sock_fd_write (struct sock_stream *base_sock, const void *buf, size_t *len, struct error_info *err)
       
    46 {
       
    47     struct sock_fd *sock = SOCK_FROM_BASE(base_sock, struct sock_fd);
       
    48     int ret;
       
    49     
       
    50     // write(), and detect non-EAGAIN or EOF
       
    51     if ((ret = write(sock->fd, buf, *len)) < 0 && errno != EAGAIN)
       
    52         // unexpected error
       
    53         RETURN_SET_ERROR_ERRNO(err, ERR_WRITE);
       
    54     
       
    55     else if (ret == 0)
       
    56         // EOF
       
    57         return SET_ERROR(err, ERR_WRITE_EOF);
       
    58 
       
    59 
       
    60     if (ret < 0) {
       
    61         // EAGAIN -> zero bytes
       
    62         *len = 0;
       
    63 
       
    64     } else {
       
    65         // normal -> bytes read
       
    66         *len = ret;
       
    67     }
       
    68 
       
    69     return SUCCESS;
       
    70 }
       
    71 
       
    72 err_t sock_fd_event_init (struct sock_stream *base_sock)
       
    73 {
       
    74     struct sock_fd *sock = SOCK_FROM_BASE(base_sock, struct sock_fd);
       
    75     err_t err;
       
    76 
       
    77     // set nonblocking
       
    78     if ((err = sock_fd_set_nonblock(sock, 1)))
       
    79         return err;
       
    80 
       
    81     // add ourselves as the event handler
       
    82     if ((err = sock_fd_init_ev(sock, &sock_fd_event_handler, sock)))
       
    83         return err;
       
    84     
       
    85     // done
       
    86     return SUCCESS;
       
    87 }
       
    88 
       
    89 err_t sock_fd_event_enable (struct sock_stream *base_sock, short mask)
       
    90 {
       
    91     struct sock_fd *sock = SOCK_FROM_BASE(base_sock, struct sock_fd);
       
    92     
       
    93     // implemented in sock_fd_add_event
       
    94     return sock_fd_enable_events(sock, mask);
       
    95 }
       
    96 
       
    97 void sock_fd_init (struct sock_fd *sock, int fd)
       
    98 {
       
    99     assert(!sock->ev_read && !sock->ev_write);
       
   100 
       
   101     // initialize
       
   102     sock->fd = fd;
       
   103 }
       
   104 
       
   105 err_t sock_fd_set_nonblock (struct sock_fd *sock, bool nonblock)
       
   106 {
       
   107     // fcntl it
       
   108     // XXX: maintain old flags?
       
   109     if (fcntl(sock->fd, F_SETFL, nonblock ? O_NONBLOCK : 0) < 0)
       
   110         RETURN_SET_ERROR_ERRNO(SOCK_FD_ERR(sock), ERR_FCNTL);
       
   111 
       
   112     // ok
       
   113     return SUCCESS;
       
   114 }
       
   115 
       
   116 err_t sock_fd_init_ev (struct sock_fd *sock, void (*ev_cb)(evutil_socket_t, short, void *), void *cb_arg)
       
   117 {
       
   118     // require valid fd
       
   119     assert(sock->fd >= 0);
       
   120 
       
   121     // this is initialization
       
   122     assert(sock->ev_read == NULL && sock->ev_write == NULL);
       
   123 
       
   124     // store
       
   125     sock->ev_cb = ev_cb;
       
   126     sock->ev_arg = cb_arg;
       
   127     
       
   128     // create new event
       
   129     if ((sock->ev_read = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_READ, ev_cb, cb_arg)) == NULL)
       
   130         return SET_ERROR(SOCK_FD_ERR(sock), ERR_EVENT_NEW);
       
   131 
       
   132     if ((sock->ev_write = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_WRITE, ev_cb, cb_arg)) == NULL)
       
   133         return SET_ERROR(SOCK_FD_ERR(sock), ERR_EVENT_NEW);
       
   134 
       
   135     // ok
       
   136     return SUCCESS;
       
   137 }
       
   138 
       
   139 err_t sock_fd_enable_events (struct sock_fd *sock, short mask)
       
   140 {
       
   141     // just add the appropraite events
       
   142     if (mask & EV_READ && event_add(sock->ev_read, NULL))
       
   143         return SET_ERROR(SOCK_FD_ERR(sock), ERR_EVENT_ADD);
       
   144  
       
   145     if (mask & EV_WRITE && event_add(sock->ev_write, NULL))
       
   146         return SET_ERROR(SOCK_FD_ERR(sock), ERR_EVENT_ADD);
       
   147     
       
   148     // done
       
   149     return SUCCESS;
       
   150 }
       
   151 
       
   152 static void sock_fd_free_ev (struct sock_fd *sock)
       
   153 {
       
   154     if (sock->ev_read) {
       
   155         event_free(sock->ev_read);
       
   156 
       
   157         sock->ev_read = NULL;
       
   158     }
       
   159 
       
   160     if (sock->ev_write) {
       
   161         event_free(sock->ev_write);
       
   162         
       
   163         sock->ev_write = NULL;
       
   164     }
       
   165 }
       
   166 
       
   167 void sock_fd_deinit_ev (struct sock_fd *sock)
       
   168 {
       
   169     sock_fd_free_ev(sock);
       
   170     sock->ev_cb = NULL;
       
   171     sock->ev_arg = NULL;
       
   172 }
       
   173 
       
   174 err_t sock_fd_set (struct sock_fd *sock, int fd)
       
   175 {
       
   176     // close the old one?
       
   177     if (sock->fd >= 0)
       
   178         // XXX: warn on errors
       
   179         close(sock->fd);
       
   180     
       
   181     // remove any old events
       
   182     sock_fd_free_ev(sock);
       
   183 
       
   184     // set the new one
       
   185     sock->fd = fd;
       
   186     
       
   187     // restore them
       
   188     if (sock->ev_cb)
       
   189         return sock_fd_init_ev(sock, sock->ev_cb, sock->ev_arg);
       
   190 
       
   191     // ok
       
   192     return SUCCESS;
       
   193 }
       
   194 
       
   195 err_t sock_fd_close (struct sock_fd *sock)
       
   196 {
       
   197     struct error_info *err = SOCK_FD_ERR(sock);
       
   198     
       
   199     // no errors yet
       
   200     RESET_ERROR(err);
       
   201 
       
   202     // must be connected
       
   203     assert(sock->fd >= 0);
       
   204 
       
   205     // kill any events
       
   206     sock_fd_deinit_ev(sock);
       
   207 
       
   208     // close the socket itself
       
   209     if (close(sock->fd))
       
   210         SET_ERROR_ERRNO(err, ERR_CLOSE);
       
   211 
       
   212     // invalidate
       
   213     sock->fd = -1;
       
   214 
       
   215     return ERROR_CODE(err);
       
   216 }
       
   217