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

Socket.d

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

Generated on Sat Apr 9 20:11:28 2005 for Mango by doxygen 1.3.6