private bool TryConnect(string endPointName, TimeSpan timeout, out Exception exception, out ConnectionId connectionId) { if (endPointName == null) { throw new ArgumentNullException(nameof(endPointName)); } if (endPointName == "") { throw new ArgumentException("endPointName"); } if (timeout <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(timeout)); } if (_networkServiceDiscoverer == null) { throw new InvalidOperationException("No discoverer was specified when creating this client and thus network service discovery by name is not possible"); } var results = _networkServiceDiscoverer.FindServices(endPointName); if (results.Count == 0) { exception = new NoSuchIPEndPointException(endPointName); connectionId = ConnectionId.None; return(false); } foreach (var result in results) { if (TryConnect(result.EndPoint, timeout, out exception, out connectionId)) { return(true); } } exception = new NoSuchIPEndPointException(endPointName); connectionId = ConnectionId.None; return(false); }
/// <summary> /// Tries to connect this endPoint to the given one. /// </summary> /// <param name="endPoint"></param> /// <param name="timeout"> /// The amount of time this method should block and await a successful connection from the remote /// end-point /// </param> /// <param name="connectionId"></param> /// <param name="exception"></param> /// <exception cref="ArgumentNullException"> /// When <paramref name="endPoint" /> is null /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// When <paramref name="timeout" /> is equal or less than <see cref="TimeSpan.Zero" /> /// </exception> /// <exception cref="InvalidOperationException"> /// When this endPoint is already connected to another endPoint. /// </exception> public bool TryConnect(IPEndPoint endPoint, TimeSpan timeout, out Exception exception, out ConnectionId connectionId) { if (endPoint == null) { throw new ArgumentNullException(nameof(endPoint)); } if (Equals(endPoint, LocalEndPoint)) { throw new ArgumentException("An endPoint cannot be connected to itself", nameof(endPoint)); } if (timeout <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(timeout)); } if (IsConnected) { throw new InvalidOperationException( "This endPoint is already connected to another endPoint and cannot establish any more connections"); } Log.DebugFormat("{0}: Trying to connect to '{1}', timeout: {2}ms", Name, endPoint, timeout.TotalMilliseconds); var success = false; ISocket socket = null; try { var started = DateTime.Now; var task = new Task <Exception>(() => { try { Log.DebugFormat("Task to connect to '{0}' started", endPoint); socket = new Socket2(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp) { ExclusiveAddressUse = true, Blocking = true }; Log.DebugFormat("{0}: EndPoint connecting to remote endpoint '{1}'", Name, endPoint); socket.Connect(endPoint); Log.DebugFormat("{0}: EndPoint successfully connected to remote endpoint '{1}'", Name, endPoint); return(null); } catch (SocketException e) { return(e); } catch (Exception e) { Log.WarnFormat("{0}: Caught unexpected exception while trying to connect to socket: {1}", Name, e); return(e); } }, TaskCreationOptions.LongRunning); task.Start(); if (!task.Wait(timeout)) { exception = new NoSuchIPEndPointException(endPoint, timeout); CurrentConnectionId = connectionId = ConnectionId.None; return(false); } if (task.Result != null) { exception = new NoSuchIPEndPointException(endPoint, task.Result); CurrentConnectionId = connectionId = ConnectionId.None; return(false); } var remaining = timeout - (DateTime.Now - started); ErrorType errorType; string error; object errorReason; if (!TryPerformOutgoingHandshake(socket, remaining, out errorType, out error, out connectionId, out errorReason)) { switch (errorType) { case ErrorType.Handshake: exception = new HandshakeException(error); break; case ErrorType.AuthenticationRequired: exception = new AuthenticationRequiredException(error); break; case ErrorType.EndPointBlocked: exception = new RemoteEndpointAlreadyConnectedException(error, errorReason as IPEndPoint); break; default: exception = new AuthenticationException(error); break; } CurrentConnectionId = connectionId; return(false); } RemoteEndPoint = endPoint; LocalEndPoint = (IPEndPoint)socket.LocalEndPoint; Log.InfoFormat("{0}: EndPoint successfully connected to '{1}'", Name, endPoint); FireOnConnected(endPoint, CurrentConnectionId); success = true; exception = null; return(true); } finally { if (!success) { if (socket != null) { socket.Close(); socket.TryDispose(); } RemoteEndPoint = null; } } }