📄 server.c
字号:
NULL, NULL, 0); if (prefs.autoreconnectonfail) auto_reconnect (serv, FALSE, -1); break; case '3': /* gethostbyname finished */ waitline2 (source, host, sizeof host); waitline2 (source, ip, sizeof ip); waitline2 (source, outbuf, sizeof outbuf); EMIT_SIGNAL (XP_TE_CONNECT, sess, host, ip, outbuf, NULL, 0); break; case '4': /* success */ waitline2 (source, tbuf, sizeof (tbuf)); serv->sok = atoi (tbuf);#ifdef USE_IPV6 /* close the one we didn't end up using */ if (serv->sok == serv->sok4) closesocket (serv->sok6); else closesocket (serv->sok4);#endif#ifdef USE_OPENSSL#define SSLDOCONNTMOUT 300 if (serv->use_ssl) { char *err; /* it'll be a memory leak, if connection isn't terminated by server_cleanup() */ serv->ssl = _SSL_socket (ctx, serv->sok); if ((err = _SSL_set_verify (ctx, ssl_cb_verify, NULL))) { EMIT_SIGNAL (XP_TE_CONNFAIL, serv->front_session, err, NULL, NULL, NULL, 0); server_cleanup (serv); /* ->connecting = FALSE */ return TRUE; } /* FIXME: it'll be needed by new servers */ /* send(serv->sok, "STLS\r\n", 6, 0); sleep(1); */ set_nonblocking (serv->sok); serv->ssl_do_connect_tag = fe_timeout_add (SSLDOCONNTMOUT, ssl_do_connect, serv); } else { serv->ssl = NULL;#endif server_stopconnecting (serv); /* ->connecting = FALSE */ /* activate gtk poll */ server_connected (serv);#ifdef USE_OPENSSL }#endif break; case '5': /* prefs ip discovered */ waitline2 (source, tbuf, sizeof tbuf); prefs.local_ip = inet_addr (tbuf); break; case '7': /* gethostbyname (prefs.hostname) failed */ sprintf (outbuf, "Cannot resolve hostname %s\nCheck your IP Settings!\n", prefs.hostname); PrintText (sess, outbuf); break; case '8': PrintText (sess, "Proxy traversal failed.\n"); disconnect_server (sess, FALSE, -1); break; case '9': waitline2 (source, tbuf, sizeof tbuf); EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, tbuf, NULL, NULL, NULL, 0); break; } return TRUE;}static voidserver_stopconnecting (server * serv){ if (serv->iotag) { fe_input_remove (serv->iotag); serv->iotag = 0; }#ifndef WIN32 /* kill the child process trying to connect */ kill (serv->childpid, SIGKILL); waitpid (serv->childpid, NULL, 0);#else TerminateThread ((HANDLE)serv->childpid, 0); CloseHandle ((HANDLE)serv->childpid);#endif close (serv->childwrite); close (serv->childread);#ifdef USE_OPENSSL if (serv->ssl_do_connect_tag) { fe_timeout_remove (serv->ssl_do_connect_tag); serv->ssl_do_connect_tag = 0; }#endif fe_progressbar_end (serv->front_session); serv->connecting = FALSE;}/* kill all sockets & iotags of a server. Stop a connection attempt, or disconnect if already connected. */intserver_cleanup (server * serv){ fe_set_lag (serv, 0.0); if (serv->iotag) { fe_input_remove (serv->iotag); serv->iotag = 0; }#ifdef USE_OPENSSL if (serv->ssl) { _SSL_close (serv->ssl); serv->ssl = NULL; }#endif if (serv->connecting) { server_stopconnecting (serv); closesocket (serv->sok4); if (serv->sok6 >= 0) closesocket (serv->sok6); return 1; } if (serv->connected) { close_socket (serv->sok); serv->connected = FALSE; return 2; } /* is this server in a reconnect delay? remove it! */ if (serv->recondelay_tag) { fe_timeout_remove (serv->recondelay_tag); serv->recondelay_tag = 0; return 3; } return 0;}voiddisconnect_server (session * sess, int sendquit, int err){ server *serv = sess->server; GSList *list; char tbuf[64]; /* send our QUIT reason */ if (sendquit && serv->connected) server_sendquit (sess); /* close all sockets & io tags */ switch (server_cleanup (serv)) { case 0: /* it wasn't even connected! */ notc_msg (sess); return; case 1: /* it was in the process of connecting */ sprintf (tbuf, "%d", sess->server->childpid); EMIT_SIGNAL (XP_TE_SCONNECT, sess, tbuf, NULL, NULL, NULL, 0); return; } flush_server_queue (serv); list = sess_list; while (list) /* print "Disconnected" to each window using this server */ { sess = (struct session *) list->data; if (sess->server == serv) EMIT_SIGNAL (XP_TE_DISCON, sess, errorstring (err), NULL, NULL, NULL, 0); list = list->next; } serv->pos = 0; serv->motd_skipped = FALSE; serv->no_login = FALSE; serv->servername[0] = 0; list = sess_list; while (list) { sess = (struct session *) list->data; if (sess->server == serv) { if (sess->channel[0]) { if (sess->type == SESS_CHANNEL) { clear_channel (sess); } } else { clear_channel (sess); } } list = list->next; } notify_cleanup ();}struct sock_connect{ char version; char type; unsigned short port; unsigned long address; char username[10];};/* traverse_socks() returns: * 0 success * * 1 socks traversal failed */static inttraverse_socks (int sok, char *serverAddr, int port){ struct sock_connect sc; unsigned char buf[10]; sc.version = 4; sc.type = 1; sc.port = htons (port); sc.address = inet_addr (serverAddr); strncpy (sc.username, prefs.username, 9); send (sok, (char *) &sc, 8 + strlen (sc.username) + 1, 0); buf[1] = 0; recv (sok, buf, 10, 0); if (buf[1] == 90) return 0; return 1;}struct sock5_connect1{ char version; char nmethods; char method;};static inttraverse_socks5 (int sok, char *serverAddr, int port){ struct sock5_connect1 sc1; unsigned char *sc2; unsigned int packetlen, addrlen; unsigned char buf[10]; sc1.version = 5; sc1.nmethods = 1; sc1.method = 0; send (sok, (char *) &sc1, 3, 0); if (recv (sok, buf, 2, 0) != 2) return 1; if (buf[0] != 5 && buf[1] != 0) return 1; addrlen = strlen (serverAddr); packetlen = 4 + 1 + addrlen + 2; sc2 = malloc (packetlen); sc2[0] = 5; /* version */ sc2[1] = 1; /* command */ sc2[2] = 0; /* reserved */ sc2[3] = 3; /* address type */ sc2[4] = (unsigned char) addrlen; /* hostname length */ memcpy (sc2 + 5, serverAddr, addrlen); *((unsigned short *) (sc2 + 5 + addrlen)) = htons (port); send (sok, sc2, packetlen, 0); /* consume all of the reply */ if (recv (sok, buf, 4, 0) != 4) return 1; if (buf[0] != 5 && buf[1] != 0) return 1; if (buf[3] == 1) { if (recv (sok, buf, 6, 0) != 6) return 1; } else if (buf[3] == 4) { if (recv (sok, buf, 18, 0) != 18) return 1; } else if (buf[3] == 3) { if (recv (sok, buf, 1, 0) != 1) return 1; packetlen = buf[0] + 2; if (recv (sok, buf, packetlen, 0) != packetlen) return 1; } return 0;}static inttraverse_wingate (int sok, char *serverAddr, int port){ char buf[128]; snprintf (buf, sizeof (buf), "%s %d\r\n", serverAddr, port); send (sok, buf, strlen (buf), 0); return 0;}static inttraverse_http (int sok, char *serverAddr, int port){ char buf[128]; int n; n = snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.1\r\n\r\n", serverAddr, port); send (sok, buf, n, 0);#ifndef WIN32 waitline (sok, buf, sizeof (buf)); /* FIXME: win32 cant read() sok */ /* "HTTP/1.0 200 OK" */ if (strlen (buf) < 12) return 1; if (memcmp (buf, "HTTP/", 5) || memcmp (buf + 9, "200", 3)) return 1; for (;;) { /* read until blank line */ waitline (sok, buf, sizeof (buf)); if (!buf[0] || (buf[0] == '\r' && !buf[1])) break; }#endif return 0;}static inttraverse_proxy (int sok, char *ip, int port){ switch (prefs.proxy_type) { case 1: return traverse_wingate (sok, ip, port); case 2: return traverse_socks (sok, ip, port); case 3: return traverse_socks5 (sok, ip, port); case 4: return traverse_http (sok, ip, port); } return 1;}/* this is the child process making the connection attempt */static intserver_child (server * serv){ netstore *ns_server; netstore *ns_proxy = NULL; netstore *ns_local; int port = serv->port; int error; int sok; char *hostname = serv->hostname; char *real_hostname = NULL; char *ip; char *proxy_ip = NULL; char *local_ip; int connect_port; FILE *fd; fd = fdopen (serv->childwrite, "w"); ns_server = net_store_new (); /* is a hostname set? - bind to it */ if (prefs.hostname[0]) { ns_local = net_store_new (); local_ip = net_resolve (ns_local, prefs.hostname, 0, &real_hostname); if (local_ip != NULL) { fprintf (fd, "5\n%s\n", local_ip); net_bind (ns_local, serv->sok4, serv->sok6); } else { fprintf (fd, "7\n"); } net_store_destroy (ns_local); fflush (fd); } /* first resolve where we want to connect to */ if (!serv->dont_use_proxy && prefs.proxy_host[0] && prefs.proxy_type > 0) { fprintf (fd, "9\n%s\n", prefs.proxy_host); fflush (fd); ip = net_resolve (ns_server, prefs.proxy_host, prefs.proxy_port, &real_hostname); if (!ip) { fprintf (fd, "1\n"); goto xit; } connect_port = prefs.proxy_port; /* if using socks4, attempt to resolve ip for irc server */ if (prefs.proxy_type == 2) { ns_proxy = net_store_new (); proxy_ip = net_resolve (ns_proxy, hostname, port, &real_hostname); if (!proxy_ip) { fprintf (fd, "1\n"); goto xit; } } else /* otherwise we can just use the hostname */ proxy_ip = strdup (hostname); } else { ip = net_resolve (ns_server, hostname, port, &real_hostname); if (!ip) { fprintf (fd, "1\n"); goto xit; } connect_port = port; } fprintf (fd, "3\n%s\n%s\n%d\n", real_hostname, ip, connect_port); fflush (fd); error = net_connect (ns_server, serv->sok4, serv->sok6, &sok); if (error != 0) { fprintf (fd, "2\n%d\n", sock_error ()); } else { /* connect succeeded */ if (proxy_ip) { switch (traverse_proxy (sok, proxy_ip, port)) { case 0: fprintf (fd, "4\n%d\n", sok); /* success */ break; case 1: fprintf (fd, "8\n"); /* socks traversal failed */ break; } } else { fprintf (fd, "4\n%d\n", sok); } }xit: fflush (fd); net_store_destroy (ns_server); if (ns_proxy) net_store_destroy (ns_proxy); /* no need to free ip/real_hostname, this process is exiting */#ifdef WIN32 /* under win32 we use a thread -> shared memory, must free! */ if (proxy_ip) free (proxy_ip); if (ip) free (ip); if (real_hostname) free (real_hostname);#endif return 0;}voidconnect_server (session * sess, char *hostname, int port, int no_login){ int pid, read_des[2]; server *serv = sess->server; if (!hostname[0]) return; sess = serv->front_session; if (serv->connected || serv->connecting || serv->recondelay_tag) disconnect_server (sess, TRUE, -1); fe_progressbar_start (sess); EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, hostname, NULL, NULL, NULL, 0); strcpy (serv->servername, hostname); strcpy (serv->hostname, hostname); set_server_defaults (serv); serv->connecting = TRUE; serv->port = port; serv->no_login = no_login; fe_set_away (serv); flush_server_queue (serv); /* pipe is #defined on win32 in gwin32.h to use _pipe and O_BINARY */ if (pipe (read_des) < 0) return;#ifdef __EMX__ /* os/2 */ setmode (read_des[0], O_BINARY); setmode (read_des[1], O_BINARY);#endif serv->childread = read_des[0]; serv->childwrite = read_des[1]; /* create both sockets now, drop one later */ net_sockets (&serv->sok4, &serv->sok6);#ifdef WIN32 pid = (int)CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)server_child, serv, 0, (DWORD *)&pid);#else switch (pid = fork ()) { case -1: return; case 0: /* this is the child */ setuid (getuid ()); server_child (serv); _exit (0); }#endif serv->childpid = pid; /* the 3 tells input_add that it's a fd, not a socket */ serv->iotag = fe_input_add (serv->childread, 3, 0, 0, connected_signal, serv);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -