/// <summary> /// Implements IOutboundTransport.SubscribeClient /// </summary> /// <remarks> /// Input instructions: (both required) /// <list> /// <item><c>host</c>: host name to connect to and validate certificate for</item> /// <item><c>port</c>: port number to use</item> /// <item><c>ip</c> (optional): overrides host, which is still required for certificate validation</item> /// </list> /// /// Output instructions: none /// </remarks> public string SubscribeClient(IEnumerable <KeyValuePair <string, string> > inputInstructions, out IEnumerable <KeyValuePair <string, string> > outputInstructions) { if (_disposed) { throw new ObjectDisposedException(GetType().FullName); } if (inputInstructions == null) { throw new ArgumentNullException("inputInstructions"); } string host = null, portno = null; int port; IPAddress ipOverride = null; foreach (KeyValuePair <string, string> kvp in inputInstructions) { switch (kvp.Key) { case "host": { host = kvp.Value; break; } case "port": { portno = kvp.Value; break; } case "ip": { if (!IPAddress.TryParse(kvp.Value, out ipOverride)) { throw new TransportException("Invalid IP address specified"); } break; } } } //Parameter error detection if (host == null) { throw new TransportException("Host name not specified"); } if (portno == null) { throw new TransportException("Port number not specified"); } if (!int.TryParse(portno, out port)) { throw new TransportException("Invalid TCP port number"); } if (port < 1 || port > 65534) { throw new TransportException("Invalid TCP port number"); } outputInstructions = new Dictionary <string, string>(); try { TcpClient newTcpClient; if (ipOverride == null) { newTcpClient = new TcpClient(host, port); } else { newTcpClient = new TcpClient(ipOverride.AddressFamily) { NoDelay = true, SendBufferSize = 65536 }; newTcpClient.Connect(ipOverride, port); } SslStream sslStream = new SslStream(newTcpClient.GetStream(), false, RemoteCertificateValidation, LocalCertificateSelection); sslStream.AuthenticateAsClient(host); TlsClient newClient = new TlsClient(newTcpClient, sslStream); string id = newClient.GetHashCode().ToString(); _listLock.AcquireWriterLock(DEFAULT_JOIN_TIMEOUT); try { _clients.Add(id, newClient); return(id); } finally { _listLock.ReleaseWriterLock(); } } catch (Exception ex) { Log.Error("Unable to subscribe new TLS client"); Log.Debug("Error details: {0}", ex); throw new TransportException("Unable to subscribe client", ex); } }