4 Interface for perl socket functions
11 #define USE_SOCKETS_AS_HANDLES
13 class CPerlSock : public IPerlSock
18 virtual u_long Htonl(u_long hostlong);
19 virtual u_short Htons(u_short hostshort);
20 virtual u_long Ntohl(u_long netlong);
21 virtual u_short Ntohs(u_short netshort);
22 virtual SOCKET Accept(SOCKET s, struct sockaddr* addr, int* addrlen, int &err);
23 virtual int Bind(SOCKET s, const struct sockaddr* name, int namelen, int &err);
24 virtual int Connect(SOCKET s, const struct sockaddr* name, int namelen, int &err);
25 virtual void Endhostent(int &err);
26 virtual void Endnetent(int &err);
27 virtual void Endprotoent(int &err);
28 virtual void Endservent(int &err);
29 virtual struct hostent* Gethostbyaddr(const char* addr, int len, int type, int &err);
30 virtual struct hostent* Gethostbyname(const char* name, int &err);
31 virtual struct hostent* Gethostent(int &err);
32 virtual int Gethostname(char* name, int namelen, int &err);
33 virtual struct netent *Getnetbyaddr(long net, int type, int &err);
34 virtual struct netent *Getnetbyname(const char *, int &err);
35 virtual struct netent *Getnetent(int &err);
36 virtual int Getpeername(SOCKET s, struct sockaddr* name, int* namelen, int &err);
37 virtual struct protoent* Getprotobyname(const char* name, int &err);
38 virtual struct protoent* Getprotobynumber(int number, int &err);
39 virtual struct protoent* Getprotoent(int &err);
40 virtual struct servent* Getservbyname(const char* name, const char* proto, int &err);
41 virtual struct servent* Getservbyport(int port, const char* proto, int &err);
42 virtual struct servent* Getservent(int &err);
43 virtual int Getsockname(SOCKET s, struct sockaddr* name, int* namelen, int &err);
44 virtual int Getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen, int &err);
45 virtual unsigned long InetAddr(const char* cp, int &err);
46 virtual char* InetNtoa(struct in_addr in, int &err);
47 virtual int IoctlSocket(SOCKET s, long cmd, u_long *argp, int& err);
48 virtual int Listen(SOCKET s, int backlog, int &err);
49 virtual int Recvfrom(SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen, int &err);
50 virtual int Select(int nfds, char* readfds, char* writefds, char* exceptfds, const struct timeval* timeout, int &err);
51 virtual int Send(SOCKET s, const char* buffer, int len, int flags, int &err);
52 virtual int Sendto(SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen, int &err);
53 virtual void Sethostent(int stayopen, int &err);
54 virtual void Setnetent(int stayopen, int &err);
55 virtual void Setprotoent(int stayopen, int &err);
56 virtual void Setservent(int stayopen, int &err);
57 virtual int Setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen, int &err);
58 virtual int Shutdown(SOCKET s, int how, int &err);
59 virtual SOCKET Socket(int af, int type, int protocol, int &err);
60 virtual int Socketpair(int domain, int type, int protocol, int* fds, int &err);
62 void CloseSocket(int fh, int& err);
63 void* GetAddress(HINSTANCE hInstance, char *lpFunctionName);
64 void LoadWinSock(void);
66 inline void SetPerlObj(CPerlObj *p) { pPerl = p; };
67 inline void SetStdObj(IPerlStdIOWin *p) { pStdIO = p; };
71 inline int OpenOSfhandle(long osfhandle)
73 return pStdIO->OpenOSfhandle(osfhandle, O_RDWR|O_BINARY);
75 int GetOSfhandle(int filenum)
77 return pStdIO->GetOSfhandle(filenum);
80 inline void StartSockets(void)
88 IPerlStdIOWin *pStdIO;
92 #define SOCKETAPI PASCAL
94 typedef SOCKET (SOCKETAPI *LPSOCKACCEPT)(SOCKET, struct sockaddr *, int *);
95 typedef int (SOCKETAPI *LPSOCKBIND)(SOCKET, const struct sockaddr *, int);
96 typedef int (SOCKETAPI *LPSOCKCLOSESOCKET)(SOCKET);
97 typedef int (SOCKETAPI *LPSOCKCONNECT)(SOCKET, const struct sockaddr *, int);
98 typedef unsigned long (SOCKETAPI *LPINETADDR)(const char *);
99 typedef char* (SOCKETAPI *LPINETNTOA)(struct in_addr);
100 typedef int (SOCKETAPI *LPSOCKIOCTLSOCKET)(SOCKET, long, u_long *);
101 typedef int (SOCKETAPI *LPSOCKGETPEERNAME)(SOCKET, struct sockaddr *, int *);
102 typedef int (SOCKETAPI *LPSOCKGETSOCKNAME)(SOCKET, struct sockaddr *, int *);
103 typedef int (SOCKETAPI *LPSOCKGETSOCKOPT)(SOCKET, int, int, char *, int *);
104 typedef u_long (SOCKETAPI *LPSOCKHTONL)(u_long);
105 typedef u_short (SOCKETAPI *LPSOCKHTONS)(u_short);
106 typedef int (SOCKETAPI *LPSOCKLISTEN)(SOCKET, int);
107 typedef u_long (SOCKETAPI *LPSOCKNTOHL)(u_long);
108 typedef u_short (SOCKETAPI *LPSOCKNTOHS)(u_short);
109 typedef int (SOCKETAPI *LPSOCKRECV)(SOCKET, char *, int, int);
110 typedef int (SOCKETAPI *LPSOCKRECVFROM)(SOCKET, char *, int, int, struct sockaddr *, int *);
111 typedef int (SOCKETAPI *LPSOCKSELECT)(int, fd_set *, fd_set *, fd_set *, const struct timeval *);
112 typedef int (SOCKETAPI *LPSOCKSEND)(SOCKET, const char *, int, int);
113 typedef int (SOCKETAPI *LPSOCKSENDTO)(SOCKET, const char *, int, int, const struct sockaddr *, int);
114 typedef int (SOCKETAPI *LPSOCKSETSOCKOPT)(SOCKET, int, int, const char *, int);
115 typedef int (SOCKETAPI *LPSOCKSHUTDOWN)(SOCKET, int);
116 typedef SOCKET (SOCKETAPI *LPSOCKSOCKET)(int, int, int);
118 /* Database function prototypes */
119 typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYADDR)(const char *, int, int);
120 typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYNAME)(const char *);
121 typedef int (SOCKETAPI *LPSOCKGETHOSTNAME)(char *, int);
122 typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYPORT)(int, const char *);
123 typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYNAME)(const char *, const char *);
124 typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNUMBER)(int);
125 typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNAME)(const char *);
127 /* Microsoft Windows Extension function prototypes */
128 typedef int (SOCKETAPI *LPSOCKWSASTARTUP)(unsigned short, LPWSADATA);
129 typedef int (SOCKETAPI *LPSOCKWSACLEANUP)(void);
130 typedef int (SOCKETAPI *LPSOCKWSAGETLASTERROR)(void);
131 typedef int (SOCKETAPI *LPWSAFDIsSet)(SOCKET, fd_set *);
133 static HINSTANCE hWinSockDll = 0;
135 static LPSOCKACCEPT paccept = 0;
136 static LPSOCKBIND pbind = 0;
137 static LPSOCKCLOSESOCKET pclosesocket = 0;
138 static LPSOCKCONNECT pconnect = 0;
139 static LPINETADDR pinet_addr = 0;
140 static LPINETNTOA pinet_ntoa = 0;
141 static LPSOCKIOCTLSOCKET pioctlsocket = 0;
142 static LPSOCKGETPEERNAME pgetpeername = 0;
143 static LPSOCKGETSOCKNAME pgetsockname = 0;
144 static LPSOCKGETSOCKOPT pgetsockopt = 0;
145 static LPSOCKHTONL phtonl = 0;
146 static LPSOCKHTONS phtons = 0;
147 static LPSOCKLISTEN plisten = 0;
148 static LPSOCKNTOHL pntohl = 0;
149 static LPSOCKNTOHS pntohs = 0;
150 static LPSOCKRECV precv = 0;
151 static LPSOCKRECVFROM precvfrom = 0;
152 static LPSOCKSELECT pselect = 0;
153 static LPSOCKSEND psend = 0;
154 static LPSOCKSENDTO psendto = 0;
155 static LPSOCKSETSOCKOPT psetsockopt = 0;
156 static LPSOCKSHUTDOWN pshutdown = 0;
157 static LPSOCKSOCKET psocket = 0;
158 static LPSOCKGETHOSTBYADDR pgethostbyaddr = 0;
159 static LPSOCKGETHOSTBYNAME pgethostbyname = 0;
160 static LPSOCKGETHOSTNAME pgethostname = 0;
161 static LPSOCKGETSERVBYPORT pgetservbyport = 0;
162 static LPSOCKGETSERVBYNAME pgetservbyname = 0;
163 static LPSOCKGETPROTOBYNUMBER pgetprotobynumber = 0;
164 static LPSOCKGETPROTOBYNAME pgetprotobyname = 0;
165 static LPSOCKWSASTARTUP pWSAStartup = 0;
166 static LPSOCKWSACLEANUP pWSACleanup = 0;
167 static LPSOCKWSAGETLASTERROR pWSAGetLastError = 0;
168 static LPWSAFDIsSet pWSAFDIsSet = 0;
170 void* CPerlSock::GetAddress(HINSTANCE hInstance, char *lpFunctionName)
173 FARPROC proc = GetProcAddress(hInstance, lpFunctionName);
176 sprintf(buffer, "Unable to get address of %s in WSock32.dll", lpFunctionName);
182 void CPerlSock::LoadWinSock(void)
184 if(hWinSockDll == NULL)
186 HINSTANCE hLib = LoadLibrary("WSock32.DLL");
188 croak("Could not load WSock32.dll\n");
190 paccept = (LPSOCKACCEPT)GetAddress(hLib, "accept");
191 pbind = (LPSOCKBIND)GetAddress(hLib, "bind");
192 pclosesocket = (LPSOCKCLOSESOCKET)GetAddress(hLib, "closesocket");
193 pconnect = (LPSOCKCONNECT)GetAddress(hLib, "connect");
194 pinet_addr = (LPINETADDR)GetAddress(hLib, "inet_addr");
195 pinet_ntoa = (LPINETNTOA)GetAddress(hLib, "inet_ntoa");
196 pioctlsocket = (LPSOCKIOCTLSOCKET)GetAddress(hLib, "ioctlsocket");
197 pgetpeername = (LPSOCKGETPEERNAME)GetAddress(hLib, "getpeername");
198 pgetsockname = (LPSOCKGETSOCKNAME)GetAddress(hLib, "getsockname");
199 pgetsockopt = (LPSOCKGETSOCKOPT)GetAddress(hLib, "getsockopt");
200 phtonl = (LPSOCKHTONL)GetAddress(hLib, "htonl");
201 phtons = (LPSOCKHTONS)GetAddress(hLib, "htons");
202 plisten = (LPSOCKLISTEN)GetAddress(hLib, "listen");
203 pntohl = (LPSOCKNTOHL)GetAddress(hLib, "ntohl");
204 pntohs = (LPSOCKNTOHS)GetAddress(hLib, "ntohs");
205 precv = (LPSOCKRECV)GetAddress(hLib, "recv");
206 precvfrom = (LPSOCKRECVFROM)GetAddress(hLib, "recvfrom");
207 pselect = (LPSOCKSELECT)GetAddress(hLib, "select");
208 psend = (LPSOCKSEND)GetAddress(hLib, "send");
209 psendto = (LPSOCKSENDTO)GetAddress(hLib, "sendto");
210 psetsockopt = (LPSOCKSETSOCKOPT)GetAddress(hLib, "setsockopt");
211 pshutdown = (LPSOCKSHUTDOWN)GetAddress(hLib, "shutdown");
212 psocket = (LPSOCKSOCKET)GetAddress(hLib, "socket");
213 pgethostbyaddr = (LPSOCKGETHOSTBYADDR)GetAddress(hLib, "gethostbyaddr");
214 pgethostbyname = (LPSOCKGETHOSTBYNAME)GetAddress(hLib, "gethostbyname");
215 pgethostname = (LPSOCKGETHOSTNAME)GetAddress(hLib, "gethostname");
216 pgetservbyport = (LPSOCKGETSERVBYPORT)GetAddress(hLib, "getservbyport");
217 pgetservbyname = (LPSOCKGETSERVBYNAME)GetAddress(hLib, "getservbyname");
218 pgetprotobynumber = (LPSOCKGETPROTOBYNUMBER)GetAddress(hLib, "getprotobynumber");
219 pgetprotobyname = (LPSOCKGETPROTOBYNAME)GetAddress(hLib, "getprotobyname");
220 pWSAStartup = (LPSOCKWSASTARTUP)GetAddress(hLib, "WSAStartup");
221 pWSACleanup = (LPSOCKWSACLEANUP)GetAddress(hLib, "WSACleanup");
222 pWSAGetLastError = (LPSOCKWSAGETLASTERROR)GetAddress(hLib, "WSAGetLastError");
223 pWSAFDIsSet = (LPWSAFDIsSet)GetAddress(hLib, "__WSAFDIsSet");
229 CPerlSock::CPerlSock()
236 CPerlSock::~CPerlSock()
243 CPerlSock::Start(void)
245 unsigned short version;
248 int iSockOpt = SO_SYNCHRONOUS_NONALERT;
252 * initalize the winsock interface and insure that it is
253 * cleaned up at exit.
256 if(ret = pWSAStartup(version, &retdata))
257 croak("Unable to locate winsock library!\n");
258 if(retdata.wVersion != version)
259 croak("Could not find version 1.1 of winsock dll\n");
261 /* atexit((void (*)(void)) EndSockets); */
263 #ifdef USE_SOCKETS_AS_HANDLES
265 * Enable the use of sockets as filehandles
267 psetsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
268 (char *)&iSockOpt, sizeof(iSockOpt));
269 #endif /* USE_SOCKETS_AS_HANDLES */
275 CPerlSock::Htonl(u_long hostlong)
278 return phtonl(hostlong);
282 CPerlSock::Htons(u_short hostshort)
285 return phtons(hostshort);
289 CPerlSock::Ntohl(u_long netlong)
292 return pntohl(netlong);
296 CPerlSock::Ntohs(u_short netshort)
299 return pntohs(netshort);
303 /* thanks to Beverly Brown (beverly@datacube.com) */
304 #ifdef USE_SOCKETS_AS_HANDLES
305 # define OPEN_SOCKET(x) OpenOSfhandle(x)
306 # define TO_SOCKET(x) GetOSfhandle(x)
308 # define OPEN_SOCKET(x) (x)
309 # define TO_SOCKET(x) (x)
310 #endif /* USE_SOCKETS_AS_HANDLES */
312 #define SOCKET_TEST(x, y) \
316 err = pWSAGetLastError(); \
319 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
322 CPerlSock::Accept(SOCKET s, struct sockaddr* addr, int* addrlen, int &err)
326 SOCKET_TEST((r = paccept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
327 return OPEN_SOCKET(r);
331 CPerlSock::Bind(SOCKET s, const struct sockaddr* addr, int addrlen, int &err)
335 SOCKET_TEST_ERROR(r = pbind(TO_SOCKET(s), addr, addrlen));
340 CPerlSock::CloseSocket(int fh, int& err)
342 SOCKET_TEST_ERROR(pclosesocket(TO_SOCKET(fh)));
346 CPerlSock::Connect(SOCKET s, const struct sockaddr* addr, int addrlen, int &err)
350 SOCKET_TEST_ERROR(r = pconnect(TO_SOCKET(s), addr, addrlen));
354 void CPerlSock::Endhostent(int &err)
356 croak("endhostent not implemented!\n");
359 void CPerlSock::Endnetent(int &err)
361 croak("endnetent not implemented!\n");
364 void CPerlSock::Endprotoent(int &err)
366 croak("endprotoent not implemented!\n");
369 void CPerlSock::Endservent(int &err)
371 croak("endservent not implemented!\n");
375 CPerlSock::Gethostbyaddr(const char* addr, int len, int type, int &err)
379 SOCKET_TEST(r = pgethostbyaddr(addr, len, type), NULL);
384 CPerlSock::Gethostbyname(const char* name, int &err)
388 SOCKET_TEST(r = pgethostbyname(name), NULL);
392 struct hostent* CPerlSock::Gethostent(int &err)
394 croak("gethostent not implemented!\n");
399 CPerlSock::Gethostname(char* name, int len, int &err)
403 SOCKET_TEST_ERROR(r = pgethostname(name, len));
407 struct netent *CPerlSock::Getnetbyaddr(long net, int type, int &err)
409 croak("getnetbyaddr not implemented!\n");
413 struct netent *CPerlSock::Getnetbyname(const char *, int &err)
415 croak("getnetbyname not implemented!\n");
419 struct netent *CPerlSock::Getnetent(int &err)
421 croak("getnetent not implemented!\n");
426 CPerlSock::Getpeername(SOCKET s, struct sockaddr* addr, int* addrlen, int &err)
430 SOCKET_TEST_ERROR(r = pgetpeername(TO_SOCKET(s), addr, addrlen));
435 CPerlSock::Getprotobyname(const char* name, int &err)
439 SOCKET_TEST(r = pgetprotobyname(name), NULL);
444 CPerlSock::Getprotobynumber(int number, int &err)
448 SOCKET_TEST(r = pgetprotobynumber(number), NULL);
452 struct protoent* CPerlSock::Getprotoent(int &err)
454 croak("getprotoent not implemented!\n");
459 CPerlSock::Getservbyname(const char* name, const char* proto, int &err)
464 SOCKET_TEST(r = pgetservbyname(name, proto), NULL);
466 // r = win32_savecopyservent(&myservent, r, proto);
472 CPerlSock::Getservbyport(int port, const char* proto, int &err)
477 SOCKET_TEST(r = pgetservbyport(port, proto), NULL);
479 // r = win32_savecopyservent(&myservent, r, proto);
484 struct servent* CPerlSock::Getservent(int &err)
486 croak("getservent not implemented!\n");
491 CPerlSock::Getsockname(SOCKET s, struct sockaddr* addr, int* addrlen, int &err)
495 SOCKET_TEST_ERROR(r = pgetsockname(TO_SOCKET(s), addr, addrlen));
500 CPerlSock::Getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen, int &err)
504 SOCKET_TEST_ERROR(r = pgetsockopt(TO_SOCKET(s), level, optname, optval, optlen));
509 CPerlSock::InetAddr(const char* cp, int &err)
513 SOCKET_TEST(r = pinet_addr(cp), INADDR_NONE);
518 CPerlSock::InetNtoa(struct in_addr in, int &err)
522 SOCKET_TEST(r = pinet_ntoa(in), NULL);
527 CPerlSock::IoctlSocket(SOCKET s, long cmd, u_long *argp, int& err)
531 SOCKET_TEST_ERROR(r = pioctlsocket(TO_SOCKET(s), cmd, argp));
536 CPerlSock::Listen(SOCKET s, int backlog, int &err)
540 SOCKET_TEST_ERROR(r = plisten(TO_SOCKET(s), backlog));
545 CPerlSock::Recvfrom(SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen, int &err)
549 SOCKET_TEST_ERROR(r = precvfrom(TO_SOCKET(s), buffer, len, flags, from, fromlen));
554 CPerlSock::Select(int nfds, char* rd, char* wr, char* ex, const struct timeval* timeout, int &err)
557 int i, fd, bit, offset;
558 FD_SET nrd, nwr, nex;
563 for (i = 0; i < nfds; i++)
566 bit = 1L<<(i % (sizeof(char)*8));
567 offset = i / (sizeof(char)*8);
568 if(rd != NULL && (rd[offset] & bit))
570 if(wr != NULL && (wr[offset] & bit))
572 if(ex != NULL && (ex[offset] & bit))
575 SOCKET_TEST_ERROR(r = pselect(nfds, &nrd, &nwr, &nex, timeout));
577 for(i = 0; i < nfds; i++)
580 bit = 1L<<(i % (sizeof(char)*8));
581 offset = i / (sizeof(char)*8);
582 if(rd != NULL && (rd[offset] & bit))
584 if(!pWSAFDIsSet(fd, &nrd))
587 if(wr != NULL && (wr[offset] & bit))
589 if(!pWSAFDIsSet(fd, &nwr))
592 if(ex != NULL && (ex[offset] & bit))
594 if(!pWSAFDIsSet(fd, &nex))
602 CPerlSock::Send(SOCKET s, const char* buffer, int len, int flags, int &err)
606 SOCKET_TEST_ERROR(r = psend(TO_SOCKET(s), buffer, len, flags));
611 CPerlSock::Sendto(SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen, int &err)
615 SOCKET_TEST_ERROR(r = psendto(TO_SOCKET(s), buffer, len, flags, to, tolen));
619 void CPerlSock::Sethostent(int stayopen, int &err)
621 croak("sethostent not implemented!\n");
624 void CPerlSock::Setnetent(int stayopen, int &err)
626 croak("setnetent not implemented!\n");
629 void CPerlSock::Setprotoent(int stayopen, int &err)
631 croak("setprotoent not implemented!\n");
634 void CPerlSock::Setservent(int stayopen, int &err)
636 croak("setservent not implemented!\n");
640 CPerlSock::Setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen, int &err)
644 SOCKET_TEST_ERROR(r = psetsockopt(TO_SOCKET(s), level, optname, optval, optlen));
649 CPerlSock::Shutdown(SOCKET s, int how, int &err)
653 SOCKET_TEST_ERROR(r = pshutdown(TO_SOCKET(s), how));
658 CPerlSock::Socket(int af, int type, int protocol, int &err)
662 #ifdef USE_SOCKETS_AS_HANDLES
664 if((s = psocket(af, type, protocol)) == INVALID_SOCKET)
665 err = pWSAGetLastError();
669 SOCKET_TEST(s = psocket(af, type, protocol), INVALID_SOCKET);
670 #endif /* USE_SOCKETS_AS_HANDLES */
675 int CPerlSock::Socketpair(int domain, int type, int protocol, int* fds, int &err)
677 croak("socketpair not implemented!\n");