Changeset 395

Show
Ignore:
Timestamp:
07/21/08 10:53:23 (4 months ago)
Author:
FeepingCreature
Message:
  • Okay, this better work.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/tools/tools/fixed_socket.d

    r394 r395  
    44 
    55public import std.socket; 
    6 version(Windows) private import std.c.windows.winsock: hostent, gethostbyname, sockaddr, sockaddr_in; 
    7 else version(Unix) private import std.c.unix.unix, std.c.stdlib: ERANGE; 
    8 else version(linux) private import std.c.linux.socket, std.c.stdlib: ERANGE; 
    9 else static assert(0); // No socket support yet. 
    10  
    11 import std.string; 
    12  
    13 class ActuallyThreadsafeInternetHost { 
    14   string name; 
    15   string[] aliases; 
    16   uint[] addrList; 
    17   void validHostent(hostent* he) { 
    18     if (he.h_addrtype != cast(int)AddressFamily.INET || he.h_length != 4) 
    19       throw new HostException("Address family mismatch"); 
    20   } 
    21   void populate(hostent* he) { 
    22     char* p; 
    23     name = std.string.toString(he.h_name).dup; 
    24     int i; 
    25     for(i = 0;; i++) { 
    26       p = he.h_aliases[i]; 
    27       if (!p) break; 
     6version(Windows) { 
     7  // no problem under win32 
     8  alias InternetHost ActuallyThreadsafeInternetHost; 
     9  alias Address ActuallyWorkingInternetAddress; 
     10} else { 
     11  version(Unix) private import std.c.unix.unix, std.c.stdlib: ERANGE; 
     12  else version(linux) private import std.c.linux.socket, std.c.stdlib: ERANGE; 
     13  else static assert(0); // No socket support yet. 
     14   
     15  import std.string; 
     16   
     17  class ActuallyThreadsafeInternetHost { 
     18    string name; 
     19    string[] aliases; 
     20    uint[] addrList; 
     21    void validHostent(hostent* he) { 
     22      if (he.h_addrtype != cast(int)AddressFamily.INET || he.h_length != 4) 
     23        throw new HostException("Address family mismatch"); 
    2824    } 
    29     if (i) { 
    30       aliases = new string[i]; 
    31       foreach (id, ref _alias; aliases) _alias=std.string.toString(he.h_aliases[id]).dup; 
    32     } else aliases = null; 
     25    void populate(hostent* he) { 
     26      char* p; 
     27      name = std.string.toString(he.h_name).dup; 
     28      int i; 
     29      for(i = 0;; i++) { 
     30        p = he.h_aliases[i]; 
     31        if (!p) break; 
     32      } 
     33      if (i) { 
     34        aliases = new string[i]; 
     35        foreach (id, ref _alias; aliases) _alias=std.string.toString(he.h_aliases[id]).dup; 
     36      } else aliases = null; 
     37       
     38      for(i = 0;; i++) { 
     39        p=he.h_addr_list[i]; 
     40        if (!p) break; 
     41      } 
     42      if(i) { 
     43        addrList = new uint[i]; 
     44        foreach (id, ref entry; addrList) entry = ntohl(*(cast(uint*)he.h_addr_list[id])); 
     45      } 
     46      else addrList = null; 
     47    } 
    3348     
    34     for(i = 0;; i++) { 
    35       p=he.h_addr_list[i]; 
    36       if (!p) break; 
     49    bool getHostByName(string name) 
     50    { 
     51      version (Windows) 
     52        hostent* he = gethostbyname(toStringz(name)); 
     53      else { 
     54        auto he = new hostent; 
     55        auto buffer=new char[512]; 
     56        int errno; 
     57        getHostByName_retry: // if we had extended do { } while { } this would not be necessary. 
     58        auto res = gethostbyname_r(toStringz(name), he, buffer.ptr, buffer.length, &he, &errno); 
     59        if (res == ERANGE) { buffer.length = buffer.length * 2; if (!he) he=new hostent; goto getHostByName_retry; } 
     60      } 
     61      if(!he) return false; 
     62      validHostent(he); 
     63      populate(he); 
     64      return true; 
    3765    } 
    38     if(i) { 
    39       addrList = new uint[i]; 
    40       foreach (id, ref entry; addrList) entry = ntohl(*(cast(uint*)he.h_addr_list[id])); 
     66     
     67    bool getHostByAddr(uint addr) 
     68    { 
     69      uint x = htonl(addr); 
     70      hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET); 
     71      if(!he) 
     72              return false; 
     73      validHostent(he); 
     74      populate(he); 
     75      return true; 
    4176    } 
    42     else addrList = null; 
     77    bool getHostByAddr(string addr) 
     78    { 
     79      uint x = inet_addr(std.string.toStringz(addr)); 
     80      hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET); 
     81      if(!he) 
     82              return false; 
     83      validHostent(he); 
     84      populate(he); 
     85      return true; 
     86    } 
    4387  } 
    4488   
    45   bool getHostByName(string name) 
    46   { 
    47     version (Windows) 
    48       hostent* he = gethostbyname(toStringz(name)); 
    49     else { 
    50       auto he = new hostent; 
    51       auto buffer=new char[512]; 
    52       int errno; 
    53       getHostByName_retry: // if we had extended do { } while { } this would not be necessary. 
    54       auto res = gethostbyname_r(toStringz(name), he, buffer.ptr, buffer.length, &he, &errno); 
    55       if (res == ERANGE) { buffer.length = buffer.length * 2; if (!he) he=new hostent; goto getHostByName_retry; } 
    56     } 
    57     if(!he) return false; 
    58     validHostent(he); 
    59     populate(he); 
    60     return true; 
    61   } 
    62    
    63   bool getHostByAddr(uint addr) 
    64   { 
    65     uint x = htonl(addr); 
    66     hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET); 
    67     if(!he) 
    68             return false; 
    69     validHostent(he); 
    70     populate(he); 
    71     return true; 
    72   } 
    73   bool getHostByAddr(string addr) 
    74   { 
    75     uint x = inet_addr(std.string.toStringz(addr)); 
    76     hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET); 
    77     if(!he) 
    78             return false; 
    79     validHostent(he); 
    80     populate(he); 
    81     return true; 
     89  class ActuallyWorkingInternetAddress : Address { 
     90    protected: 
     91      sockaddr_in sin; 
     92      sockaddr* name() { return cast(sockaddr*)&sin; } 
     93      int nameLen() { return sin.sizeof; }  
     94      this() { } 
     95    public: 
     96      const uint ADDR_ANY = INADDR_ANY; /// Any IPv4 address number. 
     97      const uint ADDR_NONE = INADDR_NONE;   /// An invalid IPv4 address number. 
     98      const ushort PORT_ANY = 0;        /// Any IPv4 port number. 
     99       
     100      AddressFamily addressFamily() { return cast(AddressFamily)AddressFamily.INET; } 
     101      ushort port() { return ntohs(sin.sin_port); } 
     102      uint addr() { return ntohl(sin.sin_addr.s_addr); } 
     103      this(string addr, ushort port) { 
     104        uint uiaddr = parse(addr); 
     105        if(ADDR_NONE == uiaddr) 
     106        { 
     107                auto ih = new ActuallyThreadsafeInternetHost; 
     108                if(!ih.getHostByName(addr)) 
     109                        //throw new AddressException("Invalid internet address"); 
     110                        throw new AddressException("Unable to resolve host '" ~ addr ~ "'"); 
     111                uiaddr = ih.addrList[0]; 
     112        } 
     113        sin.sin_addr.s_addr = htonl(uiaddr); 
     114        sin.sin_port = htons(port); 
     115      } 
     116      this(uint addr, ushort port) { 
     117        sin.sin_addr.s_addr = htonl(addr); 
     118        sin.sin_port = htons(port); 
     119      } 
     120      this(ushort port) { 
     121        sin.sin_addr.s_addr = 0; //any, "0.0.0.0" 
     122        sin.sin_port = htons(port); 
     123      } 
     124      string toAddrString() { return std.string.toString(inet_ntoa(sin.sin_addr)).dup; } 
     125      string toPortString() { return std.string.toString(port()); } 
     126      string toString() { return toAddrString() ~ ":" ~ toPortString(); } 
     127      static uint parse(string addr) { return ntohl(inet_addr(std.string.toStringz(addr))); } 
    82128  } 
    83129} 
    84  
    85 class ActuallyWorkingInternetAddress : Address { 
    86   protected: 
    87     sockaddr_in sin; 
    88     sockaddr* name() { return cast(sockaddr*)&sin; } 
    89     int nameLen() { return sin.sizeof; }  
    90     this() { } 
    91   public: 
    92     const uint ADDR_ANY = INADDR_ANY;   /// Any IPv4 address number. 
    93     const uint ADDR_NONE = INADDR_NONE; /// An invalid IPv4 address number. 
    94     const ushort PORT_ANY = 0;      /// Any IPv4 port number. 
    95      
    96     AddressFamily addressFamily() { return cast(AddressFamily)AddressFamily.INET; } 
    97     ushort port() { return ntohs(sin.sin_port); } 
    98     uint addr() { return ntohl(sin.sin_addr.s_addr); } 
    99     this(string addr, ushort port) { 
    100       uint uiaddr = parse(addr); 
    101       if(ADDR_NONE == uiaddr) 
    102       { 
    103               auto ih = new ActuallyThreadsafeInternetHost; 
    104               if(!ih.getHostByName(addr)) 
    105                       //throw new AddressException("Invalid internet address"); 
    106                       throw new AddressException("Unable to resolve host '" ~ addr ~ "'"); 
    107               uiaddr = ih.addrList[0]; 
    108       } 
    109       sin.sin_addr.s_addr = htonl(uiaddr); 
    110       sin.sin_port = htons(port); 
    111     } 
    112     this(uint addr, ushort port) { 
    113       sin.sin_addr.s_addr = htonl(addr); 
    114       sin.sin_port = htons(port); 
    115     } 
    116     this(ushort port) { 
    117       sin.sin_addr.s_addr = 0; //any, "0.0.0.0" 
    118       sin.sin_port = htons(port); 
    119     } 
    120     string toAddrString() { return std.string.toString(inet_ntoa(sin.sin_addr)).dup; } 
    121     string toPortString() { return std.string.toString(port()); } 
    122     string toString() { return toAddrString() ~ ":" ~ toPortString(); } 
    123     static uint parse(string addr) { return ntohl(inet_addr(std.string.toStringz(addr))); } 
    124 }