/************************************************************************** Try to connect to a server (get_server_address() must be called first!): - try to create a TCP socket and connect it to `server_addr' - if successful: - start monitoring the socket for packets from the server - send a "login request" packet to the server and - return 0 - if unable to create the connection, close the socket, put an error message in ERRBUF and return the Unix error code (ie., errno, which will be non-zero). **************************************************************************/ static int try_to_connect(const char *username, char *errbuf, int errbufsize) { close_socket_set_callback(close_socket_callback); /* connection in progress? wait. */ if (client.conn.used) { (void) mystrlcpy(errbuf, _("Connection in progress."), errbufsize); return -1; } if ((client.conn.sock = socket(server_addr.saddr.sa_family, SOCK_STREAM, 0)) == -1) { (void) mystrlcpy(errbuf, fc_strerror(fc_get_errno()), errbufsize); return -1; } if (fc_connect(client.conn.sock, &server_addr.saddr, sockaddr_size(&server_addr)) == -1) { (void) mystrlcpy(errbuf, fc_strerror(fc_get_errno()), errbufsize); fc_closesocket(client.conn.sock); client.conn.sock = -1; #ifdef HAVE_WINSOCK return -1; #else return errno; #endif } make_connection(client.conn.sock, username); return 0; }
/************************************************************************** Try to connect to a server (get_server_address() must be called first!): - try to create a TCP socket and connect it to `names' - if successful: - start monitoring the socket for packets from the server - send a "login request" packet to the server and - return 0 - if unable to create the connection, close the socket, put an error message in ERRBUF and return the Unix error code (ie., errno, which will be non-zero). **************************************************************************/ static int try_to_connect(const char *username, char *errbuf, int errbufsize) { int i; int sock = -1; connections_set_close_callback(client_conn_close_callback); /* connection in progress? wait. */ if (client.conn.used) { (void) fc_strlcpy(errbuf, _("Connection in progress."), errbufsize); return -1; } /* Try all (IPv4, IPv6, ...) addresses until we have a connection. */ sock = -1; for (i = 0; i < name_count; i++) { if ((sock = socket(names[i].saddr.sa_family, SOCK_STREAM, 0)) == -1) { /* Probably EAFNOSUPPORT or EPROTONOSUPPORT. */ continue; } if (fc_connect(sock, &names[i].saddr, sockaddr_size(&names[i])) == -1) { fc_closesocket(sock); sock = -1; continue; } else { /* We have a connection! */ break; } } client.conn.sock = sock; if (client.conn.sock == -1) { fc_errno err = fc_get_errno(); /* Save errno value before calling anything */ (void) fc_strlcpy(errbuf, fc_strerror(err), errbufsize); #ifdef HAVE_WINSOCK return -1; #else return err; #endif /* HAVE_WINSOCK */ } make_connection(client.conn.sock, username); return 0; }
/**************************************************************************** Begin a metaserver scan for servers. This just initiates the connection to the metaserver; later get_meta_server_list should be called whenever the socket has data pending to read and parse it. Returns FALSE on error (in which case errbuf will contain an error message). ****************************************************************************/ static bool begin_metaserver_scan(struct server_scan *scan) { union fc_sockaddr addr; int s; scan->meta.urlpath = fc_lookup_httpd(scan->meta.name, &scan->meta.port, metaserver); if (!scan->meta.urlpath) { scan->error_func(scan, _("Invalid $http_proxy or metaserver value, must " "start with 'http://'")); return FALSE; } if (!net_lookup_service(scan->meta.name, scan->meta.port, &addr, FALSE)) { scan->error_func(scan, _("Failed looking up metaserver's host")); return FALSE; } if ((s = socket(addr.saddr.sa_family, SOCK_STREAM, 0)) == -1) { scan->error_func(scan, fc_strerror(fc_get_errno())); return FALSE; } fc_nonblock(s); if (fc_connect(s, &addr.saddr, sockaddr_size(&addr)) == -1) { if (errno == EINPROGRESS) { /* With non-blocking sockets this is the expected result. */ scan->meta.state = META_CONNECTING; scan->sock = s; } else { fc_closesocket(s); scan->error_func(scan, fc_strerror(fc_get_errno())); return FALSE; } } else { /* Instant connection? Whoa. */ scan->sock = s; scan->meta.state = META_CONNECTING; meta_send_request(scan); } return TRUE; }