Free TCP data on disconnect.
[jelmer/ctrlproxy.git] / src / network.c
1 /*
2         ctrlproxy: A modular IRC proxy
3         (c) 2002-2007 Jelmer Vernooij <jelmer@nl.linux.org>
4
5         This program is free software; you can redistribute it and/or modify
6         it under the terms of the GNU General Public License as published by
7         the Free Software Foundation; either version 2 of the License, or
8         (at your option) any later version.
9
10         This program is distributed in the hope that it will be useful,
11         but WITHOUT ANY WARRANTY; without even the implied warranty of
12         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13         GNU General Public License for more details.
14
15         You should have received a copy of the GNU General Public License
16         along with this program; if not, write to the Free Software
17         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "internals.h"
21 #include "irc.h"
22 #include "ssl.h"
23
24 static GHashTable *virtual_network_ops = NULL;
25
26 static gboolean delayed_connect_server(struct network *s);
27 static gboolean connect_server(struct network *s);
28 static gboolean close_server(struct network *s);
29 static void reconnect(struct network *server, gboolean rm_source);
30 static void clients_send_state(GList *clients, struct network_state *s);
31
32 struct new_network_notify_data {
33         new_network_notify_fn fn;
34         void *data;
35 };
36
37 void register_new_network_notify(struct global *global, new_network_notify_fn fn, void *userdata)
38 {
39         struct new_network_notify_data *p = g_new0(struct new_network_notify_data, 1);
40         p->fn = fn;
41         p->data = userdata;
42         global->new_network_notifiers = g_list_append(global->new_network_notifiers, p);
43 }
44
45 static void state_log_helper(enum log_level l, void *userdata, const char *msg)
46 {
47         log_network(l, (const struct network *)userdata, "%s", msg);
48 }
49
50 static void server_send_login (struct network *s) 
51 {
52         g_assert(s);
53
54         s->connection.state = NETWORK_CONNECTION_STATE_LOGIN_SENT;
55
56         log_network(LOG_TRACE, s, "Sending login details");
57
58         s->state = network_state_init(s->config->nick, s->config->username, 
59                                                                   get_my_hostname());
60         s->state->userdata = s;
61         s->state->log = state_log_helper;
62         s->linestack = new_linestack(s);
63         g_assert(s->linestack != NULL);
64
65         if (s->config->type == NETWORK_TCP && 
66            s->connection.data.tcp.current_server->password) { 
67                 network_send_args(s, "PASS", 
68                                         s->connection.data.tcp.current_server->password, NULL);
69         } else if (s->config->password) {
70                 network_send_args(s, "PASS", s->config->password, NULL);
71         }
72         network_send_args(s, "NICK", s->config->nick, NULL);
73         network_send_args(s, "USER", s->config->username, s->config->username, 
74                                           s->config->name, s->config->fullname, NULL);
75 }
76
77 /**
78  * Change the character set used to communicate with the server.
79  *
80  * @param n network to change the character set for
81  * @param name name of the character set to use
82  * @return true if setting the charset worked
83  */
84 gboolean network_set_charset(struct network *n, const char *name)
85 {
86         GIConv tmp;
87
88         if (name != NULL) {
89                 tmp = g_iconv_open(name, "UTF-8");
90
91                 if (tmp == (GIConv)-1) {
92                         log_network(LOG_WARNING, n, "Unable to find charset `%s'", name);
93                         return FALSE;
94                 }
95         } else {
96                 tmp = (GIConv)-1;
97         }
98         
99         if (n->connection.outgoing_iconv != (GIConv)-1)
100                 g_iconv_close(n->connection.outgoing_iconv);
101
102         n->connection.outgoing_iconv = tmp;
103
104         if (name != NULL) {
105                 tmp = g_iconv_open("UTF-8", name);
106                 if (tmp == (GIConv)-1) {
107                         log_network(LOG_WARNING, n, "Unable to find charset `%s'", name);
108                         return FALSE;
109                 }
110         } else {
111                 tmp = (GIConv)-1;
112         }
113
114         if (n->connection.incoming_iconv != (GIConv)-1)
115                 g_iconv_close(n->connection.incoming_iconv);
116
117         n->connection.incoming_iconv = tmp;
118
119         if (n->config->type == NETWORK_VIRTUAL)
120                 return TRUE;
121
122         return TRUE;
123 }
124
125 /**
126  * Update the isupport settings for a local network based on the 
127  * ISUPPORT info sent by a server.
128  *
129  * @param net_info Current information
130  * @param remote_info Remote information
131  * @return Whether updating went ok.
132  */
133 static gboolean network_update_isupport(struct network_info *net_info,
134                                                                                 struct network_info *remote_info)
135 {
136         if (remote_info->name != NULL) {
137                 g_free(net_info->name);
138                 net_info->name = g_strdup(remote_info->name);
139         }
140
141         if (remote_info->prefix != NULL) {
142                 g_free(net_info->prefix);
143                 net_info->prefix = g_strdup(remote_info->prefix);
144         }
145
146         if (remote_info->chantypes != NULL) {
147                 g_free(net_info->chantypes);
148                 net_info->chantypes = g_strdup(remote_info->chantypes);
149         }
150
151         if (remote_info->casemapping != CASEMAP_UNKNOWN) {
152                 net_info->casemapping = remote_info->casemapping;
153         }
154
155         if (remote_info->supported_user_modes != NULL) {
156                 g_free(net_info->supported_user_modes);
157                 net_info->supported_user_modes = g_strdup(remote_info->supported_user_modes);
158         } 
159
160         if (remote_info->supported_channel_modes != NULL) {
161                 g_free(net_info->supported_channel_modes);
162                 net_info->supported_channel_modes = g_strdup(remote_info->supported_channel_modes);
163         }
164
165         return TRUE;
166 }
167
168 /**
169  * Process a line received from the server
170  *
171  * @param n Network the line is received at
172  * @param l Line received
173  * @return Whether the message was received ok
174  */
175 static gboolean process_from_server(struct network *n, struct line *l)
176 {
177         struct line *lc;
178         GError *error = NULL;
179
180         g_assert(n);
181         g_assert(l);
182
183         log_network_line(n, l, TRUE);
184
185         /* Silently drop empty messages, as allowed by RFC */
186         if (l->argc == 0) {
187                 return TRUE;
188         }
189
190         n->connection.last_line_recvd = time(NULL);
191
192         if (n->state == NULL) {
193                 log_network(LOG_WARNING, n, 
194                                         "Dropping message '%s' because network is disconnected.", 
195                                         l->args[0]);
196                 return FALSE;
197         }
198
199         run_log_filter(n, lc = linedup(l), FROM_SERVER); free_line(lc);
200         run_replication_filter(n, lc = linedup(l), FROM_SERVER); free_line(lc);
201
202         g_assert(n->state);
203
204         state_handle_data(n->state, l);
205
206         g_assert(l->args[0]);
207
208         if (!g_strcasecmp(l->args[0], "PING")){
209                 network_send_args(n, "PONG", l->args[1], NULL);
210                 return TRUE;
211         } else if (!g_strcasecmp(l->args[0], "PONG")){
212                 return TRUE;
213         } else if (!g_strcasecmp(l->args[0], "ERROR")) {
214                 log_network(LOG_ERROR, n, "error: %s", l->args[1]);
215         } else if (!g_strcasecmp(l->args[0], "433") && 
216                           n->connection.state == NETWORK_CONNECTION_STATE_LOGIN_SENT){
217                 char *tmp = g_strdup_printf("%s_", l->args[2]);
218                 network_send_args(n, "NICK", tmp, NULL);
219                 log_network(LOG_WARNING, n, "%s was already in use, trying %s", 
220                                         l->args[2], tmp);
221                 g_free(tmp);
222         } else if (atoi(l->args[0]) == RPL_ENDOFMOTD ||
223                           atoi(l->args[0]) == ERR_NOMOTD) {
224                 GList *gl;
225                 n->connection.state = NETWORK_CONNECTION_STATE_MOTD_RECVD;
226
227                 network_set_charset(n, get_charset(&n->info));
228
229                 if (error != NULL)
230                         log_network(LOG_WARNING, n, "Error setting charset %s: %s", 
231                                 get_charset(&n->info), error->message);
232
233                 log_network(LOG_INFO, n, "Successfully logged in");
234
235                 network_update_isupport(&n->info, &n->state->info);
236
237                 nickserv_identify_me(n, n->state->me.nick);
238
239                 clients_send_state(n->clients, n->state);
240
241                 server_connected_hook_execute(n);
242
243                 network_send_args(n, "USERHOST", n->state->me.nick, NULL);
244
245                 /* Rejoin channels */
246                 for (gl = n->config->channels; gl; gl = gl->next) {
247                         struct channel_config *c = gl->data;
248
249                         if (c->autojoin) {
250                                 network_send_args(n, "JOIN", c->name, c->key, NULL);
251                         } 
252                 }
253         } 
254
255         if ( n->connection.state == NETWORK_CONNECTION_STATE_MOTD_RECVD) {
256                 gboolean linestack_store = TRUE;
257                 if (atoi(l->args[0])) {
258                         linestack_store &= (!redirect_response(n, l));
259                 } else if (!g_strcasecmp(l->args[0], "PRIVMSG") && l->argc > 2 && 
260                         l->args[2][0] == '\001' && 
261                         g_strncasecmp(l->args[2], "\001ACTION", 7) != 0) {
262                         ctcp_process_network_request(n, l);
263                 } else if (!g_strcasecmp(l->args[0], "NOTICE") && l->argc > 2 && 
264                         l->args[2][0] == '\001') {
265                         ctcp_process_network_reply(n, l);
266                 } else if (run_server_filter(n, l, FROM_SERVER)) {
267                         clients_send(n->clients, l, NULL);
268                 } 
269
270                 if (linestack_store)
271                         linestack_insert_line(n->linestack, l, FROM_SERVER, n->state);
272         } 
273
274         return TRUE;
275 }
276
277 static void network_report_disconnect(struct network *n, const char *fmt, ...)
278 {
279         va_list ap;
280         char *tmp;
281         va_start(ap, fmt);
282         tmp = g_strdup_vprintf(fmt, ap);
283         va_end(ap);
284
285         g_free(n->connection.data.tcp.last_disconnect_reason);
286         n->connection.data.tcp.last_disconnect_reason = tmp;
287
288         log_network(LOG_WARNING, n, "%s", tmp);
289 }
290
291 static gboolean handle_server_receive (GIOChannel *c, GIOCondition cond, void *_server)
292 {
293         struct network *server = (struct network *)_server;
294         struct line *l;
295         gboolean ret;
296
297         g_assert(c != NULL);
298         g_assert(server != NULL);
299
300         if (cond & G_IO_HUP) {
301                 network_report_disconnect(server, "Hangup from server, scheduling reconnect");
302                 reconnect(server, FALSE);
303                 return FALSE;
304         }
305
306         if (cond & G_IO_ERR) {
307                 network_report_disconnect(server, "Error from server, scheduling reconnect");
308                 reconnect(server, FALSE);
309                 return FALSE;
310         }
311
312         if (cond & G_IO_IN) {
313                 GError *err = NULL;
314                 GIOStatus status;
315                 
316                 while ((status = irc_recv_line(c, server->connection.incoming_iconv, 
317                                                                            &err, &l)) == G_IO_STATUS_NORMAL) 
318                 {
319                         g_assert(l != NULL);
320
321                         ret = process_from_server(server, l);
322
323                         free_line(l);
324
325                         if (!ret)
326                                 return FALSE;
327                 }
328
329                 switch (status) {
330                 case G_IO_STATUS_AGAIN:
331                         return TRUE;
332                 case G_IO_STATUS_EOF:
333                         if (server->connection.state != NETWORK_CONNECTION_STATE_NOT_CONNECTED) 
334                                 reconnect(server, FALSE);
335                         return FALSE;
336                 case G_IO_STATUS_ERROR:
337                         g_assert(err != NULL);
338                         log_network(LOG_WARNING, server, 
339                                                 "Error \"%s\" reading from server", err->message);
340                         if (l != NULL) {
341                                 ret = process_from_server(server, l);
342
343                                 free_line(l);
344
345                                 return ret;
346                         }
347
348                         return TRUE;
349                 default: abort();
350                 }
351
352                 return TRUE;
353         }
354
355         return TRUE;
356 }
357
358 static struct tcp_server_config *network_get_next_tcp_server(struct network *n)
359 {
360         GList *cur;
361         
362         g_assert(n);
363         g_assert(n->config);
364         cur = g_list_find(n->config->type_settings.tcp_servers, n->connection.data.tcp.current_server);
365
366         /* Get next available server */
367         if (cur != NULL && cur->next != NULL) 
368                 cur = cur->next; 
369         else 
370                 cur = n->config->type_settings.tcp_servers;
371
372         if (cur != NULL) 
373                 return cur->data; 
374
375         return NULL;
376 }
377
378 static gboolean antiflood_allow_line(struct network *s)
379 {
380         /* FIXME: Implement antiflood, use s->config->queue_speed */
381         return TRUE;
382 }
383
384 static gboolean server_send_queue(GIOChannel *ch, GIOCondition cond, 
385                                                                   gpointer user_data)
386 {
387         struct network *s = user_data;
388         GError *error = NULL;
389         GIOStatus status;
390
391         while (!g_queue_is_empty(s->connection.pending_lines)) {
392                 struct line *l = g_queue_peek_head(s->connection.pending_lines);
393
394                 /* Check if antiflood allows us to send a line */
395                 if (!antiflood_allow_line(s)) 
396                         return TRUE;
397
398                 status = irc_send_line(s->connection.outgoing, s->connection.outgoing_iconv, l, &error);
399
400                 if (status == G_IO_STATUS_AGAIN)
401                         return TRUE;
402
403                 g_queue_pop_head(s->connection.pending_lines);
404
405                 if (status != G_IO_STATUS_NORMAL) {
406                         log_network(LOG_WARNING, s, "Error sending line '%s': %s",
407                    l->args[0], error != NULL?error->message:"ERROR");
408                         free_line(l);
409
410                         return FALSE;
411                 }
412                 s->connection.last_line_sent = time(NULL);
413
414                 free_line(l);
415         }
416
417         s->connection.outgoing_id = 0;
418         return FALSE;
419 }
420
421 static gboolean network_send_line_direct(struct network *s, struct client *c, 
422                                                                                  const struct line *ol)
423 {
424         struct line nl, *l;
425
426         g_assert(s->config != NULL);
427
428         g_assert(s->config->type == NETWORK_TCP ||
429                  s->config->type == NETWORK_PROGRAM ||
430                  s->config->type == NETWORK_IOCHANNEL ||
431                  s->config->type == NETWORK_VIRTUAL);
432
433         l = &nl;
434         memcpy(l, ol, sizeof(struct line));
435         nl.origin = NULL;
436
437         /* origin lines should never be sent to the server */
438         g_assert(l->origin == NULL);
439
440         if (s->config->type == NETWORK_VIRTUAL) {
441                 if (s->connection.data.virtual.ops == NULL) 
442                         return FALSE;
443                 return s->connection.data.virtual.ops->to_server(s, c, l);
444         } else if (s->connection.outgoing_id == 0) {
445                 GError *error = NULL;
446
447                 GIOStatus status = irc_send_line(s->connection.outgoing, s->connection.outgoing_iconv, l, &error);
448
449                 if (status == G_IO_STATUS_AGAIN) {
450                         g_queue_push_tail(s->connection.pending_lines, linedup(l));
451                         s->connection.outgoing_id = g_io_add_watch(s->connection.outgoing, G_IO_OUT, server_send_queue, s);
452                 } else if (status != G_IO_STATUS_NORMAL) {
453                         log_network(LOG_WARNING, s, "Error sending line '%s': %s",
454                    l->args[0], error != NULL?error->message:"ERROR");
455                         return FALSE;
456                 }
457
458                 s->connection.last_line_sent = time(NULL);
459                 return TRUE;
460         } else {
461                 g_queue_push_tail(s->connection.pending_lines, linedup(l));
462         }
463
464         return TRUE;
465 }
466
467 /**
468  * Send a line to the network.
469  * @param s Network to send to.
470  * @param c Client the line was sent by originally.
471  * @param ol Line to send to the network
472  * @param is_private Whether the line should not be broadcast to other clients
473  */
474 gboolean network_send_line(struct network *s, struct client *c, 
475                                                    const struct line *ol, gboolean is_private)
476 {
477         struct line l;
478         char *tmp = NULL;
479         struct line *lc;
480
481         g_assert(ol);
482         g_assert(s);
483         l = *ol;
484
485         if (l.origin == NULL && s->state != NULL) {
486                 tmp = l.origin = g_strdup(s->state->me.hostmask);
487         }
488
489         if (l.origin != NULL) {
490                 if (!run_server_filter(s, &l, TO_SERVER)) {
491                         g_free(tmp);
492                         return TRUE;
493                 }
494
495                 run_log_filter(s, lc = linedup(&l), TO_SERVER); free_line(lc);
496                 run_replication_filter(s, lc = linedup(&l), TO_SERVER); free_line(lc);
497                 linestack_insert_line(s->linestack, ol, TO_SERVER, s->state);
498         }
499
500         g_assert(l.args[0] != NULL);
501
502         /* Also write this message to all other clients currently connected */
503         if (!is_private && 
504            (!g_strcasecmp(l.args[0], "PRIVMSG") || 
505                 !g_strcasecmp(l.args[0], "NOTICE"))) {
506                 g_assert(l.origin);
507                 clients_send(s->clients, &l, c);
508         }
509
510         g_free(tmp);
511
512         log_network_line(s, ol, FALSE);
513
514         redirect_record(s, c, ol);
515
516         return network_send_line_direct(s, c, ol);
517 }
518
519 /**
520  * Indicate that a response is received by a virtual network.
521  *
522  * @param n Network to receive data
523  * @param num Number of the response to receive
524  */
525 gboolean virtual_network_recv_response(struct network *n, int num, ...) 
526 {
527         va_list ap;
528         struct line *l;
529         gboolean ret;
530
531         g_assert(n);
532         g_assert(n->config->type == NETWORK_VIRTUAL);
533
534         va_start(ap, num);
535         l = virc_parse_line(n->info.name, ap);
536         va_end(ap);
537
538         l->args = g_realloc(l->args, sizeof(char *) * (l->argc+4));
539         memmove(&l->args[2], &l->args[0], l->argc * sizeof(char *));
540
541         l->args[0] = g_strdup_printf("%03d", num);
542
543         if (n->state != NULL && n->state->me.nick != NULL) 
544                 l->args[1] = g_strdup(n->state->me.nick);
545         else 
546                 l->args[1] = g_strdup("*");
547
548         l->argc+=2;
549         l->args[l->argc] = NULL;
550
551         ret = virtual_network_recv_line(n, l);
552
553         free_line(l);
554
555         return ret;
556 }
557
558 /**
559  * Indicate that a line is received by a virtual network.
560  *
561  * @param s Network to send to.
562  * @param l Line to receive.
563  */
564 gboolean virtual_network_recv_line(struct network *s, struct line *l)
565 {
566         g_assert(s != NULL);
567         g_assert(l != NULL);
568
569         if (l->origin == NULL) 
570                 l->origin = g_strdup(get_my_hostname());
571
572         return process_from_server(s, l);
573 }
574
575 /**
576  * Indicate that a line has been received.
577  *
578  * @param s Network to use.
579  * @param origin Origin to make the data originate from
580  */
581 gboolean virtual_network_recv_args(struct network *s, const char *origin, ...)
582 {
583         va_list ap;
584         struct line *l;
585         gboolean ret;
586
587         g_assert(s);
588
589         va_start(ap, origin);
590         l = virc_parse_line(origin, ap);
591         va_end(ap);
592
593         ret = virtual_network_recv_line(s, l);
594
595         free_line(l);
596
597         return ret;
598 }
599
600 /**
601  * Send a new line to the network.
602  *
603  * @param s Network
604  * @param ... Arguments terminated by NULL
605  */
606 gboolean network_send_args(struct network *s, ...)
607 {
608         va_list ap;
609         struct line *l;
610         gboolean ret;
611
612         g_assert(s);
613
614         va_start(ap, s);
615         l = virc_parse_line(NULL, ap);
616         va_end(ap);
617
618         ret = network_send_line(s, NULL, l, TRUE);
619
620         free_line(l);
621
622         return ret;
623 }
624
625 static gboolean bindsock(struct network *s,
626                                                  int sock, struct addrinfo *res, 
627                                                  const char *address,
628                                                  const char *service)
629 {
630         struct addrinfo hints_bind;
631         int error;
632         struct addrinfo *res_bind, *addrinfo_bind;
633
634         memset(&hints_bind, 0, sizeof(hints_bind));
635         hints_bind.ai_family = res->ai_family;
636         hints_bind.ai_flags = AI_ADDRCONFIG;
637         hints_bind.ai_socktype = res->ai_socktype;
638         hints_bind.ai_protocol = res->ai_protocol;
639
640         error = getaddrinfo(address, service, &hints_bind, &addrinfo_bind);
641         if (error) {
642                 log_network(LOG_ERROR, s, 
643                                         "Unable to lookup %s:%s %s", address, service, 
644                                         gai_strerror(error));
645                 return FALSE;
646         } 
647
648         for (res_bind = addrinfo_bind; 
649                  res_bind; res_bind = res_bind->ai_next) {
650                 if (bind(sock, res_bind->ai_addr, res_bind->ai_addrlen) < 0) {
651                         log_network(LOG_ERROR, s, "Unable to bind to %s:%s %s", 
652                                                 address, service, strerror(errno));
653                 } else 
654                         break;
655         }
656         freeaddrinfo(addrinfo_bind);
657
658         return (res_bind != NULL);
659 }
660
661 /**
662  * Ping the network.
663  *
664  * @param server network to ping
665  * @param ping_source GSource id of the ping event
666  */
667 static void ping_server(struct network *server, gboolean ping_source)
668 {
669         gint silent_time = time(NULL) - server->connection.last_line_recvd;
670         if (silent_time > MAX_SILENT_TIME) {
671                 disconnect_network(server);
672         } else if (silent_time > MIN_SILENT_TIME) {
673                 network_send_args(server, "PING", "ctrlproxy", NULL);
674         }
675 }
676
677 static gboolean connect_current_tcp_server(struct network *s) 
678 {
679         struct addrinfo *res;
680         int sock = -1;
681         socklen_t size;
682         struct tcp_server_config *cs;
683         GIOChannel *ioc = NULL;
684         struct addrinfo hints;
685         struct addrinfo *addrinfo = NULL;
686         int error;
687
688         g_assert(s != NULL);
689
690         if (!s->connection.data.tcp.current_server) {
691                 s->connection.data.tcp.current_server = network_get_next_tcp_server(s);
692         }
693
694         log_network(LOG_TRACE, s, "connect_current_tcp_server");
695         
696         cs = s->connection.data.tcp.current_server;
697         if (cs == NULL) {
698                 s->config->autoconnect = FALSE;
699                 log_network(LOG_WARNING, s, "No servers listed, not connecting");
700                 return FALSE;
701         }
702
703         log_network(LOG_INFO, s, "Connecting with %s:%s", 
704                           cs->host, 
705                           cs->port);
706
707         memset(&hints, 0, sizeof(hints));
708         hints.ai_family = PF_UNSPEC;
709         hints.ai_socktype = SOCK_STREAM;
710         hints.ai_flags = AI_ADDRCONFIG;
711
712         /* Lookup */
713         error = getaddrinfo(cs->host, cs->port, &hints, &addrinfo);
714         if (error) {
715                 log_network(LOG_ERROR, s, "Unable to lookup %s:%s %s", cs->host, cs->port, gai_strerror(error));
716                 freeaddrinfo(addrinfo);
717                 return FALSE;
718         }
719
720         /* Connect */
721
722         for (res = addrinfo; res; res = res->ai_next) {
723
724                 sock = socket(res->ai_family, res->ai_socktype,
725                                           res->ai_protocol);
726                 if (sock < 0) {
727                         continue;
728                 }
729
730                 if (cs->bind_address || cs->bind_port)
731                         bindsock(s, sock, res, cs->bind_address, cs->bind_port);
732
733                 ioc = g_io_channel_unix_new(sock);
734                 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0 && errno != EINPROGRESS) {
735                         g_io_channel_unref(ioc);
736                         ioc = NULL;
737                         continue;
738                 }
739
740                 break; 
741         }
742
743         freeaddrinfo(addrinfo);
744
745         if (!ioc) {
746                 log_network(LOG_ERROR, s, "Unable to connect: %s", strerror(errno));
747                 return FALSE;
748         }
749
750 #ifdef HAVE_IPV6
751         size = sizeof(struct sockaddr_in6);
752 #else
753         size = sizeof(struct sockaddr_in);
754 #endif
755         g_assert(s->connection.data.tcp.local_name == NULL);
756         g_assert(s->connection.data.tcp.remote_name == NULL);
757         s->connection.data.tcp.remote_name = g_malloc(size);
758         s->connection.data.tcp.local_name = g_malloc(size);
759         s->connection.data.tcp.namelen = getsockname(sock, s->connection.data.tcp.local_name, &size);
760         getpeername(sock, s->connection.data.tcp.remote_name, &size);
761
762         if (cs->ssl) {
763 #ifdef HAVE_GNUTLS
764                 g_io_channel_set_close_on_unref(ioc, TRUE);
765                 g_io_channel_set_flags(ioc, G_IO_FLAG_NONBLOCK, NULL);
766
767                 ioc = ssl_wrap_iochannel (ioc, SSL_TYPE_CLIENT, 
768                                                                  s->connection.data.tcp.current_server->host,
769                                                                  s->ssl_credentials
770                                                                  );
771                 g_assert(ioc != NULL);
772 #else
773                 log_network(LOG_WARNING, s, "SSL enabled for %s:%s, but no SSL support loaded", cs->host, cs->port);
774 #endif
775         }
776
777         if (!ioc) {
778                 log_network(LOG_ERROR, s, "Couldn't connect via server %s:%s", cs->host, cs->port);
779                 return FALSE;
780         }
781
782         network_set_iochannel(s, ioc);
783
784         g_io_channel_unref(s->connection.outgoing);
785
786         s->connection.data.tcp.ping_id = g_timeout_add(5000, 
787                                                                    (GSourceFunc) ping_server, s);
788
789
790         return TRUE;
791 }
792
793
794 static void reconnect(struct network *server, gboolean rm_source)
795 {
796         g_assert(server);
797
798         g_assert(server->connection.state != NETWORK_CONNECTION_STATE_RECONNECT_PENDING);
799
800         if (server->connection.state == NETWORK_CONNECTION_STATE_MOTD_RECVD) {
801                 server_disconnected_hook_execute(server);
802         }
803
804         close_server(server);
805
806         g_assert(server->config);
807
808         if (server->config->type == NETWORK_TCP)
809                 server->connection.data.tcp.current_server = network_get_next_tcp_server(server);
810
811         if (server->config->type == NETWORK_TCP ||
812                 server->config->type == NETWORK_IOCHANNEL ||
813                 server->config->type == NETWORK_PROGRAM) {
814                 server->connection.state = NETWORK_CONNECTION_STATE_RECONNECT_PENDING;
815                 server->reconnect_id = g_timeout_add(1000 * 
816                                                                 server->config->reconnect_interval, 
817                                                                 (GSourceFunc) delayed_connect_server, server);
818         } else {
819                 connect_server(server); 
820         }
821 }
822
823 static void clients_send_state(GList *clients, struct network_state *s)
824 {
825         GList *gl;
826
827         for (gl = clients; gl; gl = gl->next) {
828                 struct client *c = gl->data;
829                 client_send_state(c, s);
830         }
831 }
832
833 static void clients_invalidate_state(GList *clients, struct network_state *s)
834 {
835         GList *gl;
836
837         /* Leave channels */
838         for (gl = s->channels; gl; gl = gl->next) {
839                 struct channel_state *ch = gl->data;
840
841                 clients_send_args_ex(clients, s->me.hostmask, "PART", ch->name, 
842                                                          "Network disconnected", NULL);
843         }
844
845         /* private queries quit */
846         for (gl = s->nicks; gl; gl = gl->next) {
847                 struct network_nick *gn = gl->data;
848
849                 if (!gn->query || gn == &s->me) continue;
850
851                 clients_send_args_ex(clients, gn->hostmask, "QUIT", "Network disconnected", NULL);
852         }
853 }
854
855 static gboolean close_server(struct network *n) 
856 {
857         g_assert(n);
858
859         if (n->connection.state == NETWORK_CONNECTION_STATE_RECONNECT_PENDING) {
860                 g_source_remove(n->reconnect_id);
861                 n->reconnect_id = 0;
862                 n->connection.state = NETWORK_CONNECTION_STATE_NOT_CONNECTED;
863         }
864
865         if (n->connection.state == NETWORK_CONNECTION_STATE_NOT_CONNECTED) {
866                 return FALSE;
867         } 
868
869         network_send_args(n, "QUIT", NULL);
870
871         if (n->connection.state == NETWORK_CONNECTION_STATE_MOTD_RECVD) {
872                 server_disconnected_hook_execute(n);
873                 clients_invalidate_state(n->clients, n->state);
874                 network_update_config(n->state, n->config);
875         }
876
877         if (n->state) {
878                 free_linestack_context(n->linestack);
879                 n->linestack = NULL;
880                 free_network_state(n->state); 
881                 n->state = NULL;
882         }
883
884         g_assert(n->config);
885
886         switch (n->config->type) {
887         case NETWORK_TCP: 
888         case NETWORK_PROGRAM: 
889         case NETWORK_IOCHANNEL:
890                 g_assert(n->connection.incoming_id > 0);
891                 g_source_remove(n->connection.incoming_id); 
892                 n->connection.incoming_id = 0;
893                 if (n->connection.outgoing_id > 0)
894                         g_source_remove(n->connection.outgoing_id); 
895                 if (n->connection.data.tcp.ping_id > 0) {
896                         g_source_remove(n->connection.data.tcp.ping_id);
897                         n->connection.data.tcp.ping_id = 0;
898                 }
899                 n->connection.outgoing_id = 0;
900                 g_free(n->connection.data.tcp.local_name);
901                 g_free(n->connection.data.tcp.remote_name);
902                 n->connection.data.tcp.local_name = NULL;
903                 n->connection.data.tcp.remote_name = NULL;
904                 break;
905         case NETWORK_VIRTUAL:
906                 if (n->connection.data.virtual.ops && 
907                         n->connection.data.virtual.ops->fini) {
908                         n->connection.data.virtual.ops->fini(n);
909                 }
910                 break;
911                 default: g_assert(0);
912         }
913
914         n->connection.state = NETWORK_CONNECTION_STATE_NOT_CONNECTED;
915         redirect_clear(n);
916
917         return TRUE;
918 }
919
920 void clients_send_args_ex(GList *clients, const char *hostmask, ...)
921 {
922         struct line *l;
923         va_list ap;
924
925         va_start(ap, hostmask);
926         l = virc_parse_line(hostmask, ap);
927         va_end(ap);
928
929         clients_send(clients, l, NULL);
930
931         free_line(l); l = NULL;
932 }
933
934 /**
935  * Send a line to a list of clients.
936  *
937  * @param clients List of clients to send to
938  * @param l Line to send
939  * @param exception Client to which nothing should be sent. Can be NULL.
940  */
941 void clients_send(GList *clients, struct line *l, 
942                                   const struct client *exception) 
943 {
944         GList *g;
945
946         for (g = clients; g; g = g->next) {
947                 struct client *c = (struct client *)g->data;
948                 if (c != exception) {
949                         if (run_client_filter(c, l, FROM_SERVER)) { 
950                                 client_send_line(c, l);
951                         }
952                 }
953         }
954 }
955
956 static pid_t piped_child(char* const command[], int *f_in)
957 {
958         pid_t pid;
959         int sock[2];
960
961         if (socketpair(PF_UNIX, SOCK_STREAM, AF_LOCAL, sock) == -1) {
962                 log_global(LOG_ERROR, "socketpair: %s", strerror(errno));
963                 return -1;
964         }
965
966         *f_in = sock[0];
967
968         fcntl(sock[0], F_SETFL, O_NONBLOCK);
969
970         pid = fork();
971
972         if (pid == -1) {
973                 log_global(LOG_ERROR, "fork: %s", strerror(errno));
974                 return -1;
975         }
976
977         if (pid == 0) {
978                 close(0);
979                 close(1);
980                 close(2);
981                 close(sock[0]);
982
983                 dup2(sock[1], 0);
984                 dup2(sock[1], 1);
985                 execvp(command[0], command);
986                 exit(-1);
987         }
988
989         close(sock[1]);
990
991         return pid;
992 }
993
994 /**
995  * Change the IO channel used to communicate with a network.
996  * @param s Network to set the IO channel for.
997  * @param ioc IO channel to use
998  */
999 void network_set_iochannel(struct network *s, GIOChannel *ioc)
1000 {
1001         g_assert(s->config->type != NETWORK_VIRTUAL);
1002         g_io_channel_set_encoding(ioc, NULL, NULL);
1003         g_io_channel_set_close_on_unref(ioc, TRUE);
1004         g_io_channel_set_flags(ioc, G_IO_FLAG_NONBLOCK, NULL);
1005
1006         s->connection.outgoing = ioc;
1007         g_io_channel_set_close_on_unref(s->connection.outgoing, TRUE);
1008
1009         s->connection.incoming_id = g_io_add_watch(s->connection.outgoing, 
1010                                                                 G_IO_IN | G_IO_HUP | G_IO_ERR, 
1011                                                                 handle_server_receive, s);
1012         handle_server_receive(s->connection.outgoing, 
1013                                   g_io_channel_get_buffer_condition(s->connection.outgoing), 
1014                                   s);
1015
1016         server_send_login(s);
1017 }
1018
1019 static gboolean connect_program(struct network *s)
1020 {
1021         int sock;
1022         char *cmd[2];
1023         pid_t pid;
1024         
1025         g_assert(s);
1026         g_assert(s->config);
1027         g_assert(s->config->type == NETWORK_PROGRAM);
1028         
1029         cmd[0] = s->config->type_settings.program_location;
1030         cmd[1] = NULL;
1031         pid = piped_child(cmd, &sock);
1032
1033         if (pid == -1) return FALSE;
1034
1035         network_set_iochannel(s, g_io_channel_unix_new(sock));
1036
1037         g_io_channel_unref(s->connection.outgoing);
1038
1039
1040         if (s->info.name == NULL) {
1041                 if (strchr(s->config->type_settings.program_location, '/')) {
1042                         s->info.name = g_strdup(strrchr(s->config->type_settings.program_location, '/')+1);
1043                 } else {
1044                         s->info.name = g_strdup(s->config->type_settings.program_location);
1045                 }
1046         }
1047
1048         return TRUE;
1049 }
1050
1051 static gboolean connect_server(struct network *s)
1052 {
1053         g_assert(s);
1054         g_assert(s->config);
1055
1056         switch (s->config->type) {
1057         case NETWORK_TCP:
1058                 return connect_current_tcp_server(s);
1059
1060         case NETWORK_PROGRAM:
1061                 return connect_program(s);
1062
1063         case NETWORK_VIRTUAL:
1064                 s->connection.data.virtual.ops = g_hash_table_lookup(
1065                                                                 virtual_network_ops, 
1066                                                                 s->config->type_settings.virtual_type);
1067                 if (!s->connection.data.virtual.ops) 
1068                         return FALSE;
1069
1070                 s->state = network_state_init(s->config->nick, s->config->username, 
1071                                                                           get_my_hostname());
1072                 s->state->userdata = s;
1073                 s->state->log = state_log_helper;
1074                 s->linestack = new_linestack(s);
1075                 s->connection.state = NETWORK_CONNECTION_STATE_MOTD_RECVD;
1076
1077                 if (s->connection.data.virtual.ops->init)
1078                         return s->connection.data.virtual.ops->init(s);
1079
1080                 return TRUE;
1081         default: g_assert(0);
1082         }
1083
1084         return TRUE;
1085 }
1086
1087 static gboolean delayed_connect_server(struct network *s)
1088 {
1089         g_assert(s);
1090         connect_server(s);
1091         return (s->connection.state == NETWORK_CONNECTION_STATE_RECONNECT_PENDING);
1092 }
1093
1094 /**
1095  * Load a network from a configuration file specification.
1096  *
1097  * @param global Global context to use.
1098  * @param sc Network configuration to load form
1099  * @return A new network instance, already added to the global context.
1100  */
1101 struct network *load_network(struct global *global, struct network_config *sc)
1102 {
1103         struct network *s;
1104         GList *gl;
1105
1106         g_assert(sc);
1107
1108         if (global != NULL) {
1109                 /* Don't connect to the same network twice */
1110                 s = find_network(global, sc->name);
1111                 if (s) 
1112                         return s;
1113         }
1114
1115         s = g_new0(struct network, 1);
1116         s->config = sc;
1117         network_info_init(&s->info);
1118         s->info.name = g_strdup(s->config->name);
1119         s->connection.pending_lines = g_queue_new();
1120         s->global = global;
1121         s->info.forced_nick_changes = TRUE; /* Forced nick changes are done by ctrlproxy */
1122         s->connection.outgoing_iconv = s->connection.incoming_iconv = (GIConv)-1;
1123
1124         if (global != NULL) {
1125                 g_free(s->info.charset);
1126                 if (s->global->config->client_charset != NULL) {
1127                         s->info.charset = g_strdup(s->global->config->client_charset);
1128                 }
1129
1130                 global->networks = g_list_append(global->networks, s);
1131
1132                 for (gl = global->new_network_notifiers; gl; gl = gl->next) {
1133                         struct new_network_notify_data *p = gl->data;
1134
1135                         p->fn(s, p->data);
1136                 }
1137         }
1138
1139 #ifdef HAVE_GNUTLS
1140         s->ssl_credentials = ssl_get_client_credentials(NULL);
1141 #endif
1142
1143         return s;
1144 }
1145
1146 /**
1147  * Connect to a network, returns TRUE if connection was successful 
1148  * (or startup of connection was successful) 
1149  *
1150  * @param s Network to connect to
1151  */
1152 gboolean connect_network(struct network *s) 
1153 {
1154         g_assert(s);
1155         g_assert(s->connection.state == NETWORK_CONNECTION_STATE_NOT_CONNECTED ||
1156                          s->connection.state == NETWORK_CONNECTION_STATE_RECONNECT_PENDING);
1157
1158         return connect_server(s);
1159 }
1160
1161 static void free_pending_line(void *_line, void *userdata)
1162 {
1163         free_line((struct line *)_line);
1164 }
1165
1166 /** 
1167  * Unload a network from a global context.
1168  *
1169  * @param s Network to unload.
1170  */
1171 void unload_network(struct network *s)
1172 {
1173         GList *l;
1174         
1175         g_assert(s);
1176         if (s->connection.state == NETWORK_CONNECTION_STATE_MOTD_RECVD) {
1177                 log_network(LOG_INFO, s, "Closing connection");
1178         }
1179
1180         l = s->clients;
1181
1182         while(l) {
1183                 struct client *c = l->data;
1184                 l = l->next;
1185                 disconnect_client(c, "Server exiting");
1186         }
1187
1188         if (s->global != NULL) {
1189                 s->global->networks = g_list_remove(s->global->networks, s);
1190         }
1191
1192         g_queue_foreach(s->connection.pending_lines, free_pending_line, NULL);
1193         g_queue_free(s->connection.pending_lines);
1194
1195         free_network_info(&s->info);
1196
1197 #ifdef HAVE_GNUTLS
1198         ssl_free_client_credentials(s->ssl_credentials);
1199 #endif
1200
1201         g_iconv_close(s->connection.incoming_iconv);
1202         g_iconv_close(s->connection.outgoing_iconv);
1203
1204         g_free(s);
1205 }
1206
1207 /** 
1208  * Disconnect from a network. The network will still be kept in memory, 
1209  * but all socket connections associated with it will be dropped.
1210  *
1211  * @param s Network to disconnect from
1212  * @return Whether disconnecting succeeded.
1213  */
1214 gboolean disconnect_network(struct network *s)
1215 {
1216         g_assert(s);
1217         if (s->connection.state == NETWORK_CONNECTION_STATE_NOT_CONNECTED) {
1218                 return FALSE;
1219         }
1220         log_network(LOG_INFO, s, "Disconnecting");
1221         return close_server(s);
1222 }
1223
1224 /**
1225  * Check whether a client is still associated with a network.
1226  *
1227  * The client pointer does not have to point to a valid piece of memory.
1228  *
1229  * @param s Network the client should be associated with.
1230  * @param c The client.
1231  * @return Whether the client is still associated with the network.
1232  */
1233 gboolean verify_client(const struct network *s, const struct client *c)
1234 {
1235         GList *gl;
1236
1237         g_assert(s);
1238         g_assert(c);
1239         
1240         for (gl = s->clients; gl; gl = gl->next) {
1241                 struct client *nc = (struct client *)gl->data;
1242                 if (c == nc) return 1;
1243         }
1244
1245         return 0;
1246 }
1247
1248 /**
1249  * Register a new virtual network type.
1250  *
1251  * @param ops Callback functions for the virtual network type.
1252  */
1253 void register_virtual_network(struct virtual_network_ops *ops)
1254 {
1255         if (virtual_network_ops == NULL)
1256                 virtual_network_ops = g_hash_table_new(g_str_hash, g_str_equal);
1257         g_assert(ops);
1258         g_hash_table_insert(virtual_network_ops, ops->name, ops);
1259 }
1260
1261 /**
1262  * Autoconnect to all the networks in a global context.
1263  *
1264  * @param Global global context
1265  * @return TRUE
1266  */
1267 gboolean autoconnect_networks(struct global *global)
1268 {
1269         GList *gl;
1270         for (gl = global->networks; gl; gl = gl->next)
1271         {
1272                 struct network *n = gl->data;
1273                 g_assert(n);
1274                 g_assert(n->config);
1275                 if (n->config->autoconnect)
1276                         connect_network(n);
1277         }
1278
1279         return TRUE;
1280 }
1281
1282 /**
1283  * Load all the networks in a configuration file.
1284  *
1285  * @param global Global context to load networks into.
1286  * @param cfg Configuration to read from
1287  * @return TRUE
1288  */
1289 gboolean load_networks(struct global *global, struct ctrlproxy_config *cfg)
1290 {
1291         GList *gl;
1292         g_assert(cfg);
1293         for (gl = cfg->networks; gl; gl = gl->next)
1294         {
1295                 struct network_config *nc = gl->data;
1296                 load_network(global, nc);
1297         }
1298
1299         return TRUE;
1300 }
1301
1302 /**
1303  * Find a network by name.
1304  *
1305  * @param global Global context to search in.
1306  * @param name Name of the network to search for.
1307  * @return first network found or NULL
1308  */
1309 struct network *find_network(struct global *global, const char *name)
1310 {
1311         GList *gl;
1312         for (gl = global->networks; gl; gl = gl->next) {
1313                 struct network *n = gl->data;
1314                 if (n->info.name && !g_strcasecmp(n->info.name, name)) 
1315                         return n;
1316         }
1317
1318         return NULL;
1319 }
1320
1321 /**
1322  * Find a network by host name and port or name.
1323  * 
1324  * @param global Context to search in
1325  * @param hostname Hostname to search for
1326  * @param port Port to search from.
1327  * @param create Whether to create the network if it wasn't found.
1328  * @return the network found or created or NULL
1329  */
1330 struct network *find_network_by_hostname(struct global *global, 
1331                                                                                  const char *hostname, guint16 port, 
1332                                                                                  gboolean create)
1333 {
1334         GList *gl;
1335         char *portname = g_strdup_printf("%d", port);
1336         g_assert(portname != NULL);
1337         g_assert(hostname != NULL);
1338         
1339         for (gl = global->networks; gl; gl = gl->next) {
1340                 GList *sv;
1341                 struct network *n = gl->data;
1342                 g_assert(n);
1343
1344                 if (n->info.name && !g_strcasecmp(n->info.name, hostname)) {
1345                         g_free(portname);
1346                         return n;
1347                 }
1348
1349                 g_assert(n->config);
1350                 if (n->config->type == NETWORK_TCP) 
1351                 {
1352                         for (sv = n->config->type_settings.tcp_servers; sv; sv = sv->next)
1353                         {
1354                                 struct tcp_server_config *server = sv->data;
1355
1356                                 if (!g_strcasecmp(server->host, hostname) && 
1357                                         !g_strcasecmp(server->port, portname)) {
1358                                         g_free(portname);
1359                                         return n;
1360                                 }
1361                         } 
1362                 }
1363
1364                 if (n->info.name && !g_strcasecmp(n->info.name, hostname)) {
1365                         g_free(portname);
1366                         return n;
1367                 }
1368         }
1369
1370         /* Create a new server */
1371         if (create)
1372         {
1373                 struct tcp_server_config *s = g_new0(struct tcp_server_config, 1);
1374                 struct network_config *nc;
1375                 nc = network_config_init(global->config);
1376
1377                 nc->name = g_strdup(hostname);
1378                 nc->type = NETWORK_TCP;
1379                 s->host = g_strdup(hostname);
1380                 s->port = portname;
1381
1382                 nc->type_settings.tcp_servers = g_list_append(nc->type_settings.tcp_servers, s);
1383
1384                 return load_network(global, nc);
1385         }
1386
1387         g_free(portname);
1388
1389         return NULL;
1390 }
1391
1392 /**
1393  * Disconnect from and unload all networks.
1394  *
1395  * @param global Global context
1396  */
1397 void fini_networks(struct global *global)
1398 {
1399         GList *gl;
1400         while((gl = global->networks)) {
1401                 struct network *n = (struct network *)gl->data;
1402                 disconnect_network(n);
1403                 unload_network(n);
1404         }
1405
1406         if (virtual_network_ops != NULL)
1407                 g_hash_table_destroy(virtual_network_ops);
1408         virtual_network_ops = NULL;
1409 }
1410
1411 /**
1412  * Switch to the next server listed for a network.
1413  *
1414  * @param n Network
1415  */
1416 void network_select_next_server(struct network *n)
1417 {
1418         g_assert(n);
1419         g_assert(n->config);
1420
1421         if (n->config->type != NETWORK_TCP) 
1422                 return;
1423
1424         log_network(LOG_INFO, n, "Trying next server");
1425         n->connection.data.tcp.current_server = network_get_next_tcp_server(n);
1426 }
1427
1428 /**
1429  * Generate 005-response string to send to client connected to a network.
1430  *
1431  * @param n Network to generate for
1432  * @return An 005 string, newly allocated
1433  */
1434 char *network_generate_feature_string(struct network *n)
1435 {
1436         g_assert(n);
1437
1438         return network_info_string(&n->info);
1439 }
1440
1441