summaryrefslogtreecommitdiff
path: root/csharp/src/Ice/NetworkProxy.cs
diff options
context:
space:
mode:
authorMatthew Newhook <matthew@zeroc.com>2015-03-21 15:35:40 -0230
committerMatthew Newhook <matthew@zeroc.com>2015-03-21 15:35:40 -0230
commit630a37d2fe66f24518299e705f958b571803c522 (patch)
tree969723791bdc4d73bb099c19d45554d0ca241ad9 /csharp/src/Ice/NetworkProxy.cs
parentFix some README.md markdown formatting (diff)
downloadice-630a37d2fe66f24518299e705f958b571803c522.tar.bz2
ice-630a37d2fe66f24518299e705f958b571803c522.tar.xz
ice-630a37d2fe66f24518299e705f958b571803c522.zip
py -> python
rb -> ruby objc -> objective-c cs -> csharp
Diffstat (limited to 'csharp/src/Ice/NetworkProxy.cs')
-rw-r--r--csharp/src/Ice/NetworkProxy.cs311
1 files changed, 311 insertions, 0 deletions
diff --git a/csharp/src/Ice/NetworkProxy.cs b/csharp/src/Ice/NetworkProxy.cs
new file mode 100644
index 00000000000..6e4a3ed9ffa
--- /dev/null
+++ b/csharp/src/Ice/NetworkProxy.cs
@@ -0,0 +1,311 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+namespace IceInternal
+{
+ using System;
+ using System.Net;
+ using System.Net.Sockets;
+ using System.Diagnostics;
+ using System.Text;
+
+ public interface NetworkProxy
+ {
+ //
+ // Write the connection request on the connection established
+ // with the network proxy server. This is called right after
+ // the connection establishment succeeds.
+ //
+ void beginWrite(EndPoint endpoint, Buffer buf);
+ int endWrite(Buffer buf);
+
+ //
+ // Once the connection request has been sent, this is called
+ // to prepare and read the response from the proxy server.
+ //
+ void beginRead(Buffer buf);
+ int endRead(Buffer buf);
+
+ //
+ // This is called when the response from the proxy has been
+ // read. The proxy should copy the extra read data (if any) in the
+ // given byte vector.
+ //
+ void finish(Buffer readBuffer, Buffer writeBuffer);
+
+#if !SILVERLIGHT
+ //
+ // If the proxy host needs to be resolved, this should return
+ // a new NetworkProxy containing the IP address of the proxy.
+ // This is called from the endpoint host resolver thread, so
+ // it's safe if this this method blocks.
+ //
+ NetworkProxy resolveHost(int protocolSupport);
+#endif
+ //
+ // Returns the IP address of the network proxy. This method
+ // must not block. It's only called on a network proxy object
+ // returned by resolveHost().
+ //
+ EndPoint getAddress();
+
+ //
+ // Returns the name of the proxy, used for tracing purposes.
+ //
+ string getName();
+
+ //
+ // Returns the protocols supported by the proxy.
+ //
+ int getProtocolSupport();
+ }
+
+ public sealed class SOCKSNetworkProxy : NetworkProxy
+ {
+ public SOCKSNetworkProxy(string host, int port)
+ {
+#if SILVERLIGHT
+ _address = new DnsEndPoint(host, port, AddressFamily.InterNetwork);
+#else
+ _host = host;
+ _port = port;
+#endif
+ }
+
+ private SOCKSNetworkProxy(EndPoint address)
+ {
+ _address = address;
+ }
+
+ public void beginWrite(EndPoint endpoint, Buffer buf)
+ {
+ if(!(endpoint is IPEndPoint))
+ {
+ throw new Ice.FeatureNotSupportedException("SOCKS4 does not support domain names");
+ }
+ else if(endpoint.AddressFamily != AddressFamily.InterNetwork)
+ {
+ throw new Ice.FeatureNotSupportedException("SOCKS4 only supports IPv4 addresses");
+ }
+
+ //
+ // SOCKS connect request
+ //
+ IPEndPoint addr = (IPEndPoint)endpoint;
+ buf.resize(9, false);
+ ByteBuffer.ByteOrder order = buf.b.order();
+ buf.b.order(ByteBuffer.ByteOrder.BIG_ENDIAN); // Network byte order.
+ buf.b.position(0);
+ buf.b.put(0x04); // SOCKS version 4.
+ buf.b.put(0x01); // Command, establish a TCP/IP stream connection
+ buf.b.putShort((short)addr.Port); // Port
+ buf.b.put(addr.Address.GetAddressBytes()); // IPv4 address
+ buf.b.put(0x00); // User ID.
+ buf.b.position(0);
+ buf.b.limit(buf.size());
+ buf.b.order(order);
+ }
+
+ public int endWrite(Buffer buf)
+ {
+ // Once the request is sent, read the response
+ return buf.b.hasRemaining() ? SocketOperation.Write : SocketOperation.Read;
+ }
+
+ public void beginRead(Buffer buf)
+ {
+ //
+ // Read the SOCKS4 response whose size is 8 bytes.
+ //
+ buf.resize(8, true);
+ buf.b.position(0);
+ }
+
+ public int endRead(Buffer buf)
+ {
+ // We're done once we read the response
+ return buf.b.hasRemaining() ? SocketOperation.Read : SocketOperation.None;
+ }
+
+ public void finish(Buffer readBuffer, Buffer writeBuffer)
+ {
+ readBuffer.b.position(0);
+ byte b1 = readBuffer.b.get();
+ byte b2 = readBuffer.b.get();
+ if(b1 != 0x00 || b2 != 0x5a)
+ {
+ throw new Ice.ConnectFailedException();
+ }
+ }
+
+#if !SILVERLIGHT
+ public NetworkProxy resolveHost(int protocolSupport)
+ {
+ Debug.Assert(_host != null);
+ return new SOCKSNetworkProxy(Network.getAddresses(_host,
+ _port,
+ protocolSupport,
+ Ice.EndpointSelectionType.Random,
+ false,
+ true)[0]);
+ }
+#endif
+
+ public EndPoint getAddress()
+ {
+ Debug.Assert(_address != null); // Host must be resolved.
+ return _address;
+ }
+
+ public string getName()
+ {
+ return "SOCKS";
+ }
+
+ public int getProtocolSupport()
+ {
+ return Network.EnableIPv4;
+ }
+
+#if !SILVERLIGHT
+ private readonly string _host;
+ private readonly int _port;
+#endif
+ private readonly EndPoint _address;
+ }
+
+ public sealed class HTTPNetworkProxy : NetworkProxy
+ {
+ public HTTPNetworkProxy(string host, int port)
+ {
+#if SILVERLIGHT
+ _address = new DnsEndPoint(host, port, AddressFamily.InterNetwork);
+ _protocolSupport = Network.EnableIPv4;
+#else
+ _host = host;
+ _port = port;
+ _protocolSupport = Network.EnableBoth;
+#endif
+ }
+
+ private HTTPNetworkProxy(EndPoint address, int protocolSupport)
+ {
+ _address = address;
+ _protocolSupport = protocolSupport;
+ }
+
+ public void beginWrite(EndPoint endpoint, Buffer buf)
+ {
+ string addr = Network.addrToString(endpoint);
+ StringBuilder str = new StringBuilder();
+ str.Append("CONNECT ");
+ str.Append(addr);
+ str.Append(" HTTP/1.1\r\nHost: ");
+ str.Append(addr);
+ str.Append("\r\n\r\n");
+
+#if SILVERLIGHT
+ byte[] b = System.Text.Encoding.UTF8.GetBytes(str.ToString());
+#else
+ byte[] b = System.Text.Encoding.ASCII.GetBytes(str.ToString());
+#endif
+
+ //
+ // HTTP connect request
+ //
+ buf.resize(b.Length, false);
+ buf.b.position(0);
+ buf.b.put(b);
+ buf.b.position(0);
+ buf.b.limit(buf.size());
+ }
+
+ public int endWrite(Buffer buf)
+ {
+ // Once the request is sent, read the response
+ return buf.b.hasRemaining() ? SocketOperation.Write : SocketOperation.Read;
+ }
+
+ public void beginRead(Buffer buf)
+ {
+ //
+ // Read the HTTP response
+ //
+ buf.resize(7, true); // Enough space for reading at least HTTP1.1
+ buf.b.position(0);
+ }
+
+ public int endRead(Buffer buf)
+ {
+ //
+ // Check if we received the full HTTP response, if not, continue
+ // reading otherwise we're done.
+ //
+ int end = new HttpParser().isCompleteMessage(buf.b, 0, buf.b.position());
+ if(end < 0 && !buf.b.hasRemaining())
+ {
+ //
+ // Read one more byte, we can't easily read bytes in advance
+ // since the transport implenentation might be be able to read
+ // the data from the memory instead of the socket.
+ //
+ buf.resize(buf.size() + 1, true);
+ return SocketOperation.Read;
+ }
+ return SocketOperation.None;
+ }
+
+ public void finish(Buffer readBuffer, Buffer writeBuffer)
+ {
+ HttpParser parser = new HttpParser();
+ parser.parse(readBuffer.b, 0, readBuffer.b.position());
+ if(parser.status() != 200)
+ {
+ throw new Ice.ConnectFailedException();
+ }
+ }
+
+#if !SILVERLIGHT
+ public NetworkProxy resolveHost(int protocolSupport)
+ {
+ Debug.Assert(_host != null);
+ return new HTTPNetworkProxy(Network.getAddresses(_host,
+ _port,
+ protocolSupport,
+ Ice.EndpointSelectionType.Random,
+ false,
+ true)[0],
+ protocolSupport);
+ }
+#endif
+
+ public EndPoint getAddress()
+ {
+ Debug.Assert(_address != null); // Host must be resolved.
+ return _address;
+ }
+
+ public string getName()
+ {
+ return "HTTP";
+ }
+
+ public int getProtocolSupport()
+ {
+ return _protocolSupport;
+ }
+
+#if !SILVERLIGHT
+ private readonly string _host;
+ private readonly int _port;
+#endif
+ private readonly EndPoint _address;
+ private readonly int _protocolSupport;
+ }
+}