src/sock_tcp.c
changeset 117 9cb405164250
parent 109 bfe9b9a8fe5b
child 139 55b9dcc2b73a
equal deleted inserted replaced
116:92e71129074d 117:9cb405164250
     3 #include "log.h"
     3 #include "log.h"
     4 
     4 
     5 #include <stdlib.h>
     5 #include <stdlib.h>
     6 #include <sys/types.h>
     6 #include <sys/types.h>
     7 #include <sys/socket.h>
     7 #include <sys/socket.h>
     8 #include <unistd.h>
       
     9 #include <fcntl.h>
       
    10 #include <string.h>
     8 #include <string.h>
    11 #include <assert.h>
     9 
    12 
    10 static void sock_tcp_release (struct sock_stream *base_sock)
    13 /*
       
    14  * Our basic socket event handler for driving our callbacks
       
    15  */
       
    16 static void sock_tcp_event_handler (evutil_socket_t fd, short what, void *arg) 
       
    17 {
       
    18     struct sock_tcp *sock = arg;
       
    19 
       
    20     (void) fd;
       
    21 
       
    22     // invoke appropriate callback
       
    23     sock_stream_invoke_callbacks(SOCK_TCP_BASE(sock), what);
       
    24 }
       
    25 
       
    26 /*
       
    27  * Our sock_stream_methods.read method
       
    28  */
       
    29 static err_t sock_tcp_read (struct sock_stream *base_sock, void *buf, size_t *len)
       
    30 {
    11 {
    31     struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
    12     struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
    32     int ret;
       
    33     
       
    34     // read(), and detect non-EAGAIN or EOF
       
    35     if ((ret = read(sock->fd, buf, *len)) < 0 && errno != EAGAIN)
       
    36         // unexpected error
       
    37         RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_READ);
       
    38     
       
    39     else if (ret == 0)
       
    40         // EOF
       
    41         return SET_ERROR(SOCK_TCP_ERR(sock), ERR_READ_EOF);
       
    42 
       
    43 
       
    44     if (ret < 0) {
       
    45         // EAGAIN -> zero bytes
       
    46         *len = 0;
       
    47 
       
    48     } else {
       
    49         // normal -> bytes read
       
    50         *len = ret;
       
    51     }
       
    52 
       
    53     // ok
       
    54     return SUCCESS;
       
    55 }
       
    56 
       
    57 /*
       
    58  * Our sock_stream_methods.write method
       
    59  */
       
    60 static err_t sock_tcp_write (struct sock_stream *base_sock, const void *buf, size_t *len)
       
    61 {
       
    62     struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
       
    63     int ret;
       
    64     
       
    65     // write(), and detect non-EAGAIN or EOF
       
    66     if ((ret = write(sock->fd, buf, *len)) < 0 && errno != EAGAIN)
       
    67         // unexpected error
       
    68         RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_WRITE);
       
    69     
       
    70     else if (ret == 0)
       
    71         // EOF
       
    72         return SET_ERROR(SOCK_TCP_ERR(sock), ERR_WRITE_EOF);
       
    73 
       
    74 
       
    75     if (ret < 0) {
       
    76         // EAGAIN -> zero bytes
       
    77         *len = 0;
       
    78 
       
    79     } else {
       
    80         // normal -> bytes read
       
    81         *len = ret;
       
    82     }
       
    83 
       
    84     return SUCCESS;
       
    85 }
       
    86 
       
    87 static err_t sock_tcp_event_init (struct sock_stream *base_sock)
       
    88 {
       
    89     struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
       
    90     err_t err;
       
    91 
       
    92     // set nonblocking
       
    93     if ((err = sock_tcp_set_nonblock(sock, 1)))
       
    94         return err;
       
    95 
       
    96     // add ourselves as the event handler
       
    97     if ((err = sock_tcp_init_ev(sock, &sock_tcp_event_handler, sock)))
       
    98         return err;
       
    99     
       
   100     // done
       
   101     return SUCCESS;
       
   102 }
       
   103 
       
   104 static err_t sock_tcp_event_enable (struct sock_stream *base_sock, short mask)
       
   105 {
       
   106     struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
       
   107     
       
   108     // implemented in sock_tcp_add_event
       
   109     return sock_tcp_add_event(sock, mask);
       
   110 }
       
   111 
       
   112 static void sock_tcp_release (struct sock_stream *base_sock)
       
   113 {
       
   114     struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
       
   115     
    13     
   116     // close and free
    14     // close and free
   117     sock_tcp_close(sock);
    15     sock_fd_close(SOCK_TCP_FD(sock));
   118     sock_tcp_free(sock);
    16     sock_tcp_free(sock);
   119 }
    17 }
   120 
    18 
   121 /*
    19 /*
   122  * Our sock_stream_type
    20  * Our sock_stream_type
   123  */
    21  */
   124 static struct sock_stream_type sock_tcp_type = {
    22 static struct sock_stream_type sock_tcp_type = {
   125     .methods                = {
    23     .methods                = {
   126         .read               = &sock_tcp_read,
    24         .read               = &sock_fd_read,
   127         .write              = &sock_tcp_write,
    25         .write              = &sock_fd_write,
   128         .event_init         = &sock_tcp_event_init,
    26         .event_init         = &sock_fd_event_init,
   129         .event_enable       = &sock_tcp_event_enable,
    27         .event_enable       = &sock_fd_event_enable,
   130         .release            = &sock_tcp_release,
    28         .release            = &sock_tcp_release,
   131     },
    29     },
   132 };
    30 };
   133 
    31 
   134 err_t sock_tcp_alloc (struct sock_tcp **sock_ptr)
    32 static err_t sock_tcp_alloc (struct sock_tcp **sock_ptr)
   135 {
    33 {
   136     // alloc
    34     // alloc
   137     if ((*sock_ptr = calloc(1, sizeof(**sock_ptr))) == NULL)
    35     if ((*sock_ptr = calloc(1, sizeof(**sock_ptr))) == NULL)
   138         return ERR_CALLOC;
    36         return ERR_CALLOC;
   139     
    37     
   140     // initialize base with sock_tcp_type
    38     // initialize base with sock_tcp_type
   141     sock_stream_init(SOCK_TCP_BASE(*sock_ptr), &sock_tcp_type);
    39     sock_stream_init(SOCK_TCP_BASE(*sock_ptr), &sock_tcp_type);
   142 
    40 
   143     // invalid fds are <0
    41     // init without any fd
   144     (*sock_ptr)->fd = -1;
    42     sock_fd_init(SOCK_TCP_FD(*sock_ptr), -1);
   145 
    43 
   146     // done
    44     // done
   147     return SUCCESS;
    45     return SUCCESS;
   148 }
    46 }
   149 
    47 
   150 err_t sock_tcp_init_fd (struct sock_tcp *sock, int fd)
    48 err_t sock_tcp_init_socket (struct sock_tcp *sock, struct addrinfo *addr, struct error_info *err)
   151 {
    49 {
   152     // valid fd
    50     int fd;
   153     assert(fd >= 0);
    51 
   154 
    52     // call socket
   155     // initialize
    53     if ((fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) < 0)
   156     sock->fd = fd;
    54         RETURN_SET_ERROR_ERRNO(err, ERR_SOCKET);
   157 
       
   158     // done
       
   159     return SUCCESS;
       
   160 }
       
   161 
       
   162 err_t sock_tcp_init_ev (struct sock_tcp *sock, void (*ev_cb)(evutil_socket_t, short, void *), void *cb_arg)
       
   163 {
       
   164     // require valid fd
       
   165     assert(sock->fd >= 0);
       
   166 
       
   167     // this is initialization
       
   168     assert(sock->ev_read == NULL && sock->ev_write == NULL);
       
   169     
       
   170     // create new event
       
   171     if ((sock->ev_read = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_READ, ev_cb, cb_arg)) == NULL)
       
   172         return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_NEW);
       
   173 
       
   174     if ((sock->ev_write = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_WRITE, ev_cb, cb_arg)) == NULL)
       
   175         return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_NEW);
       
   176 
    55 
   177     // ok
    56     // ok
   178     return SUCCESS;
    57     sock_fd_init(SOCK_TCP_FD(sock), fd);
   179 }
    58 
   180 
       
   181 void sock_tcp_deinit_ev (struct sock_tcp *sock)
       
   182 {
       
   183     if (sock->ev_read) {
       
   184         event_free(sock->ev_read);
       
   185 
       
   186         sock->ev_read = NULL;
       
   187     }
       
   188 
       
   189     if (sock->ev_write) {
       
   190         event_free(sock->ev_write);
       
   191         
       
   192         sock->ev_write = NULL;
       
   193     }
       
   194 }
       
   195 
       
   196 err_t sock_tcp_init_socket (struct sock_tcp *sock, struct addrinfo *addr, struct error_info *err)
       
   197 {
       
   198     // must not be set already
       
   199     assert(sock->fd < 0);
       
   200 
       
   201     // call socket
       
   202     if ((sock->fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) < 0)
       
   203         RETURN_SET_ERROR_ERRNO(err, ERR_SOCKET);
       
   204 
       
   205     // ok
       
   206     return SUCCESS;
       
   207 }
       
   208 
       
   209 err_t sock_tcp_add_event (struct sock_tcp *sock, short mask)
       
   210 {
       
   211     // just add the appropraite events
       
   212     if (mask & EV_READ && event_add(sock->ev_read, NULL))
       
   213         return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD);
       
   214  
       
   215     if (mask & EV_WRITE && event_add(sock->ev_write, NULL))
       
   216         return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD);
       
   217     
       
   218     // done
       
   219     return SUCCESS;
    59     return SUCCESS;
   220 }
    60 }
   221 
    61 
   222 /**
    62 /**
   223  * Attempt to connect to the given addrinfo, or the next one, if that fails, etc.
    63  * Attempt to connect to the given addrinfo, or the next one, if that fails, etc.
   255  * Our async connect operation has completed, clean up addrinfos and events, and call the user callback. The given
    95  * Our async connect operation has completed, clean up addrinfos and events, and call the user callback. The given
   256  * \a err should be NULL for successful completion, or the error for unsuccesfully completion.
    96  * \a err should be NULL for successful completion, or the error for unsuccesfully completion.
   257  */
    97  */
   258 static void sock_tcp_connect_async_done (struct sock_tcp *sock, struct error_info *err)
    98 static void sock_tcp_connect_async_done (struct sock_tcp *sock, struct error_info *err)
   259 {
    99 {
       
   100     struct sock_stream *sock_base = SOCK_TCP_BASE(sock);
       
   101 
   260     // free the addrinfo
   102     // free the addrinfo
   261     freeaddrinfo(sock->async_res); 
   103     freeaddrinfo(sock->async_res); 
   262     sock->async_res = sock->async_cur = NULL;
   104     sock->async_res = sock->async_cur = NULL;
   263 
   105 
   264     // remove our event handler so the user can install their own
   106     // remove our event handler so the user can install their own
   265     sock_tcp_deinit_ev(sock);
   107     sock_fd_deinit_ev(SOCK_TCP_FD(sock));
   266 
   108 
   267     // ok, run callback
   109     // ok, run callback
   268     SOCK_TCP_BASE(sock)->conn_cb_func(SOCK_TCP_BASE(sock), err, SOCK_TCP_BASE(sock)->conn_cb_arg);
   110     sock_base->conn_cb_func(sock_base, err, sock_base->conn_cb_arg);
   269 }
   111 }
   270 
   112 
   271 /**
   113 /**
   272  * Our start_connect callback
   114  * Our start_connect callback
   273  */
   115  */
   301     // done
   143     // done
   302     return sock_tcp_connect_async_done(sock, NULL);
   144     return sock_tcp_connect_async_done(sock, NULL);
   303 
   145 
   304 error:
   146 error:
   305     // close the socket
   147     // close the socket
   306     if ((tmp = sock_tcp_close(sock)))
   148     if ((tmp = sock_fd_close(SOCK_TCP_FD(sock))))
   307         log_warn("error closing socket after connect error: %s", error_name(tmp));
   149         log_warn("error closing socket after connect error: %s", error_name(tmp));
   308 
   150 
   309     // log a warning
   151     // log a warning
   310     log_warn("connect to '%s' failed: %s", sock->async_cur->ai_canonname, error_msg(&err));
   152     log_warn("connect to '%s' failed: %s", sock->async_cur->ai_canonname, error_msg(&err));
   311 
   153 
   322     // first, create the socket
   164     // first, create the socket
   323     if (sock_tcp_init_socket(sock, addr, err))
   165     if (sock_tcp_init_socket(sock, addr, err))
   324         return ERROR_CODE(err);
   166         return ERROR_CODE(err);
   325 
   167 
   326     // then, set it up as nonblocking
   168     // then, set it up as nonblocking
   327     if ((ERROR_CODE(err) = sock_tcp_set_nonblock(sock, true)))
   169     if ((ERROR_CODE(err) = sock_fd_set_nonblock(SOCK_TCP_FD(sock), true)))
   328         goto error;
   170         goto error;
   329 
   171 
   330     // then, initiate the connect
   172     // then, initiate the connect
   331     if ((ret = connect(sock->fd, addr->ai_addr, addr->ai_addrlen)) < 0 && errno != EINPROGRESS) 
   173     if ((ret = connect(SOCK_TCP_FD(sock)->fd, addr->ai_addr, addr->ai_addrlen)) < 0 && errno != EINPROGRESS) 
   332         JUMP_SET_ERROR_ERRNO(err, ERR_CONNECT);
   174         JUMP_SET_ERROR_ERRNO(err, ERR_CONNECT);
   333     
   175     
   334     if (ret < 0) {
   176     if (ret < 0) {
   335         // ok, connect started, setup our completion callback
   177         // ok, connect started, setup our completion callback
   336         if ((ERROR_CODE(err) = sock_tcp_init_ev(sock, &sock_tcp_connect_cb, sock)))
   178         if ((ERROR_CODE(err) = sock_fd_init_ev(SOCK_TCP_FD(sock), &sock_tcp_connect_cb, sock)))
   337             goto error;
   179             goto error;
   338     
   180     
   339         // enable for write
   181         // enable for write
   340         if ((ERROR_CODE(err) = sock_tcp_add_event(sock, EV_WRITE)))
   182         if ((ERROR_CODE(err) = sock_fd_enable_events(SOCK_TCP_FD(sock), EV_WRITE)))
   341             goto error;
   183             goto error;
   342 
   184 
   343         // set the "current" address in case it fails and we need to try the next one
   185         // set the "current" address in case it fails and we need to try the next one
   344         sock->async_cur = addr;
   186         sock->async_cur = addr;
   345 
   187 
   352     // ok
   194     // ok
   353     return SUCCESS;
   195     return SUCCESS;
   354 
   196 
   355 error:
   197 error:
   356     // close the stuff we did open
   198     // close the stuff we did open
   357     if ((tmp = sock_tcp_close(sock)))
   199     if ((tmp = sock_fd_close(SOCK_TCP_FD(sock))))
   358         log_warn("error closing socket after connect error: %s", error_name(tmp));
   200         log_warn("error closing socket after connect error: %s", error_name(tmp));
   359 
   201 
   360     return ERROR_CODE(err);
   202     return ERROR_CODE(err);
   361 }
   203 }
   362 
   204 
   373     // resolve
   215     // resolve
   374     if ((ret = getaddrinfo(hostname, service, &hints, &sock->async_res)))
   216     if ((ret = getaddrinfo(hostname, service, &hints, &sock->async_res)))
   375         RETURN_SET_ERROR_EXTRA(err, ERR_GETADDRINFO, ret);
   217         RETURN_SET_ERROR_EXTRA(err, ERR_GETADDRINFO, ret);
   376     
   218     
   377     // start connecting
   219     // start connecting
   378     return sock_tcp_connect_async_continue(sock, sock->async_res, err);
   220     if (sock_tcp_connect_async_continue(sock, sock->async_res, err))
       
   221         goto error;
       
   222 
       
   223     // ok
       
   224     return SUCCESS;
       
   225 
       
   226 error:
       
   227     // cleanup
       
   228     if (sock->async_res) {
       
   229         freeaddrinfo(sock->async_res);
       
   230         sock->async_res = NULL;
       
   231     }
       
   232 
       
   233     return ERROR_CODE(err);
   379 }
   234 }
   380 
   235 
   381 err_t sock_tcp_connect_blocking (struct sock_tcp *sock, const char *hostname, const char *service, struct error_info *err)
   236 err_t sock_tcp_connect_blocking (struct sock_tcp *sock, const char *hostname, const char *service, struct error_info *err)
   382 {
   237 {
   383     struct addrinfo hints, *res, *r;
   238     struct addrinfo hints, *res, *r;
   396         RETURN_SET_ERROR_EXTRA(err, ERR_GETADDRINFO, ret);
   251         RETURN_SET_ERROR_EXTRA(err, ERR_GETADDRINFO, ret);
   397 
   252 
   398     // try each result in turn
   253     // try each result in turn
   399     for (r = res; r; r = r->ai_next) {
   254     for (r = res; r; r = r->ai_next) {
   400         // create the socket
   255         // create the socket
   401         if ((sock->fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) < 0) {
   256         if ((SOCK_TCP_FD(sock)->fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) < 0) {
   402             // remember error
   257             // remember error
   403             SET_ERROR_ERRNO(err, ERR_SOCKET);
   258             SET_ERROR_ERRNO(err, ERR_SOCKET);
   404 
   259 
   405             // skip to next one
   260             // skip to next one
   406             continue;
   261             continue;
   407         }
   262         }
   408         
   263         
   409         // connect to remote address
   264         // connect to remote address
   410         if (connect(sock->fd, r->ai_addr, r->ai_addrlen)) {
   265         if (connect(SOCK_TCP_FD(sock)->fd, r->ai_addr, r->ai_addrlen)) {
   411             // remember error
   266             // remember error
   412             SET_ERROR_ERRNO(err, ERR_CONNECT);
   267             SET_ERROR_ERRNO(err, ERR_CONNECT);
   413             
   268             
   414             // close/invalidate socket
   269             // close/invalidate socket
   415             close(sock->fd);
   270             sock_fd_close(SOCK_TCP_FD(sock));
   416             sock->fd = -1;
       
   417 
   271 
   418             // skip to next one
   272             // skip to next one
   419             continue;
   273             continue;
   420         }
   274         }
   421         
   275         
   422         // valid socket, use this
   276         // valid socket, use this
   423         break;
   277         break;
   424     }
   278     }
   425     
   279     
   426     // ensure we got some valid socket, else return last error code
   280     // ensure we got some valid socket, else return last error code
   427     if (sock->fd < 0) {
   281     if (SOCK_TCP_FD(sock)->fd < 0) {
   428         // did we hit some error?
   282         // did we hit some error?
   429         if (IS_ERROR(err))
   283         if (IS_ERROR(err))
   430             // return last error
   284             // return last error
   431             return ERROR_CODE(err);
   285             return ERROR_CODE(err);
   432         
   286         
   433         else
   287         else
   434             // no results
   288             // no results
   435             return SET_ERROR(err, ERR_GETADDRINFO_EMPTY);
   289             return SET_ERROR(err, ERR_GETADDRINFO_EMPTY);
   436     }
   290     }
   437     
   291 
   438     // ok, done
   292     // ok, done
   439     return 0;    
   293     return 0;    
   440 }
   294 }
   441 
   295 
   442 err_t sock_tcp_set_nonblock (struct sock_tcp *sock, bool nonblock)
       
   443 {
       
   444     // fcntl it
       
   445     // XXX: maintain old flags?
       
   446     if (fcntl(sock->fd, F_SETFL, nonblock ? O_NONBLOCK : 0) < 0)
       
   447         RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_FCNTL);
       
   448 
       
   449     // ok
       
   450     return SUCCESS;
       
   451 }
       
   452 
       
   453 err_t sock_tcp_close (struct sock_tcp *sock)
       
   454 {
       
   455     struct error_info *err = SOCK_TCP_ERR(sock);
       
   456     
       
   457     // no errors yet
       
   458     RESET_ERROR(err);
       
   459 
       
   460     // must be connected
       
   461     assert(sock->fd >= 0);
       
   462 
       
   463     // kill any events
       
   464     sock_tcp_deinit_ev(sock);
       
   465 
       
   466     // close the socket itself
       
   467     if (close(sock->fd))
       
   468         SET_ERROR_ERRNO(err, ERR_CLOSE);
       
   469 
       
   470     // invalidate
       
   471     sock->fd = -1;
       
   472 
       
   473     return ERROR_CODE(err);
       
   474 }
       
   475 
       
   476 void sock_tcp_free (struct sock_tcp *sock)
   296 void sock_tcp_free (struct sock_tcp *sock)
   477 {
   297 {
   478     // must not be connected
       
   479     assert(sock->fd < 0);
       
   480 
       
   481     // free
   298     // free
   482     free(sock);
   299     free(sock);
   483 }
   300 }
   484 
   301 
   485 err_t sock_tcp_connect (struct sock_stream **sock_ptr, const char *host, const char *service, struct error_info *err)
   302 err_t sock_tcp_connect (struct sock_stream **sock_ptr, const char *host, const char *service, struct error_info *err)