private void Close(bool socketDisposed) { if (beginClosing) { return; } lock (interLocker) { if (status == TCPClient.ClientStatus.Closed) { return; } if (status == TCPClient.ClientStatus.Connecting) { requireClose = true; if (connectingCanBeCannelled) { CannelConnecting(); } return; } status = TCPClient.ClientStatus.Closed; beginClosing = true; } InternalClose(true, false, socketDisposed, false); }
private void InternalClose(bool callCloseEvent, bool causedByError, bool socketDisposed, bool checkReClosing) { if (checkReClosing) { lock (interLocker) { if (status == TCPClient.ClientStatus.Closed) { return; } status = TCPClient.ClientStatus.Closed; } } CleanForClose(callCloseEvent, causedByError); if (socketDisposed) { socket.Close(); return; } SocketAsyncEventArgs closeAsyncEventArgs = new SocketAsyncEventArgs { RemoteEndPoint = endpoint }; closeAsyncEventArgs.Completed += IO_Completed; try { if (!socket.DisconnectAsync(closeAsyncEventArgs)) { FinallyShutdownClose(); } return; } catch (SocketException e) { if (errorRecorder != null) { errorRecorder.RecordError("Internal closing failed. SocketException means accessing socket is failed.", e); } socket.Close(); } catch (ObjectDisposedException) { socket.Close(); } }
//----------------[ Constructor ]-----------------------// public TCPConnection(EndPoint endpoint) { interLocker = new object(); this.endpoint = endpoint; status = TCPClient.ClientStatus.Closed; beginClosing = false; requireClose = false; connectingCanBeCannelled = false; socket = new Socket(SocketType.Stream, ProtocolType.Tcp); receiveAsyncEventArgs = new SocketAsyncEventArgs { RemoteEndPoint = endpoint }; receiveAsyncEventArgs.Completed += IO_Completed; currSendOffset = 0; currSendBuffer = null; sendQueue = new Queue <byte[]>(); callbackTimeoutMap = new Dictionary <Int64, HashSet <AnswerCallbackUnit> >(); callbackSeqNumMap = new Dictionary <UInt32, AnswerCallbackUnit>(); }
private void CloseWhenConnectingError() { ClientEngine.UnregisterConnection(this); lock (interLocker) { if (status == TCPClient.ClientStatus.Closed) { return; } status = TCPClient.ClientStatus.Closed; beginClosing = true; } CallConnectionConnectedDelegate(0, false, "Connecting failed event exception. Remote endpoint: " + endpoint + "."); connectionCloseDelegate = null; ClearAllCallback(ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION); socket.Close(); }
private void ConnectCompleted(object sender, SocketAsyncEventArgs e) { if (e.SocketError != SocketError.Success) { if (errorRecorder != null && !requireClose) { errorRecorder.RecordError("Connect to " + endpoint + " failed. Due to SocketError: " + e.SocketError); } CloseWhenConnectingError(); return; } if (requireClose) { CallConnectionConnectedDelegate(0, false, "Connecting cannel event exception. Remote endpoint: " + endpoint + "."); connectionCloseDelegate = null; Close(); return; } receiveAsyncEventArgs.SetBuffer(receiver.buffer, receiver.offset, receiver.requireLength - receiver.offset); connectionId = socket.Handle.ToInt64(); CallConnectionConnectedDelegate(connectionId, true, "Connected event exception. Remote endpoint: " + endpoint + "."); lock (interLocker) { status = TCPClient.ClientStatus.Connected; } if (requireClose) { Close(); return; } if (ClientEngine.RegisterConnectedConnection(this) == false) { Close(); return; } CheckSending(); try { if (!socket.ReceiveAsync(receiveAsyncEventArgs)) { ReceiveCompleted(socket, receiveAsyncEventArgs); } } catch (ObjectDisposedException ex) { CloseByException("Receive data from " + endpoint + " exception. Connection is broken.", ex, true); } catch (SocketException ex) { CloseByException("Receive data from " + endpoint + " exception. Access socket is error.", ex, false); } }
//----------------[ I/O Operations ]-----------------------// public void AsyncConnect(int connectTimeout) { lock (interLocker) { if (status != TCPClient.ClientStatus.Closed) { return; } status = TCPClient.ClientStatus.Connecting; } if (ClientEngine.RegisterConnectingConnection(this, connectTimeout) == false) { lock (interLocker) { status = TCPClient.ClientStatus.Closed; beginClosing = true; } CallConnectionConnectedDelegate(0, false, "Connecting cannel event exception. Remote endpoint: " + endpoint + "."); connectionCloseDelegate = null; socket.Close(); return; } connectionId = 0; receiver = new StandardReceiver(); sendAsyncEventArgs = new SocketAsyncEventArgs { RemoteEndPoint = endpoint }; sendAsyncEventArgs.Completed += IO_Completed; recursionDeepOfReceiveFunction = 0; recursionDeepOfSendFunction = 0; try { if (!socket.ConnectAsync(receiveAsyncEventArgs)) //-- Synchronous { ConnectCompleted(socket, receiveAsyncEventArgs); } else { lock (interLocker) { if (requireClose) { CannelConnecting(); } else { connectingCanBeCannelled = true; } } } } catch (SocketException e) { if (errorRecorder != null) { errorRecorder.RecordError("Connect to " + endpoint + " failed.", e); } CloseWhenConnectingError(); } catch (ObjectDisposedException e) { if (errorRecorder != null) { errorRecorder.RecordError("Connect to " + endpoint + " failed.", e); } CloseWhenConnectingError(); } }
private void ConnectCompleted(object sender, SocketAsyncEventArgs e) { int unityDisCompliantSign = System.Threading.Interlocked.Exchange(ref connectCompletedSignForUnityIl2CPPDisCompliantImplement, 1); if (unityDisCompliantSign != 0) { if (e.SocketError != SocketError.Success) { lock (interLocker) { if (status == TCPClient.ClientStatus.Connecting) { requireClose = true; return; } else if (status == TCPClient.ClientStatus.Closed) { return; } } //-- status == TCPClient.ClientStatus.Connected Close(); } return; } if (e.SocketError != SocketError.Success) { if (errorRecorder != null && !requireClose) { errorRecorder.RecordError("Connect to " + endpoint + " failed. Due to SocketError: " + e.SocketError); } CloseWhenConnectingError(); return; } if (requireClose) { CallConnectionConnectedDelegate(0, false, "Connecting cannel event exception. Remote endpoint: " + endpoint + "."); connectionCloseDelegate = null; Close(); return; } receiveAsyncEventArgs.SetBuffer(receiver.buffer, receiver.offset, receiver.requireLength - receiver.offset); connectionId = socket.Handle.ToInt64(); CallConnectionConnectedDelegate(connectionId, true, "Connected event exception. Remote endpoint: " + endpoint + "."); lock (interLocker) { status = TCPClient.ClientStatus.Connected; } if (requireClose) { Close(); return; } if (ClientEngine.RegisterConnectedConnection(this) == false) { Close(); return; } CheckSending(); try { if (!socket.ReceiveAsync(receiveAsyncEventArgs)) { ReceiveCompleted(socket, receiveAsyncEventArgs); } } catch (ObjectDisposedException ex) { CloseByException("Receive data from " + endpoint + " exception. Connection is broken.", ex, true); } catch (SocketException ex) { CloseByException("Receive data from " + endpoint + " exception. Access socket is error.", ex, false); } catch (InvalidOperationException) { //-- Do nothings } }