Support for IPv6:
(tcp_listen, player_addrlen): New. IPv4-only code factored out of player_init(). (player_init): Use them. (player_accept): Address family independence. (tcp_connect): New. (main): Use it. (hostaddr, hostconnect, hostport): Internal linkage.
This commit is contained in:
parent
75a511a749
commit
19d88af312
7 changed files with 267 additions and 87 deletions
|
@ -30,11 +30,14 @@
|
|||
* Known contributors to this file:
|
||||
* Dave Pare, 1989
|
||||
* Steve McClure, 1998
|
||||
* Markus Armbruster, 2005
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -48,9 +51,55 @@
|
|||
#include <io.h>
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
/*
|
||||
* Inspired by example code from W. Richard Stevens: UNIX Network
|
||||
* Programming, Vol. 1
|
||||
*/
|
||||
|
||||
int
|
||||
tcp_connect(char *host, char *serv)
|
||||
{
|
||||
int sockfd, n;
|
||||
struct addrinfo hints, *res, *ressave;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((n = getaddrinfo(host, serv, &hints, &res)) != 0) {
|
||||
fprintf(stderr, "Can't connect to %s:%s: %s\n",
|
||||
host, serv, gai_strerror(n));
|
||||
exit(1);
|
||||
}
|
||||
ressave = res;
|
||||
|
||||
do {
|
||||
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (sockfd < 0)
|
||||
continue; /* ignore this one */
|
||||
|
||||
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
|
||||
break; /* success */
|
||||
|
||||
close(sockfd); /* ignore this one */
|
||||
} while ((res = res->ai_next) != NULL);
|
||||
|
||||
if (res == NULL) { /* errno set from final connect() */
|
||||
fprintf(stderr, "Can't connect to %s:%s: %s\n",
|
||||
host, serv, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
freeaddrinfo(ressave);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
#else /* !HAVE_GETADDRINFO */
|
||||
|
||||
static int
|
||||
hostaddr(char *name, struct sockaddr_in *addr)
|
||||
{
|
||||
struct hostent *hp;
|
||||
|
@ -68,7 +117,7 @@ hostaddr(char *name, struct sockaddr_in *addr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
hostport(char *name, struct sockaddr_in *addr)
|
||||
{
|
||||
struct servent *sp;
|
||||
|
@ -86,9 +135,10 @@ hostport(char *name, struct sockaddr_in *addr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
hostconnect(struct sockaddr_in *addr)
|
||||
{
|
||||
/* FIXME should attempt connect to all addresses of multi-homed host, not just 1st */
|
||||
int s;
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
@ -108,3 +158,26 @@ hostconnect(struct sockaddr_in *addr)
|
|||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
tcp_connect(char *host, char *serv)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int sock;
|
||||
|
||||
if (!hostport(serv, &sin)) {
|
||||
fprintf(stderr, "Can't resolve Empire port %s\n", serv);
|
||||
exit(1);
|
||||
}
|
||||
if (!hostaddr(host, &sin)) {
|
||||
fprintf(stderr, "Can't resolve Empire host %s\n", host);
|
||||
exit(1);
|
||||
}
|
||||
if ((sock = hostconnect(&sin)) < 0) {
|
||||
fprintf(stderr, "Can't connect to %s:%s: %s\n",
|
||||
serv, host, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue