using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TradeIdeas.ServerConnection
{
///
/// In a simple program it's not hard to create a TCP/IP connection or an HTTP
/// connection. In a realistic program, the part of the program that reads the
/// configuration information from the user and the part of the program that
/// actually creates the connection may be separated by many layers. This
/// interface allows us to pass something very simple through the intermediate
/// layers.
///
/// Initally we are creating two obvious implementations of this. One for HTTP
/// and one for TCP/IP. However, the possibilities are endless. You could make
/// one that included a list of other IConnectionFactories, then use a simple
/// round robin scheduler to pick the next one in the list. Or you could make
/// a more complicated version of that which has some history, knowing which
/// connections seem to work better and which don't.
///
public interface IConnectionFactory
{
///
/// This is the most important part of the connection factory. This creates
/// the connection on demand. This can be called any number of times and
/// should create a new connection each time.
///
/// This is used by the low level libraries to receive data.
/// A brand new connection.
IConnection CreateConnection(ConnectionCallbacks connectionCallbacks);
///
/// Some options are global variables, and not tied to any particular
/// connection or factory. However, they are only used by certain connection
/// types, and they are ignored by others. So the program will still work if
/// you set these at the wrong time. But it might make sense for the GUI to
/// hide or disable certain controls when they don't matter.
///
/// For example, if the user selects the HTTP tunnel option, the TI Pro GUI
/// will disable the password field and enable the timeout field. This is
/// not required, but it makes things clearer for the user.
///
/// True if this is an HTTP connection factory.
bool UsesHTTP();
///
/// Some options are global variables, and not tied to any particular
/// connection or factory. However, they are only used by certain connection
/// types, and they are ignored by others. So the program will still work if
/// you set these at the wrong time. But it might make sense for the GUI to
/// hide or disable certain controls when they don't matter.
///
/// For example, if the user selects the HTTP tunnel option, the TI Pro GUI
/// will disable the password field and enable the timeout field. This is
/// not required, but it makes things clearer for the user.
///
/// True if this connection can work with a socks proxy.
bool UsesSocks();
}
///
/// This type of factory creates a TCP/IP connection. This is the preferred tyope
/// of connection. This offers the highest performance.
///
public class TcpIpConnectionFactory : IConnectionFactory
{
///
/// This is the address of the server. For example "www.trade-ideas.com".
/// There is no default value for this. If you do not fill it in, it will fail.
///
public string Address { get; set; }
///
/// This is the port number for the server. We often use different values
/// to distinguish the test servers from the prodution servers. Also, we
/// often open special ports just to help people with their firewalls.
/// There is no default value for this. If you do not fill it in, it will fail.
///
public int Port { get; set; }
///
/// Create an empy factory. Use and to
/// fill in the required values.
///
public TcpIpConnectionFactory()
{
}
///
/// Create a new factory initialized to the given address and port.
///
///
///
public TcpIpConnectionFactory(string address, int port)
{
Address = address;
Port = port;
}
///
///
///
/// This is used by the low level libraries to receive data.
/// A brand new connection
public IConnection CreateConnection(ConnectionCallbacks connectionCallbacks)
{
return new TcpIpConnection(Address, Port, connectionCallbacks);
}
///
/// Always returns false. The HTTP options do not apply to TCP/IP connections.
///
/// false
public bool UsesHTTP()
{
return false;
}
///
/// Always returns true. You can use a socks proxy with this type of connection.
///
///
/// true
public bool UsesSocks()
{
return true;
}
}
///
/// This type of connection works behind a lot of firewalls. It is slower and uses more
/// CPU and bandwidth. Use it as a last resort.
///
public class HttpConnectionFactory : IConnectionFactory
{
///
/// This is the address used to make the initial connection.
/// If you leave this as null, the software will use a complied in default.
///
public string InitialUrl { get; set; }
///
/// Create a new connection factory, optionally initializing it.
///
///
public HttpConnectionFactory(string initialUrl = null)
{
InitialUrl = initialUrl;
}
///
/// Create new HTTP connection
///
/// This is used by the low level libraries to receive data.
/// new HTTP Connection
public IConnection CreateConnection(ConnectionCallbacks connectionCallbacks)
{
HttpOptions options;
options.InitialUrl = InitialUrl;
options.ConnectionCallbacks = connectionCallbacks;
return new HttpConnection(options);
}
///
/// This is always true.
///
///
/// true
public bool UsesHTTP()
{
return true;
}
///
/// This is always false. At this time there is no way to make the HTTP connection work through a socks proxy.
///
/// false
public bool UsesSocks()
{
return false;
}
}
///
/// This type of connection is the best of both worlds.
/// This uses encryptption (if this is done over https/wss).
/// This works with almost any firewall.
/// Aside from the optional encryption, this is almost as efficient as a raw TCP/IP connection.
///
public class WebSocketConnectionFactory : IConnectionFactory
{
///
/// This is the address used to make the initial connection.
/// Should not be null.
/// (WebSocketConnection only uses one url.
/// We say "Initial" because we are sharing some code with HttpConnection which always has several URLs per connection.)
///
public string InitialUrl { get; set; }
///
/// Create a new connection factory, optionally initializing it.
///
///
public WebSocketConnectionFactory(string initialUrl = null)
{
InitialUrl = initialUrl;
}
///
/// Create new HTTP connection
///
/// This is used by the low level libraries to receive data.
/// new HTTP Connection
public IConnection CreateConnection(ConnectionCallbacks connectionCallbacks)
{
HttpOptions options;
options.InitialUrl = InitialUrl;
options.ConnectionCallbacks = connectionCallbacks;
return new WebSocketConnection(options);
}
///
/// This is always true.
///
///
/// true
public bool UsesHTTP()
{
return true;
}
///
/// This is always false. At this time there is no way to make the HTTP connection work through a socks proxy.
///
/// false
public bool UsesSocks()
{
return false;
}
}
}