2 * Copyright (C) 1998 Peter Zelezny.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 * MS Proxy (ISA server) support is (c) 2006 Pavel Fedin <sonic_amiga@rambler.ru>
19 * based on Dante source code
20 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
21 * Inferno Nettverk A/S, Norway. All rights reserved.
24 /*#define DEBUG_MSPROXY*/
51 #include "proto-irc.h"
56 #include <openssl/ssl.h> /* SSL_() */
57 #include <openssl/err.h> /* ERR_() */
71 static struct session
*g_sess
= NULL
;
74 static GSList
*away_list
= NULL
;
75 GSList
*serv_list
= NULL
;
77 static void auto_reconnect (server
*serv
, int send_quit
, int err
);
78 static void server_disconnect (session
* sess
, int sendquit
, int err
);
79 static int server_cleanup (server
* serv
);
80 static void server_connect (server
*serv
, char *hostname
, int port
, int no_login
);
83 extern pxProxyFactory
*libproxy_factory
;
86 /* actually send to the socket. This might do a character translation or
87 send via SSL. server/dcc both use this function. */
90 tcp_send_real (void *ssl
, int sok
, char *encoding
, int using_irc
, char *buf
, int len
)
96 if (encoding
== NULL
) /* system */
99 if (!prefs
.utf8_locale
)
101 const gchar
*charset
;
103 g_get_charset (&charset
);
104 locale
= g_convert_with_fallback (buf
, len
, charset
, "UTF-8",
105 "?", 0, &loc_len
, 0);
109 if (using_irc
) /* using "IRC" encoding (CP1252/UTF-8 hybrid) */
110 /* if all chars fit inside CP1252, use that. Otherwise this
111 returns NULL and we send UTF-8. */
112 locale
= g_convert (buf
, len
, "CP1252", "UTF-8", 0, &loc_len
, 0);
114 locale
= g_convert_with_fallback (buf
, len
, encoding
, "UTF-8",
115 "?", 0, &loc_len
, 0);
123 ret
= send (sok
, locale
, len
, 0);
125 ret
= _SSL_send (ssl
, locale
, len
);
127 ret
= send (sok
, locale
, len
, 0);
134 ret
= send (sok
, buf
, len
, 0);
136 ret
= _SSL_send (ssl
, buf
, len
);
138 ret
= send (sok
, buf
, len
, 0);
146 server_send_real (server
*serv
, char *buf
, int len
)
148 fe_add_rawlog (serv
, buf
, len
, TRUE
);
150 return tcp_send_real (serv
->ssl
, serv
->sok
, serv
->encoding
, serv
->using_irc
,
154 /* new throttling system, uses the same method as the Undernet
155 ircu2.10 server; under test, a 200-line paste didn't flood
159 tcp_send_queue (server
*serv
)
164 time_t now
= time (0);
166 /* did the server close since the timeout was added? */
167 if (!is_server (serv
))
170 /* try priority 2,1,0 */
174 list
= serv
->outbound_queue
;
177 buf
= (char *) list
->data
;
180 buf
++; /* skip the priority byte */
183 if (serv
->next_send
< now
)
184 serv
->next_send
= now
;
185 if (serv
->next_send
- now
>= 10)
187 /* check for clock skew */
188 if (now
>= serv
->prev_now
)
189 return 1; /* don't remove the timeout handler */
190 /* it is skewed, reset to something sane */
191 serv
->next_send
= now
;
194 for (p
= buf
, i
= len
; i
&& *p
!= ' '; p
++, i
--);
195 serv
->next_send
+= (2 + i
/ 120);
196 serv
->sendq_len
-= len
;
197 serv
->prev_now
= now
;
198 fe_set_throttle (serv
);
200 server_send_real (serv
, buf
, len
);
203 serv
->outbound_queue
= g_slist_remove (serv
->outbound_queue
, buf
);
205 list
= serv
->outbound_queue
;
214 return 0; /* remove the timeout handler */
218 tcp_send_len (server
*serv
, char *buf
, int len
)
221 int noqueue
= !serv
->outbound_queue
;
224 return server_send_real (serv
, buf
, len
);
226 dbuf
= malloc (len
+ 2); /* first byte is the priority */
227 dbuf
[0] = 2; /* pri 2 for most things */
228 memcpy (dbuf
+ 1, buf
, len
);
231 /* privmsg and notice get a lower priority */
232 if (strncasecmp (dbuf
+ 1, "PRIVMSG", 7) == 0 ||
233 strncasecmp (dbuf
+ 1, "NOTICE", 6) == 0)
239 /* WHO/MODE get the lowest priority */
240 if (strncasecmp (dbuf
+ 1, "WHO ", 4) == 0 ||
241 /* but only MODE queries, not changes */
242 (strncasecmp (dbuf
+ 1, "MODE", 4) == 0 &&
243 strchr (dbuf
, '-') == NULL
&&
244 strchr (dbuf
, '+') == NULL
))
248 serv
->outbound_queue
= g_slist_append (serv
->outbound_queue
, dbuf
);
249 serv
->sendq_len
+= len
; /* tcp_send_queue uses strlen */
251 if (tcp_send_queue (serv
) && noqueue
)
252 fe_timeout_add (500, tcp_send_queue
, serv
);
258 tcp_send (server *serv, char *buf)
260 return tcp_send_len (serv, buf, strlen (buf));
264 tcp_sendf (server
*serv
, char *fmt
, ...)
267 /* keep this buffer in BSS. Converting UTF-8 to ISO-8859-x might make the
268 string shorter, so allow alot more than 512 for now. */
269 static char send_buf
[1540]; /* good code hey (no it's not overflowable) */
272 va_start (args
, fmt
);
273 len
= vsnprintf (send_buf
, sizeof (send_buf
) - 1, fmt
, args
);
276 send_buf
[sizeof (send_buf
) - 1] = '\0';
277 if (len
< 0 || len
> (sizeof (send_buf
) - 1))
278 len
= strlen (send_buf
);
280 tcp_send_len (serv
, send_buf
, len
);
284 close_socket_cb (gpointer sok
)
286 closesocket (GPOINTER_TO_INT (sok
));
291 close_socket (int sok
)
293 /* close the socket in 5 seconds so the QUIT message is not lost */
294 fe_timeout_add (5000, close_socket_cb
, GINT_TO_POINTER (sok
));
297 /* handle 1 line of text received from the server */
300 server_inline (server
*serv
, char *line
, int len
)
302 char *utf_line_allocated
= NULL
;
304 /* Checks whether we're set to use UTF-8 charset */
305 if (serv
->using_irc
|| /* 1. using CP1252/UTF-8 Hybrid */
306 (serv
->encoding
== NULL
&& prefs
.utf8_locale
) || /* OR 2. using system default->UTF-8 */
307 (serv
->encoding
!= NULL
&& /* OR 3. explicitly set to UTF-8 */
308 (strcasecmp (serv
->encoding
, "UTF8") == 0 ||
309 strcasecmp (serv
->encoding
, "UTF-8") == 0)))
311 /* The user has the UTF-8 charset set, either via /charset
312 command or from his UTF-8 locale. Thus, we first try the
313 UTF-8 charset, and if we fail to convert, we assume
314 it to be ISO-8859-1 (see text_validate). */
316 utf_line_allocated
= text_validate (&line
, &len
);
320 /* Since the user has an explicit charset set, either
321 via /charset command or from his non-UTF8 locale,
322 we don't fallback to ISO-8859-1 and instead try to remove
323 errnoeous octets till the string is convertable in the
326 const char *encoding
= NULL
;
328 if (serv
->encoding
!= NULL
)
329 encoding
= serv
->encoding
;
331 g_get_charset (&encoding
);
333 if (encoding
!= NULL
)
335 char *conv_line
; /* holds a copy of the original string */
336 int conv_len
; /* tells g_convert how much of line to convert */
342 conv_line
= g_malloc (len
+ 1);
343 memcpy (conv_line
, line
, len
);
347 /* if CP1255, convert it with the NUL terminator.
348 Works around SF bug #1122089 */
349 if (serv
->using_cp1255
)
356 utf_line_allocated
= g_convert_with_fallback (conv_line
, conv_len
, "UTF-8", encoding
, "?", &read_len
, &utf_len
, &err
);
359 if (err
->code
== G_CONVERT_ERROR_ILLEGAL_SEQUENCE
&& conv_len
> (read_len
+ 1))
361 /* Make our best bet by removing the erroneous char.
362 This will work for casual 8-bit strings with non-standard chars. */
363 memmove (conv_line
+ read_len
, conv_line
+ read_len
+ 1, conv_len
- read_len
-1);
373 /* If any conversion has occured at all. Conversion might fail
374 due to errors other than invalid sequences, e.g. unknown charset. */
375 if (utf_line_allocated
!= NULL
)
377 line
= utf_line_allocated
;
379 if (serv
->using_cp1255
&& len
> 0)
384 /* If all fails, treat as UTF-8 with fallback to ISO-8859-1. */
385 utf_line_allocated
= text_validate (&line
, &len
);
390 fe_add_rawlog (serv
, line
, len
, FALSE
);
392 /* let proto-irc.c handle it */
393 serv
->p_inline (serv
, line
, len
);
395 if (utf_line_allocated
!= NULL
) /* only if a special copy was allocated */
396 g_free (utf_line_allocated
);
399 /* read data from socket */
402 server_read (GIOChannel
*source
, GIOCondition condition
, server
*serv
)
413 len
= recv (sok
, lbuf
, sizeof (lbuf
) - 2, 0);
416 len
= _SSL_recv (serv
->ssl
, lbuf
, sizeof (lbuf
) - 2);
425 error
= sock_error ();
427 if (!serv
->end_of_motd
)
429 server_disconnect (serv
->server_session
, FALSE
, error
);
430 if (!servlist_cycle (serv
))
432 if (prefs
.autoreconnect
)
433 auto_reconnect (serv
, FALSE
, error
);
437 if (prefs
.autoreconnect
)
438 auto_reconnect (serv
, FALSE
, error
);
440 server_disconnect (serv
->server_session
, FALSE
, error
);
457 serv
->linebuf
[serv
->pos
] = 0;
458 server_inline (serv
, serv
->linebuf
, serv
->pos
);
463 serv
->linebuf
[serv
->pos
] = lbuf
[i
];
464 if (serv
->pos
>= (sizeof (serv
->linebuf
) - 1))
466 "*** XCHAT WARNING: Buffer overflow - shit server!\n");
476 server_connected (server
* serv
)
478 prefs
.wait_on_exit
= TRUE
;
479 serv
->ping_recv
= time (0);
480 serv
->connected
= TRUE
;
481 set_nonblocking (serv
->sok
);
482 serv
->iotag
= fe_input_add (serv
->sok
, FIA_READ
|FIA_EX
, server_read
, serv
);
485 EMIT_SIGNAL (XP_TE_CONNECTED
, serv
->server_session
, NULL
, NULL
, NULL
,
490 (!(((ircnet
*)serv
->network
)->flags
& FLAG_USE_GLOBAL
) &&
491 (((ircnet
*)serv
->network
)->user
)) ?
492 (((ircnet
*)serv
->network
)->user
) :
494 (!(((ircnet
*)serv
->network
)->flags
& FLAG_USE_GLOBAL
) &&
495 (((ircnet
*)serv
->network
)->real
)) ?
496 (((ircnet
*)serv
->network
)->real
) :
500 serv
->p_login (serv
, prefs
.username
, prefs
.realname
);
504 EMIT_SIGNAL (XP_TE_SERVERCONNECTED
, serv
->server_session
, NULL
, NULL
,
508 server_set_name (serv
, serv
->servername
);
509 fe_server_event (serv
, FE_SE_CONNECT
, 0);
514 server_stopconnecting (server
* serv
)
518 fe_input_remove (serv
->iotag
);
522 if (serv
->joindelay_tag
)
524 fe_timeout_remove (serv
->joindelay_tag
);
525 serv
->joindelay_tag
= 0;
528 /* kill the child process trying to connect */
529 kill (serv
->childpid
, SIGKILL
);
530 waitpid (serv
->childpid
, NULL
, 0);
532 close (serv
->childwrite
);
533 close (serv
->childread
);
536 if (serv
->ssl_do_connect_tag
)
538 fe_timeout_remove (serv
->ssl_do_connect_tag
);
539 serv
->ssl_do_connect_tag
= 0;
543 fe_progressbar_end (serv
);
545 serv
->connecting
= FALSE
;
546 fe_server_event (serv
, FE_SE_DISCONNECT
, 0);
550 #define SSLTMOUT 90 /* seconds */
552 ssl_cb_info (SSL
* s
, int where
, int ret
)
557 return; /* FIXME: make debug level adjustable in serverlist or settings */
559 /* snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
561 EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
563 fprintf (stderr, "%s\n", buf);*/
567 ssl_cb_verify (int ok
, X509_STORE_CTX
* ctx
)
574 X509_NAME_oneline (X509_get_subject_name (ctx
->current_cert
), subject
,
576 X509_NAME_oneline (X509_get_issuer_name (ctx
->current_cert
), issuer
,
579 snprintf (buf
, sizeof (buf
), "* Subject: %s", subject
);
580 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, g_sess
, buf
, NULL
, NULL
, NULL
, 0);
581 snprintf (buf
, sizeof (buf
), "* Issuer: %s", issuer
);
582 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, g_sess
, buf
, NULL
, NULL
, NULL
, 0);
584 return (TRUE
); /* always ok */
588 ssl_do_connect (server
* serv
)
592 g_sess
= serv
->server_session
;
593 if (SSL_connect (serv
->ssl
) <= 0)
599 if ((err
= ERR_get_error ()) > 0)
601 ERR_error_string (err
, err_buf
);
602 snprintf (buf
, sizeof (buf
), "(%d) %s", err
, err_buf
);
603 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
,
606 if (ERR_GET_REASON (err
) == SSL_R_WRONG_VERSION_NUMBER
)
607 PrintText (serv
->server_session
, _("Are you sure this is a SSL capable server and port?\n"));
609 server_cleanup (serv
);
611 if (prefs
.autoreconnect
) {
612 auto_reconnect (serv
, FALSE
, -1);
616 return (0); /* remove it (0) */
621 if (SSL_is_init_finished (serv
->ssl
))
623 struct cert_info cert_info
;
624 struct chiper_info
*chiper_info
;
628 if (!_SSL_get_cert_info (&cert_info
, serv
->ssl
))
630 snprintf (buf
, sizeof (buf
), "* Certification info:");
631 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
633 snprintf (buf
, sizeof (buf
), " Subject:");
634 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
636 for (i
= 0; cert_info
.subject_word
[i
]; i
++)
638 snprintf (buf
, sizeof (buf
), " %s", cert_info
.subject_word
[i
]);
639 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
642 snprintf (buf
, sizeof (buf
), " Issuer:");
643 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
645 for (i
= 0; cert_info
.issuer_word
[i
]; i
++)
647 snprintf (buf
, sizeof (buf
), " %s", cert_info
.issuer_word
[i
]);
648 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
651 snprintf (buf
, sizeof (buf
), " Public key algorithm: %s (%d bits)",
652 cert_info
.algorithm
, cert_info
.algorithm_bits
);
653 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
655 /*if (cert_info.rsa_tmp_bits)
657 snprintf (buf, sizeof (buf),
658 " Public key algorithm uses ephemeral key with %d bits",
659 cert_info.rsa_tmp_bits);
660 EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
663 snprintf (buf
, sizeof (buf
), " Sign algorithm %s",
664 cert_info
.sign_algorithm
/*, cert_info.sign_algorithm_bits*/);
665 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
667 snprintf (buf
, sizeof (buf
), " Valid since %s to %s",
668 cert_info
.notbefore
, cert_info
.notafter
);
669 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
673 snprintf (buf
, sizeof (buf
), " * No Certificate");
674 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
678 chiper_info
= _SSL_get_cipher_info (serv
->ssl
); /* static buffer */
679 snprintf (buf
, sizeof (buf
), "* Cipher info:");
680 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
, NULL
,
682 snprintf (buf
, sizeof (buf
), " Version: %s, cipher %s (%u bits)",
683 chiper_info
->version
, chiper_info
->chiper
,
684 chiper_info
->chiper_bits
);
685 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
, NULL
,
688 verify_error
= SSL_get_verify_result (serv
->ssl
);
689 switch (verify_error
)
692 /* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
693 /* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
695 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
:
696 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
:
697 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
:
698 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
:
699 case X509_V_ERR_CERT_HAS_EXPIRED
:
700 case X509_V_ERR_CERT_UNTRUSTED
:
701 if (serv
->accept_invalid_cert
)
703 snprintf (buf
, sizeof (buf
), "* Verify E: %s.? (%d) -- Ignored",
704 X509_verify_cert_error_string (verify_error
),
706 EMIT_SIGNAL (XP_TE_SSLMESSAGE
, serv
->server_session
, buf
, NULL
, NULL
,
711 snprintf (buf
, sizeof (buf
), "%s.? (%d)",
712 X509_verify_cert_error_string (verify_error
),
714 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
, NULL
,
717 server_cleanup (serv
);
722 server_stopconnecting (serv
);
724 /* activate gtk poll */
725 server_connected (serv
);
727 return (0); /* remove it (0) */
730 if (serv
->ssl
->session
&& serv
->ssl
->session
->time
+ SSLTMOUT
< time (NULL
))
732 snprintf (buf
, sizeof (buf
), "SSL handshake timed out");
733 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, buf
, NULL
,
735 server_cleanup (serv
); /* ->connecting = FALSE */
737 if (prefs
.autoreconnect
) {
738 auto_reconnect (serv
, FALSE
, -1);
742 return (0); /* remove it (0) */
745 return (1); /* call it more (1) */
751 timeout_auto_reconnect (server
*serv
)
753 if (is_server (serv
)) /* make sure it hasnt been closed during the delay */
755 serv
->recondelay_tag
= 0;
756 if (!serv
->connected
&& !serv
->connecting
&& serv
->server_session
)
758 server_connect (serv
, serv
->hostname
, serv
->port
, FALSE
);
761 return 0; /* returning 0 should remove the timeout handler */
765 auto_reconnect (server
*serv
, int send_quit
, int err
)
771 if (serv
->server_session
== NULL
)
775 while (list
) /* make sure auto rejoin can work */
778 if (s
->type
== SESS_CHANNEL
&& s
->channel
[0])
780 strcpy (s
->waitchannel
, s
->channel
);
781 strcpy (s
->willjoinchannel
, s
->channel
);
787 server_disconnect (serv
->server_session
, send_quit
, err
);
789 del
= prefs
.recon_delay
* 1000;
791 del
= 500; /* so it doesn't block the gui */
793 if (err
== -1 || err
== 0 || err
== ECONNRESET
|| err
== ETIMEDOUT
)
794 serv
->reconnect_away
= serv
->is_away
;
796 /* is this server in a reconnect delay? remove it! */
797 if (serv
->recondelay_tag
)
799 fe_timeout_remove (serv
->recondelay_tag
);
800 serv
->recondelay_tag
= 0;
803 serv
->recondelay_tag
= fe_timeout_add (del
, timeout_auto_reconnect
, serv
);
804 fe_server_event (serv
, FE_SE_RECONDELAY
, del
);
808 server_flush_queue (server
*serv
)
810 list_free (&serv
->outbound_queue
);
812 fe_set_throttle (serv
);
815 #define waitline2(source,buf,size) waitline(serv->childread,buf,size,0)
817 /* connect() successed */
820 server_connect_success (server
*serv
)
823 #define SSLDOCONNTMOUT 300
828 /* it'll be a memory leak, if connection isn't terminated by
830 serv
->ssl
= _SSL_socket (serv
->ctx
, serv
->sok
);
831 if ((err
= _SSL_set_verify (serv
->ctx
, ssl_cb_verify
, NULL
)))
833 EMIT_SIGNAL (XP_TE_CONNFAIL
, serv
->server_session
, err
, NULL
,
835 server_cleanup (serv
); /* ->connecting = FALSE */
838 /* FIXME: it'll be needed by new servers */
839 /* send(serv->sok, "STLS\r\n", 6, 0); sleep(1); */
840 set_nonblocking (serv
->sok
);
841 serv
->ssl_do_connect_tag
= fe_timeout_add (SSLDOCONNTMOUT
,
842 ssl_do_connect
, serv
);
848 server_stopconnecting (serv
); /* ->connecting = FALSE */
849 /* activate glib poll */
850 server_connected (serv
);
853 /* receive info from the child-process about connection progress */
856 server_read_child (GIOChannel
*source
, GIOCondition condition
, server
*serv
)
858 session
*sess
= serv
->server_session
;
865 waitline2 (source
, tbuf
, sizeof tbuf
);
869 case '0': /* print some text */
870 waitline2 (source
, tbuf
, sizeof tbuf
);
871 PrintText (serv
->server_session
, tbuf
);
873 case '1': /* unknown host */
874 server_stopconnecting (serv
);
875 closesocket (serv
->sok4
);
876 if (serv
->proxy_sok4
!= -1)
877 closesocket (serv
->proxy_sok4
);
879 if (serv
->sok6
!= -1)
880 closesocket (serv
->sok6
);
881 if (serv
->proxy_sok6
!= -1)
882 closesocket (serv
->proxy_sok6
);
884 EMIT_SIGNAL (XP_TE_UKNHOST
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
885 if (!servlist_cycle (serv
))
886 if (prefs
.autoreconnect
)
887 auto_reconnect (serv
, FALSE
, -1);
889 case '2': /* connection failed */
890 waitline2 (source
, tbuf
, sizeof tbuf
);
891 server_stopconnecting (serv
);
892 closesocket (serv
->sok4
);
893 if (serv
->proxy_sok4
!= -1)
894 closesocket (serv
->proxy_sok4
);
896 if (serv
->sok6
!= -1)
897 closesocket (serv
->sok6
);
898 if (serv
->proxy_sok6
!= -1)
899 closesocket (serv
->proxy_sok6
);
901 EMIT_SIGNAL (XP_TE_CONNFAIL
, sess
, errorstring (atoi (tbuf
)), NULL
,
903 if (!servlist_cycle (serv
))
904 if (prefs
.autoreconnect
)
905 auto_reconnect (serv
, FALSE
, -1);
907 case '3': /* gethostbyname finished */
908 waitline2 (source
, host
, sizeof host
);
909 waitline2 (source
, ip
, sizeof ip
);
910 waitline2 (source
, outbuf
, sizeof outbuf
);
911 EMIT_SIGNAL (XP_TE_CONNECT
, sess
, host
, ip
, outbuf
, NULL
, 0);
912 snprintf (outbuf
, sizeof (outbuf
), "%s/auth/xchat_auth",
914 if (access (outbuf
, X_OK
) == 0)
916 snprintf (outbuf
, sizeof (outbuf
), "exec -d %s/auth/xchat_auth %s",
917 g_get_home_dir (), prefs
.username
);
918 handle_command (serv
->server_session
, outbuf
, FALSE
);
921 case '4': /* success */
922 waitline2 (source
, tbuf
, sizeof (tbuf
));
924 serv
->sok
= strtol (tbuf
, &p
, 10);
927 serv
->proxy_sok
= strtol (p
, &p
, 10);
928 serv
->msp_state
.clientid
= strtol (++p
, &p
, 10);
929 serv
->msp_state
.serverid
= strtol (++p
, &p
, 10);
930 serv
->msp_state
.seq_sent
= atoi (++p
);
932 serv
->proxy_sok
= -1;
934 printf ("Parent got main socket: %d, proxy socket: %d\n", serv
->sok
, serv
->proxy_sok
);
935 printf ("Client ID 0x%08x server ID 0x%08x seq_sent %d\n", serv
->msp_state
.clientid
, serv
->msp_state
.serverid
, serv
->msp_state
.seq_sent
);
938 serv
->sok
= atoi (tbuf
);
941 /* close the one we didn't end up using */
942 if (serv
->sok
== serv
->sok4
)
943 closesocket (serv
->sok6
);
945 closesocket (serv
->sok4
);
946 if (serv
->proxy_sok
!= -1)
948 if (serv
->proxy_sok
== serv
->proxy_sok4
)
949 closesocket (serv
->proxy_sok6
);
951 closesocket (serv
->proxy_sok4
);
954 server_connect_success (serv
);
956 case '5': /* prefs ip discovered */
957 waitline2 (source
, tbuf
, sizeof tbuf
);
958 prefs
.local_ip
= inet_addr (tbuf
);
960 case '7': /* gethostbyname (prefs.hostname) failed */
962 _("Cannot resolve hostname %s\nCheck your IP Settings!\n"),
964 PrintText (sess
, outbuf
);
967 PrintText (sess
, _("Proxy traversal failed.\n"));
968 server_disconnect (sess
, FALSE
, -1);
969 if (prefs
.autoreconnect
)
970 auto_reconnect (serv
, FALSE
, -1);
973 waitline2 (source
, tbuf
, sizeof tbuf
);
974 EMIT_SIGNAL (XP_TE_SERVERLOOKUP
, sess
, tbuf
, NULL
, NULL
, NULL
, 0);
981 /* kill all sockets & iotags of a server. Stop a connection attempt, or
982 disconnect if already connected. */
985 server_cleanup (server
* serv
)
987 fe_set_lag (serv
, 0.0);
991 fe_input_remove (serv
->iotag
);
995 if (serv
->joindelay_tag
)
997 fe_timeout_remove (serv
->joindelay_tag
);
998 serv
->joindelay_tag
= 0;
1004 SSL_shutdown (serv
->ssl
);
1005 SSL_free (serv
->ssl
);
1010 if (serv
->connecting
)
1012 server_stopconnecting (serv
);
1013 closesocket (serv
->sok4
);
1014 if (serv
->proxy_sok4
!= -1)
1015 closesocket (serv
->proxy_sok4
);
1016 if (serv
->sok6
!= -1)
1017 closesocket (serv
->sok6
);
1018 if (serv
->proxy_sok6
!= -1)
1019 closesocket (serv
->proxy_sok6
);
1023 if (serv
->connected
)
1025 close_socket (serv
->sok
);
1026 if (serv
->proxy_sok
)
1027 close_socket (serv
->proxy_sok
);
1028 serv
->connected
= FALSE
;
1029 serv
->end_of_motd
= FALSE
;
1033 /* is this server in a reconnect delay? remove it! */
1034 if (serv
->recondelay_tag
)
1036 fe_timeout_remove (serv
->recondelay_tag
);
1037 serv
->recondelay_tag
= 0;
1045 server_disconnect (session
* sess
, int sendquit
, int err
)
1047 server
*serv
= sess
->server
;
1050 gboolean shutup
= FALSE
;
1052 /* send our QUIT reason */
1053 if (sendquit
&& serv
->connected
)
1055 server_sendquit (sess
);
1058 fe_server_event (serv
, FE_SE_DISCONNECT
, 0);
1060 /* close all sockets & io tags */
1061 switch (server_cleanup (serv
))
1063 case 0: /* it wasn't even connected! */
1066 case 1: /* it was in the process of connecting */
1067 sprintf (tbuf
, "%d", sess
->server
->childpid
);
1068 EMIT_SIGNAL (XP_TE_STOPCONNECT
, sess
, tbuf
, NULL
, NULL
, NULL
, 0);
1071 shutup
= TRUE
; /* won't print "disconnected" in channels */
1074 server_flush_queue (serv
);
1079 sess
= (struct session
*) list
->data
;
1080 if (sess
->server
== serv
)
1082 if (!shutup
|| sess
->type
== SESS_SERVER
)
1083 /* print "Disconnected" to each window using this server */
1084 EMIT_SIGNAL (XP_TE_DISCON
, sess
, errorstring (err
), NULL
, NULL
, NULL
, 0);
1086 if (!sess
->channel
[0] || sess
->type
== SESS_CHANNEL
)
1087 clear_channel (sess
);
1093 serv
->motd_skipped
= FALSE
;
1094 serv
->no_login
= FALSE
;
1095 serv
->servername
[0] = 0;
1101 /* send a "print text" command to the parent process - MUST END IN \n! */
1104 proxy_error (int fd
, char *msg
)
1106 write (fd
, "0\n", 2);
1107 write (fd
, msg
, strlen (msg
));
1119 /* traverse_socks() returns:
1121 * 1 socks traversal failed */
1124 traverse_socks (int print_fd
, int sok
, char *serverAddr
, int port
)
1126 struct sock_connect sc
;
1127 unsigned char buf
[256];
1131 sc
.port
= htons (port
);
1132 sc
.address
= inet_addr (serverAddr
);
1133 strncpy (sc
.username
, prefs
.username
, 9);
1135 send (sok
, (char *) &sc
, 8 + strlen (sc
.username
) + 1, 0);
1137 recv (sok
, buf
, 10, 0);
1141 snprintf (buf
, sizeof (buf
), "SOCKS\tServer reported error %d,%d.\n", buf
[0], buf
[1]);
1142 proxy_error (print_fd
, buf
);
1146 struct sock5_connect1
1154 traverse_socks5 (int print_fd
, int sok
, char *serverAddr
, int port
)
1156 struct sock5_connect1 sc1
;
1158 unsigned int packetlen
, addrlen
;
1159 unsigned char buf
[260];
1160 int auth
= prefs
.proxy_auth
&& prefs
.proxy_user
[0] && prefs
.proxy_pass
[0];
1165 sc1
.method
= 2; /* Username/Password Authentication (UPA) */
1167 sc1
.method
= 0; /* NO Authentication */
1168 send (sok
, (char *) &sc1
, 3, 0);
1169 if (recv (sok
, buf
, 2, 0) != 2)
1174 proxy_error (print_fd
, "SOCKS\tServer is not socks version 5.\n");
1178 /* did the server say no auth required? */
1184 int len_u
=0, len_p
=0;
1186 /* authentication sub-negotiation (RFC1929) */
1187 if (buf
[1] != 2) /* UPA not supported by server */
1189 proxy_error (print_fd
, "SOCKS\tServer doesn't support UPA authentication.\n");
1193 memset (buf
, 0, sizeof(buf
));
1195 /* form the UPA request */
1196 len_u
= strlen (prefs
.proxy_user
);
1197 len_p
= strlen (prefs
.proxy_pass
);
1200 memcpy (buf
+ 2, prefs
.proxy_user
, len_u
);
1201 buf
[2 + len_u
] = len_p
;
1202 memcpy (buf
+ 3 + len_u
, prefs
.proxy_pass
, len_p
);
1204 send (sok
, buf
, 3 + len_u
+ len_p
, 0);
1205 if ( recv (sok
, buf
, 2, 0) != 2 )
1209 proxy_error (print_fd
, "SOCKS\tAuthentication failed. "
1210 "Is username and password correct?\n");
1211 return 1; /* UPA failed! */
1218 proxy_error (print_fd
, "SOCKS\tAuthentication required but disabled in settings.\n");
1223 addrlen
= strlen (serverAddr
);
1224 packetlen
= 4 + 1 + addrlen
+ 2;
1225 sc2
= malloc (packetlen
);
1226 sc2
[0] = 5; /* version */
1227 sc2
[1] = 1; /* command */
1228 sc2
[2] = 0; /* reserved */
1229 sc2
[3] = 3; /* address type */
1230 sc2
[4] = (unsigned char) addrlen
; /* hostname length */
1231 memcpy (sc2
+ 5, serverAddr
, addrlen
);
1232 *((unsigned short *) (sc2
+ 5 + addrlen
)) = htons (port
);
1233 send (sok
, sc2
, packetlen
, 0);
1236 /* consume all of the reply */
1237 if (recv (sok
, buf
, 4, 0) != 4)
1239 if (buf
[0] != 5 || buf
[1] != 0)
1242 snprintf (buf
, sizeof (buf
), "SOCKS\tProxy refused to connect to host (not allowed).\n");
1244 snprintf (buf
, sizeof (buf
), "SOCKS\tProxy failed to connect to host (error %d).\n", buf
[1]);
1245 proxy_error (print_fd
, buf
);
1248 if (buf
[3] == 1) /* IPV4 32bit address */
1250 if (recv (sok
, buf
, 6, 0) != 6)
1252 } else if (buf
[3] == 4) /* IPV6 128bit address */
1254 if (recv (sok
, buf
, 18, 0) != 18)
1256 } else if (buf
[3] == 3) /* string, 1st byte is size */
1258 if (recv (sok
, buf
, 1, 0) != 1) /* read the string size */
1260 packetlen
= buf
[0] + 2; /* can't exceed 260 */
1261 if (recv (sok
, buf
, packetlen
, 0) != packetlen
)
1265 return 0; /* success */
1268 proxy_error (print_fd
, "SOCKS\tRead error from server.\n");
1273 traverse_wingate (int print_fd
, int sok
, char *serverAddr
, int port
)
1277 snprintf (buf
, sizeof (buf
), "%s %d\r\n", serverAddr
, port
);
1278 send (sok
, buf
, strlen (buf
), 0);
1283 /* stuff for HTTP auth is here */
1286 three_to_four (char *from
, char *to
)
1288 static const char tab64
[64]=
1290 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
1291 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
1292 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
1293 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
1296 to
[0] = tab64
[ (from
[0] >> 2) & 63 ];
1297 to
[1] = tab64
[ ((from
[0] << 4) | (from
[1] >> 4)) & 63 ];
1298 to
[2] = tab64
[ ((from
[1] << 2) | (from
[2] >> 6)) & 63 ];
1299 to
[3] = tab64
[ from
[2] & 63 ];
1303 base64_encode (char *to
, char *from
, unsigned int len
)
1307 three_to_four (from
, to
);
1314 char three
[3]={0,0,0};
1318 three_to_four (three
, to
);
1320 to
[2] = to
[3] = '=';
1329 http_read_line (int print_fd
, int sok
, char *buf
, int len
)
1331 len
= waitline (sok
, buf
, len
, TRUE
);
1334 /* print the message out (send it to the parent process) */
1335 write (print_fd
, "0\n", 2);
1337 if (buf
[len
-1] == '\r')
1340 write (print_fd
, buf
, len
);
1343 write (print_fd
, buf
, len
);
1344 write (print_fd
, "\n", 1);
1352 traverse_http (int print_fd
, int sok
, char *serverAddr
, int port
)
1355 char auth_data
[256];
1356 char auth_data2
[252];
1359 n
= snprintf (buf
, sizeof (buf
), "CONNECT %s:%d HTTP/1.0\r\n",
1361 if (prefs
.proxy_auth
)
1363 n2
= snprintf (auth_data2
, sizeof (auth_data2
), "%s:%s",
1364 prefs
.proxy_user
, prefs
.proxy_pass
);
1365 base64_encode (auth_data
, auth_data2
, n2
);
1366 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "Proxy-Authorization: Basic %s\r\n", auth_data
);
1368 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "\r\n");
1369 send (sok
, buf
, n
, 0);
1371 n
= http_read_line (print_fd
, sok
, buf
, sizeof (buf
));
1372 /* "HTTP/1.0 200 OK" */
1375 if (memcmp (buf
, "HTTP/", 5) || memcmp (buf
+ 9, "200", 3))
1379 /* read until blank line */
1380 n
= http_read_line (print_fd
, sok
, buf
, sizeof (buf
));
1381 if (n
< 1 || (n
== 1 && buf
[0] == '\n'))
1388 traverse_proxy (int proxy_type
, int print_fd
, int sok
, char *ip
, int port
, struct msproxy_state_t
*state
, netstore
*ns_proxy
, int csok4
, int csok6
, int *csok
, char bound
)
1393 return traverse_wingate (print_fd
, sok
, ip
, port
);
1395 return traverse_socks (print_fd
, sok
, ip
, port
);
1397 return traverse_socks5 (print_fd
, sok
, ip
, port
);
1399 return traverse_http (print_fd
, sok
, ip
, port
);
1402 return traverse_msproxy (sok
, ip
, port
, state
, ns_proxy
, csok4
, csok6
, csok
, bound
);
1409 /* this is the child process making the connection attempt */
1412 server_child (server
* serv
)
1414 netstore
*ns_server
;
1415 netstore
*ns_proxy
= NULL
;
1417 int port
= serv
->port
;
1420 char *hostname
= serv
->hostname
;
1421 char *real_hostname
= NULL
;
1423 char *proxy_ip
= NULL
;
1429 char *proxy_host
= NULL
;
1432 ns_server
= net_store_new ();
1434 /* is a hostname set? - bind to it */
1435 if (prefs
.hostname
[0])
1437 ns_local
= net_store_new ();
1438 local_ip
= net_resolve (ns_local
, prefs
.hostname
, 0, &real_hostname
);
1439 if (local_ip
!= NULL
)
1441 snprintf (buf
, sizeof (buf
), "5\n%s\n", local_ip
);
1442 write (serv
->childwrite
, buf
, strlen (buf
));
1443 net_bind (ns_local
, serv
->sok4
, serv
->sok6
);
1447 write (serv
->childwrite
, "7\n", 2);
1449 net_store_destroy (ns_local
);
1452 if (!serv
->dont_use_proxy
) /* blocked in serverlist? */
1457 else if (prefs
.proxy_type
== 5)
1462 url
= g_strdup_printf ("irc://%s:%d", hostname
, port
);
1463 proxy_list
= px_proxy_factory_get_proxies (libproxy_factory
, url
);
1466 /* can use only one */
1467 proxy
= proxy_list
[0];
1468 if (!strncmp (proxy
, "direct", 6))
1470 else if (!strncmp (proxy
, "http", 4))
1472 else if (!strncmp (proxy
, "socks5", 6))
1474 else if (!strncmp (proxy
, "socks", 5))
1480 c
= strchr (proxy
, ':') + 3;
1481 proxy_host
= strdup (c
);
1482 c
= strchr (proxy_host
, ':');
1484 proxy_port
= atoi (c
+ 1);
1487 g_strfreev (proxy_list
);
1491 else if (prefs
.proxy_host
[0] &&
1492 prefs
.proxy_type
> 0 &&
1493 prefs
.proxy_use
!= 2) /* proxy is NOT dcc-only */
1495 proxy_type
= prefs
.proxy_type
;
1496 proxy_host
= strdup (prefs
.proxy_host
);
1497 proxy_port
= prefs
.proxy_port
;
1501 serv
->proxy_type
= proxy_type
;
1503 /* first resolve where we want to connect to */
1506 snprintf (buf
, sizeof (buf
), "9\n%s\n", proxy_host
);
1507 write (serv
->childwrite
, buf
, strlen (buf
));
1508 ip
= net_resolve (ns_server
, proxy_host
, proxy_port
, &real_hostname
);
1512 write (serv
->childwrite
, "1\n", 2);
1515 connect_port
= proxy_port
;
1517 /* if using socks4 or MS Proxy, attempt to resolve ip for irc server */
1518 if ((proxy_type
== 2) || (proxy_type
== 5))
1520 ns_proxy
= net_store_new ();
1521 proxy_ip
= net_resolve (ns_proxy
, hostname
, port
, &real_hostname
);
1524 write (serv
->childwrite
, "1\n", 2);
1527 } else /* otherwise we can just use the hostname */
1528 proxy_ip
= strdup (hostname
);
1531 ip
= net_resolve (ns_server
, hostname
, port
, &real_hostname
);
1534 write (serv
->childwrite
, "1\n", 2);
1537 connect_port
= port
;
1540 snprintf (buf
, sizeof (buf
), "3\n%s\n%s\n%d\n",
1541 real_hostname
, ip
, connect_port
);
1542 write (serv
->childwrite
, buf
, strlen (buf
));
1544 if (!serv
->dont_use_proxy
&& (proxy_type
== 5))
1545 error
= net_connect (ns_server
, serv
->proxy_sok4
, serv
->proxy_sok6
, &psok
);
1548 error
= net_connect (ns_server
, serv
->sok4
, serv
->sok6
, &sok
);
1554 snprintf (buf
, sizeof (buf
), "2\n%d\n", sock_error ());
1555 write (serv
->childwrite
, buf
, strlen (buf
));
1558 /* connect succeeded */
1561 switch (traverse_proxy (proxy_type
, serv
->childwrite
, psok
, proxy_ip
, port
, &serv
->msp_state
, ns_proxy
, serv
->sok4
, serv
->sok6
, &sok
, bound
))
1563 case 0: /* success */
1565 if (!serv
->dont_use_proxy
&& (proxy_type
== 5))
1566 snprintf (buf
, sizeof (buf
), "4\n%d %d %d %d %d\n", sok
, psok
, serv
->msp_state
.clientid
, serv
->msp_state
.serverid
,
1567 serv
->msp_state
.seq_sent
);
1570 snprintf (buf
, sizeof (buf
), "4\n%d\n", sok
); /* success */
1571 write (serv
->childwrite
, buf
, strlen (buf
));
1573 case 1: /* socks traversal failed */
1574 write (serv
->childwrite
, "8\n", 2);
1579 snprintf (buf
, sizeof (buf
), "4\n%d\n", sok
); /* success */
1580 write (serv
->childwrite
, buf
, strlen (buf
));
1586 #if defined (USE_IPV6)
1587 /* this is probably not needed */
1588 net_store_destroy (ns_server
);
1590 net_store_destroy (ns_proxy
);
1593 /* no need to free ip/real_hostname, this process is exiting */
1599 server_connect (server
*serv
, char *hostname
, int port
, int no_login
)
1601 int pid
, read_des
[2];
1602 session
*sess
= serv
->server_session
;
1605 if (!serv
->ctx
&& serv
->use_ssl
)
1607 if (!(serv
->ctx
= _SSL_context_init (ssl_cb_info
)))
1609 fprintf (stderr
, "_SSL_context_init failed\n");
1620 /* use default port for this server type */
1627 port
&= 0xffff; /* wrap around */
1629 if (serv
->connected
|| serv
->connecting
|| serv
->recondelay_tag
)
1630 server_disconnect (sess
, TRUE
, -1);
1632 fe_progressbar_start (sess
);
1634 EMIT_SIGNAL (XP_TE_SERVERLOOKUP
, sess
, hostname
, NULL
, NULL
, NULL
, 0);
1636 safe_strcpy (serv
->servername
, hostname
, sizeof (serv
->servername
));
1637 /* overlap illegal in strncpy */
1638 if (hostname
!= serv
->hostname
)
1639 safe_strcpy (serv
->hostname
, hostname
, sizeof (serv
->hostname
));
1644 char cert_file
[256];
1645 serv
->have_cert
= FALSE
;
1647 /* first try network specific cert/key */
1648 snprintf (cert_file
, sizeof (cert_file
), "%s/%s.pem",
1649 get_xdir_fs (), server_get_network (serv
, TRUE
));
1650 if (SSL_CTX_use_certificate_file (serv
->ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1652 if (SSL_CTX_use_PrivateKey_file (serv
->ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1653 serv
->have_cert
= TRUE
;
1657 /* if that doesn't exist, try ~/.xchat2/client.pem */
1658 snprintf (cert_file
, sizeof (cert_file
), "%s/%s.pem",
1659 get_xdir_fs (), "client");
1660 if (SSL_CTX_use_certificate_file (serv
->ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1662 if (SSL_CTX_use_PrivateKey_file (serv
->ctx
, cert_file
, SSL_FILETYPE_PEM
) == 1)
1663 serv
->have_cert
= TRUE
;
1669 server_set_defaults (serv
);
1670 serv
->connecting
= TRUE
;
1672 serv
->no_login
= no_login
;
1674 fe_server_event (serv
, FE_SE_CONNECTING
, 0);
1676 server_flush_queue (serv
);
1678 if (pipe (read_des
) < 0)
1680 serv
->childread
= read_des
[0];
1681 serv
->childwrite
= read_des
[1];
1683 /* create both sockets now, drop one later */
1684 net_sockets (&serv
->sok4
, &serv
->sok6
);
1686 /* In case of MS Proxy we have a separate UDP control connection */
1687 if (!serv
->dont_use_proxy
&& (serv
->proxy_type
== 5))
1688 udp_sockets (&serv
->proxy_sok4
, &serv
->proxy_sok6
);
1692 serv
->proxy_sok4
= -1;
1693 serv
->proxy_sok6
= -1;
1697 rand(); /* CL: net_resolve calls rand() when LOOKUPD is set, so prepare a different seed for each child. This method giver a bigger variation in seed values than calling srand(time(0)) in the child itself. */
1699 switch (pid
= fork ())
1705 /* this is the child */
1707 server_child (serv
);
1710 serv
->childpid
= pid
;
1711 serv
->iotag
= fe_input_add (serv
->childread
, FIA_READ
, server_read_child
,
1716 server_fill_her_up (server
*serv
)
1718 serv
->connect
= server_connect
;
1719 serv
->disconnect
= server_disconnect
;
1720 serv
->cleanup
= server_cleanup
;
1721 serv
->flush_queue
= server_flush_queue
;
1722 serv
->auto_reconnect
= auto_reconnect
;
1724 proto_fill_her_up (serv
);
1728 server_set_encoding (server
*serv
, char *new_encoding
)
1734 free (serv
->encoding
);
1735 /* can be left as NULL to indicate system encoding */
1736 serv
->encoding
= NULL
;
1737 serv
->using_cp1255
= FALSE
;
1738 serv
->using_irc
= FALSE
;
1743 serv
->encoding
= strdup (new_encoding
);
1744 /* the serverlist GUI might have added a space
1745 and short description - remove it. */
1746 space
= strchr (serv
->encoding
, ' ');
1750 /* server_inline() uses these flags */
1751 if (!strcasecmp (serv
->encoding
, "CP1255") ||
1752 !strcasecmp (serv
->encoding
, "WINDOWS-1255"))
1753 serv
->using_cp1255
= TRUE
;
1754 else if (!strcasecmp (serv
->encoding
, "IRC"))
1755 serv
->using_irc
= TRUE
;
1765 serv
= malloc (sizeof (struct server
));
1766 memset (serv
, 0, sizeof (struct server
));
1768 /* use server.c and proto-irc.c functions */
1769 server_fill_her_up (serv
);
1773 strcpy (serv
->nick
, prefs
.nick1
);
1774 server_set_defaults (serv
);
1776 serv_list
= g_slist_prepend (serv_list
, serv
);
1778 fe_new_server (serv
);
1784 is_server (server
*serv
)
1786 return g_slist_find (serv_list
, serv
) ? 1 : 0;
1790 server_set_defaults (server
*serv
)
1792 if (serv
->chantypes
)
1793 free (serv
->chantypes
);
1794 if (serv
->chanmodes
)
1795 free (serv
->chanmodes
);
1796 if (serv
->nick_prefixes
)
1797 free (serv
->nick_prefixes
);
1798 if (serv
->nick_modes
)
1799 free (serv
->nick_modes
);
1801 serv
->chantypes
= strdup ("#&!+");
1802 serv
->chanmodes
= strdup ("beI,k,l");
1803 serv
->nick_prefixes
= strdup ("@%+");
1804 serv
->nick_modes
= strdup ("ohv");
1806 serv
->nickcount
= 1;
1807 serv
->end_of_motd
= FALSE
;
1808 serv
->is_away
= FALSE
;
1809 serv
->supports_watch
= FALSE
;
1810 serv
->supports_monitor
= FALSE
;
1811 serv
->bad_prefix
= FALSE
;
1812 serv
->use_who
= TRUE
;
1813 serv
->have_namesx
= FALSE
;
1814 serv
->have_awaynotify
= FALSE
;
1815 serv
->have_uhnames
= FALSE
;
1816 serv
->have_whox
= FALSE
;
1817 serv
->have_idmsg
= FALSE
;
1818 serv
->have_accnotify
= FALSE
;
1819 serv
->have_extjoin
= FALSE
;
1820 serv
->have_sasl
= FALSE
;
1821 serv
->have_except
= FALSE
;
1825 server_get_network (server
*serv
, gboolean fallback
)
1828 return ((ircnet
*)serv
->network
)->name
;
1831 return serv
->servername
;
1837 server_set_name (server
*serv
, char *name
)
1839 GSList
*list
= sess_list
;
1843 name
= serv
->hostname
;
1845 /* strncpy parameters must NOT overlap */
1846 if (name
!= serv
->servername
)
1848 safe_strcpy (serv
->servername
, name
, sizeof (serv
->servername
));
1853 sess
= (session
*) list
->data
;
1854 if (sess
->server
== serv
)
1855 fe_set_title (sess
);
1859 if (serv
->server_session
->type
== SESS_SERVER
)
1863 safe_strcpy (serv
->server_session
->channel
, ((ircnet
*)serv
->network
)->name
, CHANLEN
);
1866 safe_strcpy (serv
->server_session
->channel
, name
, CHANLEN
);
1868 fe_set_channel (serv
->server_session
);
1873 server_away_find_message (server
*serv
, char *nick
)
1875 struct away_msg
*away
;
1876 GSList
*list
= away_list
;
1879 away
= (struct away_msg
*) list
->data
;
1880 if (away
->server
== serv
&& !serv
->p_cmp (nick
, away
->nick
))
1888 server_away_free_messages (server
*serv
)
1890 GSList
*list
, *next
;
1891 struct away_msg
*away
;
1898 if (away
->server
== serv
)
1900 away_list
= g_slist_remove (away_list
, away
);
1902 free (away
->message
);
1911 server_away_save_message (server
*serv
, char *nick
, char *msg
)
1913 struct away_msg
*away
= server_away_find_message (serv
, nick
);
1915 if (away
) /* Change message for known user */
1918 free (away
->message
);
1919 away
->message
= strdup (msg
);
1921 /* Create brand new entry */
1923 away
= malloc (sizeof (struct away_msg
));
1926 away
->server
= serv
;
1927 safe_strcpy (away
->nick
, nick
, sizeof (away
->nick
));
1928 away
->message
= strdup (msg
);
1929 away_list
= g_slist_prepend (away_list
, away
);
1935 server_free (server
*serv
)
1937 serv
->cleanup (serv
);
1939 serv_list
= g_slist_remove (serv_list
, serv
);
1941 dcc_notify_kill (serv
);
1942 serv
->flush_queue (serv
);
1943 server_away_free_messages (serv
);
1945 free (serv
->nick_modes
);
1946 free (serv
->nick_prefixes
);
1947 free (serv
->chanmodes
);
1948 free (serv
->chantypes
);
1949 if (serv
->bad_nick_prefixes
)
1950 free (serv
->bad_nick_prefixes
);
1951 if (serv
->last_away_reason
)
1952 free (serv
->last_away_reason
);
1954 free (serv
->encoding
);
1956 free (serv
->autojoin
);
1959 _SSL_context_free (serv
->ctx
);
1962 fe_server_callback (serv
);