private static void ForwardMessage(iRTVOMessage incomingMessage) { var allRelayConnections = NetworkComms.GetExistingConnection();// (from current in NetworkComms.GetExistingConnection() where current != connection select current).ToArray(); incomingMessage.Source = NetworkComms.NetworkIdentifier; logger.Info("Forwarding Command {0} to {1} Clients", incomingMessage.Command, allRelayConnections.Count); //We will now send the message to every other connection foreach (var relayConnection in allRelayConnections) { if (relayConnection.ConnectionInfo.NetworkIdentifier == incomingMessage.Source) { logger.Debug("Not sending redundant message to {0}", incomingMessage.Source); continue; } //We ensure we perform the send within a try catch //To ensure a single failed send will not prevent the //relay to all working connections. try { relayConnection.SendObject("iRTVOMessage", incomingMessage); } catch (CommsException ex) { logger.Warn("Broadcast to {0} failed: {1}", relayConnection, ex.ToString()); } } }
// 某客户端用户的状态改变后,通知其他用户 private void UserStateNotify(string userID, OnlineState ustate) { try { //用户状态契约类 UserStateContract userState = new UserStateContract(); userState.UserID = userID; userState.OnLine = ustate; IList <ShortGuid> allUserID; lock (syncLocker) { //获取所有用户字典中的用户链接标识 allUserID = new List <ShortGuid>(userManager.Values); } //给所有用户发送某用户的在线状态 foreach (ShortGuid netID in allUserID) { List <Connection> result = NetworkComms.GetExistingConnection(netID, ConnectionType.TCP); if (result.Count > 0 && result[0].ConnectionInfo.NetworkIdentifier == netID) { result[0].SendObject("UserStateNotify", userState); } } } catch (Exception ex) { LogTools.LogException(ex, "MainForm.UserStateNotify"); } }
private void ProcessCommandAsHost(PacketHeader packetHeader, Connection connection, Command cmd) { foreach (Connection hostConnection in NetworkComms.GetExistingConnection(ConnectionType.TCP)) { connection.SendObject("Command", cmd); } }
public override void Run() { //Message to send Console.WriteLine("\nEnter a message to send all clients or \"quit\" and press ENTER:"); string messageToSend; while ((messageToSend = Console.ReadLine()) != "quit") { if (!string.IsNullOrEmpty(messageToSend)) { foreach (Connection connection in NetworkComms.GetExistingConnection(ConnectionType.TCP)) { connection.SendObject("Message", messageToSend); } } } //The first available connection should become new host foreach (Connection connection in NetworkComms.GetExistingConnection(ConnectionType.TCP)) { connection.SendObject("Config", NetworkComms.GetExistingConnection(ConnectionType.TCP).First().ConnectionInfo.RemoteEndPoint.ToString()); } //We have used comms so we make sure to call shutdown NetworkComms.Shutdown(); }
/// <summary> /// add incomming message on chat and relay it /// </summary> private void AppendToChat(Connection connection, Message incomingMessage) { if (lastPeerMessageDict.ContainsKey(incomingMessage.SourceIdentifier)) { if (lastPeerMessageDict[incomingMessage.SourceIdentifier].MessageIndex < incomingMessage.MessageIndex) { AppendLineToRichChatBox("[" + (DateTime.Now).ToString(hourFormat) + "] " + incomingMessage.SourceName + " : " + incomingMessage.MessageContent); lastPeerMessageDict[incomingMessage.SourceIdentifier] = incomingMessage; } } else { lastPeerMessageDict.Add(incomingMessage.SourceIdentifier, incomingMessage); AppendLineToRichChatBox("[" + (DateTime.Now).ToString(hourFormat) + "] " + incomingMessage.SourceName + " : " + incomingMessage.MessageContent); } if (incomingMessage.RelayCount < relayMaximum) { var allRelayConnections = (from current in NetworkComms.GetExistingConnection() where current != connection select current).ToArray(); incomingMessage.IncrementRelayCount(); foreach (var relayConnection in allRelayConnections) { try { relayConnection.SendObject("Message", incomingMessage); } catch (CommsException) { /* Catch the comms exception, ignore and continue */ } } } }
/// <summary> /// Broadcast a message to all/specific client(s) /// </summary> /// <param name="messageForAll">message for all clients</param> /// <param name="messageForSender">message for specific client</param> private void BroadcastMessage(Connection connection, Message incomingMessage, string messageForAll, string messageForSender, string header = "CHAT") { var allRelayConnections = (from current in NetworkComms.GetExistingConnection() select current).ToArray(); incomingMessage.IncrementRelayCount(); foreach (var relayConnection in allRelayConnections) { try { string msg; if (connection == relayConnection) { msg = messageForSender; } else { msg = messageForAll; } if (!string.IsNullOrEmpty(msg)) { Message message = new Message(NetworkComms.NetworkIdentifier, "Server", header, msg, messageSendIndex++); lastPeerMessageDict[NetworkComms.NetworkIdentifier] = message; relayConnection.SendObject("Message", message); } } catch (CommsException) { // Catch the comms exception, ignore and continue } } }
private void testTimer_Tick(object sender, EventArgs e) { List <Connection> currentConnections = NetworkComms.GetExistingConnection(); lblConnCnt.Text = "Connected Clients: " + currentConnections.Count.ToString(); txtInfo.Text = infoText; }
public void Send(Guid guid, PacketData packetData) { List <Connection> connections = NetworkComms.GetExistingConnection(guid, ConnectionType.TCP); foreach (Connection connection in connections) { TCPConnection.GetConnection(connection.ConnectionInfo).SendObject("Custom", packetData.ToPacket()); } }
private void TurnOff() { List <Connection> currentConnections = NetworkComms.GetExistingConnection(); foreach (Connection conn in currentConnections) { VRCommand cmd = new VRCommand(Enums.ControlMessage.TURN_OFF); SendCommandToClientSpecific(conn, cmd); } }
private void GetClientStatus() { List <Connection> currentConnections = NetworkComms.GetExistingConnection(); foreach (Connection conn in currentConnections) { VRCommand cmd = new VRCommand(Enums.ControlMessage.STATUS); SendCommandToClientSpecific(conn, cmd); } }
private void buttonShowQuickHelp_Click(object sender, EventArgs e) { List <Connection> currentConnections = NetworkComms.GetExistingConnection(); foreach (Connection conn in currentConnections) { VRCommand cmd = new VRCommand(Enums.ControlMessage.SHOW_QUICK_HELP); SendCommandToClientSpecific(conn, cmd); } }
public void CloseConnections() { List <Connection> oldConnections = NetworkComms.GetExistingConnection(ApplicationLayerProtocolStatus.Enabled); foreach (Connection c in oldConnections) { c.CloseConnection(false); } CommsNetworking.CloseConnection(); }
/// <summary> /// Performs whatever functions we might so desire when we receive an incoming ChatMessage /// </summary> /// <param name="header">The PacketHeader corresponding with the received object</param> /// <param name="connection">The Connection from which this object was received</param> /// <param name="incomingMessage">The incoming ChatMessage we are after</param> private void HandleIncomingChatMessage(PacketHeader header, Connection connection, ChatMessage incomingMessage) { //We only want to write a message once to the chat window //Because we allow relaying and may receive the same message twice //we use our history and message indexes to ensure we have a new message lock (lastPeerMessageDict) { if (lastPeerMessageDict.ContainsKey(incomingMessage.SourceIdentifier)) { if (lastPeerMessageDict[incomingMessage.SourceIdentifier].MessageIndex < incomingMessage.MessageIndex) { //If this message index is greater than the last seen from this source we can safely //write the message to the ChatBox AppendLineToChatBox(incomingMessage.SourceName + " - " + incomingMessage.Message); //We now replace the last received message with the current one lastPeerMessageDict[incomingMessage.SourceIdentifier] = incomingMessage; } } else { //If we have never had a message from this source before then it has to be new //by definition lastPeerMessageDict.Add(incomingMessage.SourceIdentifier, incomingMessage); AppendLineToChatBox(incomingMessage.SourceName + " - " + incomingMessage.Message); } } //Once we have written to the ChatBox we refresh the MessagesFromWindow RefreshMessagesFromBox(); //This last section of the method is the relay function //We start by checking to see if this message has already been relayed //the maximum number of times if (incomingMessage.RelayCount < relayMaximum) { //If we are going to relay this message we need an array of //all other known connections var allRelayConnections = (from current in NetworkComms.GetExistingConnection() where current != connection select current).ToArray(); //We increment the relay count before we send incomingMessage.IncrementRelayCount(); //We will now send the message to every other connection foreach (var relayConnection in allRelayConnections) { //We ensure we perform the send within a try catch //To ensure a single failed send will not prevent the //relay to all working connections. try { relayConnection.SendObject("ChatMessage", incomingMessage); } catch (CommsException) { /* Catch the comms exception, ignore and continue */ } } } }
private void buttonSendTileConfig_Click(object sender, EventArgs e) { List <Connection> currentConnections = NetworkComms.GetExistingConnection(); TileConfig tc = BuildMockTileData(); foreach (Connection conn in currentConnections) { VRCommand cmd = new VRCommand(tc); SendCommandToClientSpecific(conn, cmd); } }
private void EndNow() { List <Connection> currentConnections = NetworkComms.GetExistingConnection(); foreach (Connection conn in currentConnections) { EndNow endNow = new EndNow("Your time is up!" + Environment.NewLine + "Thanks for playing!"); VRCommand cmd = new VRCommand(endNow); SendCommandToClientSpecific(conn, cmd); } }
// Print msg via ip for now. private void PrintIncMsg(PacketHeader packetHeader, Connection connection, string incomingObject) { String msg = connection.ToString() + ": " + incomingObject + ""; ChatLog.Items.Add(msg); List <Connection> l = NetworkComms.GetExistingConnection(); foreach (Connection i in l) { if (i != connection) { i.SendObject(textBox1.Text); } } }
/// <summary> /// Deal with incomming message (print or subprocess) /// </summary> /// <param name="header">packet header</param> /// <param name="connection">connection</param> /// <param name="incomingMessage">message sent</param> private void HandleIncomingMessage(PacketHeader header, Connection connection, Message incomingMessage) { lock (lastPeerMessageDict) { if (lastPeerMessageDict.ContainsKey(incomingMessage.SourceIdentifier)) { if (lastPeerMessageDict[incomingMessage.SourceIdentifier].MessageIndex < incomingMessage.MessageIndex) { if (incomingMessage.coincheHeader == "CHAT") { AppendLineToRichChatBox("[" + (DateTime.Now).ToString("HH:mm:ss dd/MM/yyyy") + "] " + incomingMessage.SourceName + " : " + incomingMessage.MessageContent); lastPeerMessageDict[incomingMessage.SourceIdentifier] = incomingMessage; } } if (incomingMessage.coincheHeader != "CHAT") { HandleSpecificMessage(incomingMessage); } } else { if (incomingMessage.coincheHeader == "CHAT") { lastPeerMessageDict.Add(incomingMessage.SourceIdentifier, incomingMessage); AppendLineToRichChatBox("[" + (DateTime.Now).ToString("HH:mm:ss dd/MM/yyyy") + "] " + incomingMessage.SourceName + " : " + incomingMessage.MessageContent); } else { HandleSpecificMessage(incomingMessage); } } } if (incomingMessage.RelayCount < relayMaximum) { var allRelayConnections = (from current in NetworkComms.GetExistingConnection() where current != connection select current).ToArray(); incomingMessage.IncrementRelayCount(); foreach (var relayConnection in allRelayConnections) { try { relayConnection.SendObject("Message", incomingMessage); } catch (CommsException) { /* Catch the comms exception, ignore and continue */ } } } }
private void button5_Click(object sender, EventArgs e) { try { lock (syncLocker) { LogInfo.LogMessage(DateTime.Now.ToString(), "查看连接信息"); foreach (Connection conn in NetworkComms.GetExistingConnection()) { LogInfo.LogMessage("本地端点" + conn.ConnectionInfo.LocalEndPoint + "远程端点" + conn.ConnectionInfo.RemoteEndPoint, "查看连接信息"); } } } catch (Exception ex) { LogTools.LogException(ex, "button5_Click"); } }
/// <summary> /// Attempts to complete the connection establish with a minimum of locking to prevent possible deadlocking /// </summary> /// <param name="remoteConnectionInfo"><see cref="ConnectionInfo"/> corresponding with remoteEndPoint</param> /// <param name="possibleClashConnectionWithPeer_ByEndPoint">True if a connection already exists with provided remoteEndPoint</param> /// <param name="existingConnection">A reference to an existing connection if it exists</param> /// <returns>True if connection is successfully setup, otherwise false</returns> private bool ConnectionSetupHandlerFinal(ConnectionInfo remoteConnectionInfo, ref bool possibleClashConnectionWithPeer_ByEndPoint, ref Connection existingConnection) { lock (NetworkComms.globalDictAndDelegateLocker) { Connection connectionByEndPoint = NetworkComms.GetExistingConnection(ConnectionInfo.RemoteEndPoint, ConnectionInfo.ConnectionType); //If we no longer have the original endPoint reference (set in the constructor) then the connection must have been closed already if (connectionByEndPoint == null) { connectionSetupException = true; connectionSetupExceptionStr = "Connection setup received after connection closure with " + ConnectionInfo; } else { //We need to check for a possible GUID clash //Probability of a clash is approx 0.1% if 1E19 connection are maintained simultaneously (This many connections has not be tested ;)) //but hey, we live in a crazy world! if (remoteConnectionInfo.NetworkIdentifier == NetworkComms.NetworkIdentifier) { connectionSetupException = true; connectionSetupExceptionStr = "Remote peer has same network idendifier to local, " + remoteConnectionInfo.NetworkIdentifier + ". A real duplication is vanishingly improbable so this exception has probably been thrown because the local and remote application are the same."; } else if (connectionByEndPoint != this) { possibleClashConnectionWithPeer_ByEndPoint = true; existingConnection = connectionByEndPoint; } else { //Update the connection info //We never change the this.ConnectionInfo.RemoteEndPoint.Address as there might be NAT involved //We may update the port however IPEndPoint newRemoteIPEndPoint = new IPEndPoint(this.ConnectionInfo.RemoteEndPoint.Address, remoteConnectionInfo.LocalEndPoint.Port); NetworkComms.UpdateConnectionReferenceByEndPoint(this, newRemoteIPEndPoint); ConnectionInfo.UpdateInfoAfterRemoteHandshake(remoteConnectionInfo, newRemoteIPEndPoint); return(true); } } } return(false); }
//客户端获取在线的所有用户的p2p在线信息 private void IncomingP2PInfo(PacketHeader header, Connection Connection, string param) { lock (syncLocker) { IList <UserIDEndPoint> userInfoList = new List <UserIDEndPoint>(); //在用户字典中找到网络连接相对应的用户ID foreach (var kv in userManager) { foreach (Connection conn in NetworkComms.GetExistingConnection(userManager[kv.Key], ConnectionType.TCP)) { UserIDEndPoint userIDEndPoint = new UserIDEndPoint(); userIDEndPoint.UserID = kv.Key; userIDEndPoint.IPAddress = conn.ConnectionInfo.RemoteEndPoint.Address.ToString(); userIDEndPoint.Port = conn.ConnectionInfo.RemoteEndPoint.Port; userInfoList.Add(userIDEndPoint); } } Connection.SendObject("ResP2pInfo", userInfoList); } }
public IPlayer Start() { Console.WriteLine("Game started...."); var allRelayConnections = (from current in NetworkComms.GetExistingConnection() where current != null select current).ToArray(); foreach (var relayConnection in allRelayConnections) { relayConnection.SendObject("Message", "Game started..."); } List <string> playerNames = this.allPlayers.Select(x => x.Name).ToList(); foreach (InternalPlayer player in this.allPlayers) { StartGameContext StartGameContext = new StartGameContext(playerNames, this.initialMoney); player.StartGame(StartGameContext); player.Connection.SendObject("StartGameContext", StartGameContext); } while (this.allPlayers.Count(x => x.PlayerMoney.Money > 0) > 1) { var smallBlind = SmallBlinds[(this.HandsPlayed) / 10]; this.HandsPlayed++; IHandLogic hand = this.HandsPlayed % 2 == 1 ? new TwoPlayersHandLogic(new[] { this.firstPlayer, this.secondPlayer }, this.HandsPlayed, smallBlind) : new TwoPlayersHandLogic(new[] { this.secondPlayer, this.firstPlayer }, this.HandsPlayed, smallBlind); hand.Play(); } var winner = this.allPlayers.FirstOrDefault(x => x.PlayerMoney.Money > 0); foreach (var player in this.allPlayers) { EndGameContext EndGameContext = new EndGameContext(winner.Name); player.EndGame(EndGameContext); player.Connection.SendObject("EndGameContext", EndGameContext); } return(winner); }
private void button4_Click(object sender, EventArgs e) { try { lock (syncLocker) { LogInfo.LogMessage(DateTime.Now.ToString(), "查看连接数"); foreach (Connection conn in NetworkComms.GetExistingConnection()) { //If true the remote end of the Connection responded to an alive/ping test if (conn.ConnectionAlive()) { LogInfo.LogMessage(conn.ConnectionInfo.RemoteEndPoint.ToString(), "查看连接数"); } } } } catch (Exception ex) { LogTools.LogException(ex, "button4_Click"); } }
/// <summary> /// Writes the provided message to the console window /// </summary> /// <param name="header">The packet header associated with the incoming message</param> /// <param name="connection">The connection used by the incoming message</param> /// <param name="message">The message to be printed to the console</param> private static void ReceiveChatMessage(PacketHeader header, Connection connection, string message) { loggingTextBox.Invoke(new MethodInvoker( delegate() { loggingTextBox.AppendText(Environment.NewLine + "▶ A message was received" + connection.ToString() + " => " + message); // 스크롤 마지막으로 이동 loggingTextBox.SelectionStart = loggingTextBox.Text.Length; loggingTextBox.ScrollToCaret(); })); //UDPConnection.SendObject("Message", "Broadcast Message", new IPEndPoint(IPAddress.Broadcast, 1000)); var allRelayConnections = (from current in NetworkComms.GetExistingConnection() where current != connection select current).ToArray(); foreach (var relayConnection in allRelayConnections) { try { relayConnection.SendObject("SendChatMessage", message); } catch (CommsException) { /* Catch the general comms exception, ignore and continue */ } } //UDPConnection.SendObject("BroadMessage", "Broad Message", new IPEndPoint(IPAddress.Broadcast, 1000)); }
public static void BroadcastMessage(iRTVOMessage m) { if (isServer) // Server Broadcasts to all clients { var allRelayConnections = NetworkComms.GetExistingConnection(); // (from current in NetworkComms.GetExistingConnection() where current != connection select current).ToArray(); logger.Debug("Broadcasting Command {0} to {1} Clients", m.Command, allRelayConnections.Count); //We will now send the message to every other connection foreach (var relayConnection in allRelayConnections) { //We ensure we perform the send within a try catch //To ensure a single failed send will not prevent the //relay to all working connections. try { relayConnection.SendObject("iRTVOMessage", m); } catch (CommsException ex) { logger.Warn("Broadcast to {0} failed: {1}", relayConnection, ex.ToString()); } } return; } else // Client only sends to server { if (serverConnection != null) { logger.Debug("Sending Command '{0}' to Server", m.Command); try { serverConnection.SendObject("iRTVOMessage", m); } catch (CommsException ex) { logger.Error("Sending of Command '{0}' failed: {1}", m.Command, ex.ToString()); } } } }
public static void SendMessage(string targetClient, string Command, params object[] Arguments) { if (!isServer) { throw new UnauthorizedAccessException("Only the server can call this function!"); } string[] args = new string[Arguments.Length]; for (int i = 0; i < Arguments.Length; i++) { args[i] = Convert.ToString(Arguments[i]); } iRTVOMessage m = new iRTVOMessage(NetworkComms.NetworkIdentifier, Command, args); var allRelayConnections = NetworkComms.GetExistingConnection();// (from current in NetworkComms.GetExistingConnection() where current != connection select current).ToArray(); logger.Info("Sending Command {0} to {1} ", Command, targetClient); //We will now send the message to every other connection foreach (var relayConnection in allRelayConnections) { if (relayConnection.ConnectionInfo.NetworkIdentifier != targetClient) { continue; } //We ensure we perform the send within a try catch //To ensure a single failed send will not prevent the //relay to all working connections. try { relayConnection.SendObject("iRTVOMessage", m); } catch (CommsException ex) { logger.Warn("Broadcast to {0} failed: {1}", relayConnection, ex.ToString()); } } }
/// <summary> /// Internal UDP creation method that performs the necessary tasks /// </summary> /// <param name="connectionInfo"></param> /// <param name="defaultSendReceiveOptions"></param> /// <param name="level"></param> /// <param name="listenForReturnPackets"></param> /// <param name="existingListenerConnection"></param> /// <param name="possibleHandshakeUDPDatagram"></param> /// <param name="establishIfRequired">Will establish the connection, triggering connection establish delegates if a new /// connection is returned</param> /// <returns></returns> internal static UDPConnection GetConnection(ConnectionInfo connectionInfo, UDPOptions level, SendReceiveOptions defaultSendReceiveOptions, bool listenForReturnPackets, UDPConnection existingListenerConnection, HandshakeUDPDatagram possibleHandshakeUDPDatagram, bool establishIfRequired = true) { connectionInfo.ConnectionType = ConnectionType.UDP; bool newConnection = false; UDPConnection connection = null; lock (NetworkComms.globalDictAndDelegateLocker) { List <Connection> existingConnections = NetworkComms.GetExistingConnection(connectionInfo.RemoteIPEndPoint, connectionInfo.LocalIPEndPoint, ConnectionType.UDP, connectionInfo.ApplicationLayerProtocol); if (existingConnections.Count > 0) { connection = (UDPConnection)existingConnections[0]; } else { //If we are listening on what will be the outgoing adaptor we send with that client to ensure if our connection info is handed off we are connectable by others if (existingListenerConnection == null) { try { IPEndPoint localEndPoint = IPTools.BestLocalEndPoint(connectionInfo.RemoteIPEndPoint); //Set the port to 0 so that we match any listener localEndPoint.Port = 0; List <UDPConnectionListener> existingListeners = Connection.ExistingLocalListeners <UDPConnectionListener>(localEndPoint); for (int i = 0; i < existingListeners.Count; i++) { if (existingListeners[i].UDPConnection.ConnectionInfo.ApplicationLayerProtocol == connectionInfo.ApplicationLayerProtocol) { existingListenerConnection = existingListeners[i].UDPConnection; //If we are using an existing listener there is no need to listen for packets listenForReturnPackets = false; //Once we have a matching connection we can break break; } } } catch (Exception) { if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Failed to determine preferred existing udpClientListener to " + connectionInfo.RemoteIPEndPoint.Address + ":" + connectionInfo.RemoteIPEndPoint.Port.ToString() + ". Will create an isolated UDP connection instead."); } } } //If an existing connection does not exist but the info we are using suggests it should we need to reset the info //so that it can be reused correctly. This case generally happens when using Comms in the format //UDPConnection.GetConnection(info).SendObject(packetType, objToSend); if (connectionInfo.ConnectionState == ConnectionState.Established || connectionInfo.ConnectionState == ConnectionState.Shutdown) { connectionInfo.ResetConnectionInfo(); } connection = new UDPConnection(connectionInfo, defaultSendReceiveOptions, level, listenForReturnPackets, existingListenerConnection); newConnection = true; } } //If we expect a UDP handshake we need to handle incoming datagrams here, if we have it available, // before trying to establish the connection. //This is different for TCP connections because things happen in the reverse order //UDP - Already listening, receive connectionsetup, configure connection //TCP - Receive TCPClient, configure connection, start listening for connectionsetup, wait for connectionsetup // //possibleHandshakeUDPDatagram will only be set when GetConnection() is called from a listener //If multiple threads try to create an outgoing UDP connection to the same endPoint all but the originating //thread will be held on connection.WaitForConnectionEstablish(); if (possibleHandshakeUDPDatagram != null && (connection.ConnectionUDPOptions & UDPOptions.Handshake) == UDPOptions.Handshake) { lock (connection.packetBuilder.Locker) { if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace(" ... " + possibleHandshakeUDPDatagram.DatagramBytes.Length.ToString() + " handshake bytes added to packetBuilder for " + connection.ConnectionInfo + ". Cached " + connection.packetBuilder.TotalBytesCached.ToString() + " bytes, expecting " + connection.packetBuilder.TotalBytesExpected.ToString() + " bytes."); } connection.packetBuilder.AddPartialPacket(possibleHandshakeUDPDatagram.DatagramBytes.Length, possibleHandshakeUDPDatagram.DatagramBytes); if (connection.packetBuilder.TotalBytesCached > 0) { connection.IncomingPacketHandleHandOff(connection.packetBuilder); } } if (connection.packetBuilder.TotalPartialPacketCount > 0) { LogTools.LogException(new Exception("Packet builder had " + connection.packetBuilder.TotalBytesCached + " bytes remaining after a call to IncomingPacketHandleHandOff with connection " + connection.ConnectionInfo + ". Until sequenced packets are implemented this indicates a possible error."), "UDPConnectionError"); } possibleHandshakeUDPDatagram.DatagramHandled = true; } //We must perform the establish outside the lock as for TCP connections if (newConnection && establishIfRequired) { //Call establish on the connection if it is not a rogue sender or listener if (!connectionInfo.RemoteIPEndPoint.Address.Equals(IPAddress.Any) && !connectionInfo.RemoteIPEndPoint.Address.Equals(IPAddress.IPv6Any)) { connection.EstablishConnection(); } } else if (!newConnection) { connection.WaitForConnectionEstablish(NetworkComms.ConnectionEstablishTimeoutMS); } //UDP does not need keep alives //if (!NetworkComms.commsShutdown) // TriggerConnectionKeepAliveThread(); return(connection); }
/// <summary> /// The distributed file system (DFS) allows for the high performance distribution of large files /// within a cluster of peers. This sytem replicates the behaviour the bitTorrent protocol by using /// NetworkCommsDotNet. This example demonstrates the DFS in action. /// </summary> public static void RunExample() { //Select launch mode Console.WriteLine("Launching DFS system ...\n"); Console.WriteLine("Please select host or peer mode:"); Console.WriteLine("1 - Host Mode (Original source of data)"); Console.WriteLine("2 - Peer Mode (Builds data and then acts as subhost)"); //Read in user choice //if (Console.ReadKey(true).Key == ConsoleKey.D1) hostMode = true; //else hostMode = false; hostMode = false; if (hostMode) { //Prepare DFS in host mode #region ServerMode Console.WriteLine("\n ... host mode selected."); Console.WriteLine("\nPlease enter how large the test data packet should be in MB and press return, e.g. 50:"); int numberMegsToCreate = int.Parse(Console.ReadLine()); //Fill a byte[] with random data DateTime startTime = DateTime.Now; Random randGen = new Random(); byte[] someRandomData = new byte[numberMegsToCreate * 1024 * 1024]; randGen.NextBytes(someRandomData); Console.WriteLine("\n ... successfully created a {0}MB test packet.", ((double)someRandomData.Length / (1024.0 * 1024.0)).ToString("0.###")); object listLocker = new object(); List <IPEndPoint> connectedClients = new List <IPEndPoint>(); //Initialise the DFS before creating the test object to ensure the correct port and IP are used as the seed DFS.Initialise(10000); //Create the item to be distributed List <ConnectionInfo> seedConnectionInfoList = (from current in Connection.ExistingLocalListenEndPoints(ConnectionType.TCP) select new ConnectionInfo(ConnectionType.TCP, NetworkComms.NetworkIdentifier, current, true)).ToList(); DistributedItem newItem = new DistributedItem("exampleItem", "example1", new MemoryStream(someRandomData), seedConnectionInfoList, DataBuildMode.Memory_Single); NetworkComms.ConnectionEstablishShutdownDelegate clientEstablishDelegate = (connection) => { lock (listLocker) connectedClients.Remove((IPEndPoint)connection.ConnectionInfo.RemoteEndPoint); Console.WriteLine("Client " + connection.ConnectionInfo + " connected."); }; NetworkComms.ConnectionEstablishShutdownDelegate clientShutdownDelegate = (connection) => { lock (listLocker) connectedClients.Remove((IPEndPoint)connection.ConnectionInfo.RemoteEndPoint); Console.WriteLine("Client " + connection.ConnectionInfo + " disconnected."); }; NetworkComms.PacketHandlerCallBackDelegate <int> ReplyDelegate = (packetHeader, connection, incomingObject) => { //Push the item into the swarm lock (listLocker) if (!connectedClients.Contains(connection.ConnectionInfo.RemoteEndPoint)) { connectedClients.Add((IPEndPoint)connection.ConnectionInfo.RemoteEndPoint); } DFS.PushItemToPeer(connection, newItem, "BigDataRequestResponse"); Console.WriteLine("Pushing item to " + connection.ConnectionInfo + " (" + connection.ConnectionInfo.NetworkIdentifier + "). {0} in swarm. P#={1}, S#={2}.", connectedClients.Count, newItem.PushCount, newItem.TotalChunkSupplyCount); }; NetworkComms.PacketHandlerCallBackDelegate <string> InfoDelegate = (packetHeader, connectionId, incomingString) => { Console.WriteLine(" ... " + connectionId + " - " + incomingString); }; Console.WriteLine(" ... DFS has been initialised."); NetworkComms.AppendGlobalConnectionEstablishHandler(clientEstablishDelegate); NetworkComms.AppendGlobalConnectionCloseHandler(clientShutdownDelegate); NetworkComms.AppendGlobalIncomingPacketHandler("BigDataRequest", ReplyDelegate); NetworkComms.AppendGlobalIncomingPacketHandler("ClientInfo", InfoDelegate); Console.WriteLine("\nListening for incoming connections on:"); foreach (IPEndPoint localEndPoint in Connection.ExistingLocalListenEndPoints(ConnectionType.TCP)) { Console.WriteLine("{0}:{1}", localEndPoint.Address, localEndPoint.Port); } Console.WriteLine("\nIdentifier - {0}", NetworkComms.NetworkIdentifier); Console.WriteLine("\nPress 's' to write out stats, 'q' to close any connected peers, 'ctrl+q' to close this host.\n"); while (true) { ConsoleKeyInfo pressedKey = Console.ReadKey(true); #region Host Shutdown if (pressedKey.Modifiers != ConsoleModifiers.Control && pressedKey.Key == ConsoleKey.Q) { Console.WriteLine("Sending shutdown to clients..."); lock (listLocker) { for (int i = 0; i < connectedClients.Count; i++) { try { TCPConnection.GetConnection(new ConnectionInfo(connectedClients[i])).SendObject("ClientCommand", 0); } catch (Exception) { Console.WriteLine("Exception telling client to shutdown. Probably already disconnected."); } } } } else if (pressedKey.Modifiers == ConsoleModifiers.Control && pressedKey.Key == ConsoleKey.Q) { Console.WriteLine("Sending shutdown to clients and closing local host..."); lock (listLocker) { for (int i = 0; i < connectedClients.Count; i++) { try { TCPConnection.GetConnection(new ConnectionInfo(connectedClients[i])).SendObject("ClientCommand", 0); } catch (Exception) { Console.WriteLine("Exception telling client to shutdown. Probably already disconnected."); } } } Console.WriteLine("Closing host."); break; } else if (pressedKey.Key == ConsoleKey.S) { #region Stats Console.WriteLine("\nCurrent Stats:"); Console.WriteLine("{0} comms connections.", NetworkComms.TotalNumConnections()); if (NetworkComms.TotalNumConnections() > 0) { Console.WriteLine("Connections with: "); var connections = NetworkComms.GetExistingConnection(); foreach (var connection in connections) { Console.WriteLine("\t{0}", connection.ConnectionInfo); } } #endregion } #endregion } #endregion } else if (!hostMode) { //Prepare DFS in peer mode #region PeerMode Console.WriteLine("\n ... peer mode selected."); try { ConnectionInfo serverConnectionInfo = new ConnectionInfo("192.168.0.105", 10000); //ExampleHelper.GetServerDetails(out serverConnectionInfo); DFS.Initialise(10000); Console.WriteLine(" ... DFS has been initialised."); bool shutDown = false; bool buildComplete = true; DateTime startTime = DateTime.Now; int buildCount = 0; NetworkComms.PacketHandlerCallBackDelegate <byte[]> ReplyDelegate = (packetHeader, connection, dataBytes) => { try { buildCount++; DistributedItem item = DFS.MostRecentlyCompletedItem(); Console.WriteLine(" ... full item build " + buildCount + " took {0} secs ({1} MB/s) using {2} total peers. {3} builds completed.", (DateTime.Now - startTime).TotalSeconds.ToString("0.00"), (((double)dataBytes.Length / 1048576.0) / (DateTime.Now - startTime).TotalSeconds).ToString("0.0"), item.SwarmChunkAvailability.NumPeersInSwarm(), buildCount); double speed = (((double)dataBytes.Length / 1048576.0) / (DateTime.Now - startTime).TotalSeconds); connection.SendObject("ClientInfo", " ... build " + buildCount + " took " + (DateTime.Now - startTime).TotalSeconds.ToString("0.00") + " secs (" + speed.ToString("0.0") + " MB/s) using " + item.SwarmChunkAvailability.NumPeersInSwarm() + " peers. " + buildCount + " builds completed."); buildComplete = true; dataBytes = null; GC.Collect(); } catch (Exception ex) { LogTools.LogException(ex, "DFSTestCallbackError"); Console.WriteLine("Shutting down due to exception."); shutDown = true; } }; NetworkComms.PacketHandlerCallBackDelegate <int> ShutdownDelegate = (packetHeader, connectionId, packetDataBytes) => { shutDown = true; }; NetworkComms.AppendGlobalIncomingPacketHandler("BigDataRequestResponse", ReplyDelegate); NetworkComms.AppendGlobalIncomingPacketHandler("ClientCommand", ShutdownDelegate); Console.WriteLine("\nIdentifier - {0}", NetworkComms.NetworkIdentifier); Console.WriteLine("\nListening for incoming objects on:"); foreach (IPEndPoint localEndPoint in Connection.ExistingLocalListenEndPoints(ConnectionType.TCP)) { Console.WriteLine("{0}:{1}", localEndPoint.Address, localEndPoint.Port); } startTime = DateTime.Now; //while (true) //{ if (!shutDown && buildComplete) { //Console.WriteLine("\nPress 'r' to rebuild or any other key to shutdown."); //var shutdownKey = Console.ReadKey(true).Key; //if (shutdownKey != ConsoleKey.R) shutDown = true; //if (!shutDown) //{ DistributedItem item = DFS.MostRecentlyCompletedItem(); if (item != null) { DFS.RemoveItem(item.Data.CompleteDataCheckSum); Console.WriteLine("\n ... item removed from local and rebuilding at {0}.", DateTime.Now.ToString("HH:mm:ss.fff")); startTime = DateTime.Now; } buildComplete = false; TCPConnection.GetConnection(serverConnectionInfo).SendObject("BigDataRequest"); Console.WriteLine(" ... initiating item build ..."); //} } else if (shutDown) { shutDown = true; DFS.Shutdown(); //break; } Thread.Sleep(250); //} while (!buildComplete) { Thread.Sleep(250); } try { TCPConnection.GetConnection(serverConnectionInfo).SendObject("ClientInfo", "... shutting down, initiating DFS shutdown."); } catch (CommsException) { Console.WriteLine("... unable to inform local of shutdown. Connection probably already closed."); } Console.WriteLine("Done. Completed {0} builds.", buildCount); } catch (Exception ex) { Console.WriteLine("Bad Error!"); LogTools.LogException(ex, "DFSTestError_" + NetworkComms.NetworkIdentifier); } #endregion } DFS.Shutdown(); NetworkComms.Shutdown(); }
/// <summary> /// Internal <see cref="TCPConnection"/> creation which hides the necessary internal calls /// </summary> /// <param name="connectionInfo">ConnectionInfo to be used to create connection</param> /// <param name="defaultSendReceiveOptions">Connection default SendReceiveOptions</param> /// <param name="tcpClient">If this is an incoming connection we will already have access to the tcpClient, otherwise use null</param> /// <param name="establishIfRequired">Establish during create if true</param> /// <param name="sslOptions">SSL options that will be used with this connection.</param> /// <returns>An existing connection or a new one</returns> internal static TCPConnection GetConnection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions, TcpClient tcpClient, bool establishIfRequired, SSLOptions sslOptions = null) #endif { connectionInfo.ConnectionType = ConnectionType.TCP; //If we have a tcpClient at this stage we must be server side #if WINDOWS_PHONE || NETFX_CORE if (socket != null) { connectionInfo.ServerSide = true; } #else if (tcpClient != null) { connectionInfo.ServerSide = true; } if (sslOptions == null) { sslOptions = new SSLOptions(); } #endif //Set default connection options if none have been provided if (defaultSendReceiveOptions == null) { defaultSendReceiveOptions = NetworkComms.DefaultSendReceiveOptions; } bool newConnection = false; TCPConnection connection; lock (NetworkComms.globalDictAndDelegateLocker) { List <Connection> existingConnections = NetworkComms.GetExistingConnection(connectionInfo.RemoteIPEndPoint, connectionInfo.LocalIPEndPoint, connectionInfo.ConnectionType, connectionInfo.ApplicationLayerProtocol); //Check to see if a connection already exists, if it does return that connection, if not return a new one if (existingConnections.Count > 0) { if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Attempted to create new TCPConnection to connectionInfo='" + connectionInfo + "' but there is an existing connection. Existing connection will be returned instead."); } establishIfRequired = false; connection = (TCPConnection)existingConnections[0]; } else { if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Creating new TCPConnection to connectionInfo='" + connectionInfo + "'." + (establishIfRequired ? " Connection will be established." : " Connection will not be established.")); } if (connectionInfo.ConnectionState == ConnectionState.Establishing) { throw new ConnectionSetupException("Connection state for connection " + connectionInfo + " is marked as establishing. This should only be the case here due to a bug."); } //If an existing connection does not exist but the info we are using suggests it should we need to reset the info //so that it can be reused correctly. This case generally happens when using Comms in the format //TCPConnection.GetConnection(info).SendObject(packetType, objToSend); if (connectionInfo.ConnectionState == ConnectionState.Established || connectionInfo.ConnectionState == ConnectionState.Shutdown) { connectionInfo.ResetConnectionInfo(); } //We add a reference to networkComms for this connection within the constructor #if WINDOWS_PHONE || NETFX_CORE connection = new TCPConnection(connectionInfo, defaultSendReceiveOptions, socket); #else connection = new TCPConnection(connectionInfo, defaultSendReceiveOptions, tcpClient, sslOptions); #endif newConnection = true; } } if (newConnection && establishIfRequired) { connection.EstablishConnection(); } else if (!newConnection) { connection.WaitForConnectionEstablish(NetworkComms.ConnectionEstablishTimeoutMS); } if (!NetworkComms.commsShutdown) { TriggerConnectionKeepAliveThread(); } return(connection); }
/// <summary> /// Attempts to complete the connection establish with a minimum of locking to avoid possible deadlocking /// </summary> /// <param name="remoteConnectionInfo"><see cref="ConnectionInfo"/> corresponding with remoteEndPoint</param> /// <param name="possibleClashWithExistingConnection">True if a connection already exists with provided remoteEndPoint</param> /// <param name="existingConnection">A reference to an existing connection if it exists</param> /// <returns>True if connection is successfully setup, otherwise false</returns> private bool ConnectionSetupHandlerFinal(ConnectionInfo remoteConnectionInfo, ref bool possibleClashWithExistingConnection, ref Connection existingConnection) { lock (NetworkComms.globalDictAndDelegateLocker) { List <Connection> connectionByEndPoint = NetworkComms.GetExistingConnection(ConnectionInfo.RemoteEndPoint, ConnectionInfo.LocalEndPoint, ConnectionInfo.ConnectionType, ConnectionInfo.ApplicationLayerProtocol); //If we no longer have the original endPoint reference (set in the constructor) then the connection must have been closed already if (connectionByEndPoint.Count == 0) { connectionSetupException = true; connectionSetupExceptionStr = "Connection setup received after connection closure with " + ConnectionInfo; } else { //COMMENT: As of version 3.0.0 we have allowed loop back connections where the identifier is the same //We need to check for a possible GUID clash //Probability of a clash is approx 0.1% if 1E19 connections are maintained simultaneously (This many connections has not be tested ;)) //but hey, we live in a crazy world! //if (remoteConnectionInfo.NetworkIdentifier == NetworkComms.NetworkIdentifier) //{ // connectionSetupException = true; // connectionSetupExceptionStr = "Remote peer has same network identifier to local, " + remoteConnectionInfo.NetworkIdentifier + ". A real duplication is vanishingly improbable so this exception has probably been thrown because the local and remote application are the same."; //} //else if (connectionByEndPoint[0] != this) { possibleClashWithExistingConnection = true; existingConnection = connectionByEndPoint[0]; } else if (connectionByEndPoint[0].ConnectionInfo.NetworkIdentifier != ShortGuid.Empty && connectionByEndPoint[0].ConnectionInfo.NetworkIdentifier != remoteConnectionInfo.NetworkIdentifier) { //We are in the same connection, so don't need to throw and exception but the remote network identifier //has changed. //This can happen for connection types where the local connection (this) may not have been closed //when the remote peer closed. We need to trigger the connection close delegates with the old info, update //the connection info and then call the establish delegates #region Reset Connection without closing //Call the connection close delegates try { //Almost there //Last thing is to call any connection specific shutdown delegates if (ConnectionSpecificShutdownDelegate != null) { if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Debug("Triggered connection specific shutdown delegates with " + ConnectionInfo); } ConnectionSpecificShutdownDelegate(this); } } catch (Exception ex) { LogTools.LogException(ex, "ConnectionSpecificShutdownDelegateError", "Error while executing connection specific shutdown delegates for " + ConnectionInfo + ". Ensure any shutdown exceptions are caught in your own code."); } try { //Last but not least we call any global connection shutdown delegates if (NetworkComms.globalConnectionShutdownDelegates != null) { if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Debug("Triggered global shutdown delegates with " + ConnectionInfo); } NetworkComms.globalConnectionShutdownDelegates(this); } } catch (Exception ex) { LogTools.LogException(ex, "GlobalConnectionShutdownDelegateError", "Error while executing global connection shutdown delegates for " + ConnectionInfo + ". Ensure any shutdown exceptions are caught in your own code."); } EndPoint newRemoteEndPoint; if (this.ConnectionInfo.RemoteEndPoint.GetType() == typeof(IPEndPoint) && remoteConnectionInfo.LocalEndPoint.GetType() == typeof(IPEndPoint)) { newRemoteEndPoint = new IPEndPoint(this.ConnectionInfo.RemoteIPEndPoint.Address, remoteConnectionInfo.LocalIPEndPoint.Port); } else { throw new NotImplementedException("ConnectionSetupHandlerFinal not implemented for EndPoints of type " + this.ConnectionInfo.RemoteEndPoint.GetType()); } NetworkComms.UpdateConnectionReferenceByEndPoint(this, newRemoteEndPoint, this.ConnectionInfo.LocalEndPoint); ConnectionInfo.UpdateInfoAfterRemoteHandshake(remoteConnectionInfo, newRemoteEndPoint); //Trigger the establish delegates TriggerConnectionEstablishDelegates(); #endregion return(true); } else { //Update the connection info //We never change the this.ConnectionInfo.RemoteEndPoint.Address as there might be NAT involved //We may update the port however EndPoint newRemoteEndPoint; if (this is IPConnection) { newRemoteEndPoint = new IPEndPoint(this.ConnectionInfo.RemoteIPEndPoint.Address, remoteConnectionInfo.LocalIPEndPoint.Port); } #if NET35 || NET4 else if (this is BluetoothConnection) { newRemoteEndPoint = ConnectionInfo.RemoteBTEndPoint; } #endif else { throw new NotImplementedException("ConnectionSetupHandlerFinal not implemented for EndPoints of type " + this.ConnectionInfo.RemoteEndPoint.GetType()); } NetworkComms.UpdateConnectionReferenceByEndPoint(this, newRemoteEndPoint, this.ConnectionInfo.LocalEndPoint); ConnectionInfo.UpdateInfoAfterRemoteHandshake(remoteConnectionInfo, newRemoteEndPoint); return(true); } } } return(false); }
/// <summary> /// Updates the configuration of this instance depending on set fields /// </summary> public void RefreshNetworkCommsConfiguration() { #region First Initialisation //On first initialisation we need to configure NetworkComms.Net to handle our incoming packet types //We only need to add the packet handlers once. If we call NetworkComms.Shutdown() at some future point these are not removed. if (FirstInitialisation) { FirstInitialisation = false; //Configure NetworkComms.Net to handle any incoming packet of type 'ChatMessage' //e.g. If we receive a packet of type 'ChatMessage' execute the method 'HandleIncomingChatMessage' NetworkComms.AppendGlobalIncomingPacketHandler <ChatMessage>("ChatMessage", HandleIncomingChatMessage); //Configure NetworkComms.Net to perform some action when a connection is closed //e.g. When a connection is closed execute the method 'HandleConnectionClosed' NetworkComms.AppendGlobalConnectionCloseHandler(HandleConnectionClosed); } #endregion #region Set serializer //Set the default send recieve options to use the specified serializer. Keep the DataProcessors and Options from the previous defaults NetworkComms.DefaultSendReceiveOptions = new SendReceiveOptions(Serializer, NetworkComms.DefaultSendReceiveOptions.DataProcessors, NetworkComms.DefaultSendReceiveOptions.Options); #endregion #region Optional Encryption //Configure encryption if requested if (EncryptionEnabled && !NetworkComms.DefaultSendReceiveOptions.DataProcessors.Contains(DPSManager.GetDataProcessor <RijndaelPSKEncrypter>())) { //Encryption is currently implemented using a pre-shared key (PSK) system //NetworkComms.Net supports multiple data processors which can be used with any level of granularity //To enable encryption globally (i.e. for all connections) we first add the encryption password as an option RijndaelPSKEncrypter.AddPasswordToOptions(NetworkComms.DefaultSendReceiveOptions.Options, _encryptionKey); //Finally we add the RijndaelPSKEncrypter data processor to the sendReceiveOptions NetworkComms.DefaultSendReceiveOptions.DataProcessors.Add(DPSManager.GetDataProcessor <RijndaelPSKEncrypter>()); } else if (!EncryptionEnabled && NetworkComms.DefaultSendReceiveOptions.DataProcessors.Contains(DPSManager.GetDataProcessor <RijndaelPSKEncrypter>())) { //If encryption has been disabled but is currently enabled //To disable encryption we just remove the RijndaelPSKEncrypter data processor from the sendReceiveOptions NetworkComms.DefaultSendReceiveOptions.DataProcessors.Remove(DPSManager.GetDataProcessor <RijndaelPSKEncrypter>()); } #endregion #region Local Server Mode and Connection Type Changes if (LocalServerEnabled && ConnectionType == ConnectionType.TCP && !Connection.Listening(ConnectionType.TCP)) { //If we were previously listening for UDP we first shutdown NetworkComms.Net. if (Connection.Listening(ConnectionType.UDP)) { AppendLineToChatHistory("Connection mode has been changed. Any existing connections will be closed."); NetworkComms.Shutdown(); } else { AppendLineToChatHistory("Enabling local server mode. Any existing connections will be closed."); NetworkComms.Shutdown(); } //Start listening for new incoming TCP connections //We want to select a random port on all available adaptors so provide //an IPEndPoint using IPAddress.Any and port 0. Connection.StartListening(ConnectionType.TCP, new IPEndPoint(IPAddress.Any, 0)); //Write the IP addresses and ports that we are listening on to the chatBox AppendLineToChatHistory("Listening for incoming TCP connections on:"); foreach (IPEndPoint listenEndPoint in Connection.ExistingLocalListenEndPoints(ConnectionType.TCP)) { AppendLineToChatHistory(listenEndPoint.Address + ":" + listenEndPoint.Port); } //Add a blank line after the initialisation output AppendLineToChatHistory(System.Environment.NewLine); } else if (LocalServerEnabled && ConnectionType == ConnectionType.UDP && !Connection.Listening(ConnectionType.UDP)) { //If we were previously listening for TCP we first shutdown NetworkComms.Net. if (Connection.Listening(ConnectionType.TCP)) { AppendLineToChatHistory("Connection mode has been changed. Any existing connections will be closed."); NetworkComms.Shutdown(); } else { AppendLineToChatHistory("Enabling local server mode. Any existing connections will be closed."); NetworkComms.Shutdown(); } //Start listening for new incoming UDP connections //We want to select a random port on all available adaptors so provide //an IPEndPoint using IPAddress.Any and port 0. Connection.StartListening(ConnectionType.UDP, new IPEndPoint(IPAddress.Any, 0)); //Write the IP addresses and ports that we are listening on to the chatBox AppendLineToChatHistory("Listening for incoming UDP connections on:"); foreach (IPEndPoint listenEndPoint in Connection.ExistingLocalListenEndPoints(ConnectionType.UDP)) { AppendLineToChatHistory(listenEndPoint.Address + ":" + listenEndPoint.Port); } //Add a blank line after the initialisation output AppendLineToChatHistory(System.Environment.NewLine); } else if (!LocalServerEnabled && (Connection.Listening(ConnectionType.TCP) || Connection.Listening(ConnectionType.UDP))) { //If the local server mode has been disabled but we are still listening we need to stop accepting incoming connections NetworkComms.Shutdown(); AppendLineToChatHistory("Local server mode disabled. Any existing connections will be closed."); AppendLineToChatHistory(System.Environment.NewLine); } else if (!LocalServerEnabled && ((ConnectionType == ConnectionType.UDP && NetworkComms.GetExistingConnection(ConnectionType.TCP).Count > 0) || (ConnectionType == ConnectionType.TCP && NetworkComms.GetExistingConnection(ConnectionType.UDP).Count > 0))) { //If we are not running a local server but have changed the connection type after creating connections we need to close //existing connections. NetworkComms.Shutdown(); AppendLineToChatHistory("Connection mode has been changed. Existing connections will be closed."); AppendLineToChatHistory(System.Environment.NewLine); } #endregion }