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