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

Generated on Tue Jan 25 21:18:23 2005 for Mango by doxygen 1.3.6