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