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

Generated on Fri May 27 18:11:56 2005 for Mango by  doxygen 1.4.0