⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 The major functionality added in this release includes: - Rootless mode in X11 - Widget Templt
💻 C
📖 第 1 页 / 共 2 页
字号:
/* X-Chat * Copyright (C) 1998 Peter Zelezny. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#define WANTSOCKET#define WANTARPA#include "inet.h"#ifndef WIN32#include <signal.h>#include <sys/wait.h>#else#include <winbase.h>#endif#include "xchat.h"#include "plugin.h"#include "fe.h"#include "cfgfiles.h"#include "network.h"#include "notify.h"#include "xchatc.h"#include "inbound.h"#include "outbound.h"#include "text.h"#include "util.h"#include "server.h"#ifdef USE_OPENSSL#include <openssl/ssl.h>		  /* SSL_() */#include <openssl/err.h>		  /* ERR_() */#include "ssl.h"#endif#ifdef USE_JCODE#include "jcode.h"#endif#ifdef WIN32#include "identd.c"#endif#ifdef USE_OPENSSLextern SSL_CTX *ctx;				  /* xchat.c *//* local variables */static struct session *g_sess = NULL;#endifstatic void server_stopconnecting (server * serv);static gbooleanread_data (GIOChannel *source, GIOCondition condition, server *serv);static intclose_socket_cb (int sok){	closesocket (sok);	return 0;}static voidclose_socket (int sok){	/* close the socket in 5 seconds so the QUIT message is not lost */	fe_timeout_add (5000, close_socket_cb, (void *) sok);}static voidserver_connected (server * serv){	char hostname[256];	char outbuf[512];	serv->ping_recv = time (0);#ifdef WIN32	identd_start ();#else	sprintf (outbuf, "%s/auth/xchat_auth", g_get_home_dir ());	if (access (outbuf, X_OK) == 0)	{		sprintf (outbuf, "/exec %s/auth/xchat_auth %s", g_get_home_dir (),					prefs.username);		handle_command (outbuf, serv->front_session, FALSE, FALSE);	}#endif	serv->connected = TRUE;	serv->iotag = fe_input_add (serv->sok, 1, 0, 1, read_data, serv);	if (!serv->no_login)	{		EMIT_SIGNAL (XP_TE_CONNECTED, serv->front_session, NULL, NULL, NULL,						 NULL, 0);		if (serv->password[0])		{			sprintf (outbuf, "PASS %s\r\n", serv->password);			tcp_send (serv, outbuf);		}		gethostname (hostname, sizeof (hostname) - 1);		hostname[sizeof (hostname) - 1] = 0;		if (hostname[0] == 0)			strcpy (hostname, "0");		snprintf (outbuf, sizeof (outbuf),					 "NICK %s\r\n"					 "USER %s %s %s :%s\r\n",					 serv->nick, prefs.username, hostname,					 serv->servername, prefs.realname);		tcp_send (serv, outbuf);	} else	{		EMIT_SIGNAL (XP_TE_SERVERCONNECTED, serv->front_session, NULL, NULL,						 NULL, NULL, 0);	}	set_nonblocking (serv->sok);	set_server_name (serv, serv->servername);}#ifdef USE_OPENSSL#define	SSLTMOUT	10				  /* seconds */voidssl_cb_info (SSL * s, int where, int ret){/*	char buf[128];*/	return;							  /* FIXME: make debug level adjustable in serverlist or settings *//*	snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);	if (g_sess)		EMIT_SIGNAL (XP_TE_SERVTEXT, g_sess, buf, NULL, NULL, NULL, 0);	else		fprintf (stderr, "%s\n", buf);*/}static intssl_cb_verify (int ok, X509_STORE_CTX * ctx){	char subject[256];	char issuer[256];	char buf[512];	X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), subject,							 sizeof (subject));	X509_NAME_oneline (X509_get_issuer_name (ctx->current_cert), issuer,							 sizeof (issuer));	snprintf (buf, sizeof (buf), "* Subject: %s", subject);	EMIT_SIGNAL (XP_TE_SERVTEXT, g_sess, buf, NULL, NULL, NULL, 0);	snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);	EMIT_SIGNAL (XP_TE_SERVTEXT, g_sess, buf, NULL, NULL, NULL, 0);	return (TRUE);					  /* always ok */}static intssl_do_connect (server * serv){	char buf[128];	g_sess = serv->front_session;	if (SSL_connect (serv->ssl) <= 0)	{		char err_buf[128];		int err;		g_sess = NULL;		if ((err = ERR_get_error ()) > 0)		{			ERR_error_string (err, err_buf);			snprintf (buf, sizeof (buf), "(%d) %s", err, err_buf);			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->front_session, buf, NULL,							 NULL, NULL, 0);			server_cleanup (serv);			if (prefs.autoreconnectonfail)				auto_reconnect (serv, FALSE, -1);			return (0);				  /* remove it (0) */		}	}	g_sess = NULL;	if (SSL_is_init_finished (serv->ssl))	{		struct cert_info cert_info;		struct chiper_info *chiper_info;		int verify_error;		int i;		if (!_SSL_get_cert_info (&cert_info, serv->ssl))		{			snprintf (buf, sizeof (buf), "* Certification info:");			EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,							 NULL, 0);			snprintf (buf, sizeof (buf), "  Subject:");			EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,							 NULL, 0);			for (i = 0; cert_info.subject_word[i]; i++)			{				snprintf (buf, sizeof (buf), "    %s", cert_info.subject_word[i]);				EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,								 NULL, 0);			}			snprintf (buf, sizeof (buf), "  Issuer:");			EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,							 NULL, 0);			for (i = 0; cert_info.issuer_word[i]; i++)			{				snprintf (buf, sizeof (buf), "    %s", cert_info.issuer_word[i]);				EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,								 NULL, 0);			}			snprintf (buf, sizeof (buf), "  Public key algorithm: %s (%d bits)",						 cert_info.algorithm, cert_info.algorithm_bits);			EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,							 NULL, 0);			if (cert_info.rsa_tmp_bits)			{				snprintf (buf, sizeof (buf),							 "  Public key algorithm uses ephemeral key with %d bits",							 cert_info.rsa_tmp_bits);				EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,								 NULL, 0);			}			snprintf (buf, sizeof (buf), "  Sign algorithm %s (%d bits)",						 cert_info.sign_algorithm, cert_info.sign_algorithm_bits);			EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,							 NULL, 0);			snprintf (buf, sizeof (buf), "  Valid since %s to %s",						 cert_info.notbefore, cert_info.notafter);			EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,							 NULL, 0);		} else		{			snprintf (buf, sizeof (buf), " * No Certificate");			EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,							 NULL, 0);		}		chiper_info = _SSL_get_cipher_info (serv->ssl);	/* static buffer */		snprintf (buf, sizeof (buf), "* Chiper info:");		EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL, NULL,						 0);		snprintf (buf, sizeof (buf), "  Version: %s, cipher %s (%u bits)",					 chiper_info->version, chiper_info->chiper,					 chiper_info->chiper_bits);		EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL, NULL,						 0);		verify_error = SSL_get_verify_result (serv->ssl);		switch (verify_error)		{		case X509_V_OK:			/* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */			/* EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL, NULL, 0); */			break;		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:		case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:			if (serv->accept_invalid_cert)			{				snprintf (buf, sizeof (buf), "* Verify E: %s.? (%d) -- Ignored",							 X509_verify_cert_error_string (verify_error),							 verify_error);				EMIT_SIGNAL (XP_TE_SERVTEXT, serv->front_session, buf, NULL, NULL,								 NULL, 0);				break;			}		default:			snprintf (buf, sizeof (buf), "%s.? (%d)",						 X509_verify_cert_error_string (verify_error),						 verify_error);			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->front_session, buf, NULL, NULL,							 NULL, 0);			server_cleanup (serv);			return (0);		}		server_stopconnecting (serv);		/* activate gtk poll */		server_connected (serv);		return (0);					  /* remove it (0) */	} else	{		if (serv->ssl->session->time + SSLTMOUT < time (NULL))		{			snprintf (buf, sizeof (buf), "SSL handshake timed out");			EMIT_SIGNAL (XP_TE_CONNFAIL, serv->front_session, buf, NULL,							 NULL, NULL, 0);			server_cleanup (serv); /* ->connecting = FALSE */			if (prefs.autoreconnectonfail)				auto_reconnect (serv, FALSE, -1);			return (0);				  /* remove it (0) */		}		return (1);					  /* call it more (1) */	}}#endifstatic inttimeout_auto_reconnect (struct server *serv){	if (is_server (serv))		  /* make sure it hasnt been closed during the delay */	{		serv->recondelay_tag = 0;		if (!serv->connected && !serv->connecting && serv->front_session)		{			connect_server (serv->front_session, serv->hostname, serv->port,								 FALSE);		}	}	return 0;						  /* returning 0 should remove the timeout handler */}voidauto_reconnect (struct server *serv, int send_quit, int err){	session *s;	GSList *list;	int del;	if (serv->front_session == NULL)		return;	list = sess_list;	while (list)				  /* make sure auto rejoin can work */	{		s = list->data;		if (s->type == SESS_CHANNEL && s->channel[0])		{			strcpy (s->waitchannel, s->channel);			strcpy (s->willjoinchannel, s->channel);		}		list = list->next;	}	if (serv->connected)		disconnect_server (serv->front_session, send_quit, err);	del = prefs.recon_delay * 1000;	if (del < 1000)		del = 500;				  /* so it doesn't block the gui */#ifndef WIN32	if (err == 0 || err == ECONNRESET || err == ETIMEDOUT)#else	if (err == 0 || err == WSAECONNRESET || err == WSAETIMEDOUT)#endif		serv->reconnect_away = serv->is_away;	serv->recondelay_tag = fe_timeout_add (del, timeout_auto_reconnect, serv);}static gbooleanread_data (GIOChannel *source, GIOCondition condition, server *serv){	int sok = serv->sok;	int error, i, len;	char lbuf[2050];	char *temp;#ifdef USE_JCODE	char *jtemp;#endif	while (1)	{		if (!EMIT_SIGNAL (XP_IF_RECV, &len, (void *) sok, &lbuf,								(void *) ((sizeof (lbuf)) - 2), NULL, 0))		{#ifdef USE_OPENSSL			if (!serv->ssl)#endif				len = recv (sok, lbuf, sizeof (lbuf) - 2, 0);#ifdef USE_OPENSSL			else				len = _SSL_recv (serv->ssl, lbuf, sizeof (lbuf) - 2);#endif		}		if (len < 1)		{			if (len < 0)			{				if (would_block_again ())					return TRUE;				error = sock_error ();			} else			{				error = 0;			}			if (prefs.autoreconnect)				auto_reconnect (serv, FALSE, error);			else				disconnect_server (serv->front_session, FALSE, error);			return TRUE;		} else		{			i = 0;			lbuf[len] = 0;			while (i < len)			{				switch (lbuf[i])				{				case '\r':					break;				case '\n':					serv->linebuf[serv->pos] = 0;#ifdef USE_TRANS					if (prefs.use_trans)						serv2user (serv->linebuf);#endif					if (prefs.stripcolor)					{						temp = strip_color (serv->linebuf);#ifdef USE_JCODE						if (prefs.kanji_conv)						{							jtemp = kanji_conv_to_locale (temp);							if (jtemp)							{								process_line (serv, jtemp);								free (jtemp);							} else								process_line (serv, temp);						} else							process_line (serv, temp);#else						process_line (serv, temp);#endif						free (temp);					} else					{#ifdef USE_JCODE						if (prefs.kanji_conv)						{							jtemp = kanji_conv_to_locale (serv->linebuf);							if (jtemp)							{								process_line (serv, jtemp);								free (jtemp);							} else								process_line (serv, serv->linebuf);						} else							process_line (serv, serv->linebuf);#else						process_line (serv, serv->linebuf);#endif					}					serv->pos = 0;					break;				default:					serv->linebuf[serv->pos] = lbuf[i];					if (serv->pos > 519)						fprintf (stderr,									"*** XCHAT WARNING: Buffer overflow - shit server!\n");					else						serv->pos++;				}				i++;			}		}	}}voidflush_server_queue (struct server *serv){	list_free (&serv->outbound_queue);	serv->sendq_len = 0;	fe_set_throttle (serv);}#ifdef WIN32static intwaitline2 (GIOChannel *source, char *buf, int bufsize){	int i = 0;	int len;	while (1)	{		if (g_io_channel_read (source, &buf[i], 1, &len) != G_IO_ERROR_NONE)			return -1;		if (buf[i] == '\n' || bufsize == i + 1)		{			buf[i] = 0;			return i;		}		i++;	}}#else#define waitline2(source,buf,size) waitline(serv->childread,buf,size)#endifstatic gbooleanconnected_signal (GIOChannel *source, GIOCondition condition, server *serv){	session *sess = serv->front_session;	char tbuf[128];	char outbuf[512];	char host[100];	char ip[100];	waitline2 (source, tbuf, sizeof tbuf);	switch (tbuf[0])	{	case '1':						  /* unknown host */		server_stopconnecting (serv);		closesocket (serv->sok4);		if (serv->sok6 >= 0)			closesocket (serv->sok6);		EMIT_SIGNAL (XP_TE_UKNHOST, sess, NULL, NULL, NULL, NULL, 0);		if (prefs.autoreconnectonfail)			auto_reconnect (serv, FALSE, -1);		break;	case '2':						  /* connection failed */		waitline2 (source, tbuf, sizeof tbuf);		server_stopconnecting (serv);		closesocket (serv->sok4);		if (serv->sok6 >= 0)			closesocket (serv->sok6);		EMIT_SIGNAL (XP_TE_CONNFAIL, sess, errorstring (atoi (tbuf)), NULL,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -