/// <summary> /// This method begins accepting a client from the pending connections queue. In this method, the client is /// created and the IP address is checked for brute-force attacks. If the client is validated, then the server /// will begin receiving data packets from the client. /// </summary> /// <param name="result">Represents the status of an asynchronous operation.</param> public void AcceptConnection(IAsyncResult result) { try { // Accept the socket from the asynchronous result: Socket clientSocket = EndAccept(result); // If the socket is valid and the IP address was not found to be a brute-force attack on the socket's // security algorithm, accept the connection. if (clientSocket != null) { // Assign a new asynchronous state to the socket: AsynchronousState state = new AsynchronousState(clientSocket); OnClientConnect?.Invoke(state); // Begin Receiving data and handling the client. If the exchange socket event is not null, // handle the key exchange for the packet cipher; else, accept data from the client. if (OnClientExchange != null) { state.Buffer = new byte[EXCHANGE_BUFFER_SIZE]; state.Socket.BeginReceive(state.Buffer, 0, EXCHANGE_BUFFER_SIZE, SocketFlags.None, PrepareReceive, state); } else if (OnClientReceive != null) { // The server does not process key exchange. Start receiving packets immediately. state.Buffer = new byte[sizeof(PacketHeader)]; state.Socket.BeginReceive(state.Buffer, 0, sizeof(PacketHeader), SocketFlags.None, AnnounceReceive, state); } else { // There are no processing methods for this server! Console.WriteLine("No processing methods defined for the " + Name); clientSocket.Disconnect(false); } } } catch (SocketException e) { // Was the connection issue a problem on the server's side or the client's side? if (e.SocketErrorCode != SocketError.Disconnecting && e.SocketErrorCode != SocketError.NotConnected && e.SocketErrorCode != SocketError.ConnectionReset && e.SocketErrorCode != SocketError.ConnectionAborted && e.SocketErrorCode != SocketError.Shutdown) { Console.WriteLine(e); } } finally { BeginAccept(AcceptConnection, null); } }
/// <summary> /// This method begins the client and server key exchange. The client sends key exchange data first, which is /// picked up by the server in this socket event and processed. Then, the exchange packet is sent back to the /// client so both the client and server have matching cipher keys, and packets are sent to the server. /// </summary> /// <param name="result">Represents the status of an asynchronous operation.</param> public void PrepareReceive(IAsyncResult result) { // Get the asynchronous state for the connection: AsynchronousState state = result.AsyncState as AsynchronousState; if (state != null && state.Socket != null && state.Socket.Connected) { try { // Get the length of the incoming packet: int length = state.Socket.EndReceive(result); Passport passport = state.Client as Passport; if (length > 0 && passport != null) { // Decrypt the exchange packet and assign variables: passport.Packet = passport.Cipher != null ? passport.Cipher.Decrypt(state.Buffer, state.Buffer.Length) : state.Buffer; // Process the exchange, then start accepting data packets: OnClientExchange(state); state.Buffer = new byte[sizeof(PacketHeader)]; state.Socket.BeginReceive(state.Buffer, 0, sizeof(PacketHeader), SocketFlags.None, AnnounceReceive, state); } else { state.Socket.Disconnect(false); } } catch (SocketException e) { // Was the connection issue a problem on the client's side or the server's side? if (e.SocketErrorCode != SocketError.Disconnecting && e.SocketErrorCode != SocketError.NotConnected && e.SocketErrorCode != SocketError.ConnectionReset && e.SocketErrorCode != SocketError.ConnectionAborted && e.SocketErrorCode != SocketError.Shutdown) { Console.WriteLine(e); } // Is the client still connected? if (state != null && state.Socket != null && state.Socket.Connected) { state.Socket.Disconnect(false); } } }
/// <summary> /// This method associates the socket with an IP address and a port. It does this by creating an IP endpoint using /// the local address and port, and requesting a remote IP endpoint using the specified IP address and port. It /// will make an attempt to connect to the server specified. /// </summary> /// <param name="ip">The IP address the client will attempt to connect to.</param> /// <param name="port">The port the socket will connect to.</param> public bool ConnectTo(string ip, int port) { try { // Make an attempt to connect to the server: AsynchronousState state = new AsynchronousState(this); BeginConnect(ip, port, CompleteConnect, state); state.Event.WaitOne(); return(Connected); } catch /*(SocketException exception)*/ { /*Console.WriteLine(exception);*/ } return(false); }
/// <summary> /// This method completes the connection attempt. If the attempt failed, an exception will be thrown; else, /// the connection event will be called and the client will begin sending data to and receiving data from the /// connected server. /// </summary> /// <param name="result">Represents the status of an asynchronous operation.</param> private void CompleteConnect(IAsyncResult result) { try { // Accept the socket from the asynchronous result: AsynchronousState state = result.AsyncState as AsynchronousState; // If the socket is valid, complete the connection attempt. if (state != null && state.Socket != null) { // Complete the connection attempt: try { state.Socket.EndConnect(result); } catch /*(SocketException exception)*/ { /*Console.WriteLine(exception);*/ } finally { state.Event.Set(); } // If the connection was not successful, discontinue; else, handle the on connect event: if (!state.Socket.Connected) { return; } if (OnClientConnect != null) { OnClientConnect(state); } // Begin receiving data from the server. If the exchange socket event is not null, // handle the key exchange for the packet cipher; else, accept data from the server. if (OnClientExchange != null) { state.Buffer = new byte[EXCHANGE_BUFFER_SIZE]; state.Socket.BeginReceive(state.Buffer, 0, EXCHANGE_BUFFER_SIZE, SocketFlags.None, PrepareReceive, state); } else if (OnClientReceive != null) { //Console.WriteLine("Starting recv process..."); // The server does not process key exchange. Start receiving packets immediately. state.Buffer = new byte[MAX_PACKET_SIZE]; state.Socket.BeginReceive(state.Buffer, 0, MAX_PACKET_SIZE, SocketFlags.None, AnnounceReceive, state); } else { // There are no processing methods for this server! Console.WriteLine("No processing methods defined for the " + Name); state.Socket.Disconnect(false); } } } catch (SocketException e) { // Was the connection issue a problem on the client's side or the server's side? if (e.SocketErrorCode != SocketError.Disconnecting && e.SocketErrorCode != SocketError.NotConnected && e.SocketErrorCode != SocketError.ConnectionReset && e.SocketErrorCode != SocketError.ConnectionAborted && e.SocketErrorCode != SocketError.Shutdown) { Console.WriteLine(e); } } }