Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

Socket.d

Go to the documentation of this file.
00001 /*
00002         Copyright (C) 2004 Christopher E. Miller
00003         
00004         This software is provided 'as-is', without any express or implied
00005         warranty.  In no event will the authors be held liable for any damages
00006         arising from the use of this software.
00007         
00008         Permission is granted to anyone to use this software for any purpose,
00009         including commercial applications, and to alter it and redistribute it
00010         freely, subject to the following restrictions:
00011         
00012         1. The origin of this software must not be misrepresented; you must not
00013            claim that you wrote the original software. If you use this software
00014            in a product, an acknowledgment in the product documentation would be
00015            appreciated but is not required.
00016 
00017         2. Altered source versions must be plainly marked as such, and must not be
00018            misrepresented as being the original software.
00019 
00020         3. This notice may not be removed or altered from any source distribution.
00021 
00022 */
00023 
00024 // socket.d 1.1
00025 // Mar 2004
00026 
00027 
00028 /*******************************************************************************
00029 
00030         @file Socket.d
00031         
00032         Mango coercion of the excellent socket.d implementation written by 
00033         Chris Miller.
00034 
00035         The original code has been modified in several ways:
00036 
00037         1) It has been altered to fit within the Mango environment, meaning
00038            that certain original classes have been reorganized, and/or have
00039            subclassed Mango base-classes. For example, the original Socket
00040            class has been wrapped with three distinct subclasses, and now
00041            derives from class mango.io.Resource.
00042 
00043         2) All exception instances now subclass the Mango IOException.
00044 
00045         3) Construction of new Socket instances via accept() is now
00046            overloadable.
00047 
00048         4) Constants and enums have been moved within a class boundary to
00049            ensure explicit namespace usage.
00050 
00051         5) changed Socket.select() to loop if it was interrupted.
00052 
00053 
00054         All changes within the main body of code all marked with "MANGO:"
00055 
00056         For a good tutorial on socket-programming I highly recommend going 
00057         here: http://www.ecst.csuchico.edu/~beej/guide/net/
00058 
00059         
00060         @version        Initial version, March 2004      
00061         @author         Christopher Miller, Kris Bell
00062 
00063 
00064 *******************************************************************************/
00065 
00066 
00067 
00068 // MANGO: added all this module & import stuff ...
00069 module mango.io.Socket;
00070 
00071 private import  mango.utils.Text;
00072 
00073 private import  mango.base.System;
00074 
00075 private import  mango.io.Resource,
00076                 mango.io.Exception;
00077 
00078 private import  mango.io.model.IBuffer;
00079 
00080 /*******************************************************************************
00081 
00082 
00083 *******************************************************************************/
00084 
00085 version(linux)
00086 {
00087         version = BsdSockets;
00088 }
00089 
00090 version(Win32)
00091 {
00092         typedef uint socket_t = ~0;
00093 }
00094 else version(BsdSockets)
00095 {
00096         typedef int socket_t = -1;
00097 }
00098 else
00099 {
00100         static assert(0); // No socket support yet
00101 }
00102 
00103 private:
00104 
00105 const socket_t INVALID_SOCKET = socket_t.init;
00106 const int SOCKET_ERROR = -1;
00107 
00108 
00109 /*******************************************************************************
00110 
00111         Load and unload the Win32 socket library
00112 
00113 *******************************************************************************/
00114 
00115 static this()
00116 {
00117         version(Win32)
00118         {
00119                 WSADATA wd;
00120                 if(WSAStartup(0x0101, &wd))
00121                         throw new SocketException("Unable to initialize socket library.");
00122         }
00123 }
00124 
00125 
00126 static ~this()
00127 {
00128         Socket.cancelAll (true);
00129         version(Win32)
00130         {
00131                 WSACleanup();
00132         }
00133 }
00134 
00135 
00136 
00137 private import std.stdint;
00138 
00139 
00140 /*******************************************************************************
00141 
00142 
00143 *******************************************************************************/
00144 
00145 version(Win32)
00146 {
00147         import std.c.windows.windows;
00148         
00149 
00150         
00151         extern(Windows)
00152         {
00153                 const int WSADESCRIPTION_LEN = 256;
00154                 const int WSASYS_STATUS_LEN = 128;
00155                 
00156                 struct WSADATA
00157                 {
00158                         WORD wVersion;
00159                         WORD wHighVersion;
00160                         char szDescription[WSADESCRIPTION_LEN+1];
00161                         char szSystemStatus[WSASYS_STATUS_LEN+1];
00162                         ushort iMaxSockets;
00163                         ushort iMaxUdpDg;
00164                         char* lpVendorInfo;
00165                 }
00166                 alias WSADATA* LPWSADATA;
00167                 
00168                 
00169                 const int IOCPARM_MASK =  0x7f;
00170                 const int IOC_IN =        cast(int)0x80000000;
00171                 const int FIONBIO =       IOC_IN | ((uint.sizeof & IOCPARM_MASK) << 16) | (102 << 8) | 126;
00172                 const int SOL_SOCKET =    0xFFFF;
00173                 const int SO_TYPE =       0x1008;
00174                 
00175                 
00176                 int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
00177                 int WSACleanup();
00178                 socket_t socket(int af, int type, int protocol);
00179                 int ioctlsocket(socket_t s, int cmd, uint* argp);
00180                 int getsockopt(socket_t s, int level, int optname, char* optval, int* optlen);
00181                 uint inet_addr(char* cp);
00182                 int bind(socket_t s, sockaddr* name, int namelen);
00183                 int connect(socket_t s, sockaddr* name, int namelen);
00184                 int listen(socket_t s, int backlog);
00185                 socket_t accept(socket_t s, sockaddr* addr, int* addrlen);
00186                 int closesocket(socket_t s);
00187                 int shutdown(socket_t s, int how);
00188                 int getpeername(socket_t s, sockaddr* name, int* namelen);
00189                 int getsockname(socket_t s, sockaddr* name, int* namelen);
00190                 int send(socket_t s, void* buf, int len, int flags);
00191                 int sendto(socket_t s, void* buf, int len, int flags, sockaddr* to, int tolen);
00192                 int recv(socket_t s, void* buf, int len, int flags);
00193                 int recvfrom(socket_t s, void* buf, int len, int flags, sockaddr* from, int* fromlen);
00194                 int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout);
00195                 //int __WSAFDIsSet(socket_t s, fd_set* fds);
00196                 int getsockopt(socket_t s, int level, int optname, void* optval, int* optlen);
00197                 int setsockopt(socket_t s, int level, int optname, void* optval, int optlen);
00198                 int gethostname(void* namebuffer, int buflen);
00199                 char* inet_ntoa(uint ina);
00200                 hostent* gethostbyname(char* name);
00201                 hostent* gethostbyaddr(void* addr, int len, int type);
00202                 
00203                 
00204                 const int WSAEWOULDBLOCK =  10035;
00205                 const int WSAEINTR =        10004;
00206                 
00207                 int WSAGetLastError();
00208         }
00209 }
00210 else version(BsdSockets)
00211 {
00212         extern(C)
00213         {
00214                 const int F_GETFL =       3;
00215                 const int F_SETFL =       4;
00216                 const int O_NONBLOCK =    0x4000;
00217                 const int SOL_SOCKET =    0xFFFF;
00218                 const int SO_TYPE =       0x1008;
00219                 
00220                 
00221                 socket_t socket(int af, int type, int protocol);
00222                 int fcntl(socket_t s, int f, ...);
00223                 int getsockopt(socket_t s, int level, int optname, char* optval, int* optlen);
00224                 uint inet_addr(char* cp);
00225                 int bind(socket_t s, sockaddr* name, int namelen);
00226                 int connect(socket_t s, sockaddr* name, int namelen);
00227                 int listen(socket_t s, int backlog);
00228                 socket_t accept(socket_t s, sockaddr* addr, int* addrlen);
00229                 int close(socket_t s);
00230                 int shutdown(socket_t s, int how);
00231                 int getpeername(socket_t s, sockaddr* name, int* namelen);
00232                 int getsockname(socket_t s, sockaddr* name, int* namelen);
00233                 int send(socket_t s, void* buf, int len, int flags);
00234                 int sendto(socket_t s, void* buf, int len, int flags, sockaddr* to, int tolen);
00235                 int recv(socket_t s, void* buf, int len, int flags);
00236                 int recvfrom(socket_t s, void* buf, int len, int flags, sockaddr* from, int* fromlen);
00237                 int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout);
00238                 int getsockopt(socket_t s, int level, int optname, void* optval, int* optlen);
00239                 int setsockopt(socket_t s, int level, int optname, void* optval, int optlen);
00240                 int gethostname(void* namebuffer, int buflen);
00241                 char* inet_ntoa(uint ina);
00242                 hostent* gethostbyname(char* name);
00243                 hostent* gethostbyaddr(void* addr, int len, int type);
00244                 
00245                 
00246                 const int EINTR =           4;
00247                 version(linux)
00248                 {
00249                         const int EINPROGRESS =  115; //EWOULDBLOCK
00250                         
00251                         
00252                         import std.c.linux.linux; //for getErrno
00253                 }
00254                 else
00255                 {
00256                         static assert(0);
00257                 }
00258         }
00259 }
00260 
00261 /+
00262 #ifdef INCLUDE_ALL_FOR_DOXYGEN
00263 +/
00264 
00265 /*******************************************************************************
00266         
00267         Internal structs: 
00268 
00269 *******************************************************************************/
00270 
00271 struct timeval
00272 {
00273         int tv_sec; //seconds
00274         int tv_usec; //microseconds
00275 }
00276 
00277 
00278 //transparent
00279 struct fd_set
00280 {
00281 }
00282 
00283 
00284 struct sockaddr
00285 {
00286         ushort sa_family;               
00287         char[14] sa_data = [0];             
00288 }
00289 
00290 
00291 struct hostent
00292 {
00293         char* h_name;
00294         char** h_aliases;
00295         version(Win32)
00296         {
00297                 short h_addrtype;
00298                 short h_length;
00299         }
00300         else version(BsdSockets)
00301         {
00302                 int h_addrtype;
00303                 int h_length;
00304         }
00305         char** h_addr_list;
00306         
00307         
00308         char* h_addr()
00309         {
00310                 return h_addr_list[0];
00311         }
00312 }
00313 
00314 
00315 /*******************************************************************************
00316         
00317         conversions for network byte-order
00318 
00319 *******************************************************************************/
00320 
00321 version(BigEndian)
00322 {
00323         uint16_t htons(uint16_t x)
00324         {
00325                 return x;
00326         }
00327         
00328         
00329         uint32_t htonl(uint32_t x)
00330         {
00331                 return x;
00332         }
00333 }
00334 else version(LittleEndian)
00335 {
00336         import std.intrinsic;
00337         
00338         
00339         uint16_t htons(uint16_t x)
00340         {
00341                 return (x >> 8) | (x << 8);
00342         }
00343 
00344 
00345         uint32_t htonl(uint32_t x)
00346         {
00347                 return bswap(x);
00348         }
00349 }
00350 else
00351 {
00352         static assert(0);
00353 }
00354 
00355 
00356 uint16_t ntohs(uint16_t x)
00357 {
00358         return htons(x);
00359 }
00360 
00361 
00362 uint32_t ntohl(uint32_t x)
00363 {
00364         return htonl(x);
00365 }
00366 
00367 /+
00368 #endif
00369 +/
00370 
00371 
00372 
00373 /*******************************************************************************
00374 
00375         Public interface ...
00376 
00377 *******************************************************************************/
00378 
00379 public:
00380 
00381 
00382 /*******************************************************************************
00383 
00384 
00385 *******************************************************************************/
00386 
00387 class HostException: IOException
00388 {
00389         this(char[] msg)
00390         {
00391                 super(msg);
00392         }
00393 }
00394 
00395 
00396 /*******************************************************************************
00397 
00398 
00399 *******************************************************************************/
00400 
00401 class SocketException: IOException
00402 {
00403         this(char[] msg)
00404         {
00405                 super(msg);
00406         }
00407 }
00408 
00409 
00410 /*******************************************************************************
00411 
00412 
00413 *******************************************************************************/
00414 
00415 class AddressException: SocketException
00416 {
00417         this(char[] msg)
00418         {
00419                 super(msg);
00420         }
00421 }
00422 
00423 
00424 /*******************************************************************************
00425 
00426 
00427 *******************************************************************************/
00428 
00429 class SocketAcceptException: SocketException
00430 {
00431         this(char[] msg)
00432         {
00433                 super(msg);
00434         }
00435 }
00436 
00437 
00438 /*******************************************************************************
00439 
00440 
00441 *******************************************************************************/
00442 
00443 static int lastError ()
00444 {
00445         version (Win32)
00446                 {       
00447                 return WSAGetLastError();
00448                 } 
00449         version (linux)
00450                 {
00451                 return getErrno();
00452                 }
00453 }
00454 
00455         
00456 /*******************************************************************************
00457 
00458         MANGO: socket now subclasses mango.io.Resource
00459 
00460 *******************************************************************************/
00461 
00462 class Socket : Resource
00463 {
00464         private:
00465         socket_t sock;
00466         Socket.AddressFamily _family;
00467         static bool cancelled;
00468 
00469         version(Win32)
00470                 bit _blocking = false;
00471         
00472         
00473         /***********************************************************************
00474 
00475                 Construct a Socket from a handle. This is used internally
00476                 to create new Sockets via an accept().
00477 
00478         ***********************************************************************/
00479 
00480         protected this(socket_t sock)
00481         {
00482                 // MANGO: exposed the constructor functionality: see below.
00483                 set (sock);
00484         }
00485         
00486         /***********************************************************************
00487         
00488                 MANGO: moved this out from the above constructor so that it
00489                 can be called from the FreeList version of SocketConduit
00490 
00491         ***********************************************************************/
00492 
00493         protected void set (socket_t sock)
00494         {
00495                 this.sock = sock;
00496 
00497                 // MANGO: bump the usage count
00498                 acquire();
00499         }
00500                 
00501         /***********************************************************************
00502         
00503                 MANGO: added to reset socket
00504 
00505         ***********************************************************************/
00506 
00507         protected void reset ()
00508         {
00509                 this.sock = INVALID_SOCKET;
00510         }
00511         
00512         
00513         public:
00514 
00515         /***********************************************************************
00516         
00517                 MANGO: added for subscriber control
00518 
00519         ***********************************************************************/
00520 
00521         static bool isCancelled ()
00522         {
00523                 return cancelled;
00524         }
00525         
00526         /***********************************************************************
00527         
00528                 MANGO: added for subscriber control
00529 
00530         ***********************************************************************/
00531 
00532         static void cancelAll (bool cancel)
00533         {
00534                 cancelled = cancel;
00535                 version (TraceLinux)
00536                         {
00537                         printf ("socket cancel status now set\n");
00538                         }
00539         }
00540 
00541 
00542         /***********************************************************************
00543 
00544 
00545         ***********************************************************************/
00546 
00547         /+
00548         #ifdef INCLUDE_ALL_FOR_DOXYGEN
00549         +/
00550         
00551         version (Win32)
00552         {
00553                 /***************************************************************
00554 
00555 
00556                 ***************************************************************/
00557 
00558                 enum Option: int
00559                 {
00560                         //consistent
00561                         SO_DEBUG =         0x1,
00562 
00563                         //possibly Winsock-only values
00564                         SO_BROADCAST =  0x20,
00565                         SO_REUSEADDR =  0x4,
00566                         SO_LINGER =     0x80,
00567                         SO_DONTLINGER = ~(SO_LINGER),
00568                         SO_OOBINLINE =  0x100,
00569                         SO_SNDBUF =     0x1001,
00570                         SO_RCVBUF =     0x1002,
00571                         SO_ERROR =      0x1007,
00572 
00573                         SO_ACCEPTCONN =    0x2, // ?
00574                         SO_KEEPALIVE =     0x8, // ?
00575                         SO_DONTROUTE =     0x10, // ?
00576                         SO_TYPE =          0x1008, // ?
00577 
00578                         // OptionLevel.IP settings
00579                         IP_MULTICAST_LOOP = 0x4,
00580                         IP_ADD_MEMBERSHIP = 0x5,
00581                         IP_DROP_MEMBERSHIP = 0x6,
00582                 }
00583 
00584                 /***************************************************************
00585 
00586 
00587                 ***************************************************************/
00588 
00589                 union linger
00590                 {
00591                         struct {
00592                                ushort l_onoff;          // option on/off
00593                                ushort l_linger;         // linger time
00594                                };
00595                         ushort[2]       array;          // combined 
00596                 }
00597 
00598                 /***************************************************************
00599 
00600 
00601                 ***************************************************************/
00602 
00603                 enum OptionLevel
00604                 {
00605                         SOCKET =  0xFFFF, 
00606                         IP =      0,
00607                         TCP =     6,
00608                         UDP =     17,
00609                 }
00610         }
00611 
00612         version (BsdSockets)
00613         {
00614                 /***************************************************************
00615 
00616                         these appear to be compatible with x86 platforms, 
00617                         but not others!
00618 
00619                 ***************************************************************/
00620 
00621                 enum Option: int
00622                 {
00623                         //consistent
00624                         SO_DEBUG        = 1,
00625                         SO_BROADCAST    = 6,
00626                         SO_REUSEADDR    = 2,
00627                         SO_LINGER       = 13,
00628                         SO_DONTLINGER   = ~(SO_LINGER),
00629                         SO_OOBINLINE    = 10,
00630                         SO_SNDBUF       = 7,
00631                         SO_RCVBUF       = 8,
00632                         SO_ERROR        = 4,
00633 
00634                         SO_ACCEPTCONN   = 30,
00635                         SO_KEEPALIVE    = 9, 
00636                         SO_DONTROUTE    = 5, 
00637                         SO_TYPE         = 3, 
00638 
00639                         // OptionLevel.IP settings
00640                         IP_MULTICAST_LOOP = 34,
00641                         IP_ADD_MEMBERSHIP = 35,
00642                         IP_DROP_MEMBERSHIP = 36,
00643                 }
00644 
00645                 /***************************************************************
00646 
00647 
00648                 ***************************************************************/
00649 
00650                 union linger
00651                 {
00652                         struct {
00653                                int l_onoff;             // option on/off
00654                                int l_linger;            // linger time
00655                                };
00656                         int[2]          array;          // combined
00657                 }
00658 
00659                 /***************************************************************
00660 
00661 
00662                 ***************************************************************/
00663 
00664                 enum OptionLevel
00665                 {
00666                         SOCKET =  1,  // correct for linux on x86 
00667                         IP =      0,  // appears to be correct
00668                         TCP =     6,  // appears to be correct
00669                         UDP =     17, // appears to be correct
00670                 }
00671         }
00672 
00673         /***********************************************************************
00674 
00675 
00676         ***********************************************************************/
00677 
00678         enum Shutdown: int
00679         {
00680                 RECEIVE =  0,
00681                 SEND =     1,
00682                 BOTH =     2,
00683         }
00684 
00685         /***********************************************************************
00686 
00687 
00688         ***********************************************************************/
00689 
00690         enum Flags: int
00691         {
00692                 NONE =           0,
00693                 OOB =            0x1, //out of band
00694                 PEEK =           0x02, //only for receiving
00695                 DONTROUTE =      0x04, //only for sending
00696         }
00697 
00698         /***********************************************************************
00699 
00700 
00701         ***********************************************************************/
00702 
00703         enum Type: int
00704         {
00705                 STREAM =     1,
00706                 DGRAM =      2,
00707                 RAW =        3,
00708                 RDM =        4,
00709                 SEQPACKET =  5,
00710         }
00711 
00712 
00713         /***********************************************************************
00714 
00715 
00716         ***********************************************************************/
00717 
00718         enum Protocol: int
00719         {
00720                 IP =    0,
00721                 ICMP =  1,      // apparently a no-no for linux?
00722                 IGMP =  2,
00723                 GGP =   3,
00724                 TCP =   6,
00725                 PUP =   12,
00726                 UDP =   17,
00727                 IDP =   22,
00728                 ND =    77,
00729                 RAW =   255,
00730                 MAX =   256,
00731         }
00732 
00733 
00734         /***********************************************************************
00735 
00736 
00737         ***********************************************************************/
00738 
00739         version(Win32)
00740         {
00741                 enum AddressFamily: int
00742                 {
00743                         UNSPEC =     0,
00744                         UNIX =       1,
00745                         INET =       2,
00746                         IPX =        6,
00747                         APPLETALK =  16,
00748                         //INET6 =      ? // Need Windows XP ?
00749                 }
00750         }
00751         else version(BsdSockets)
00752         {
00753                 enum AddressFamily: int
00754                 {
00755                         UNSPEC =     0,
00756                         UNIX =       1,
00757                         INET =       2,
00758                         IPX =        4,
00759                         APPLETALK =  5,
00760                         //INET6 =      10,
00761                 }
00762         }
00763 
00764         /+
00765         #endif
00766         +/
00767         
00768 
00769         /***********************************************************************
00770 
00771 
00772         ***********************************************************************/
00773 
00774         this (Socket.AddressFamily af, Socket.Type type, Socket.Protocol protocol)
00775         {
00776                 create (af, type, protocol);
00777 
00778                 // MANGO: bump the usage count
00779                 acquire();
00780         }
00781         
00782         
00783         /***********************************************************************
00784 
00785                 MANGO: added for multicast support
00786 
00787         ***********************************************************************/
00788 
00789         protected void create (Socket.AddressFamily af, Socket.Type type, Socket.Protocol protocol)
00790         {
00791                 sock = socket (af, type, protocol);
00792                 if(sock == sock.init)
00793                    exception("Unable to create socket: ");
00794                 _family = af;
00795         }
00796         
00797         
00798         /***********************************************************************
00799 
00800                 get underlying socket handle
00801 
00802         ***********************************************************************/
00803 
00804         socket_t handle()
00805         {
00806                 return sock;
00807         }
00808         
00809         
00810         /***********************************************************************
00811 
00812 
00813         ***********************************************************************/
00814 
00815         override char[] toString()
00816         {
00817                 return "Socket";
00818         }
00819         
00820         
00821         /***********************************************************************
00822 
00823                 getter
00824 
00825         ***********************************************************************/
00826 
00827         bit blocking()
00828         {
00829                 version(Win32)
00830                 {
00831                         return _blocking;
00832                 }
00833                 else version(BsdSockets)
00834                 {
00835                         return !(fcntl(handle, F_GETFL, 0) & O_NONBLOCK);
00836                 }
00837         }
00838         
00839         
00840         /***********************************************************************
00841 
00842                 setter
00843 
00844         ***********************************************************************/
00845 
00846         void blocking(bit byes)
00847         {
00848                 version(Win32)
00849                 {
00850                         uint num = !byes;
00851                         if(SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &num))
00852                                 goto err;
00853                         _blocking = byes;
00854                 }
00855                 else version(BsdSockets)
00856                 {
00857                         int x = fcntl(handle, F_GETFL, 0);
00858                         if(byes)
00859                                 x &= ~O_NONBLOCK;
00860                         else
00861                                 x |= O_NONBLOCK;
00862                         if(SOCKET_ERROR == fcntl(sock, F_SETFL, x))
00863                                 goto err;
00864                 }
00865                 return; //success
00866                 
00867                 err:
00868                 exception("Unable to set socket blocking: ");
00869         }
00870         
00871         
00872         /***********************************************************************
00873 
00874 
00875         ***********************************************************************/
00876 
00877         AddressFamily addressFamily()
00878         {
00879                 return _family;
00880         }
00881         
00882         
00883         /***********************************************************************
00884 
00885 
00886         ***********************************************************************/
00887 
00888         bit isAlive()
00889         {
00890                 int type, typesize = type.sizeof;
00891                 return getsockopt (sock, SOL_SOCKET, SO_TYPE, cast(char*) &type, &typesize) != SOCKET_ERROR;
00892         }
00893         
00894         
00895         /***********************************************************************
00896 
00897 
00898         ***********************************************************************/
00899 
00900         void bind(Address addr)
00901         {
00902                 if(SOCKET_ERROR == .bind (sock, addr.name(), addr.nameLen()))
00903                    exception ("Unable to bind socket: ");
00904         }
00905         
00906         
00907         /***********************************************************************
00908 
00909 
00910         ***********************************************************************/
00911  
00912         void connect(Address to)
00913         {
00914                 if(SOCKET_ERROR == .connect (sock, to.name(), to.nameLen()))
00915                 {
00916                         if(!blocking)
00917                         {
00918                                 version(Win32)
00919                                 {
00920                                         if(WSAEWOULDBLOCK == WSAGetLastError())
00921                                                 return;
00922                                 }
00923                                 else version(linux)
00924                                 {
00925                                         if(EINPROGRESS == getErrno())
00926                                                 return;
00927                                 }
00928                                 else
00929                                 {
00930                                         static assert(0);
00931                                 }
00932                         }
00933                         exception ("Unable to connect socket: ");
00934                 }
00935         }
00936         
00937         
00938         /***********************************************************************
00939 
00940                 need to bind() first
00941 
00942         ***********************************************************************/
00943 
00944         void listen(int backlog)
00945         {
00946                 if(SOCKET_ERROR == .listen (sock, backlog))
00947                    exception ("Unable to listen on socket: ");
00948         }
00949         
00950         /***********************************************************************
00951 
00952                 MANGO: added
00953 
00954         ***********************************************************************/
00955 
00956         protected Socket createSocket (socket_t handle)
00957         {
00958                 return new Socket (handle);
00959         }
00960 
00961         /***********************************************************************
00962 
00963 
00964         ***********************************************************************/
00965 
00966         Socket accept()
00967         {       
00968                 socket_t newsock = .accept (sock, null, null);
00969                 if(INVALID_SOCKET == newsock)
00970                    // MANGO: return null rather than throwing an exception because
00971                    // this is a valid condition upon thread-termination.
00972                   {
00973                   return null;
00974                   //exception("Unable to accept socket connection.");
00975                   }
00976 
00977                 // MANGO: changed to indirect construction
00978                 Socket newSocket = createSocket (newsock);
00979 
00980                 version(Win32)
00981                         newSocket._blocking = _blocking; //inherits blocking mode
00982                 newSocket._family = _family; //same family
00983                 return newSocket;
00984         }
00985         
00986         
00987         /***********************************************************************
00988 
00989 
00990         ***********************************************************************/
00991 
00992         void shutdown()
00993         {       //printf ("shutdown\n");
00994                 .shutdown (sock, cast(int) Shutdown.BOTH);
00995         }
00996         
00997         /***********************************************************************
00998 
00999 
01000         ***********************************************************************/
01001 
01002         void shutdown(Socket.Shutdown how)
01003         {
01004                 .shutdown (sock, cast(int)how);
01005         }
01006         
01007 
01008         /***********************************************************************
01009 
01010                 MANGO: added
01011 
01012         ***********************************************************************/
01013 
01014         void setLingerPeriod (int period)
01015         {
01016                 linger l;
01017 
01018                 l.l_onoff = 1;          //option on/off
01019                 l.l_linger = period;    //linger time
01020         
01021                 setOption (OptionLevel.SOCKET, Option.SO_LINGER, l.array);
01022         }
01023         
01024 
01025         /***********************************************************************
01026 
01027 
01028                 MANGO: added
01029 
01030         ***********************************************************************/
01031 
01032         void setAddressReuse (bool enabled)
01033         {
01034                 int[1] x = enabled;
01035                 setOption (OptionLevel.SOCKET, Option.SO_REUSEADDR, x);
01036         }
01037 
01038         
01039         /***********************************************************************
01040 
01041                 Helper function to handle the adding and dropping of group
01042                 membership.
01043 
01044                 MANGO: Added
01045 
01046         ***********************************************************************/
01047 
01048         bool setGroup (InternetAddress address, Socket.Option option)
01049         {
01050                 struct ip_mreq 
01051                 {
01052                 uint  imr_multiaddr;  /* IP multicast address of group */
01053                 uint  imr_interface;  /* local IP address of interface */
01054                 };
01055 
01056                 ip_mreq mrq;
01057 
01058                 mrq.imr_interface = 0;
01059                 mrq.imr_multiaddr = address.sin.sin_addr;
01060                 return .setsockopt(handle(), OptionLevel.IP, option, &mrq, mrq.sizeof) != SOCKET_ERROR;
01061         }
01062 
01063 
01064         /***********************************************************************
01065 
01066                 calling shutdown() before this is recommended for connection-
01067                 oriented sockets
01068 
01069                 MANGO: changed from close() to IResource.closure()
01070 
01071         ***********************************************************************/
01072 
01073         override void closure ()
01074         {
01075                 version (TraceLinux)
01076                         {
01077                         printf ("closing socket handle ...\n");
01078                         }
01079                 version(Win32)
01080                 {
01081                         .closesocket (sock);
01082                 }
01083                 else version(BsdSockets)
01084                 {
01085                         .close (sock);
01086                 }
01087                 sock = sock.init;
01088                 version (TraceLinux)
01089                         {
01090                         printf ("socket handle closed\n");
01091                         }
01092         }       
01093         
01094 
01095         /***********************************************************************
01096 
01097 
01098         ***********************************************************************/
01099 
01100         private Address newFamilyObject ()
01101         {
01102                 Address result;
01103                 switch(_family)
01104                 {
01105                         case AddressFamily.INET:
01106                                 result = new InternetAddress;
01107                                 break;
01108                         
01109                         default:
01110                                 result = new UnknownAddress;
01111                 }
01112                 return result;
01113         }
01114         
01115         
01116         /***********************************************************************
01117 
01118                 Mango: added this to return the hostname
01119 
01120         ***********************************************************************/
01121 
01122         static char[] hostName ()
01123         {
01124                 char[64] name;
01125 
01126                 if(SOCKET_ERROR == .gethostname (name, name.length))
01127                    exception ("Unable to obtain host name: ");
01128                 return name [0 .. std.string.strlen(name)].dup;
01129         }
01130         
01131 
01132         /***********************************************************************
01133 
01134                 Mango: added this to return the default host address (IPv4)
01135 
01136         ***********************************************************************/
01137 
01138         static uint hostAddress ()
01139         {
01140                 InternetHost ih = new InternetHost;
01141 
01142                 char[] hostname = hostName();
01143                 ih.getHostByName (hostname);
01144                 assert (ih.addrList.length);
01145                 return ih.addrList[0];
01146         }
01147 
01148         
01149         /***********************************************************************
01150 
01151 
01152         ***********************************************************************/
01153 
01154         Address remoteAddress ()
01155         {
01156                 Address addr = newFamilyObject ();
01157                 int nameLen = addr.nameLen ();
01158                 if(SOCKET_ERROR == .getpeername (sock, addr.name(), &nameLen))
01159                    exception ("Unable to obtain remote socket address: ");
01160                 assert (addr.addressFamily() == _family);
01161                 return addr;
01162         }
01163         
01164         
01165         /***********************************************************************
01166 
01167 
01168         ***********************************************************************/
01169 
01170         Address localAddress ()
01171         {
01172                 Address addr = newFamilyObject ();
01173                 int nameLen = addr.nameLen();
01174                 if(SOCKET_ERROR == .getsockname (sock, addr.name(), &nameLen))
01175                    exception ("Unable to obtain local socket address: ");
01176                 assert (addr.addressFamily() == _family);
01177                 return addr;
01178         }
01179         
01180         
01181         /***********************************************************************
01182 
01183                 returns number of bytes actually sent, or -1 on error
01184 
01185         ***********************************************************************/
01186 
01187         int send (void[] buf, Socket.Flags flags = Socket.Flags.NONE)
01188         {
01189                 int sent = .send (sock, buf, buf.length, cast(int)flags);
01190                 return sent;
01191         }
01192         
01193         
01194         /***********************************************************************
01195 
01196                 -to- is ignored if connected ?
01197 
01198         ***********************************************************************/
01199 
01200         int sendTo (void[] buf, Socket.Flags flags, Address to)
01201         {
01202                 int sent = .sendto (sock, buf, buf.length, cast(int)flags, to.name(), to.nameLen());
01203                 return sent;
01204         }
01205         
01206         
01207         /***********************************************************************
01208 
01209                 -to- is ignored if connected ?
01210 
01211         ***********************************************************************/
01212 
01213         int sendTo (void[] buf, Address to)
01214         {
01215                 return sendTo (buf, Socket.Flags.NONE, to);
01216         }
01217         
01218         
01219         /***********************************************************************
01220 
01221                 assumes you connect()ed
01222 
01223         ***********************************************************************/
01224 
01225         int sendTo (void[] buf, Socket.Flags flags = Socket.Flags.NONE)
01226         {
01227                 int sent = .sendto (sock, buf, buf.length, cast(int)flags, null, 0);
01228                 return sent;
01229         }
01230         
01231         
01232         /***********************************************************************
01233 
01234                 returns number of bytes actually received, 0 on connection 
01235                 closure, or -1 on error
01236 
01237         ***********************************************************************/
01238 
01239         int receive (void[] buf, Socket.Flags flags = Socket.Flags.NONE)
01240         {
01241                 if(!buf.length) //return 0 and don't think the connection closed
01242                         return 0;
01243                 int read = .recv(sock, buf, buf.length, cast(int)flags);
01244                 if (read == SOCKET_ERROR)
01245                     exception ("Failed while receiving socket data: ");
01246                 // if(!read) //connection closed
01247                 return read;
01248         }
01249         
01250         
01251         /***********************************************************************
01252 
01253                 -from- is ignored if connected ?
01254 
01255         ***********************************************************************/
01256 
01257         int receiveFrom (void[] buf, Socket.Flags flags, out Address from)
01258         {
01259                 if(!buf.length) //return 0 and don't think the connection closed
01260                         return 0;
01261                 version (TraceLinux)
01262                         {
01263                         printf ("executing recvFrom() \n");
01264                         }
01265                 from = newFamilyObject ();
01266                 int nameLen = from.nameLen ();
01267                 int read = .recvfrom (sock, buf, buf.length, cast(int)flags, from.name(), &nameLen);
01268                 version (TraceLinux)
01269                         {
01270                         printf ("recvFrom returns %d\n", read);
01271                         }
01272                 if (read == SOCKET_ERROR)
01273                     exception ("Failed while receiving socket data: ");
01274 
01275                 assert (from.addressFamily() == _family);
01276                 // if(!read) //connection closed
01277                 return read;
01278         }
01279         
01280         
01281         /***********************************************************************
01282 
01283                 -from- is ignored if connected ?
01284 
01285         ***********************************************************************/
01286 
01287         int receiveFrom (void[] buf, out Address from)
01288         {
01289                 return receiveFrom (buf, Socket.Flags.NONE, from);
01290         }
01291         
01292         
01293         /***********************************************************************
01294 
01295                 assumes you connect()ed
01296 
01297         ***********************************************************************/
01298 
01299         int receiveFrom (void[] buf, Socket.Flags flags)
01300         {
01301                 if(!buf.length) //return 0 and don't think the connection closed
01302                         return 0;
01303                 int read = .recvfrom (sock, buf, buf.length, cast(int)flags, null, null);
01304                 if (read == SOCKET_ERROR)
01305                     exception ("Failed while receiving socket data: ");
01306                 // if(!read) //connection closde
01307                 return read;
01308         }
01309         
01310         
01311         /***********************************************************************
01312 
01313                 assumes you connect()ed
01314 
01315         ***********************************************************************/
01316 
01317         int receiveFrom (void[] buf)
01318         {
01319                 return receiveFrom (buf, Socket.Flags.NONE);
01320         }
01321         
01322         
01323         /***********************************************************************
01324 
01325                 returns the length, in bytes, of the actual result - very 
01326                 different from getsockopt()
01327 
01328         ***********************************************************************/
01329 
01330         int getOption (Socket.OptionLevel level, Socket.Option option, void[] result)
01331         {
01332                 int len = result.length;
01333                 if(SOCKET_ERROR == .getsockopt (sock, cast(int)level, cast(int)option, result, &len))
01334                    exception ("Unable to get socket option: ");
01335                 return len;
01336         }
01337         
01338         
01339         /***********************************************************************
01340 
01341 
01342         ***********************************************************************/
01343 
01344         void setOption (Socket.OptionLevel level, Socket.Option option, void[] value)
01345         {
01346                 if(SOCKET_ERROR == .setsockopt (sock, cast(int)level, cast(int)option, value, value.length))
01347                    exception ("Unable to set socket option: ");
01348         }
01349         
01350         
01351         /***********************************************************************
01352 
01353                 Mango: added this common function
01354 
01355         ***********************************************************************/
01356 
01357         protected static void exception (char[] msg)
01358         {
01359                 msg ~= System.error (lastError);
01360                 throw new SocketException (msg);
01361         }
01362         
01363 
01364         /***********************************************************************
01365 
01366                 SocketSet's are updated to include only those sockets which an 
01367                 event occured.
01368                 
01369                 Returns the number of events, 0 on timeout, or -1 on interruption
01370 
01371                 for a connect()ing socket, writeability means connected 
01372                 for a listen()ing socket, readability means listening 
01373 
01374                 Winsock: possibly internally limited to 64 sockets per set
01375 
01376         ***********************************************************************/
01377 
01378         static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, timeval* tv)
01379         in
01380         {
01381                 //make sure none of the SocketSet's are the same object
01382                 if(checkRead)
01383                 {
01384                         assert(checkRead !== checkWrite);
01385                         assert(checkRead !== checkError);
01386                 }
01387                 if(checkWrite)
01388                 {
01389                         assert(checkWrite !== checkError);
01390                 }
01391         }
01392         body
01393         {
01394                 fd_set* fr, fw, fe;
01395                 
01396                 version(Win32)
01397                 {
01398                         //Windows has a problem with empty fd_set's that aren't null
01399                         fr = (checkRead && checkRead.count()) ? checkRead.toFd_set() : null;
01400                         fw = (checkWrite && checkWrite.count()) ? checkWrite.toFd_set() : null;
01401                         fe = (checkError && checkError.count()) ? checkError.toFd_set() : null;
01402                 }
01403                 else
01404                 {
01405                         fr = checkRead ? checkRead.toFd_set() : null;
01406                         fw = checkWrite ? checkWrite.toFd_set() : null;
01407                         fe = checkError ? checkError.toFd_set() : null;
01408                 }
01409                
01410                 int result;
01411               
01412                 // MANGO: if select() was interrupted, we now try again
01413                 while ((result = .select (socket_t.max - 1, fr, fw, fe, tv)) == -1)              
01414                         version(Win32)
01415                         {
01416                                 if(WSAGetLastError() != WSAEINTR)
01417                                    break;
01418                         }
01419                         else version(linux)
01420                         {
01421                                 if(getErrno() != EINTR)
01422                                    break;
01423                         }
01424                         else
01425                         {
01426                                 static assert(0);
01427                         }
01428                 
01429                 // MANGO: don't throw an exception here ... wait until we get 
01430                 // a bit further back along the control path
01431                 //if(SOCKET_ERROR == result)
01432                 //   throw new SocketException("Socket select error.");
01433                 
01434                 return result;
01435         }
01436         
01437         
01438         /***********************************************************************
01439 
01440 
01441         ***********************************************************************/
01442 
01443         static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, int microseconds)
01444         {
01445                 timeval tv;
01446                 tv.tv_sec = 0;
01447                 tv.tv_usec = microseconds;
01448                 return select (checkRead, checkWrite, checkError, &tv);
01449         }
01450         
01451         
01452         /***********************************************************************
01453 
01454                 maximum timeout
01455 
01456         ***********************************************************************/
01457 
01458         static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError)
01459         {
01460                 return select (checkRead, checkWrite, checkError, null);
01461         }
01462         
01463         
01464         /***********************************************************************
01465 
01466 
01467         ***********************************************************************/
01468 
01469         /+
01470         bit poll (events)
01471         {
01472                 int WSAEventSelect(socket_t s, WSAEVENT hEventObject, int lNetworkEvents); // Winsock 2 ?
01473                 int poll(pollfd* fds, int nfds, int timeout); // Unix ?
01474         }
01475         +/
01476 
01477 
01478 }
01479 
01480 
01481 
01482 /*******************************************************************************
01483 
01484 
01485 *******************************************************************************/
01486 
01487 abstract class Address
01488 {
01489         protected sockaddr* name();
01490         protected int nameLen();
01491         Socket.AddressFamily addressFamily();
01492         char[] toString();
01493 }
01494 
01495 
01496 /*******************************************************************************
01497 
01498 
01499 *******************************************************************************/
01500 
01501 class UnknownAddress: Address
01502 {
01503         protected:
01504         sockaddr sa;
01505         
01506         
01507         /***********************************************************************
01508 
01509 
01510         ***********************************************************************/
01511 
01512         sockaddr* name()
01513         {
01514                 return &sa;
01515         }
01516         
01517         
01518         /***********************************************************************
01519 
01520 
01521         ***********************************************************************/
01522 
01523         int nameLen()
01524         {
01525                 return sa.sizeof;
01526         }
01527         
01528         
01529         public:
01530         /***********************************************************************
01531 
01532 
01533         ***********************************************************************/
01534 
01535         Socket.AddressFamily addressFamily()
01536         {
01537                 return cast(Socket.AddressFamily)sa.sa_family;
01538         }
01539         
01540         
01541         /***********************************************************************
01542 
01543 
01544         ***********************************************************************/
01545 
01546         char[] toString()
01547         {
01548                 return "Unknown";
01549         }
01550 }
01551 
01552 
01553 /*******************************************************************************
01554 
01555 
01556 *******************************************************************************/
01557 
01558 class InternetHost
01559 {
01560         char[] name;
01561         char[][] aliases;
01562         uint[] addrList;
01563         
01564         
01565         /***********************************************************************
01566 
01567 
01568         ***********************************************************************/
01569 
01570         protected void validHostent(hostent* he)
01571         {
01572                 if(he.h_addrtype != cast(int)Socket.AddressFamily.INET || he.h_length != 4)
01573                         throw new HostException("Address family mismatch.");
01574         }
01575         
01576         
01577         /***********************************************************************
01578 
01579 
01580         ***********************************************************************/
01581 
01582         void populate(hostent* he)
01583         {
01584                 int i;
01585                 char* p;
01586                 
01587                 name = std.string.toString(he.h_name);
01588                 
01589                 for(i = 0;; i++)
01590                 {
01591                         p = he.h_aliases[i];
01592                         if(!p)
01593                                 break;
01594                 }
01595                 
01596                 if(i)
01597                 {
01598                         aliases = new char[][i];
01599                         for(i = 0; i != aliases.length; i++)
01600                         {
01601                                 aliases[i] = std.string.toString(he.h_aliases[i]);
01602                         }
01603                 }
01604                 else
01605                 {
01606                         aliases = null;
01607                 }
01608                 
01609                 for(i = 0;; i++)
01610                 {
01611                         p = he.h_addr_list[i];
01612                         if(!p)
01613                                 break;
01614                 }
01615                 
01616                 if(i)
01617                 {
01618                         addrList = new uint[i];
01619                         for(i = 0; i != addrList.length; i++)
01620                         {
01621                                 addrList[i] = ntohl(*(cast(uint*)he.h_addr_list[i]));
01622                         }
01623                 }
01624                 else
01625                 {
01626                         addrList = null;
01627                 }
01628         }
01629         
01630         
01631         /***********************************************************************
01632 
01633 
01634         ***********************************************************************/
01635 
01636         bit getHostByName(char[] name)
01637         {
01638                 hostent* he = gethostbyname(std.string.toStringz(name));
01639                 if(!he)
01640                         return false;
01641                 validHostent(he);
01642                 populate(he);
01643                 return true;
01644         }
01645         
01646         
01647         /***********************************************************************
01648 
01649 
01650         ***********************************************************************/
01651 
01652         bit getHostByAddr(uint addr)
01653         {
01654                 uint x = htonl(addr);
01655                 hostent* he = gethostbyaddr(&x, 4, cast(int)Socket.AddressFamily.INET);
01656                 if(!he)
01657                         return false;
01658                 validHostent(he);
01659                 populate(he);
01660                 return true;
01661         }
01662         
01663         
01664         /***********************************************************************
01665 
01666 
01667         ***********************************************************************/
01668 
01669         //shortcut
01670         bit getHostByAddr(char[] addr)
01671         {
01672                 uint x = inet_addr(std.string.toStringz(addr));
01673                 hostent* he = gethostbyaddr(&x, 4, cast(int)Socket.AddressFamily.INET);
01674                 if(!he)
01675                         return false;
01676                 validHostent(he);
01677                 populate(he);
01678                 return true;
01679         }
01680 }
01681 
01682 
01683 unittest
01684 {
01685         InternetHost ih = new InternetHost;
01686         assert(ih.addrList.length);
01687         InternetAddress ia = new InternetAddress(ih.addrList[0], InternetAddress.PORT_ANY);
01688         printf("IP address = %.*s\nname = %.*s\n", ia.toAddrString(), ih.name);
01689         foreach(int i, char[] s; ih.aliases)
01690         {
01691                 printf("aliases[%d] = %.*s\n", i, s);
01692         }
01693         
01694         printf("---\n");
01695         
01696         assert(ih.getHostByAddr(ih.addrList[0]));
01697         printf("name = %.*s\n", ih.name);
01698         foreach(int i, char[] s; ih.aliases)
01699         {
01700                 printf("aliases[%d] = %.*s\n", i, s);
01701         }
01702 }
01703 
01704 
01705 /*******************************************************************************
01706 
01707 
01708 *******************************************************************************/
01709 
01710 class InternetAddress: Address
01711 {
01712         /+
01713         #ifdef INCLUDE_ALL_FOR_DOXYGEN
01714         +/
01715         protected:
01716         /***********************************************************************
01717 
01718 
01719         ***********************************************************************/
01720 
01721         struct sockaddr_in
01722         {
01723                 ushort sin_family = cast(ushort)Socket.AddressFamily.INET;
01724                 ushort sin_port;
01725                 uint sin_addr; //in_addr
01726                 char[8] sin_zero = [0];
01727         }
01728         /+
01729         #endif
01730         +/
01731 
01732         sockaddr_in sin;
01733         
01734         
01735         /***********************************************************************
01736 
01737 
01738         ***********************************************************************/
01739 
01740         sockaddr* name()
01741         {
01742                 return cast(sockaddr*)&sin;
01743         }
01744         
01745         
01746         /***********************************************************************
01747 
01748 
01749         ***********************************************************************/
01750 
01751         int nameLen()
01752         {
01753                 return sin.sizeof;
01754         }
01755         
01756         
01757         /***********************************************************************
01758 
01759 
01760         ***********************************************************************/
01761 
01762         this()
01763         {
01764         }
01765         
01766         
01767         public:
01768         const uint ADDR_ANY = 0;
01769         const uint ADDR_NONE = cast(int)-1;
01770         const ushort PORT_ANY = 0;
01771         
01772         
01773         /***********************************************************************
01774 
01775 
01776         ***********************************************************************/
01777 
01778         Socket.AddressFamily addressFamily()
01779         {
01780                 return Socket.AddressFamily.INET;
01781         }
01782         
01783         
01784         /***********************************************************************
01785 
01786 
01787         ***********************************************************************/
01788 
01789         ushort port()
01790         {
01791                 return ntohs(sin.sin_port);
01792         }
01793         
01794         
01795         /***********************************************************************
01796 
01797 
01798         ***********************************************************************/
01799 
01800         uint addr()
01801         {
01802                 return ntohl(sin.sin_addr);
01803         }
01804         
01805         
01806         /***********************************************************************
01807 
01808                 -port- can be PORT_ANY
01809                 -addr- is an IP address or host name
01810 
01811         ***********************************************************************/
01812 
01813         this(char[] addr, ushort port = PORT_ANY)
01814         {
01815                 uint uiaddr = parse(addr);
01816                 if(ADDR_NONE == uiaddr)
01817                 {
01818                         InternetHost ih = new InternetHost;
01819                         if(!ih.getHostByName(addr))
01820                                 throw new AddressException("Invalid internet address '"~addr~"'");
01821                         uiaddr = ih.addrList[0];
01822                 }
01823                 sin.sin_addr = htonl(uiaddr);
01824                 sin.sin_port = htons(port);
01825         }
01826         
01827         
01828         /***********************************************************************
01829 
01830 
01831         ***********************************************************************/
01832 
01833         this(uint addr, ushort port)
01834         {
01835                 sin.sin_addr = htonl(addr);
01836                 sin.sin_port = htons(port);
01837         }
01838         
01839         
01840         /***********************************************************************
01841 
01842 
01843         ***********************************************************************/
01844 
01845         this(ushort port)
01846         {
01847                 sin.sin_addr = 0; //any, "0.0.0.0"
01848                 sin.sin_port = htons(port);
01849         }
01850         
01851         
01852         /***********************************************************************
01853 
01854 
01855         ***********************************************************************/
01856 
01857         char[] toAddrString()
01858         {
01859                 return std.string.toString(inet_ntoa(sin.sin_addr)).dup;
01860         }
01861         
01862         
01863         /***********************************************************************
01864 
01865 
01866         ***********************************************************************/
01867 
01868         char[] toPortString()
01869         {
01870                 return std.string.toString(port());
01871         }
01872         
01873         
01874         /***********************************************************************
01875 
01876 
01877         ***********************************************************************/
01878 
01879         char[] toString()
01880         {
01881                 return toAddrString() ~ ":" ~ toPortString();
01882         }
01883         
01884         
01885         /***********************************************************************
01886 
01887                 -addr- is an IP address in the format "a.b.c.d"
01888                 returns ADDR_NONE on failure
01889 
01890         ***********************************************************************/
01891 
01892         static uint parse(char[] addr)
01893         {
01894                 return ntohl(inet_addr(std.string.toStringz(addr)));
01895         }
01896 }
01897 
01898 
01899 unittest
01900 {
01901         InternetAddress ia = new InternetAddress("63.105.9.61", 80);
01902         assert(ia.toString() == "63.105.9.61:80");
01903 }
01904 
01905 
01906 /*******************************************************************************
01907 
01908 
01909 *******************************************************************************/
01910 
01911 //a set of sockets for Socket.select()
01912 class SocketSet
01913 {
01914         private:
01915         uint nbytes; //Win32: excludes uint.size "count"
01916         byte* buf;
01917         
01918         
01919         version(Win32)
01920         {
01921                 uint count()
01922                 {
01923                         return *(cast(uint*)buf);
01924                 }
01925                 
01926                 
01927                 void count(int setter)
01928                 {
01929                         *(cast(uint*)buf) = setter;
01930                 }
01931                 
01932                 
01933                 socket_t* first()
01934                 {
01935                         return cast(socket_t*)(buf + uint.sizeof);
01936                 }
01937         }
01938         else version(linux)
01939         {
01940                 import std.intrinsic;
01941                 
01942                 
01943                 uint nfdbits;
01944                 
01945                 
01946                 uint fdelt(socket_t s)
01947                 {
01948                         return cast(uint)s / nfdbits;
01949                 }
01950                 
01951                 
01952                 uint fdmask(socket_t s)
01953                 {
01954                         return 1 << cast(uint)s % nfdbits;
01955                 }
01956                 
01957                 
01958                 uint* first()
01959                 {
01960                         return cast(uint*)buf;
01961                 }
01962         }
01963         
01964         
01965         public:
01966         /***********************************************************************
01967 
01968 
01969         ***********************************************************************/
01970 
01971         this(uint max)
01972         {
01973                 version(Win32)
01974                 {
01975                         nbytes = max * socket_t.sizeof;
01976                         buf = new byte[nbytes + uint.sizeof];
01977                         count = 0;
01978                 }
01979                 else version(linux)
01980                 {
01981                         if(max <= 32)
01982                                 nbytes = 32 * uint.sizeof;
01983                         else
01984                                 nbytes = max * uint.sizeof;
01985                         buf = new byte[nbytes];
01986                         nfdbits = nbytes * 8;
01987                         //clear(); //new initializes to 0
01988                 }
01989                 else
01990                 {
01991                         static assert(0);
01992                 }
01993         }
01994         
01995         
01996         /***********************************************************************
01997 
01998 
01999         ***********************************************************************/
02000 
02001         this()
02002         {
02003                 version(Win32)
02004                 {
02005                         this(64);
02006                 }
02007                 else version(linux)
02008                 {
02009                         this(32);
02010                 }
02011                 else
02012                 {
02013                         static assert(0);
02014                 }
02015         }
02016         
02017         
02018         /***********************************************************************
02019 
02020 
02021         ***********************************************************************/
02022 
02023         void reset()
02024         {
02025                 version(Win32)
02026                 {
02027                         count = 0;
02028                 }
02029                 else version(linux)
02030                 {
02031                         buf[0 .. nbytes] = 0;
02032                 }
02033                 else
02034                 {
02035                         static assert(0);
02036                 }
02037         }
02038         
02039         
02040         /***********************************************************************
02041 
02042 
02043         ***********************************************************************/
02044 
02045         void add(socket_t s)
02046         in
02047         {
02048                 version(Win32)
02049                 {
02050                         assert(count < max); //added too many sockets; specify a higher max in the constructor
02051                 }
02052         }
02053         body
02054         {
02055                 version(Win32)
02056                 {
02057                         uint c = count;
02058                         first[c] = s;
02059                         count = c + 1;
02060                 }
02061                 else version(linux)
02062                 {
02063                         bts(cast(uint*)&first[fdelt(s)], cast(uint)s % nfdbits);
02064                 }
02065                 else
02066                 {
02067                         static assert(0);
02068                 }
02069         }
02070         
02071         
02072         /***********************************************************************
02073 
02074 
02075         ***********************************************************************/
02076 
02077         void add(Socket s)
02078         {
02079                 add(s.sock);
02080         }
02081         
02082         
02083         /***********************************************************************
02084 
02085 
02086         ***********************************************************************/
02087 
02088         void remove(socket_t s)
02089         {
02090                 version(Win32)
02091                 {
02092                         uint c = count;
02093                         socket_t* start = first;
02094                         socket_t* stop = start + c;
02095                         
02096                         for(; start != stop; start++)
02097                         {
02098                                 if(*start == s)
02099                                         goto found;
02100                         }
02101                         return; //not found
02102                         
02103                         found:
02104                         for(++start; start != stop; start++)
02105                         {
02106                                 *(start - 1) = *start;
02107                         }
02108                         
02109                         count = c - 1;
02110                 }
02111                 else version(linux)
02112                 {
02113                         btr(cast(uint*)&first[fdelt(s)], cast(uint)s % nfdbits);
02114                 }
02115                 else
02116                 {
02117                         static assert(0);
02118                 }
02119         }
02120         
02121         
02122         /***********************************************************************
02123 
02124 
02125         ***********************************************************************/
02126 
02127         void remove(Socket s)
02128         {
02129                 remove(s.sock);
02130         }
02131         
02132         
02133         /***********************************************************************
02134 
02135 
02136         ***********************************************************************/
02137 
02138         int isSet(socket_t s)
02139         {
02140                 version(Win32)
02141                 {
02142                         socket_t* start = first;
02143                         socket_t* stop = start + count;
02144                         
02145                         for(; start != stop; start++)
02146                         {
02147                                 if(*start == s)
02148                                         return true;
02149                         }
02150                         return false;
02151                 }
02152                 else version(linux)
02153                 {
02154                         //return bt(cast(uint*)&first[fdelt(s)], cast(uint)s % nfdbits);
02155                         int index = cast(uint)s % nfdbits;
02156                         return (cast(uint*)&first[fdelt(s)])[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)));
02157                 }
02158                 else
02159                 {
02160                         static assert(0);
02161                 }
02162         }
02163         
02164         
02165         /***********************************************************************
02166 
02167 
02168         ***********************************************************************/
02169 
02170         int isSet(Socket s)
02171         {
02172                 return isSet(s.sock);
02173         }
02174         
02175         
02176         /***********************************************************************
02177 
02178                 max sockets that can be added, like FD_SETSIZE
02179 
02180         ***********************************************************************/
02181 
02182         uint max() 
02183         {
02184                 return nbytes / socket_t.sizeof;
02185         }
02186         
02187         
02188         /***********************************************************************
02189 
02190 
02191         ***********************************************************************/
02192 
02193         fd_set* toFd_set()
02194         {
02195                 return cast(fd_set*)buf;
02196         }
02197 }
02198 
02199 
02200 
02201 
02202 /******************************************************************************/
02203 /******************* additions for the mango.io package  **********************/           
02204 /******************************************************************************/
02205 
02206 
02207 /******************************************************************************
02208 
02209 ******************************************************************************/
02210 
02211 interface IListener
02212 {
02213         /***********************************************************************
02214 
02215                 Stop listening; this may be delayed until after the next
02216                 valid read operation.
02217 
02218         ***********************************************************************/
02219 
02220         void cancel ();
02221 }
02222 
02223 
02224 /******************************************************************************
02225 
02226 ******************************************************************************/
02227 
02228 interface ISocketReader
02229 {
02230         /***********************************************************************
02231 
02232                 Polymorphic contract for readers handed to a listener. 
02233                 Should return the number of bytes read, or -1 on error.
02234 
02235         ***********************************************************************/
02236 
02237         int read (IBuffer buffer);
02238 }
02239 
02240 
02241 

Generated on Sun Nov 7 19:06:53 2004 for Mango by doxygen 1.3.6