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         else version (darwin)
00637         {
00638                 enum Option: int
00639                 {
00640                         SO_DEBUG        = 0x0001,               /* turn on debugging info recording */
00641                         SO_BROADCAST    = 0x0020,               /* permit sending of broadcast msgs */
00642                         SO_REUSEADDR    = 0x0004,               /* allow local address reuse */
00643                         SO_LINGER       = 0x0080,               /* linger on close if data present */
00644                         SO_DONTLINGER   = ~(SO_LINGER),
00645                         SO_OOBINLINE    = 0x0100,               /* leave received OOB data in line */
00646                         SO_ACCEPTCONN   = 0x0002,               /* socket has had listen() */
00647                         SO_KEEPALIVE    = 0x0008,               /* keep connections alive */
00648                         SO_DONTROUTE    = 0x0010,               /* just use interface addresses */
00649                       //SO_TYPE
00650 
00651                         /*
00652                          * Additional options, not kept in so_options.
00653                          */
00654                         SO_SNDBUF       = 0x1001,               /* send buffer size */
00655                         SO_RCVBUF       = 0x1002,               /* receive buffer size */
00656                         SO_ERROR        = 0x1007,               /* get error status and clear */
00657 
00658                         // OptionLevel.IP settings
00659                         IP_MULTICAST_LOOP = 11,
00660                         IP_ADD_MEMBERSHIP = 12,
00661                         IP_DROP_MEMBERSHIP = 13,
00662                 }
00663 
00664                 /***************************************************************
00665 
00666 
00667                 ***************************************************************/
00668 
00669                 union linger
00670                 {
00671                         struct {
00672                                int l_onoff;             // option on/off
00673                                int l_linger;            // linger time
00674                                };
00675                         int[2]          array;          // combined
00676                 }
00677 
00678                 /***************************************************************
00679 
00680                         Question: are these correct for Darwin?
00681 
00682                 ***************************************************************/
00683 
00684                 enum OptionLevel
00685                 {
00686                         SOCKET =  1,  // correct for linux on x86 
00687                         IP =      0,  // appears to be correct
00688                         TCP =     6,  // appears to be correct
00689                         UDP =     17, // appears to be correct
00690                 }
00691         }
00692         else version (linux)
00693         {
00694                 /***************************************************************
00695 
00696                         these appear to be compatible with x86 platforms, 
00697                         but not others!
00698 
00699                 ***************************************************************/
00700 
00701                 enum Option: int
00702                 {
00703                         //consistent
00704                         SO_DEBUG        = 1,
00705                         SO_BROADCAST    = 6,
00706                         SO_REUSEADDR    = 2,
00707                         SO_LINGER       = 13,
00708                         SO_DONTLINGER   = ~(SO_LINGER),
00709                         SO_OOBINLINE    = 10,
00710                         SO_SNDBUF       = 7,
00711                         SO_RCVBUF       = 8,
00712                         SO_ERROR        = 4,
00713 
00714                         SO_ACCEPTCONN   = 30,
00715                         SO_KEEPALIVE    = 9, 
00716                         SO_DONTROUTE    = 5, 
00717                         SO_TYPE         = 3, 
00718 
00719                         // OptionLevel.IP settings
00720                         IP_MULTICAST_LOOP = 34,
00721                         IP_ADD_MEMBERSHIP = 35,
00722                         IP_DROP_MEMBERSHIP = 36,
00723                 }
00724 
00725                 /***************************************************************
00726 
00727 
00728                 ***************************************************************/
00729 
00730                 union linger
00731                 {
00732                         struct {
00733                                int l_onoff;             // option on/off
00734                                int l_linger;            // linger time
00735                                };
00736                         int[2]          array;          // combined
00737                 }
00738 
00739                 /***************************************************************
00740 
00741 
00742                 ***************************************************************/
00743 
00744                 enum OptionLevel
00745                 {
00746                         SOCKET =  1,  // correct for linux on x86 
00747                         IP =      0,  // appears to be correct
00748                         TCP =     6,  // appears to be correct
00749                         UDP =     17, // appears to be correct
00750                 }
00751         } // end versioning
00752 
00753         /***********************************************************************
00754 
00755 
00756         ***********************************************************************/
00757 
00758         enum Shutdown: int
00759         {
00760                 RECEIVE =  0,
00761                 SEND =     1,
00762                 BOTH =     2,
00763         }
00764 
00765         /***********************************************************************
00766 
00767 
00768         ***********************************************************************/
00769 
00770         enum Flags: int
00771         {
00772                 NONE =           0,
00773                 OOB =            0x1, //out of band
00774                 PEEK =           0x02, //only for receiving
00775                 DONTROUTE =      0x04, //only for sending
00776         }
00777 
00778         /***********************************************************************
00779 
00780 
00781         ***********************************************************************/
00782 
00783         enum Type: int
00784         {
00785                 STREAM =     1,
00786                 DGRAM =      2,
00787                 RAW =        3,
00788                 RDM =        4,
00789                 SEQPACKET =  5,
00790         }
00791 
00792 
00793         /***********************************************************************
00794 
00795 
00796         ***********************************************************************/
00797 
00798         enum Protocol: int
00799         {
00800                 IP =    0,
00801                 ICMP =  1,      // apparently a no-no for linux?
00802                 IGMP =  2,
00803                 GGP =   3,
00804                 TCP =   6,
00805                 PUP =   12,
00806                 UDP =   17,
00807                 IDP =   22,
00808                 ND =    77,
00809                 RAW =   255,
00810                 MAX =   256,
00811         }
00812 
00813 
00814         /***********************************************************************
00815 
00816 
00817         ***********************************************************************/
00818 
00819         version(Win32)
00820         {
00821                 enum AddressFamily: int
00822                 {
00823                         UNSPEC =     0,
00824                         UNIX =       1,
00825                         INET =       2,
00826                         IPX =        6,
00827                         APPLETALK =  16,
00828                         //INET6 =      ? // Need Windows XP ?
00829                 }
00830         }
00831         else version(BsdSockets)
00832         {
00833                 version (darwin)
00834                 {
00835                         enum AddressFamily: int
00836                         {
00837                                 UNSPEC =     0,
00838                                 UNIX =       1,
00839                                 INET =       2,
00840                                 IPX =        23,
00841                                 APPLETALK =  16,
00842                                 //INET6 =      10,
00843                         }
00844                 }
00845                 else version (linux)
00846                 {
00847                         enum AddressFamily: int
00848                         {
00849                                 UNSPEC =     0,
00850                                 UNIX =       1,
00851                                 INET =       2,
00852                                 IPX =        4,
00853                                 APPLETALK =  5,
00854                                 //INET6 =      10,
00855                         }
00856                 } // end version
00857         }
00858 
00859         /+
00860         #endif
00861         +/
00862         
00863 
00864         /***********************************************************************
00865 
00866 
00867         ***********************************************************************/
00868 
00869         this (AddressFamily af, Type type, Protocol protocol)
00870         {
00871                 create (af, type, protocol);
00872 
00873                 // MANGO: bump the usage count
00874                 acquire();
00875         }
00876         
00877         
00878         /***********************************************************************
00879 
00880                 MANGO: added for multicast support
00881 
00882         ***********************************************************************/
00883 
00884         protected void create (AddressFamily af, Type type, Protocol protocol)
00885         {
00886                 sock = socket (af, type, protocol);
00887                 if(sock == sock.init)
00888                    exception("Unable to create socket: ");
00889                 _family = af;
00890         }
00891         
00892         
00893         /***********************************************************************
00894 
00895                 get underlying socket handle
00896 
00897         ***********************************************************************/
00898 
00899         socket_t handle()
00900         {
00901                 return sock;
00902         }
00903         
00904         
00905         /***********************************************************************
00906 
00907 
00908         ***********************************************************************/
00909 
00910         override char[] toString()
00911         {
00912                 return "Socket";
00913         }
00914         
00915         
00916         /***********************************************************************
00917 
00918                 getter
00919 
00920         ***********************************************************************/
00921 
00922         bit blocking()
00923         {
00924                 version(Win32)
00925                 {
00926                         return _blocking;
00927                 }
00928                 else version(BsdSockets)
00929                 {
00930                         return !(fcntl(handle, F_GETFL, 0) & O_NONBLOCK);
00931                 }
00932         }
00933         
00934         
00935         /***********************************************************************
00936 
00937                 setter
00938 
00939         ***********************************************************************/
00940 
00941         void blocking(bit byes)
00942         {
00943                 version(Win32)
00944                 {
00945                         uint num = !byes;
00946                         if(SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &num))
00947                                 goto err;
00948                         _blocking = byes;
00949                 }
00950                 else version(BsdSockets)
00951                 {
00952                         int x = fcntl(handle, F_GETFL, 0);
00953                         if(byes)
00954                                 x &= ~O_NONBLOCK;
00955                         else
00956                                 x |= O_NONBLOCK;
00957                         if(SOCKET_ERROR == fcntl(sock, F_SETFL, x))
00958                                 goto err;
00959                 }
00960                 return; //success
00961                 
00962                 err:
00963                 exception("Unable to set socket blocking: ");
00964         }
00965         
00966         
00967         /***********************************************************************
00968 
00969 
00970         ***********************************************************************/
00971 
00972         AddressFamily addressFamily()
00973         {
00974                 return _family;
00975         }
00976         
00977         
00978         /***********************************************************************
00979 
00980 
00981         ***********************************************************************/
00982 
00983         bit isAlive()
00984         {
00985                 int type, typesize = type.sizeof;
00986                 return getsockopt (sock, SOL_SOCKET, SO_TYPE, cast(char*) &type, &typesize) != SOCKET_ERROR;
00987         }
00988         
00989         
00990         /***********************************************************************
00991 
00992 
00993         ***********************************************************************/
00994 
00995         void bind(Address addr)
00996         {
00997                 if(SOCKET_ERROR == .bind (sock, addr.name(), addr.nameLen()))
00998                    exception ("Unable to bind socket: ");
00999         }
01000         
01001         
01002         /***********************************************************************
01003 
01004 
01005         ***********************************************************************/
01006  
01007         void connect(Address to)
01008         {
01009                 if(SOCKET_ERROR == .connect (sock, to.name(), to.nameLen()))
01010                 {
01011                         if(!blocking)
01012                         {
01013                                 version(Win32)
01014                                 {
01015                                         if(WSAEWOULDBLOCK == WSAGetLastError())
01016                                                 return;
01017                                 }
01018                                 else version (Posix)
01019                                 {
01020                                         if(EINPROGRESS == getErrno())
01021                                                 return;
01022                                 }
01023                                 else
01024                                 {
01025                                         static assert(0);
01026                                 }
01027                         }
01028                         exception ("Unable to connect socket: ");
01029                 }
01030         }
01031         
01032         
01033         /***********************************************************************
01034 
01035                 need to bind() first
01036 
01037         ***********************************************************************/
01038 
01039         void listen(int backlog)
01040         {
01041                 if(SOCKET_ERROR == .listen (sock, backlog))
01042                    exception ("Unable to listen on socket: ");
01043         }
01044         
01045         /***********************************************************************
01046 
01047                 MANGO: added
01048 
01049         ***********************************************************************/
01050 
01051         protected Socket createSocket (socket_t handle)
01052         {
01053                 return new Socket (handle);
01054         }
01055 
01056         /***********************************************************************
01057 
01058 
01059         ***********************************************************************/
01060 
01061         Socket accept()
01062         {       
01063                 socket_t newsock = .accept (sock, null, null);
01064                 if(INVALID_SOCKET == newsock)
01065                    // MANGO: return null rather than throwing an exception because
01066                    // this is a valid condition upon thread-termination.
01067                   {
01068                   return null;
01069                   //exception("Unable to accept socket connection.");
01070                   }
01071 
01072                 // MANGO: changed to indirect construction
01073                 Socket newSocket = createSocket (newsock);
01074 
01075                 version(Win32)
01076                         newSocket._blocking = _blocking; //inherits blocking mode
01077                 newSocket._family = _family; //same family
01078                 return newSocket;
01079         }
01080         
01081         
01082         /***********************************************************************
01083 
01084 
01085         ***********************************************************************/
01086 
01087         void shutdown()
01088         {       //printf ("shutdown\n");
01089                 .shutdown (sock, cast(int) Shutdown.BOTH);
01090         }
01091         
01092         /***********************************************************************
01093 
01094 
01095         ***********************************************************************/
01096 
01097         void shutdown(Shutdown how)
01098         {
01099                 .shutdown (sock, cast(int)how);
01100         }
01101         
01102 
01103         /***********************************************************************
01104 
01105                 MANGO: added
01106 
01107         ***********************************************************************/
01108 
01109         void setLingerPeriod (int period)
01110         {
01111                 linger l;
01112 
01113                 l.l_onoff = 1;          //option on/off
01114                 l.l_linger = period;    //linger time
01115         
01116                 setOption (OptionLevel.SOCKET, Option.SO_LINGER, l.array);
01117         }
01118         
01119 
01120         /***********************************************************************
01121 
01122 
01123                 MANGO: added
01124 
01125         ***********************************************************************/
01126 
01127         void setAddressReuse (bool enabled)
01128         {
01129                 int[1] x = enabled;
01130                 setOption (OptionLevel.SOCKET, Option.SO_REUSEADDR, x);
01131         }
01132 
01133         
01134         /***********************************************************************
01135 
01136                 Helper function to handle the adding and dropping of group
01137                 membership.
01138 
01139                 MANGO: Added
01140 
01141         ***********************************************************************/
01142 
01143         bool setGroup (InternetAddress address, Option option)
01144         {
01145                 struct ip_mreq 
01146                 {
01147                 uint  imr_multiaddr;  /* IP multicast address of group */
01148                 uint  imr_interface;  /* local IP address of interface */
01149                 };
01150 
01151                 ip_mreq mrq;
01152 
01153                 mrq.imr_interface = 0;
01154                 mrq.imr_multiaddr = address.sin.sin_addr;
01155                 return .setsockopt(handle(), OptionLevel.IP, option, &mrq, mrq.sizeof) != SOCKET_ERROR;
01156         }
01157 
01158 
01159         /***********************************************************************
01160 
01161                 calling shutdown() before this is recommended for connection-
01162                 oriented sockets
01163 
01164                 MANGO: changed from close() to IResource.closure()
01165 
01166         ***********************************************************************/
01167 
01168         override void closure ()
01169         {
01170                 version (TraceLinux)
01171                         {
01172                         printf ("closing socket handle ...\n");
01173                         }
01174                 version(Win32)
01175                 {
01176                         .closesocket (sock);
01177                 }
01178                 else version(BsdSockets)
01179                 {
01180                         .close (sock);
01181                 }
01182                 sock = sock.init;
01183                 version (TraceLinux)
01184                         {
01185                         printf ("socket handle closed\n");
01186                         }
01187         }       
01188         
01189 
01190         /***********************************************************************
01191 
01192 
01193         ***********************************************************************/
01194 
01195         private Address newFamilyObject ()
01196         {
01197                 Address result;
01198                 switch(_family)
01199                 {
01200                         case AddressFamily.INET:
01201                                 result = new InternetAddress;
01202                                 break;
01203                         
01204                         default:
01205                                 result = new UnknownAddress;
01206                 }
01207                 return result;
01208         }
01209         
01210         
01211         /***********************************************************************
01212 
01213                 Mango: added this to return the hostname
01214 
01215         ***********************************************************************/
01216 
01217         static char[] hostName ()
01218         {
01219                 char[64] name;
01220 
01221                 if(SOCKET_ERROR == .gethostname (name, name.length))
01222                    exception ("Unable to obtain host name: ");
01223                 return name [0 .. strlen(name)].dup;
01224         }
01225         
01226 
01227         /***********************************************************************
01228 
01229                 Mango: added this to return the default host address (IPv4)
01230 
01231         ***********************************************************************/
01232 
01233         static uint hostAddress ()
01234         {
01235                 InternetHost ih = new InternetHost;
01236 
01237                 char[] hostname = hostName();
01238                 ih.getHostByName (hostname);
01239                 assert (ih.addrList.length);
01240                 return ih.addrList[0];
01241         }
01242 
01243         
01244         /***********************************************************************
01245 
01246 
01247         ***********************************************************************/
01248 
01249         Address remoteAddress ()
01250         {
01251                 Address addr = newFamilyObject ();
01252                 int nameLen = addr.nameLen ();
01253                 if(SOCKET_ERROR == .getpeername (sock, addr.name(), &nameLen))
01254                    exception ("Unable to obtain remote socket address: ");
01255                 assert (addr.addressFamily() == _family);
01256                 return addr;
01257         }
01258         
01259         
01260         /***********************************************************************
01261 
01262 
01263         ***********************************************************************/
01264 
01265         Address localAddress ()
01266         {
01267                 Address addr = newFamilyObject ();
01268                 int nameLen = addr.nameLen();
01269                 if(SOCKET_ERROR == .getsockname (sock, addr.name(), &nameLen))
01270                    exception ("Unable to obtain local socket address: ");
01271                 assert (addr.addressFamily() == _family);
01272                 return addr;
01273         }
01274         
01275         
01276         /***********************************************************************
01277 
01278                 returns number of bytes actually sent, or -1 on error
01279 
01280         ***********************************************************************/
01281 
01282         int send (void[] buf, Flags flags = Flags.NONE)
01283         {
01284                 int sent = .send (sock, buf, buf.length, cast(int)flags);
01285                 return sent;
01286         }
01287         
01288         
01289         /***********************************************************************
01290 
01291                 -to- is ignored if connected ?
01292 
01293         ***********************************************************************/
01294 
01295         int sendTo (void[] buf, Flags flags, Address to)
01296         {
01297                 int sent = .sendto (sock, buf, buf.length, cast(int)flags, to.name(), to.nameLen());
01298                 return sent;
01299         }
01300         
01301         
01302         /***********************************************************************
01303 
01304                 -to- is ignored if connected ?
01305 
01306         ***********************************************************************/
01307 
01308         int sendTo (void[] buf, Address to)
01309         {
01310                 return sendTo (buf, Flags.NONE, to);
01311         }
01312         
01313         
01314         /***********************************************************************
01315 
01316                 assumes you connect()ed
01317 
01318         ***********************************************************************/
01319 
01320         int sendTo (void[] buf, Flags flags = Flags.NONE)
01321         {
01322                 int sent = .sendto (sock, buf, buf.length, cast(int)flags, null, 0);
01323                 return sent;
01324         }
01325         
01326         
01327         /***********************************************************************
01328 
01329                 returns number of bytes actually received, 0 on connection 
01330                 closure, or -1 on error
01331 
01332         ***********************************************************************/
01333 
01334         int receive (void[] buf, Flags flags = Flags.NONE)
01335         {
01336                 if(!buf.length) //return 0 and don't think the connection closed
01337                         return 0;
01338                 int read = .recv(sock, buf, buf.length, cast(int)flags);
01339                 if (read == SOCKET_ERROR)
01340                     exception ("Failed while receiving socket data: ");
01341                 // if(!read) //connection closed
01342                 return read;
01343         }
01344         
01345         
01346         /***********************************************************************
01347 
01348                 -from- is ignored if connected ?
01349 
01350         ***********************************************************************/
01351 
01352         int receiveFrom (void[] buf, Flags flags, out Address from)
01353         {
01354                 if(!buf.length) //return 0 and don't think the connection closed
01355                         return 0;
01356                 version (TraceLinux)
01357                         {
01358                         printf ("executing recvFrom() \n");
01359                         }
01360                 from = newFamilyObject ();
01361                 int nameLen = from.nameLen ();
01362                 int read = .recvfrom (sock, buf, buf.length, cast(int)flags, from.name(), &nameLen);
01363                 version (TraceLinux)
01364                         {
01365                         printf ("recvFrom returns %d\n", read);
01366                         }
01367                 if (read == SOCKET_ERROR)
01368                     exception ("Failed while receiving socket data: ");
01369 
01370                 assert (from.addressFamily() == _family);
01371                 // if(!read) //connection closed
01372                 return read;
01373         }
01374         
01375         
01376         /***********************************************************************
01377 
01378                 -from- is ignored if connected ?
01379 
01380         ***********************************************************************/
01381 
01382         int receiveFrom (void[] buf, out Address from)
01383         {
01384                 return receiveFrom (buf, Flags.NONE, from);
01385         }
01386         
01387         
01388         /***********************************************************************
01389 
01390                 assumes you connect()ed
01391 
01392         ***********************************************************************/
01393 
01394         int receiveFrom (void[] buf, Flags flags)
01395         {
01396                 if(!buf.length) //return 0 and don't think the connection closed
01397                         return 0;
01398                 int read = .recvfrom (sock, buf, buf.length, cast(int)flags, null, null);
01399                 if (read == SOCKET_ERROR)
01400                     exception ("Failed while receiving socket data: ");
01401                 // if(!read) //connection closde
01402                 return read;
01403         }
01404         
01405         
01406         /***********************************************************************
01407 
01408                 assumes you connect()ed
01409 
01410         ***********************************************************************/
01411 
01412         int receiveFrom (void[] buf)
01413         {
01414                 return receiveFrom (buf, Flags.NONE);
01415         }
01416         
01417         
01418         /***********************************************************************
01419 
01420                 returns the length, in bytes, of the actual result - very 
01421                 different from getsockopt()
01422 
01423         ***********************************************************************/
01424 
01425         int getOption (OptionLevel level, Option option, void[] result)
01426         {
01427                 int len = result.length;
01428                 if(SOCKET_ERROR == .getsockopt (sock, cast(int)level, cast(int)option, result, &len))
01429                    exception ("Unable to get socket option: ");
01430                 return len;
01431         }
01432         
01433         
01434         /***********************************************************************
01435 
01436 
01437         ***********************************************************************/
01438 
01439         void setOption (OptionLevel level, Option option, void[] value)
01440         {
01441                 if(SOCKET_ERROR == .setsockopt (sock, cast(int)level, cast(int)option, value, value.length))
01442                    exception ("Unable to set socket option: ");
01443         }
01444         
01445         
01446         /***********************************************************************
01447 
01448                 Mango: added this common function
01449 
01450         ***********************************************************************/
01451 
01452         protected static void exception (char[] msg)
01453         {
01454                 msg ~= System.error (lastError);
01455                 throw new SocketException (msg);
01456         }
01457         
01458 
01459         /***********************************************************************
01460 
01461                 SocketSet's are updated to include only those sockets which an 
01462                 event occured.
01463                 
01464                 Returns the number of events, 0 on timeout, or -1 on interruption
01465 
01466                 for a connect()ing socket, writeability means connected 
01467                 for a listen()ing socket, readability means listening 
01468 
01469                 Winsock: possibly internally limited to 64 sockets per set
01470 
01471         ***********************************************************************/
01472 
01473         static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, timeval* tv)
01474         in
01475         {
01476                 //make sure none of the SocketSet's are the same object
01477                 if(checkRead)
01478                 {
01479                         assert(checkRead !is checkWrite);
01480                         assert(checkRead !is checkError);
01481                 }
01482                 if(checkWrite)
01483                 {
01484                         assert(checkWrite !is checkError);
01485                 }
01486         }
01487         body
01488         {
01489                 fd_set* fr, fw, fe;
01490                 
01491                 version(Win32)
01492                 {
01493                         //Windows has a problem with empty fd_set's that aren't null
01494                         fr = (checkRead && checkRead.count()) ? checkRead.toFd_set() : null;
01495                         fw = (checkWrite && checkWrite.count()) ? checkWrite.toFd_set() : null;
01496                         fe = (checkError && checkError.count()) ? checkError.toFd_set() : null;
01497                 }
01498                 else
01499                 {
01500                         fr = checkRead ? checkRead.toFd_set() : null;
01501                         fw = checkWrite ? checkWrite.toFd_set() : null;
01502                         fe = checkError ? checkError.toFd_set() : null;
01503                 }
01504                
01505                 int result;
01506               
01507                 // MANGO: if select() was interrupted, we now try again
01508                 while ((result = .select (socket_t.max - 1, fr, fw, fe, tv)) == -1)              
01509                         version(Win32)
01510                         {
01511                                 if(WSAGetLastError() != WSAEINTR)
01512                                    break;
01513                         }
01514                         else version (Posix)
01515                         {
01516                                 if(getErrno() != EINTR)
01517                                    break;
01518                         }
01519                         else
01520                         {
01521                                 static assert(0);
01522                         }
01523                 
01524                 // MANGO: don't throw an exception here ... wait until we get 
01525                 // a bit further back along the control path
01526                 //if(SOCKET_ERROR == result)
01527                 //   throw new SocketException("Socket select error.");
01528                 
01529                 return result;
01530         }
01531         
01532         
01533         /***********************************************************************
01534 
01535 
01536         ***********************************************************************/
01537 
01538         static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, int microseconds)
01539         {
01540                 timeval tv;
01541                 tv.tv_sec = 0;
01542                 tv.tv_usec = microseconds;
01543                 return select (checkRead, checkWrite, checkError, &tv);
01544         }
01545         
01546         
01547         /***********************************************************************
01548 
01549                 maximum timeout
01550 
01551         ***********************************************************************/
01552 
01553         static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError)
01554         {
01555                 return select (checkRead, checkWrite, checkError, null);
01556         }
01557         
01558         
01559         /***********************************************************************
01560 
01561 
01562         ***********************************************************************/
01563 
01564         /+
01565         bit poll (events)
01566         {
01567                 int WSAEventSelect(socket_t s, WSAEVENT hEventObject, int lNetworkEvents); // Winsock 2 ?
01568                 int poll(pollfd* fds, int nfds, int timeout); // Unix ?
01569         }
01570         +/
01571 
01572 
01573 }
01574 
01575 
01576 
01577 /*******************************************************************************
01578 
01579 
01580 *******************************************************************************/
01581 
01582 abstract class Address
01583 {
01584         protected sockaddr* name();
01585         protected int nameLen();
01586         Socket.AddressFamily addressFamily();
01587         char[] toString();
01588 }
01589 
01590 
01591 /*******************************************************************************
01592 
01593 
01594 *******************************************************************************/
01595 
01596 class UnknownAddress: Address
01597 {
01598         protected:
01599         sockaddr sa;
01600         
01601         
01602         /***********************************************************************
01603 
01604 
01605         ***********************************************************************/
01606 
01607         sockaddr* name()
01608         {
01609                 return &sa;
01610         }
01611         
01612         
01613         /***********************************************************************
01614 
01615 
01616         ***********************************************************************/
01617 
01618         int nameLen()
01619         {
01620                 return sa.sizeof;
01621         }
01622         
01623         
01624         public:
01625         /***********************************************************************
01626 
01627 
01628         ***********************************************************************/
01629 
01630         Socket.AddressFamily addressFamily()
01631         {
01632                 return cast(Socket.AddressFamily)sa.sa_family;
01633         }
01634         
01635         
01636         /***********************************************************************
01637 
01638 
01639         ***********************************************************************/
01640 
01641         char[] toString()
01642         {
01643                 return "Unknown";
01644         }
01645 }
01646 
01647 
01648 /*******************************************************************************
01649 
01650 
01651 *******************************************************************************/
01652 
01653 class InternetHost
01654 {
01655         char[] name;
01656         char[][] aliases;
01657         uint[] addrList;
01658         
01659         
01660         /***********************************************************************
01661 
01662 
01663         ***********************************************************************/
01664 
01665         protected void validHostent(hostent* he)
01666         {
01667                 if(he.h_addrtype != cast(int)Socket.AddressFamily.INET || he.h_length != 4)
01668                         throw new HostException("Address family mismatch.");
01669         }
01670         
01671         
01672         /***********************************************************************
01673 
01674 
01675         ***********************************************************************/
01676 
01677         void populate(hostent* he)
01678         {
01679                 int i;
01680                 char* p;
01681                 
01682                 name = .toString(he.h_name);
01683                 
01684                 for(i = 0;; i++)
01685                 {
01686                         p = he.h_aliases[i];
01687                         if(!p)
01688                                 break;
01689                 }
01690                 
01691                 if(i)
01692                 {
01693                         aliases = new char[][i];
01694                         for(i = 0; i != aliases.length; i++)
01695                         {
01696                                 aliases[i] = .toString(he.h_aliases[i]);
01697                         }
01698                 }
01699                 else
01700                 {
01701                         aliases = null;
01702                 }
01703                 
01704                 for(i = 0;; i++)
01705                 {
01706                         p = he.h_addr_list[i];
01707                         if(!p)
01708                                 break;
01709                 }
01710                 
01711                 if(i)
01712                 {
01713                         addrList = new uint[i];
01714                         for(i = 0; i != addrList.length; i++)
01715                         {
01716                                 addrList[i] = ntohl(*(cast(uint*)he.h_addr_list[i]));
01717                         }
01718                 }
01719                 else
01720                 {
01721                         addrList = null;
01722                 }
01723         }
01724         
01725         
01726         /***********************************************************************
01727 
01728 
01729         ***********************************************************************/
01730 
01731         bit getHostByName(char[] name)
01732         {
01733                 hostent* he = gethostbyname(name.dup);
01734                 if(!he)
01735                         return false;
01736                 validHostent(he);
01737                 populate(he);
01738                 return true;
01739         }
01740         
01741         
01742         /***********************************************************************
01743 
01744 
01745         ***********************************************************************/
01746 
01747         bit getHostByAddr(uint addr)
01748         {
01749                 uint x = htonl(addr);
01750                 hostent* he = gethostbyaddr(&x, 4, cast(int)Socket.AddressFamily.INET);
01751                 if(!he)
01752                         return false;
01753                 validHostent(he);
01754                 populate(he);
01755                 return true;
01756         }
01757         
01758         
01759         /***********************************************************************
01760 
01761 
01762         ***********************************************************************/
01763 
01764         //shortcut
01765         bit getHostByAddr(char[] addr)
01766         {
01767                 uint x = inet_addr(addr.dup);
01768                 hostent* he = gethostbyaddr(&x, 4, cast(int)Socket.AddressFamily.INET);
01769                 if(!he)
01770                         return false;
01771                 validHostent(he);
01772                 populate(he);
01773                 return true;
01774         }
01775 }
01776 
01777 
01778 unittest
01779 {
01780         InternetHost ih = new InternetHost;
01781         assert(ih.addrList.length);
01782         InternetAddress ia = new InternetAddress(ih.addrList[0], InternetAddress.PORT_ANY);
01783         printf("IP address = %.*s\nname = %.*s\n", ia.toAddrString(), ih.name);
01784         foreach(int i, char[] s; ih.aliases)
01785         {
01786                 printf("aliases[%d] = %.*s\n", i, s);
01787         }
01788         
01789         printf("---\n");
01790         
01791         assert(ih.getHostByAddr(ih.addrList[0]));
01792         printf("name = %.*s\n", ih.name);
01793         foreach(int i, char[] s; ih.aliases)
01794         {
01795                 printf("aliases[%d] = %.*s\n", i, s);
01796         }
01797 }
01798 
01799 
01800 /*******************************************************************************
01801 
01802 
01803 *******************************************************************************/
01804 
01805 class InternetAddress: Address
01806 {
01807         /+
01808         #ifdef INCLUDE_ALL_FOR_DOXYGEN
01809         +/
01810         protected:
01811         /***********************************************************************
01812 
01813 
01814         ***********************************************************************/
01815 
01816         struct sockaddr_in
01817         {
01818                 ushort sin_family = cast(ushort)Socket.AddressFamily.INET;
01819                 ushort sin_port;
01820                 uint sin_addr; //in_addr
01821                 char[8] sin_zero = [0];
01822         }
01823         /+
01824         #endif
01825         +/
01826 
01827         sockaddr_in sin;
01828         
01829         
01830         /***********************************************************************
01831 
01832 
01833         ***********************************************************************/
01834 
01835         sockaddr* name()
01836         {
01837                 return cast(sockaddr*)&sin;
01838         }
01839         
01840         
01841         /***********************************************************************
01842 
01843 
01844         ***********************************************************************/
01845 
01846         int nameLen()
01847         {
01848                 return sin.sizeof;
01849         }
01850         
01851         
01852         /***********************************************************************
01853 
01854 
01855         ***********************************************************************/
01856 
01857         this()
01858         {
01859         }
01860         
01861         
01862         public:
01863         const uint ADDR_ANY = 0;
01864         const uint ADDR_NONE = cast(uint)-1;
01865         const ushort PORT_ANY = 0;
01866         
01867         
01868         /***********************************************************************
01869 
01870 
01871         ***********************************************************************/
01872 
01873         Socket.AddressFamily addressFamily()
01874         {
01875                 return Socket.AddressFamily.INET;
01876         }
01877         
01878         
01879         /***********************************************************************
01880 
01881 
01882         ***********************************************************************/
01883 
01884         ushort port()
01885         {
01886                 return ntohs(sin.sin_port);
01887         }
01888         
01889         
01890         /***********************************************************************
01891 
01892 
01893         ***********************************************************************/
01894 
01895         uint addr()
01896         {
01897                 return ntohl(sin.sin_addr);
01898         }
01899         
01900         
01901         /***********************************************************************
01902 
01903                 -port- can be PORT_ANY
01904                 -addr- is an IP address or host name
01905 
01906         ***********************************************************************/
01907 
01908         this(char[] addr, ushort port = PORT_ANY)
01909         {
01910                 uint uiaddr = parse(addr);
01911                 if(ADDR_NONE == uiaddr)
01912                 {
01913                         InternetHost ih = new InternetHost;
01914                         if(!ih.getHostByName(addr))
01915                                 throw new AddressException("Invalid internet address '"~addr~"'");
01916                         uiaddr = ih.addrList[0];
01917                 }
01918                 sin.sin_addr = htonl(uiaddr);
01919                 sin.sin_port = htons(port);
01920         }
01921         
01922         
01923         /***********************************************************************
01924 
01925 
01926         ***********************************************************************/
01927 
01928         this(uint addr, ushort port)
01929         {
01930                 sin.sin_addr = htonl(addr);
01931                 sin.sin_port = htons(port);
01932         }
01933         
01934         
01935         /***********************************************************************
01936 
01937 
01938         ***********************************************************************/
01939 
01940         this(ushort port)
01941         {
01942                 sin.sin_addr = 0; //any, "0.0.0.0"
01943                 sin.sin_port = htons(port);
01944         }
01945         
01946         
01947         /***********************************************************************
01948 
01949 
01950         ***********************************************************************/
01951 
01952         char[] toAddrString()
01953         {
01954                 return .toString(inet_ntoa(sin.sin_addr)).dup;
01955         }
01956         
01957         
01958         /***********************************************************************
01959 
01960 
01961         ***********************************************************************/
01962 
01963         char[] toPortString()
01964         {
01965                 return Int.format(port());
01966         }
01967         
01968         
01969         /***********************************************************************
01970 
01971 
01972         ***********************************************************************/
01973 
01974         char[] toString()
01975         {
01976                 return toAddrString() ~ ":" ~ toPortString();
01977         }
01978         
01979         
01980         /***********************************************************************
01981 
01982                 -addr- is an IP address in the format "a.b.c.d"
01983                 returns ADDR_NONE on failure
01984 
01985         ***********************************************************************/
01986 
01987         static uint parse(char[] addr)
01988         {
01989                 return ntohl(inet_addr(addr.dup));
01990         }
01991 }
01992 
01993 
01994 unittest
01995 {
01996         InternetAddress ia = new InternetAddress("63.105.9.61", 80);
01997         assert(ia.toString() == "63.105.9.61:80");
01998 }
01999 
02000 
02001 /*******************************************************************************
02002 
02003 
02004 *******************************************************************************/
02005 
02006 //a set of sockets for Socket.select()
02007 class SocketSet
02008 {
02009         private:
02010         uint nbytes; //Win32: excludes uint.size "count"
02011         byte* buf;
02012         
02013         
02014         version(Win32)
02015         {
02016                 uint count()
02017                 {
02018                         return *(cast(uint*)buf);
02019                 }
02020                 
02021                 
02022                 void count(int setter)
02023                 {
02024                         *(cast(uint*)buf) = setter;
02025                 }
02026                 
02027                 
02028                 socket_t* first()
02029                 {
02030                         return cast(socket_t*)(buf + uint.sizeof);
02031                 }
02032         }
02033         else version (Posix)
02034         {
02035                 import std.intrinsic;
02036                 
02037                 
02038                 uint nfdbits;
02039                 
02040                 
02041                 uint fdelt(socket_t s)
02042                 {
02043                         return cast(uint)s / nfdbits;
02044                 }
02045                 
02046                 
02047                 uint fdmask(socket_t s)
02048                 {
02049                         return 1 << cast(uint)s % nfdbits;
02050                 }
02051                 
02052                 
02053                 uint* first()
02054                 {
02055                         return cast(uint*)buf;
02056                 }
02057         }
02058         
02059         
02060         public:
02061         /***********************************************************************
02062 
02063 
02064         ***********************************************************************/
02065 
02066         this(uint max)
02067         {
02068                 version(Win32)
02069                 {
02070                         nbytes = max * socket_t.sizeof;
02071                         buf = new byte[nbytes + uint.sizeof];
02072                         count = 0;
02073                 }
02074                 else version (Posix)
02075                 {
02076                         if(max <= 32)
02077                                 nbytes = 32 * uint.sizeof;
02078                         else
02079                                 nbytes = max * uint.sizeof;
02080                         buf = new byte[nbytes];
02081                         nfdbits = nbytes * 8;
02082                         //clear(); //new initializes to 0
02083                 }
02084                 else
02085                 {
02086                         static assert(0);
02087                 }
02088         }
02089         
02090         
02091         /***********************************************************************
02092 
02093 
02094         ***********************************************************************/
02095 
02096         this()
02097         {
02098                 version(Win32)
02099                 {
02100                         this(64);
02101                 }
02102                 else version (Posix)
02103                 {
02104                         this(32);
02105                 }
02106                 else
02107                 {
02108                         static assert(0);
02109                 }
02110         }
02111         
02112         
02113         /***********************************************************************
02114 
02115 
02116         ***********************************************************************/
02117 
02118         void reset()
02119         {
02120                 version(Win32)
02121                 {
02122                         count = 0;
02123                 }
02124                 else version (Posix)
02125                 {
02126                         buf[0 .. nbytes] = 0;
02127                 }
02128                 else
02129                 {
02130                         static assert(0);
02131                 }
02132         }
02133         
02134         
02135         /***********************************************************************
02136 
02137 
02138         ***********************************************************************/
02139 
02140         void add(socket_t s)
02141         in
02142         {
02143                 version(Win32)
02144                 {
02145                         assert(count < max); //added too many sockets; specify a higher max in the constructor
02146                 }
02147         }
02148         body
02149         {
02150                 version(Win32)
02151                 {
02152                         uint c = count;
02153                         first[c] = s;
02154                         count = c + 1;
02155                 }
02156                 else version (Posix)
02157                 {
02158                         bts(cast(uint*)&first[fdelt(s)], cast(uint)s % nfdbits);
02159                 }
02160                 else
02161                 {
02162                         static assert(0);
02163                 }
02164         }
02165         
02166         
02167         /***********************************************************************
02168 
02169 
02170         ***********************************************************************/
02171 
02172         void add(Socket s)
02173         {
02174                 add(s.sock);
02175         }
02176         
02177         
02178         /***********************************************************************
02179 
02180 
02181         ***********************************************************************/
02182 
02183         void remove(socket_t s)
02184         {
02185                 version(Win32)
02186                 {
02187                         uint c = count;
02188                         socket_t* start = first;
02189                         socket_t* stop = start + c;
02190                         
02191                         for(; start != stop; start++)
02192                         {
02193                                 if(*start == s)
02194                                         goto found;
02195                         }
02196                         return; //not found
02197                         
02198                         found:
02199                         for(++start; start != stop; start++)
02200                         {
02201                                 *(start - 1) = *start;
02202                         }
02203                         
02204                         count = c - 1;
02205                 }
02206                 else version (Posix)
02207                 {
02208                         btr(cast(uint*)&first[fdelt(s)], cast(uint)s % nfdbits);
02209                 }
02210                 else
02211                 {
02212                         static assert(0);
02213                 }
02214         }
02215         
02216         
02217         /***********************************************************************
02218 
02219 
02220         ***********************************************************************/
02221 
02222         void remove(Socket s)
02223         {
02224                 remove(s.sock);
02225         }
02226         
02227         
02228         /***********************************************************************
02229 
02230 
02231         ***********************************************************************/
02232 
02233         int isSet(socket_t s)
02234         {
02235                 version(Win32)
02236                 {
02237                         socket_t* start = first;
02238                         socket_t* stop = start + count;
02239                         
02240                         for(; start != stop; start++)
02241                         {
02242                                 if(*start == s)
02243                                         return true;
02244                         }
02245                         return false;
02246                 }
02247                 else version (Posix)
02248                 {
02249                         //return bt(cast(uint*)&first[fdelt(s)], cast(uint)s % nfdbits);
02250                         int index = cast(uint)s % nfdbits;
02251                         return (cast(uint*)&first[fdelt(s)])[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)));
02252                 }
02253                 else
02254                 {
02255                         static assert(0);
02256                 }
02257         }
02258         
02259         
02260         /***********************************************************************
02261 
02262 
02263         ***********************************************************************/
02264 
02265         int isSet(Socket s)
02266         {
02267                 return isSet(s.sock);
02268         }
02269         
02270         
02271         /***********************************************************************
02272 
02273                 max sockets that can be added, like FD_SETSIZE
02274 
02275         ***********************************************************************/
02276 
02277         uint max() 
02278         {
02279                 return nbytes / socket_t.sizeof;
02280         }
02281         
02282         
02283         /***********************************************************************
02284 
02285 
02286         ***********************************************************************/
02287 
02288         fd_set* toFd_set()
02289         {
02290                 return cast(fd_set*)buf;
02291         }
02292 }
02293 
02294 
02295 
02296 
02297 /******************************************************************************/
02298 /******************* additions for the mango.io package  **********************/           
02299 /******************************************************************************/
02300 
02301 
02302 /******************************************************************************
02303 
02304 ******************************************************************************/
02305 
02306 interface IListener
02307 {
02308         /***********************************************************************
02309 
02310                 Stop listening; this may be delayed until after the next
02311                 valid read operation.
02312 
02313         ***********************************************************************/
02314 
02315         void cancel ();
02316 }
02317 
02318 
02319 /******************************************************************************
02320 
02321 ******************************************************************************/
02322 
02323 interface ISocketReader
02324 {
02325         /***********************************************************************
02326 
02327                 Polymorphic contract for readers handed to a listener. 
02328                 Should return the number of bytes read, or -1 on error.
02329 
02330         ***********************************************************************/
02331 
02332         int read (IBuffer buffer);
02333 }
02334 
02335 
02336 

Generated on Fri Nov 11 18:44:22 2005 for Mango by  doxygen 1.4.0