diff options
author | kraxel <kraxel> | 2007-08-08 16:00:20 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2007-08-08 16:00:20 +0000 |
commit | 3a85ea7edc0cb352febcf1bc6ee242b672cf7965 (patch) | |
tree | 2d5b3b4b1070c58da7e0022efe82bf03d3eeb698 /tcp.c | |
download | amtterm-3a85ea7edc0cb352febcf1bc6ee242b672cf7965.tar.gz |
Initial revision
Diffstat (limited to 'tcp.c')
-rw-r--r-- | tcp.c | 153 |
1 files changed, 153 insertions, 0 deletions
@@ -0,0 +1,153 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> + +#include "tcp.h" + +int tcp_verbose; + +/* ------------------------------------------------------------------ */ + +static char *strfamily(int family) +{ + switch (family) { + case PF_INET6: return "ipv6"; + case PF_INET: return "ipv4"; + case PF_UNIX: return "unix"; + } + return "????"; +} + +int tcp_connect(struct addrinfo *ai, + char *addr, char *port, + char *host, char *serv) +{ + struct addrinfo *res,*e; + struct addrinfo *lres, ask; + char uaddr[INET6_ADDRSTRLEN+1]; + char uport[33]; + char uhost[INET6_ADDRSTRLEN+1]; + char userv[33]; + int sock,rc,opt=1; + + /* lookup peer */ + ai->ai_flags = AI_CANONNAME; + if (0 != (rc = getaddrinfo(host, serv, ai, &res))) { + if (tcp_verbose) + fprintf(stderr,"getaddrinfo (peer): %s\n", gai_strerror(rc)); + return -1; + } + for (e = res; e != NULL; e = e->ai_next) { + if (0 != getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, + uhost,INET6_ADDRSTRLEN,userv,32, + NI_NUMERICHOST | NI_NUMERICSERV)) { + if (tcp_verbose) + fprintf(stderr,"getnameinfo (peer): oops\n"); + continue; + } + if (-1 == (sock = socket(e->ai_family, e->ai_socktype, + e->ai_protocol))) { + if (tcp_verbose) + fprintf(stderr,"socket (%s): %s\n", + strfamily(e->ai_family),strerror(errno)); + continue; + } + setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); + if (NULL != addr || NULL != port) { + /* bind local port */ + memset(&ask,0,sizeof(ask)); + ask.ai_flags = AI_PASSIVE; + ask.ai_family = e->ai_family; + ask.ai_socktype = e->ai_socktype; + if (0 != (rc = getaddrinfo(addr, port, &ask, &lres))) { + if (tcp_verbose) + fprintf(stderr,"getaddrinfo (local): %s\n", + gai_strerror(rc)); + continue; + } + if (0 != getnameinfo((struct sockaddr*)lres->ai_addr, + lres->ai_addrlen, + uaddr,INET6_ADDRSTRLEN,uport,32, + NI_NUMERICHOST | NI_NUMERICSERV)) { + if (tcp_verbose) + fprintf(stderr,"getnameinfo (local): oops\n"); + continue; + } + if (-1 == bind(sock, lres->ai_addr, lres->ai_addrlen)) { + if (tcp_verbose) + fprintf(stderr,"%s [%s] %s bind: %s\n", + strfamily(lres->ai_family),uaddr,uport, + strerror(errno)); + continue; + } + } + /* connect to peer */ + if (-1 == connect(sock,e->ai_addr,e->ai_addrlen)) { + if (tcp_verbose) + fprintf(stderr,"%s %s [%s] %s connect: %s\n", + strfamily(e->ai_family),e->ai_canonname,uhost,userv, + strerror(errno)); + close(sock); + continue; + } + if (tcp_verbose) + fprintf(stderr,"%s %s [%s] %s open\n", + strfamily(e->ai_family),e->ai_canonname,uhost,userv); + fcntl(sock,F_SETFL,O_NONBLOCK); + return sock; + } + return -1; +} + +int tcp_listen(struct addrinfo *ai, char *addr, char *port) +{ + struct addrinfo *res,*e; + char uaddr[INET6_ADDRSTRLEN+1]; + char uport[33]; + int slisten,rc,opt=1; + + /* lookup */ + ai->ai_flags = AI_PASSIVE; + if (0 != (rc = getaddrinfo(addr, port, ai, &res))) { + if (tcp_verbose) + fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(rc)); + exit(1); + } + + /* create socket + bind */ + for (e = res; e != NULL; e = e->ai_next) { + getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, + uaddr,INET6_ADDRSTRLEN,uport,32, + NI_NUMERICHOST | NI_NUMERICSERV); + if (-1 == (slisten = socket(e->ai_family, e->ai_socktype, + e->ai_protocol))) { + if (tcp_verbose) + fprintf(stderr,"socket (%s): %s\n", + strfamily(e->ai_family),strerror(errno)); + continue; + } + opt = 1; + setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); + if (-1 == bind(slisten, e->ai_addr, e->ai_addrlen)) { + if (tcp_verbose) + fprintf(stderr,"%s [%s] %s bind: %s\n", + strfamily(e->ai_family),uaddr,uport, + strerror(errno)); + continue; + } + listen(slisten,1); + break; + } + if (NULL == e) + return -1; + + /* wait for a incoming connection */ + if (tcp_verbose) + fprintf(stderr,"listen on %s [%s] %s ...\n", + strfamily(e->ai_family),uaddr,uport); + fcntl(slisten,F_SETFL,O_NONBLOCK); + return slisten; +} |