static int unify_address(term_t t, struct sockaddr_in *addr) { term_t av = PL_new_term_refs(2); if ( !nbio_unify_ip4(av+0, ntohl(addr->sin_addr.s_addr)) || !PL_unify_integer(av+1, ntohs(addr->sin_port)) ) return FALSE; return PL_unify_term(t, PL_FUNCTOR_CHARS, ":", 2, PL_TERM, av+0, PL_TERM, av+1); }
static foreign_t pl_host_to_address(term_t Host, term_t Ip) { struct in_addr ip; char *host_name; if ( PL_get_atom_chars(Host, &host_name) ) { struct addrinfo hints; struct addrinfo *res; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; if ( getaddrinfo(host_name, NULL, &hints, &res) == 0 ) { int rc; switch( res->ai_family ) { case AF_INET: { struct sockaddr_in *addr = (struct sockaddr_in*)res->ai_addr; rc = nbio_unify_ip4(Ip, ntohl(addr->sin_addr.s_addr)); break; } case AF_INET6: { rc = PL_warning("tcp_host_to_address/2: IPv6 address not supported"); break; } default: assert(0); rc = FALSE; } freeaddrinfo(res); return rc; } else { return nbio_error(h_errno, TCP_HERRNO); } } else if ( nbio_get_ip(Ip, &ip) ) { struct hostent *host; if ( (host = gethostbyaddr((char *)&ip, sizeof(ip), AF_INET)) ) return PL_unify_atom_chars(Host, host->h_name); else return nbio_error(h_errno, TCP_HERRNO); } return FALSE; }
static foreign_t pl_accept(term_t Master, term_t Slave, term_t Peer) { int master, slave; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); if ( !tcp_get_socket(Master, &master) ) return FALSE; if ( (slave = nbio_accept(master, (struct sockaddr*)&addr, &addrlen)) < 0 ) return FALSE; /* TBD: close on failure */ if ( nbio_unify_ip4(Peer, ntohl(addr.sin_addr.s_addr)) && tcp_unify_socket(Slave, slave) ) return TRUE; return FALSE; }
static foreign_t pl_host_to_address(term_t Host, term_t Ip) { struct in_addr ip; struct hostent *host; char *host_name; if ( PL_get_atom_chars(Host, &host_name) ) { if ( (host = gethostbyname(host_name)) ) { if ( sizeof(ip) == host->h_length ) { memcpy(&ip, host->h_addr, host->h_length); return nbio_unify_ip4(Ip, ntohl(ip.s_addr)); } else return PL_warning("tcp_host_to_address/2: length mismatch in address"); } else return nbio_error(h_errno, TCP_HERRNO); } else if ( nbio_get_ip(Ip, &ip) ) { if ( (host = gethostbyaddr((char *)&ip, sizeof(ip), AF_INET)) ) return PL_unify_atom_chars(Host, host->h_name); else return nbio_error(h_errno, TCP_HERRNO); } return FALSE; }