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

Generated on Mon Nov 14 10:59:40 2005 for Mango by  doxygen 1.4.0