diff options
author | Jakub Sławiński | 2005-11-03 20:37:56 +0100 |
---|---|---|
committer | Joshua Judson Rosen | 2014-07-17 21:15:00 +0200 |
commit | 63bbc710b23893742e5ccbd430f95bf2d29c2da6 (patch) | |
tree | 06d0585724cff8a4f1a7c052b5b89fd12c404094 /src/network.c | |
parent | v0.7.2 (diff) | |
download | apf-63bbc710b23893742e5ccbd430f95bf2d29c2da6.tar.gz |
v0.7.4
- Fixed: sockets in CLOSE_WAIT state left by afclient
- Added: --localname and --localport options
- Added: --localdesname option
- Added: kicking user in 'opening' state
- Fixed: info about kicked user
- Fixed: TERM signal handling
- Fixed: id lost after reconnection
- Fixed: printing wrong client name in 'SSL_accept failed (timeout)' message
- Fixed: ignored 'certificate' and 'key' options from config file
- Added: config files for afclient
- Modified: some options in afserver config file
Diffstat (limited to 'src/network.c')
-rw-r--r-- | src/network.c | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/src/network.c b/src/network.c index 38569cc..60c17e9 100644 --- a/src/network.c +++ b/src/network.c @@ -125,6 +125,7 @@ ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, servaddr.sin_port = htons(port); if (bind((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){ + printf("bind failed\n"); return 4; } @@ -137,11 +138,14 @@ ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, } int -ip_connect(int* sockfd, const char *host, const char *serv, const char type) +ip_connect(int* sockfd, const char *host, const char *serv, const char type, + const char *lhost, const char *lserv) { #if defined(HAVE_GETADDRINFO) && defined(AF_INET6) int n; + int bindFailed; struct addrinfo hints, *res, *ressave; + struct addrinfo lhints, *lres, *lressave = NULL; bzero(&hints, sizeof(struct addrinfo)); if (type & 0x02) { @@ -160,6 +164,15 @@ ip_connect(int* sockfd, const char *host, const char *serv, const char type) hints.ai_socktype = SOCK_DGRAM; } + lhints = hints; + + if (lhost || lserv) { + if ( (n = getaddrinfo(lhost, lserv, &lhints, &lres)) != 0) { + return n; + } + lressave = lres; + } + if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { return n; } @@ -171,7 +184,24 @@ ip_connect(int* sockfd, const char *host, const char *serv, const char type) continue; /* ignore this one */ } - if (connect((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { + bindFailed = 0; + if (lhost || lserv) { + bindFailed = 1; + lres = lressave; + do { + if (bind((*sockfd), lres->ai_addr, lres->ai_addrlen) == 0) { + bindFailed = 0; + break; /* success */ + } + } while ( (lres = lres->ai_next) != NULL); + } + + if (bindFailed == 1) { + close((*sockfd)); /* ignore this one */ + continue; + } + + if (connect((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { break; /* success */ } @@ -182,11 +212,15 @@ ip_connect(int* sockfd, const char *host, const char *serv, const char type) return 1; } + if (lhost || lserv) { + freeaddrinfo(lressave); + } freeaddrinfo(ressave); #else - struct sockaddr_in servaddr; + struct sockaddr_in servaddr, lservaddr; struct hostent* hostaddr; - int port; + struct hostent* lhostaddr; + int port, lport; if (type & 0x01) { (*sockfd) = socket(AF_INET, SOCK_STREAM, 0); @@ -210,8 +244,30 @@ ip_connect(int* sockfd, const char *host, const char *serv, const char type) servaddr.sin_port = htons(port); memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length); + if (lhost || lserv) { + memset(&lservaddr, 0, sizeof(lservaddr)); + lservaddr.sin_family = AF_INET; + if (lserv) { + lport = atoi(lserv); + lservaddr.sin_port = htons(lport); + } + if (lhost) { + lhostaddr = gethostbyname(lhost); + if (lhostaddr == NULL) { + return 3; + } + memcpy(&lservaddr.sin_addr.s_addr, lhostaddr->h_addr_list[0], lhostaddr->h_length); + } + else { + lservaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + if (bind((*sockfd), (struct sockaddr*) &lservaddr, sizeof(lservaddr))){ + return 4; + } + } + if (connect((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){ - return 3; + return 5; } #endif |