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; |
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: |