Skip to content

Commit

Permalink
Http Proxy Improvements
Browse files Browse the repository at this point in the history
Bug: proxy connect packet is malformed due to a space after HTTP/1.1.
Feature: Pass the host name so proxy host acls can be matched.
Feature: Switch to the WebRequest.DefaultWebProxy which allows for overriding in app.settings file and falls back to the system proxy if not configured.
Improvement: Use ordinal comparision for IndexOf on the proxy response.
  • Loading branch information
IanLeeClaxton committed Sep 27, 2022
1 parent 63c2e05 commit 7c7d2d9
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 10 deletions.
8 changes: 8 additions & 0 deletions QuickFIXn/SocketSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ public class SocketSettings : ICloneable
{
#region Socket Settings

/// <summary>
/// Store the socket host name so we can use it to connect via proxy if required.
/// </summary>
/// <value>
/// The host name (without port number) to send to the proxy server for acl matching.
/// </value>
public string SocketConnectHost { get; internal set; }

/// <summary>
/// Gets a value that specifies whether the <see cref="T:System.Net.Sockets.Socket"/> is using the Nagle algorithm.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion QuickFIXn/Transport/SocketInitiator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ private IPEndPoint GetNextSocketEndPoint(SessionID sessionID, QuickFix.Dictionar
int port = System.Convert.ToInt32(settings.GetLong(portKey));
sessionToHostNum_[sessionID] = ++num;

socketSettings_.ServerCommonName = hostName;
socketSettings_.SocketConnectHost = socketSettings_.ServerCommonName = hostName;
return new IPEndPoint(addrs.First(a => a.AddressFamily == AddressFamily.InterNetwork), port);
}
catch (System.Exception e)
Expand Down
19 changes: 10 additions & 9 deletions QuickFIXn/Transport/StreamFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ namespace QuickFix.Transport
/// </summary>
public static class StreamFactory
{
private static Socket CreateTunnelThruProxy(string destIP, int destPort)
private static Socket CreateTunnelThruProxy(string destIP, int destPort, string destHostName)
{
string destUriWithPort = $"{destIP}:{destPort}";
UriBuilder uriBuilder = new UriBuilder(destUriWithPort);
Uri destUri = uriBuilder.Uri;
IWebProxy webProxy = WebRequest.GetSystemWebProxy();
IWebProxy webProxy = WebRequest.DefaultWebProxy;

try
{
Expand All @@ -47,18 +47,19 @@ private static Socket CreateTunnelThruProxy(string destIP, int destPort)
Socket socketThruProxy = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketThruProxy.Connect(proxyEndPoint);

string proxyMsg = $"CONNECT {destIP}:{destPort} HTTP/1.1 \n\n";
string proxyMsg = !string.IsNullOrWhiteSpace(destHostName)
? $"CONNECT {destHostName}:{destPort} HTTP/1.1\nHost: {destHostName}:{destPort}\n\n"
: $"CONNECT {destIP}:{destPort} HTTP/1.1\n\n";
byte[] buffer = Encoding.ASCII.GetBytes(proxyMsg);
byte[] buffer12 = new byte[500];
socketThruProxy.Send(buffer, buffer.Length, 0);
int msg = socketThruProxy.Receive(buffer12, 500, 0);
string data;
data = Encoding.ASCII.GetString(buffer12);
int index = data.IndexOf("200");
socketThruProxy.Receive(buffer12, 500, 0);
string data = Encoding.ASCII.GetString(buffer12);
int index = data.IndexOf("200", StringComparison.Ordinal);

if (index < 0)
throw new ApplicationException(
$"Connection failed to {destUriWithPort} through proxy server {proxyUri.ToString()}.");
$"Connection failed to {destUriWithPort} through proxy server {proxyUri}.");

return socketThruProxy;
}
Expand All @@ -73,7 +74,7 @@ private static Socket CreateTunnelThruProxy(string destIP, int destPort)
public static Stream CreateClientStream(IPEndPoint endpoint, SocketSettings settings, ILog logger)
{
// If system has configured a proxy for this config, use it.
Socket socket = CreateTunnelThruProxy(endpoint.Address.ToString(), endpoint.Port);
Socket socket = CreateTunnelThruProxy(endpoint.Address.ToString(), endpoint.Port, settings.SocketConnectHost);

// No proxy. Set up a regular socket.
if (socket == null)
Expand Down

0 comments on commit 7c7d2d9

Please sign in to comment.