public void CreateSession(string sessionId, IPAddress serverIP) { lock (sessions) { RelaySession session; if (sessions.TryGetValue(sessionId, out session)) { relay.KillSession(session); sessions.Remove(sessionId); } session = new RelaySession(sessionId) { ServerIP = serverIP, ServerReserveTime = DateTime.Now, }; sessions[sessionId] = session; if (DebugLog != null) { DebugLog.Write(TraceLevel.Info, String.Format("New session created: {0} ({1})", sessionId, serverIP)); DebugLog.Write(TraceLevel.Verbose, FormatSessionTable(sessions)); } } }
public void ConnectSession(string sessionId, IPAddress clientIP) { lock (sessions) { RelaySession session = null; if (!sessions.TryGetValue(sessionId, out session)) { throw new SessionNotFoundException(sessionId); } if (!session.ServerConnected) { throw new RelayConnectException(sessionId, "Server not connected."); } session.ClientIP = clientIP; session.ClientReserveTime = DateTime.Now; if (DebugLog != null) { DebugLog.Write(TraceLevel.Info, String.Format("Session connected: {0} ({1})", sessionId, clientIP)); DebugLog.Write(TraceLevel.Verbose, FormatSessionTable(sessions)); } } }
protected virtual void ProcessIncomingData(RelaySession session, TcpClient recvClient, byte[] buffer, int bytesRead) { if (DebugLog != null) { DebugLog.Write(TraceLevel.Verbose, "Received data from: " + recvClient.Client.RemoteEndPoint); } TcpClient sendClient = null; if (recvClient == session.ServerSocket) { sendClient = session.ClientSocket; } else if (recvClient == session.ClientSocket) { sendClient = session.ServerSocket; } if (sendClient != null) { SendData(session, recvClient, sendClient, buffer, bytesRead); } else { if (DebugLog != null) { DebugLog.Write(TraceLevel.Info, "Received data before peer has connected. Data will be stored in backlog and sent once peer connects."); } session.DataBackLog.Write(buffer, 0, bytesRead); } }
private void HandleIncomingConnection(IAsyncResult ar) { TcpClient newClient = tcpListener.EndAcceptTcpClient(ar); if (newClient.Connected) { lock (sessions) { IPAddress remoteIP = ((IPEndPoint)newClient.Client.RemoteEndPoint).Address; RelaySession session = null; foreach (var s in sessions.Values) { if (s.ServerIP != null && s.ServerIP.Equals(remoteIP) && !s.ServerConnected) { session = s; session.ServerSocket = newClient; if (DebugLog != null) { DebugLog.Write(TraceLevel.Info, String.Format("Server connected: {0}", remoteIP)); DebugLog.Write(TraceLevel.Verbose, FormatSessionTable(sessions)); } relay.AddClient(session, newClient); break; } if (s.ClientIP != null && s.ClientIP.Equals(remoteIP) && s.ServerConnected && !s.ClientConnected) { session = s; session.ClientSocket = newClient; if (DebugLog != null) { DebugLog.Write(TraceLevel.Info, String.Format("Client connected: {0}", remoteIP)); DebugLog.Write(TraceLevel.Verbose, FormatSessionTable(sessions)); } // Tell server that a client has connected byte[] buffer = Encoding.UTF8.GetBytes(ClientConnectedMsg); relay.SendData(session, session.ClientSocket, session.ServerSocket, buffer, buffer.Length); break; } } if (session == null) { newClient.Close(); } } } tcpListener.BeginAcceptTcpClient(HandleIncomingConnection, null); }
protected virtual void HandleIncomingData(IAsyncResult ar) { var socketSession = ar.AsyncState as object[]; if (socketSession != null && socketSession.Length >= 3) { RelaySession session = socketSession[0] as RelaySession; TcpClient recvClient = socketSession[1] as TcpClient; byte[] buffer = socketSession[2] as byte[]; if (buffer != null && session != null && recvClient != null && recvClient.Client != null) { try { int bytesRead = recvClient.Client.EndReceive(ar); if (bytesRead == 0) { if (DebugLog != null) { DebugLog.Write(TraceLevel.Info, "Endpoint disconnected: " + recvClient.Client.RemoteEndPoint); } OnTcpClientDisconnected(recvClient, session); } else { ProcessIncomingData(session, recvClient, buffer, bytesRead); } } catch (SocketException) { if (DebugLog != null) { DebugLog.Write(TraceLevel.Info, "Endpoint disconnected: " + recvClient.Client.RemoteEndPoint); } OnTcpClientDisconnected(recvClient, session); } catch (Exception e) { if (DebugLog != null) { DebugLog.Write(TraceLevel.Error, "HandleIncomingData", e); } } } } }
protected virtual void OnTcpClientDisconnected(TcpClient tcpClient, RelaySession session) { // Socket closed try { tcpClient.Close(); } catch { } if (tcpClient == session.ServerSocket) { KillSession(session); } else if (tcpClient == session.ClientSocket) { session.ClientSocket = null; } }
public void SendData(RelaySession session, TcpClient recvClient, TcpClient sendClient, byte[] buffer, int byteCount) { if (buffer.Length != BufferSize) { Array.Resize(ref buffer, BufferSize); } var sendArgs = new SocketAsyncEventArgs(); sendArgs.UserToken = new object[] { session, recvClient, sendClient, buffer }; sendArgs.Completed += OnSendComplete; sendArgs.SetBuffer(buffer, 0, byteCount); if (!sendClient.Client.SendAsync(sendArgs)) { // Completed synchronously OnSendComplete(null, sendArgs); } }
public virtual void KillSession(RelaySession session) { if (session != null) { if (session.ServerSocket != null) { try { session.ServerSocket.Close(); } catch {} session.ServerSocket = null; } if (session.ClientSocket != null) { try { session.ClientSocket.Close(); } catch {} session.ClientSocket = null; } sessions.Remove(session.SessionId); } }
public virtual void AddClient(RelaySession session, TcpClient tcpClient) { byte[] buffer = new byte[BufferSize]; // Match ethernet MTU object[] socketSession = new object[] { session, tcpClient, buffer }; if (session.DataBackLog.Length > 0) { if (DebugLog != null) { DebugLog.Write(TraceLevel.Info, "Sending backlog data to: " + tcpClient.Client.RemoteEndPoint); } tcpClient.Client.Send(session.DataBackLog.GetBuffer(), 0, Convert.ToInt32(session.DataBackLog.Length), SocketFlags.None); session.DataBackLog.SetLength(0); session.DataBackLog.Seek(0, SeekOrigin.Begin); } tcpClient.Client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, HandleIncomingData, socketSession); }
protected override void OnTcpClientDisconnected(System.Net.Sockets.TcpClient tcpClient, RelaySession session) { if (tcpClient == session.ClientSocket) { if (DebugLog != null) { DebugLog.Write(TraceLevel.Info, "Remote client disconnected. Sending disconnect message to server."); } // Tell server that the client has disconnected byte[] buffer = Encoding.UTF8.GetBytes(SessionManager.ClientDisconnectedMsg); SendData(session, null, session.ServerSocket, buffer, buffer.Length); } base.OnTcpClientDisconnected(tcpClient, session); }