diff options
Diffstat (limited to 'ext/Socket/Socket.xs')
-rw-r--r-- | ext/Socket/Socket.xs | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/ext/Socket/Socket.xs b/ext/Socket/Socket.xs index 7a0bf465b2..1f32dab79c 100644 --- a/ext/Socket/Socket.xs +++ b/ext/Socket/Socket.xs @@ -2,7 +2,19 @@ #include "perl.h" #include "XSUB.h" +#ifndef VMS +# ifdef I_SYS_TYPES +# include <sys/types.h> +# endif #include <sys/socket.h> +# ifdef I_NETINET_IN +# include <netinet/in.h> +# endif +#include <netdb.h> +#include <arpa/inet.h> +#else +#include "sockadapt.h" +#endif #ifndef AF_NBS #undef PF_NBS @@ -12,6 +24,14 @@ #undef PF_X25 #endif +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif /* INADDR_NONE */ +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK 0x7F000001 +#endif /* INADDR_LOOPBACK */ + + static int not_here(s) char *s; @@ -556,6 +576,7 @@ not_there: return 0; } + MODULE = Socket PACKAGE = Socket double @@ -563,3 +584,116 @@ constant(name,arg) char * name int arg + +void +inet_aton(host) + char * host + CODE: + { + struct in_addr ip_address; + struct hostent * phe; + + if (phe = gethostbyname(host)) { + Copy( phe->h_addr, &ip_address, phe->h_length, char ); + } else { + ip_address.s_addr = inet_addr(host); + } + + ST(0) = sv_newmortal(); + if(ip_address.s_addr != INADDR_NONE) { + sv_setpvn( ST(0), (char *)&ip_address, sizeof ip_address ); + } + } + +void +inet_ntoa(ip_address_sv) + SV * ip_address_sv + CODE: + { + STRLEN addrlen; + struct in_addr addr; + char * addr_str; + char * ip_address = SvPV(ip_address_sv,addrlen); + if (addrlen != sizeof(addr)) { + croak("Bad arg length for %s, length is %d, should be %d", + "Socket::inet_ntoa", + addrlen, sizeof(addr)); + } + + Copy( ip_address, &addr, sizeof addr, char ); + addr_str = inet_ntoa(addr); + + ST(0) = sv_2mortal(newSVpv(addr_str, strlen(addr_str))); + } + +void +pack_sockaddr_in(family,port,ip_address) + short family + short port + char * ip_address + CODE: + { + struct sockaddr_in sin; + + Zero( &sin, sizeof sin, char ); + sin.sin_family = family; + sin.sin_port = htons(port); + Copy( ip_address, &sin.sin_addr, sizeof sin.sin_addr, char ); + + ST(0) = sv_2mortal(newSVpv((char *)&sin, sizeof sin)); + } + +void +unpack_sockaddr_in(sin_sv) + SV * sin_sv + PPCODE: + { + STRLEN sockaddrlen; + struct sockaddr_in addr; + short family; + short port; + struct in_addr ip_address; + char * sin = SvPV(sin_sv,sockaddrlen); + if (sockaddrlen != sizeof(addr)) { + croak("Bad arg length for %s, length is %d, should be %d", + "Socket::unpack_sockaddr_in", + sockaddrlen, sizeof(addr)); + } + + Copy( sin, &addr,sizeof addr, char ); + family = addr.sin_family; + port = ntohs(addr.sin_port); + ip_address = addr.sin_addr; + + EXTEND(sp, 3); + PUSHs(sv_2mortal(newSViv(family))); + PUSHs(sv_2mortal(newSViv(port))); + PUSHs(sv_2mortal(newSVpv((char *)&ip_address,sizeof ip_address))); + } + +void +INADDR_ANY() + CODE: + { + struct in_addr ip_address; + ip_address.s_addr = htonl(INADDR_ANY); + ST(0) = sv_2mortal(newSVpv((char *)&ip_address,sizeof ip_address )); + } + +void +INADDR_LOOPBACK() + CODE: + { + struct in_addr ip_address; + ip_address.s_addr = htonl(INADDR_LOOPBACK); + ST(0) = sv_2mortal(newSVpv((char *)&ip_address,sizeof ip_address)); + } + +void +INADDR_NONE() + CODE: + { + struct in_addr ip_address; + ip_address.s_addr = htonl(INADDR_NONE); + ST(0) = sv_2mortal(newSVpv((char *)&ip_address,sizeof ip_address)); + } |