/// <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; } } }
/// <summary> /// /// </summary> /// <param name="endPoint"></param> /// <param name="timeout"></param> /// <param name="exception"></param> /// <param name="connectionId"></param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="InvalidOperationException"></exception> public bool TryConnect(NamedPipeEndPoint 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 (endPoint.Type != NamedPipeEndPoint.PipeType.Server) { throw new ArgumentException("An endpoint can only establish a connection with a server-side enpoint", 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"); } bool success = false; NamedPipeClientStream pipe = null; try { var started = DateTime.Now; pipe = new NamedPipeClientStream(Localhost, endPoint.PipeName); try { var totalMilliseconds = (int)Math.Min(int.MaxValue, timeout.TotalMilliseconds); pipe.Connect(totalMilliseconds); } catch (TimeoutException e) { exception = new NoSuchNamedPipeEndPointException(endPoint, timeout, e); connectionId = ConnectionId.None; return(false); } catch (IOException e) { exception = new NoSuchNamedPipeEndPointException(endPoint, timeout, e); connectionId = ConnectionId.None; return(false); } catch (Exception e) { Log.ErrorFormat("Cauhgt unexpected exception while connecting to '{0}': {1}", endPoint, e); exception = new NoSuchNamedPipeEndPointException(endPoint, timeout, e); connectionId = ConnectionId.None; return(false); } var remaining = timeout - (DateTime.Now - started); ErrorType errorType; string error; object errorReason; if (!TryPerformOutgoingHandshake(pipe, 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 EndPoint); break; default: exception = new AuthenticationException(error); break; } CurrentConnectionId = connectionId; return(false); } InternalRemoteEndPoint = endPoint; LocalEndPoint = NamedPipeEndPoint.FromClient(Name); Log.InfoFormat("EndPoint '{0}' successfully connected to '{1}'", Name, endPoint); FireOnConnected(endPoint, CurrentConnectionId); success = true; exception = null; return(true); } finally { if (!success) { if (pipe != null) { pipe.Close(); pipe.Dispose(); } InternalRemoteEndPoint = null; } } }