< Summary

Information
Class: Ice.Internal.SOCKSNetworkProxy
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/NetworkProxy.cs
Tag: 71_18251537082
Line coverage
95%
Covered lines: 41
Uncovered lines: 2
Coverable lines: 43
Total lines: 261
Line coverage: 95.3%
Branch coverage
70%
Covered branches: 7
Total branches: 10
Branch coverage: 70%
Method coverage
100%
Covered methods: 11
Total methods: 11
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor(...)100%11100%
beginWrite(...)50%4.02488.89%
endWrite(...)50%22100%
beginRead(...)100%11100%
endRead(...)100%11100%
finish(...)100%44100%
resolveHost(...)100%11100%
getAddress()100%11100%
getName()100%11100%
getProtocolSupport()100%11100%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/Internal/NetworkProxy.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Diagnostics;
 4using System.Net;
 5using System.Net.Sockets;
 6using System.Text;
 7
 8namespace Ice.Internal;
 9
 10public interface NetworkProxy
 11{
 12    //
 13    // Write the connection request on the connection established
 14    // with the network proxy server. This is called right after
 15    // the connection establishment succeeds.
 16    //
 17    void beginWrite(EndPoint endpoint, Buffer buf);
 18
 19    int endWrite(Buffer buf);
 20
 21    //
 22    // Once the connection request has been sent, this is called
 23    // to prepare and read the response from the proxy server.
 24    //
 25    void beginRead(Buffer buf);
 26
 27    int endRead(Buffer buf);
 28
 29    //
 30    // This is called when the response from the proxy has been
 31    // read. The proxy should copy the extra read data (if any) in the
 32    // given byte vector.
 33    //
 34    void finish(Buffer readBuffer, Buffer writeBuffer);
 35
 36    //
 37    // If the proxy host needs to be resolved, this should return
 38    // a new NetworkProxy containing the IP address of the proxy.
 39    // This is called from the endpoint host resolver thread, so
 40    // it's safe if this this method blocks.
 41    //
 42    NetworkProxy resolveHost(int protocolSupport);
 43
 44    //
 45    // Returns the IP address of the network proxy. This method
 46    // must not block. It's only called on a network proxy object
 47    // returned by resolveHost().
 48    //
 49    EndPoint getAddress();
 50
 51    //
 52    // Returns the name of the proxy, used for tracing purposes.
 53    //
 54    string getName();
 55
 56    //
 57    // Returns the protocols supported by the proxy.
 58    //
 59    int getProtocolSupport();
 60}
 61
 62public sealed class SOCKSNetworkProxy : NetworkProxy
 63{
 164    public SOCKSNetworkProxy(string host, int port)
 65    {
 166        _host = host;
 167        _port = port;
 168    }
 69
 170    private SOCKSNetworkProxy(EndPoint address) => _address = address;
 71
 72    public void beginWrite(EndPoint endpoint, Buffer buf)
 73    {
 174        if (!(endpoint is IPEndPoint))
 75        {
 076            throw new FeatureNotSupportedException("SOCKS4 does not support domain names.");
 77        }
 178        else if (endpoint.AddressFamily != AddressFamily.InterNetwork)
 79        {
 080            throw new FeatureNotSupportedException("SOCKS4 only supports IPv4 addresses.");
 81        }
 82
 83        //
 84        // SOCKS connect request
 85        //
 186        var addr = (IPEndPoint)endpoint;
 187        buf.resize(9, false);
 188        ByteBuffer.ByteOrder order = buf.b.order();
 189        buf.b.order(ByteBuffer.ByteOrder.BigEndian); // Network byte order.
 190        buf.b.position(0);
 191        buf.b.put(0x04); // SOCKS version 4.
 192        buf.b.put(0x01); // Command, establish a TCP/IP stream connection
 193        buf.b.putShort((short)addr.Port); // Port
 194        buf.b.put(addr.Address.GetAddressBytes()); // IPv4 address
 195        buf.b.put(0x00); // User ID.
 196        buf.b.position(0);
 197        buf.b.limit(buf.size());
 198        buf.b.order(order);
 199    }
 100
 101    public int endWrite(Buffer buf) =>
 102        // Once the request is sent, read the response
 1103        buf.b.hasRemaining() ? SocketOperation.Write : SocketOperation.Read;
 104
 105    public void beginRead(Buffer buf)
 106    {
 107        //
 108        // Read the SOCKS4 response whose size is 8 bytes.
 109        //
 1110        buf.resize(8, true);
 1111        buf.b.position(0);
 1112    }
 113
 114    public int endRead(Buffer buf) =>
 115        // We're done once we read the response
 1116        buf.b.hasRemaining() ? SocketOperation.Read : SocketOperation.None;
 117
 118    public void finish(Buffer readBuffer, Buffer writeBuffer)
 119    {
 1120        readBuffer.b.position(0);
 1121        byte b1 = readBuffer.b.get();
 1122        byte b2 = readBuffer.b.get();
 1123        if (b1 != 0x00 || b2 != 0x5a)
 124        {
 1125            throw new Ice.ConnectFailedException();
 126        }
 1127    }
 128
 129    public NetworkProxy resolveHost(int protocolSupport)
 130    {
 131        Debug.Assert(_host != null);
 1132        return new SOCKSNetworkProxy(Network.getAddresses(
 1133            _host,
 1134            _port,
 1135            protocolSupport,
 1136            false,
 1137            true)[0]);
 138    }
 139
 140    public EndPoint getAddress()
 141    {
 142        Debug.Assert(_address != null); // Host must be resolved.
 1143        return _address;
 144    }
 145
 1146    public string getName() => "SOCKS";
 147
 1148    public int getProtocolSupport() => Network.EnableIPv4;
 149
 150    private readonly string _host;
 151    private readonly int _port;
 152    private readonly EndPoint _address;
 153}
 154
 155public sealed class HTTPNetworkProxy : NetworkProxy
 156{
 157    public HTTPNetworkProxy(string host, int port)
 158    {
 159        _host = host;
 160        _port = port;
 161        _protocolSupport = Network.EnableBoth;
 162    }
 163
 164    private HTTPNetworkProxy(EndPoint address, int protocolSupport)
 165    {
 166        _address = address;
 167        _protocolSupport = protocolSupport;
 168    }
 169
 170    public void beginWrite(EndPoint endpoint, Buffer buf)
 171    {
 172        string addr = Network.addrToString(endpoint);
 173        var str = new StringBuilder();
 174        str.Append("CONNECT ");
 175        str.Append(addr);
 176        str.Append(" HTTP/1.1\r\nHost: ");
 177        str.Append(addr);
 178        str.Append("\r\n\r\n");
 179        byte[] b = System.Text.Encoding.ASCII.GetBytes(str.ToString());
 180
 181        //
 182        // HTTP connect request
 183        //
 184        buf.resize(b.Length, false);
 185        buf.b.position(0);
 186        buf.b.put(b);
 187        buf.b.position(0);
 188        buf.b.limit(buf.size());
 189    }
 190
 191    public int endWrite(Buffer buf) =>
 192        // Once the request is sent, read the response
 193        buf.b.hasRemaining() ? SocketOperation.Write : SocketOperation.Read;
 194
 195    public void beginRead(Buffer buf)
 196    {
 197        //
 198        // Read the HTTP response
 199        //
 200        buf.resize(7, true); // Enough space for reading at least HTTP1.1
 201        buf.b.position(0);
 202    }
 203
 204    public int endRead(Buffer buf)
 205    {
 206        //
 207        // Check if we received the full HTTP response, if not, continue
 208        // reading otherwise we're done.
 209        //
 210        int end = new HttpParser().isCompleteMessage(buf.b, 0, buf.b.position());
 211        if (end < 0 && !buf.b.hasRemaining())
 212        {
 213            //
 214            // Read one more byte, we can't easily read bytes in advance
 215            // since the transport implenentation might be be able to read
 216            // the data from the memory instead of the socket.
 217            //
 218            buf.resize(buf.size() + 1, true);
 219            return SocketOperation.Read;
 220        }
 221        return SocketOperation.None;
 222    }
 223
 224    public void finish(Buffer readBuffer, Buffer writeBuffer)
 225    {
 226        var parser = new HttpParser();
 227        parser.parse(readBuffer.b, 0, readBuffer.b.position());
 228        if (parser.status() != 200)
 229        {
 230            throw new Ice.ConnectFailedException();
 231        }
 232    }
 233
 234    public NetworkProxy resolveHost(int protocolSupport)
 235    {
 236        Debug.Assert(_host != null);
 237        return new HTTPNetworkProxy(
 238            Network.getAddresses(
 239                _host,
 240                _port,
 241                protocolSupport,
 242                false,
 243                true)[0],
 244            protocolSupport);
 245    }
 246
 247    public EndPoint getAddress()
 248    {
 249        Debug.Assert(_address != null); // Host must be resolved.
 250        return _address;
 251    }
 252
 253    public string getName() => "HTTP";
 254
 255    public int getProtocolSupport() => _protocolSupport;
 256
 257    private readonly string _host;
 258    private readonly int _port;
 259    private readonly EndPoint _address;
 260    private readonly int _protocolSupport;
 261}