src/irc_net_connect.c
branchnew-transport
changeset 156 6534a4ac957b
parent 154 f4472119de3b
child 177 a74b55104fb9
equal deleted inserted replaced
155:c59d3eaff0fb 156:6534a4ac957b
     1 
     1 
     2 #include "irc_net_internal.h"
     2 #include "irc_net_internal.h"
       
     3 #include "sock_tcp.h"
     3 #include "log.h"
     4 #include "log.h"
     4 
     5 
     5 #include <time.h>
     6 #include <time.h>
     6 #include <assert.h>
     7 #include <assert.h>
     7 
     8 
    23     }
    24     }
    24 
    25 
    25 }
    26 }
    26 
    27 
    27 /**
    28 /**
    28  * We have succesfully established a connection to our server with the given sock, so create the irc_conn and bind it
    29  * We have succesfully established a connection to our server with the given transport, so create the irc_conn and bind
    29  * to us.
    30  * it to us.
    30  *
    31  *
    31  * If this fails, this will clean up any partial state, including sock.
    32  * If this fails, this will clean up any partial state, including \a transport.
    32  */
    33  */
    33 static err_t irc_net_connected (struct irc_net *net, struct sock_stream *sock, struct error_info *err)
    34 static err_t irc_net_connected (struct irc_net *net, transport_t *transport, struct error_info *err)
    34 {
    35 {
    35     // mark state
    36     // mark state
    36     net->connecting = false;
    37     net->connecting = false;
    37 
    38 
    38     // create the irc connection state
    39     // create the irc connection state
    39     if (irc_conn_create(&net->conn, sock, &irc_net_conn_callbacks, net, err))
    40     if (irc_conn_create(&net->conn, transport, &irc_net_conn_callbacks, net, err))
    40         goto error;
    41         goto error;
    41 
    42 
    42     // add our command handlers
    43     // add our command handlers
    43     if ((ERROR_CODE(err) = irc_conn_add_cmd_handlers (net->conn, irc_net_cmd_handlers, net)))
    44     if ((ERROR_CODE(err) = irc_conn_add_cmd_handlers (net->conn, irc_net_cmd_handlers, net)))
    44         goto error;
    45         goto error;
    53 
    54 
    54     return SUCCESS;
    55     return SUCCESS;
    55 
    56 
    56 error:
    57 error:
    57     if (!net->conn) {
    58     if (!net->conn) {
    58         // cleanup sock ourselves
    59         // cleanup transport ourselves
    59         sock_stream_release(sock);
    60         transport_destroy(transport);
    60 
    61 
    61     } else {
    62     } else {
    62         // cleanup the partial stuff
    63         // cleanup the partial stuff
    63         irc_conn_destroy(net->conn);
    64         irc_conn_destroy(net->conn);
    64 
    65 
    70 
    71 
    71 /**
    72 /**
    72  * Our sock_*_connect_async callback. If the connect ended up failing, then try and reconnect later. Otherwise, do
    73  * Our sock_*_connect_async callback. If the connect ended up failing, then try and reconnect later. Otherwise, do
    73  * irc_net_connected().
    74  * irc_net_connected().
    74  */
    75  */
    75 static void irc_net_connect_cb (struct sock_stream *sock, struct error_info *conn_err, void *arg)
    76 static void irc_net_on_connect (transport_t *transport, void *arg)
    76 {
    77 {
    77     struct irc_net *net = arg;
    78     struct irc_net *net = arg;
    78     struct error_info err;
    79     error_t err;
    79     
    80     
    80     if (conn_err) {
    81     // yay
    81         // attempt reconnect later
    82     if (irc_net_connected(net, transport, &err))
    82         log_err_info(conn_err, "connect failed");
    83         log_err_info(&err, "irc_net_connected");
    83         
    84 }
    84         if (irc_net_connect(net, false, &err))
    85 
    85             log_err_info(&err, "unable to reconnect");
    86 static void irc_net_on_connect_error (transport_t *transport, const error_t *conn_err, void *arg)
    86 
    87 {
    87     } else {
    88     struct irc_net *net = arg;
    88         // yay
    89     error_t err;
    89         if (irc_net_connected(net, sock, &err))
    90 
    90             log_err_info(&err, "irc_net_connected");
    91     // clean up
    91 
    92     transport_destroy(transport);
    92     }
    93 
    93 }
    94     // attempt reconnect later
       
    95     log_err_info(conn_err, "connect failed");
       
    96     
       
    97     if (irc_net_connect(net, false, &err))
       
    98         log_err_info(&err, "unable to reconnect");
       
    99 }
       
   100 
       
   101 static const struct transport_callbacks irc_net_transport_callbacks = {
       
   102     .on_connect = irc_net_on_connect,
       
   103     .on_error   = irc_net_on_connect_error,
       
   104 };
    94 
   105 
    95 /**
   106 /**
    96  * The low-level connect() implementation, connects based on irc_net::info, calling irc_net_connected/irc_net_reconnect
   107  * The low-level connect() implementation, connects based on irc_net::info, calling irc_net_connected/irc_net_reconnect
    97  * later if this succeeds.
   108  * later if this succeeds.
    98  */
   109  */
    99 static err_t irc_net_do_connect (struct irc_net *net, struct error_info *err)
   110 static err_t irc_net_do_connect (struct irc_net *net, struct error_info *err)
   100 {
   111 {
   101     struct irc_net_info *info = &net->info;
   112     struct irc_net_info *info = &net->info;
   102     struct sock_stream *sock = NULL;
   113     struct transport_info transport_info = { &irc_net_transport_callbacks, net, TRANSPORT_READ | TRANSPORT_WRITE };
       
   114     transport_t *transport = NULL;
   103 
   115 
   104     // sanity check
   116     // sanity check
   105     assert(!net->connecting && !net->connected);
   117     assert(!net->connecting && !net->connected);
   106 
   118 
   107     // connect based on what's known
   119     // connect based on what's known
   108     if (info->raw_sock) {
   120     if (info->transport) {
   109         log_debug("connected using raw socket: %p", info->raw_sock);
   121         log_debug("connected using raw transport: %p", info->transport);
   110 
   122 
   111         // direct sock_stream connection
   123         // direct transport connection
   112         sock = info->raw_sock;
   124         transport = info->transport;
   113 
   125 
   114         // then create the conn right away
   126         // invalidate it from info since it will get destroyed later
   115         if (irc_net_connected(net, sock, err))
   127         info->transport = NULL;
       
   128 
       
   129         // then create the transport right away
       
   130         if (irc_net_connected(net, transport, err))
   116             goto error;
   131             goto error;
   117 
   132 
   118     } else if (info->ssl_cred) {
   133     } else if (info->ssl_cred) {
   119         // aquire a ref
   134         // aquire a ref
   120         // NOTE: before any error handling
   135         // NOTE: before any error handling
   121         sock_ssl_client_cred_get(info->ssl_cred);
   136         sock_ssl_client_cred_get(info->ssl_cred);
   122         
   137         
   123         log_debug("connecting to [%s]:%s using SSL", info->hostname, info->service);
   138         log_debug("connecting to [%s]:%s using SSL", info->hostname, info->service);
   124 
   139 
   125         // connect
   140         // connect
   126         if (sock_ssl_connect_async(&sock, info->hostname, info->service, info->ssl_cred, &irc_net_connect_cb, net, err))
   141         if (sock_ssl_connect(&transport_info, &transport, info->hostname, info->service, info->ssl_cred, err))
   127             goto error;
   142             goto error;
   128 
   143 
   129         net->connecting = true;
   144         net->connecting = true;
   130 
   145 
   131     } else {
   146     } else if (info->hostname || info->service) {
   132         log_debug("connecting to [%s]:%s", info->hostname, info->service);
   147         log_debug("connecting to [%s]:%s", info->hostname, info->service);
   133             
   148             
   134         // begin async connect
   149         // begin async connect
   135         if (sock_tcp_connect_async(&sock, info->hostname, info->service, &irc_net_connect_cb, net, err))
   150         if (sock_tcp_connect(&transport_info, &transport, info->hostname, info->service, err))
   136             goto error;
   151             goto error;
   137         
   152         
   138         net->connecting = true;
   153         net->connecting = true;
   139 
   154 
       
   155     } else {
       
   156         RETURN_SET_ERROR_STR(err, ERR_MISC, "no connection info specified");
       
   157 
   140     }
   158     }
   141 
   159 
   142     return SUCCESS;
   160     return SUCCESS;
   143 
   161 
   144 error:
   162 error:
   158 
   176 
   159     // execute it?
   177     // execute it?
   160     if (irc_net_connect(net, true, &err))
   178     if (irc_net_connect(net, true, &err))
   161         log_err_info(&err, "unable to reconnect");
   179         log_err_info(&err, "unable to reconnect");
   162 }
   180 }
   163 
       
   164 // XXX: to get the ev_base
       
   165 #include "sock_internal.h"
       
   166 
   181 
   167 /**
   182 /**
   168  * Schedule a reconnection attempt in IRC_NET_RECONNECT_INTERVAL.
   183  * Schedule a reconnection attempt in IRC_NET_RECONNECT_INTERVAL.
   169  */
   184  */
   170 static err_t irc_net_schedule_reconnect (struct irc_net *net, struct error_info *err)
   185 static err_t irc_net_schedule_reconnect (struct irc_net *net, struct error_info *err)
   201     return SUCCESS;
   216     return SUCCESS;
   202 
   217 
   203 error:
   218 error:
   204     return ERROR_CODE(err);
   219     return ERROR_CODE(err);
   205 }
   220 }
       
   221 
       
   222 // XXX: to get the ev_base
       
   223 #include "sock_internal.h"
       
   224 
   206 
   225 
   207 err_t irc_net_connect_init (struct irc_net *net, struct error_info *err)
   226 err_t irc_net_connect_init (struct irc_net *net, struct error_info *err)
   208 {
   227 {
   209     // look up the ev_base 
   228     // look up the ev_base 
   210     struct event_base *ev_base = _sock_stream_ctx.ev_base;
   229     struct event_base *ev_base = _sock_stream_ctx.ev_base;