Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Changeset 3393

Show
Ignore:
Timestamp:
03/24/08 14:16:01 (9 months ago)
Author:
lmartin92
Message:

Updated Telnet.d to work only with SocketConduits?. Now FtpClient?.d is broken because it needs to use SocketConduits?; not Sockets :-) ;-) I'm working on fixing FtpClient?.d to use SocketConduits? so hopefully not broken for long :-)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/lmartin/ftp/tango/net/ftp/Telnet.d

    r3137 r3393  
    1 /******************************************************************************* 
    2  
    3         copyright:      Copyright (c) 2006 UWB. All rights reserved 
    4  
    5         license:        BSD style: $(LICENSE) 
    6  
    7         version:        Initial release: June 2006 
    8  
    9         author:         UWB 
    10  
    11 *******************************************************************************/ 
    12  
     1/** 
     2 *  
     3 */ 
    134module tango.net.ftp.Telnet; 
    145 
    15 private import tango.time.Clock; 
     6private { 
     7    import tango.net.SocketConduit; 
     8    import tango.net.Socket; 
     9    import tango.net.InternetAddress; 
     10    import tango.core.Exception; 
     11
    1612 
    17 private import tango.net.Socket; 
     13class Telnet { 
    1814 
    19 private import tango.core.Exception; 
     15    /// The Socket Conduit that is used to send commands. 
     16    SocketConduit socket; 
    2017 
    21 private import Integer = tango.text.convert.Integer
     18   abstract void exception(char[] message)
    2219 
     20    /// Send a line over the Socket Conduit. 
     21    /// 
     22    ///    buf =             the bytes to send 
     23    void sendline(void[] buf) { 
     24        sendData(buf); 
     25        sendData("\r\n"); 
     26    } 
    2327 
    24 /// Utilities for telnet-based connections. 
    25 /// 
    26 /// Params: 
    27 ///    TelnetException =     the type for exceptions thrown 
    28 ///    socket =              the connected socket 
    29 ///    timeout =             the timeout for socket communication 
    30 class Telnet 
    31 
    32         /// The control connection socket. 
    33         protected Socket socket; 
     28    /// Send a line over the Socket Conduit. 
     29    /// 
     30    ///    buf =             the bytes to send 
     31    void sendData(void[] buf) { 
     32        socket.write(buf); 
     33    } 
    3434 
    35         /// The number of milliseconds to wait for socket communication or connection. 
    36         protected TimeSpan timeout = TimeSpan.millis(2500); 
     35    /// Read a CRLF terminated line from the socket. 
     36    /// 
     37    /// Returns:             the line read 
     38    char[] readLine() { 
     39        void[8 * 1024] dst; 
     40        socket.read(dst); 
     41        return dst; 
     42    } 
    3743 
    38         /// provided by host 
    39         abstract void exception (char[] msg); 
    40          
    41         /// Send a line over the socket. 
    42         /// 
    43         /// Params: 
    44         ///    buf =             the bytes to send 
     44    /// Find a server which is listening on the specified port. 
     45    /// 
     46    ///    hostname =        the hostname to lookup and connect to 
     47    ///    port =            the port to connect on 
     48    /// returns the SocketConduit this class is using 
     49    SocketConduit findAvailableServer(char[] hostname, int port) { 
     50        socket = new SocketConduit(); 
     51        socket.connect(new InternetAddress(hostname, port)); 
    4552 
    46         void sendLine(void[] buf) 
    47         { 
    48                 this.sendData(buf); 
    49                 this.sendData("\r\n"); 
    50         } 
     53        return socket; 
     54    } 
    5155 
    52         /// Send data over the socket. 
    53         /// 
    54         /// Params: 
    55         ///    buf =             the bytes to send 
    56         void sendData(void[] buf) 
    57         in 
    58         { 
    59                 assert (buf.length > 0); 
    60         } 
    61         body 
    62         { 
    63                 // At end_time, we bail. 
    64                 Time end_time = Clock.now + this.timeout; 
    65  
    66                 // Set up a SocketSet so we can use select() - it's pretty efficient. 
    67                 SocketSet set = new SocketSet(); 
    68                 scope (exit) 
    69                         delete set; 
    70  
    71                 size_t pos = 0; 
    72                 while (Clock.now < end_time) 
    73                 { 
    74                         set.reset(); 
    75                         set.add(this.socket); 
    76  
    77                         // Can we write yet, can we write yet? 
    78                         int code = Socket.select(null, set, null, this.timeout); 
    79                         if (code == -1 || code == 0) 
    80                                 break; 
    81  
    82                         // Send it (or as much as possible!) 
    83                         int delta = this.socket.send(buf[pos .. buf.length]); 
    84                         if (delta == -1) 
    85                                 break; 
    86  
    87                         pos += delta; 
    88                         if (pos >= buf.length) 
    89                                 break; 
    90                 } 
    91  
    92                 // If we didn't send everything, we're dead in the water. 
    93                 if (pos != buf.length) 
    94                     exception ("CLIENT: Timeout when sending command"); 
    95         } 
    96  
    97         /// Read a CRLF terminated line from the socket. 
    98         /// 
    99         /// Returns:             the line read 
    100         char[] readLine() 
    101         { 
    102                 // Figure, first, how long we're allowed to take. 
    103                 Time end_time = Clock.now + this.timeout; 
    104  
    105                 // An overall buffer and a one-char buffer. 
    106                 char[] buffer; 
    107                 char[1] buf; 
    108                 size_t buffer_pos = 0; 
    109  
    110                 // Push a byte onto the buffer. 
    111                 void push_byte() 
    112                 { 
    113                         // Lines aren't usually that long.  Allocate in blocks of 16 bytes. 
    114                         if (buffer.length <= buffer_pos) 
    115                                 buffer.length = buffer.length + 16; 
    116  
    117                         buffer[buffer_pos++] = buf[0]; 
    118                 } 
    119  
    120                 // Get the resultant buffer. 
    121                 char[] get_buffer() 
    122                 { 
    123                         return buffer[0 .. buffer_pos]; 
    124                 } 
    125  
    126                 // Now the socket set for selecting purposes. 
    127                 SocketSet set = new SocketSet(); 
    128                 scope (exit) 
    129                         delete set; 
    130  
    131                 while (Clock.now < end_time) 
    132                 { 
    133                         set.reset(); 
    134                         set.add(this.socket); 
    135  
    136                         // Try to read from the socket. 
    137                         int code = Socket.select(set, null, null, this.timeout); 
    138                         if (code == -1 || code == 0) 
    139                                 break; 
    140  
    141                         // Okay, now we're ready.  Read in the measly byte. 
    142                         int delta = this.socket.receive(buf); 
    143                         if (delta != 1) 
    144                                 break; 
    145  
    146                         if (buf == "\r") 
    147                                 continue; 
    148                         else if (buf == "\n") 
    149                                 break; 
    150  
    151                         push_byte(); 
    152                 } 
    153  
    154                 return get_buffer(); 
    155         } 
    156  
    157         /// Find a server which is listening on the specified port. 
    158         /// 
    159         /// Params: 
    160         ///    hostname =        the hostname to lookup and connect to 
    161         ///    port =            the port to connect on 
    162         Socket findAvailableServer(char[] hostname, int port) 
    163         { 
    164                 // First we need to get a list of IP addresses. 
    165                 auto host = new NetHost(); 
    166                 scope (exit) 
    167                         delete host; 
    168  
    169                 // Try to resolve the actual address for this hostname. 
    170                 host.getHostByName(hostname); 
    171                 scope (exit) 
    172                         delete host.addrList; 
    173  
    174                 // None were found... darn. 
    175                 if (host.addrList.length == 0) 
    176                         throw new AddressException("Unable to resolve host '" ~ hostname ~ "'"); 
    177  
    178                 // Get all the sockets ready (or just one if there's just one address.) 
    179                 Socket[] sockets = new Socket[host.addrList.length]; 
    180                 scope (exit) 
    181                         delete sockets; 
    182  
    183                 // And now just connect to all of them. 
    184                 for (int i = 0; i < host.addrList.length; i++) 
    185                 { 
    186                         sockets[i] = new Socket(AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP); 
    187                         sockets[i].blocking = false; 
    188  
    189                         Address addr = new IPv4Address(host.addrList[i], cast(ushort) port); 
    190                         scope (exit) 
    191                                 delete addr; 
    192  
    193                         // Start trying to connect as soon as possible. 
    194                         sockets[i].connect(addr); 
    195                 } 
    196  
    197                 // Set up some stuff so we can select through the hosts. 
    198                 SocketSet set = new SocketSet(); 
    199                 this.socket = null; 
    200  
    201                 scope (exit) 
    202                         delete set; 
    203  
    204                 // Wait until we find a good socket... 
    205                 while (this.socket is null) 
    206                 { 
    207                         set.reset(); 
    208                         foreach (Socket s; sockets) 
    209                                 set.add(s); 
    210  
    211                         // Anyone available? 
    212                         int code = Socket.select(null, set, null, this.timeout); 
    213                         if (code == -1 || code == 0) 
    214                                 break; 
    215  
    216                         // Now we have to check to find a good socket, and break out if we find one. 
    217                         foreach (Socket s; sockets) 
    218                                 if (set.isSet(s)) 
    219                                 { 
    220                                         this.socket = s; 
    221                                         break; 
    222                                 } 
    223                 } 
    224  
    225                 // Close the other sockets (or all on error.) 
    226                 foreach (Socket s; sockets) 
    227                         if (s !is this.socket) 
    228                         { 
    229                                 s.shutdown(SocketShutdown.BOTH); 
    230                                 s.detach(); 
    231  
    232                                 delete s; 
    233                         } 
    234  
    235                 // No socket, no data.  Can't do anything about that. 
    236                 if (this.socket is null) 
    237                    { 
    238                    char[10] tmp; 
    239                    exception ("CLIENT: Unable to connect within the specified time limit (" ~ Integer.itoa(tmp, cast(uint) this.timeout.millis) ~ " ms.)"); 
    240                    } 
    241  
    242                 // Make it blocking again, because that's the norm. 
    243                 this.socket.blocking = true; 
    244  
    245                 return this.socket; 
    246         } 
    24756}