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; } } }