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

Socket.d

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

Generated on Sat Dec 24 17:28:33 2005 for Mango by  doxygen 1.4.0