Beispiel #1
0
        /// <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);
        }
        /// <inheritdoc />
        protected override void EstablishConnectionSpecific()
        {
            if (btClient == null)
            {
                ConnectSocket();
            }

            //We should now be able to set the connectionInfo localEndPoint
            var localEndPoint = btClient.Client.LocalEndPoint as BluetoothEndPoint;

            localEndPoint = new BluetoothEndPoint(localEndPoint.Address, ConnectionInfo.RemoteBTEndPoint.Service, localEndPoint.Port);

            NetworkComms.UpdateConnectionReferenceByEndPoint(this, ConnectionInfo.RemoteEndPoint, localEndPoint);
            ConnectionInfo.UpdateLocalEndPointInfo(localEndPoint);

            btClient.Client.ReceiveBufferSize = NetworkComms.MaxReceiveBufferSizeBytes;
            btClient.Client.SendBufferSize    = NetworkComms.SendBufferSizeBytes;

            //We are going to be using the networkStream quite a bit so we pull out a reference once here
            btClientNetworkStream = btClient.GetStream();

            //Start listening for incoming data
            StartIncomingDataListen();

            //If the application layer protocol is enabled we handshake the connection
            if (ConnectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled)
            {
                ConnectionHandshake();
            }
            else
            {
                //If there is no handshake we can now consider the connection established
                TriggerConnectionEstablishDelegates();

                //Trigger any connection setup waits
                connectionSetupWait.Set();
            }
        }
Beispiel #3
0
        /// <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);
        }
Beispiel #4
0
        /// <summary>
        /// Performs a connection handshake with the remote end of the connection.
        /// Exchanges network identifier and any listener whose IPAddress matches the connection localEndPoint IPAddress.
        /// </summary>
        protected void ConnectionHandshake()
        {
            if (ConnectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Disabled)
            {
                throw new CommunicationException("Attempted to perform handshake on connection where the application protocol has been disabled.");
            }

            //If we are server side and we have just received an incoming connection we need to return a connection identifier
            //This id will be used in all future connections from this machine
            if (ConnectionInfo.ServerSide)
            {
                if (NetworkComms.LoggingEnabled)
                {
                    NetworkComms.Logger.Debug("Waiting for client connnectionInfo from " + ConnectionInfo);
                }

                //Wait for the client to send its identification
#if NET2
                if (!connectionSetupWait.WaitOne(NetworkComms.ConnectionEstablishTimeoutMS, false))
#else
                if (!connectionSetupWait.WaitOne(NetworkComms.ConnectionEstablishTimeoutMS))
#endif
                { throw new ConnectionSetupException("Timeout waiting for client connectionInfo with " + ConnectionInfo + ". Connection created at " + ConnectionInfo.ConnectionCreationTime.ToString("HH:mm:ss.fff") + ", its now " + DateTime.Now.ToString("HH:mm:ss.f")); }

                if (connectionSetupException)
                {
                    if (NetworkComms.LoggingEnabled)
                    {
                        NetworkComms.Logger.Debug("Connection setup exception. ServerSide with " + ConnectionInfo + ", " + connectionSetupExceptionStr);
                    }
                    throw new ConnectionSetupException("ServerSide. " + connectionSetupExceptionStr);
                }

                //Trigger the connection establish delegates before replying to the connection establish
                TriggerConnectionEstablishDelegates();
            }
            else
            {
                //If we are client side part of the handshake is to inform the server of a potential local listener
                //Get a list of existing listeners
                List <EndPoint> existingLocalListeners = null;
                if (ConnectionInfo.LocalEndPoint is IPEndPoint)
                {
                    existingLocalListeners = Connection.ExistingLocalListenEndPoints(ConnectionInfo.ConnectionType, new IPEndPoint(ConnectionInfo.LocalIPEndPoint.Address, 0));
                }
#if NET4 || NET35
                else if (ConnectionInfo.LocalEndPoint is InTheHand.Net.BluetoothEndPoint)
                {
                    existingLocalListeners = Connection.ExistingLocalListenEndPoints(ConnectionInfo.ConnectionType, new InTheHand.Net.BluetoothEndPoint(ConnectionInfo.LocalBTEndPoint.Address, ConnectionInfo.LocalBTEndPoint.Service));
                }
#endif

                //Check to see if we have a local listener for matching the local endpoint address
                //If we are client side we use this local listener in our reply to the server
                EndPoint selectedExistingLocalListenerEndPoint = null;
                if (existingLocalListeners != null &&                                // If we have a suitable local listener
                    existingLocalListeners.Count > 0 &&                              // If we have a suitable local listener
                    !existingLocalListeners.Contains(ConnectionInfo.RemoteEndPoint)) //If this is not an application loop back connection
                {
                    selectedExistingLocalListenerEndPoint = (existingLocalListeners.Contains(ConnectionInfo.LocalEndPoint) ? ConnectionInfo.LocalEndPoint : existingLocalListeners[0]);
                }

                //During this exchange we may note an update local listen port
                if (NetworkComms.LoggingEnabled)
                {
                    NetworkComms.Logger.Debug("Sending connnectionInfo to " + ConnectionInfo);
                }

                //Pull-out the parameters we want to send to the server
                //Doing it here rather than all in the following Send Object line keeps it clearer
                EndPoint selectedLocalListenerEndPoint = (selectedExistingLocalListenerEndPoint != null ? selectedExistingLocalListenerEndPoint : ConnectionInfo.LocalEndPoint);
                bool     connectable = selectedExistingLocalListenerEndPoint != null;

                //As the client we initiated the connection we now forward our local node identifier to the server
                //If we are listening we include our local listen port as well
                SendObject(Enum.GetName(typeof(ReservedPacketType), ReservedPacketType.ConnectionSetup), new ConnectionInfo(ConnectionInfo.ConnectionType,
                                                                                                                            NetworkComms.NetworkIdentifier,
                                                                                                                            selectedLocalListenerEndPoint,
                                                                                                                            connectable),
                           NetworkComms.InternalFixedSendReceiveOptions);

                //Wait here for the server end to return its own identifier
#if NET2
                if (!connectionSetupWait.WaitOne(NetworkComms.ConnectionEstablishTimeoutMS, false))
#else
                if (!connectionSetupWait.WaitOne(NetworkComms.ConnectionEstablishTimeoutMS))
#endif
                { throw new ConnectionSetupException("Timeout waiting for server connnectionInfo from " + ConnectionInfo + ". Connection created at " + ConnectionInfo.ConnectionCreationTime.ToString("HH:mm:ss.fff") + ", its now " + DateTime.Now.ToString("HH:mm:ss.f")); }

                //If we are client side we can update the localEndPoint for this connection to reflect what the remote end might see if we are also listening
                if (selectedExistingLocalListenerEndPoint != null && selectedExistingLocalListenerEndPoint != ConnectionInfo.LocalEndPoint)
                {
                    //We should now be able to set the connectionInfo localEndPoint
                    NetworkComms.UpdateConnectionReferenceByEndPoint(this, ConnectionInfo.RemoteEndPoint, selectedExistingLocalListenerEndPoint);
                    ConnectionInfo.UpdateLocalEndPointInfo(selectedExistingLocalListenerEndPoint);
                }

                if (connectionSetupException)
                {
                    if (NetworkComms.LoggingEnabled)
                    {
                        NetworkComms.Logger.Debug("Connection setup exception. ClientSide with " + ConnectionInfo + ", " + connectionSetupExceptionStr);
                    }
                    throw new ConnectionSetupException("ClientSide. " + connectionSetupExceptionStr);
                }

                //Trigger the connection establish delegates once the server has replied to the connection establish
                TriggerConnectionEstablishDelegates();
            }
        }
        /// <inheritdoc />
        protected override void EstablishConnectionSpecific()
        {
#if WINDOWS_PHONE || NETFX_CORE
            if (socket == null)
            {
                ConnectSocket();
            }

            //For the local endpoint
            var localEndPoint = new IPEndPoint(IPAddress.Parse(socket.Information.LocalAddress.CanonicalName.ToString()), int.Parse(socket.Information.LocalPort));

            //We should now be able to set the connectionInfo localEndPoint
            NetworkComms.UpdateConnectionReferenceByEndPoint(this, ConnectionInfo.RemoteIPEndPoint, localEndPoint);
            ConnectionInfo.UpdateLocalEndPointInfo(localEndPoint);

            //Set the outgoing buffer size
            socket.Control.OutboundBufferSizeInBytes = (uint)NetworkComms.SendBufferSizeBytes;
#else
            if (tcpClient == null)
            {
                ConnectSocket();
            }

            //We should now be able to set the connectionInfo localEndPoint
            NetworkComms.UpdateConnectionReferenceByEndPoint(this, ConnectionInfo.RemoteIPEndPoint, (IPEndPoint)tcpClient.Client.LocalEndPoint);
            ConnectionInfo.UpdateLocalEndPointInfo((IPEndPoint)tcpClient.Client.LocalEndPoint);

            if (SSLOptions.SSLEnabled)
            {
                ConfigureSSLStream();
            }
            else
            {
                //We are going to be using the networkStream quite a bit so we pull out a reference once here
                connectionStream = tcpClient.GetStream();
            }

            //When we tell the socket/client to close we want it to do so immediately
            //this.tcpClient.LingerState = new LingerOption(false, 0);

            //We need to set the keep alive option otherwise the connection will just die at some random time should we not be using it
            //NOTE: This did not seem to work reliably so was replaced with the keepAlive packet feature
            //this.tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

            tcpClient.ReceiveBufferSize = NetworkComms.MaxReceiveBufferSizeBytes;
            tcpClient.SendBufferSize    = NetworkComms.SendBufferSizeBytes;

            //This disables the 'nagle algorithm'
            //http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.nodelay.aspx
            //Basically we may want to send lots of small packets (<200 bytes) and sometimes those are time critical (e.g. when establishing a connection)
            //If we leave this enabled small packets may never be sent until a suitable send buffer length threshold is passed. i.e. BAD
            tcpClient.NoDelay        = true;
            tcpClient.Client.NoDelay = true;
#endif

            //Start listening for incoming data
            StartIncomingDataListen();

            //If the application layer protocol is enabled we handshake the connection
            if (ConnectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled)
            {
                ConnectionHandshake();
            }
            else
            {
                //If there is no handshake we can now consider the connection established
                TriggerConnectionEstablishDelegates();

                //Trigger any connection setup waits
                connectionSetupWait.Set();
            }

#if !WINDOWS_PHONE && !NETFX_CORE
            //Once the connection has been established we may want to re-enable the 'nagle algorithm' used for reducing network congestion (apparently).
            //By default we leave the nagle algorithm disabled because we want the quick through put when sending small packets
            if (EnableNagleAlgorithmForNewConnections)
            {
                tcpClient.NoDelay        = false;
                tcpClient.Client.NoDelay = false;
            }
#endif
        }
Beispiel #6
0
        /// <summary>
        /// Internal constructor for UDP connections
        /// </summary>
        /// <param name="connectionInfo"></param>
        /// <param name="defaultSendReceiveOptions"></param>
        /// <param name="level"></param>
        /// <param name="listenForIncomingPackets"></param>
        /// <param name="existingConnection"></param>
        internal UDPConnection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions, UDPOptions level, bool listenForIncomingPackets, UDPConnection existingConnection = null)
            : base(connectionInfo, defaultSendReceiveOptions)
        {
            if (connectionInfo.ConnectionType != ConnectionType.UDP)
            {
                throw new ArgumentException("Provided connectionType must be UDP.", "connectionInfo");
            }

            if (NetworkComms.LoggingEnabled)
            {
                NetworkComms.Logger.Trace("Creating new UDPConnection with " + connectionInfo);
            }

            if (connectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Disabled && level != UDPOptions.None)
            {
                throw new ArgumentException("If the application layer protocol has been disabled the provided UDPOptions can only be UDPOptions.None.");
            }

            ConnectionUDPOptions = level;

            if (listenForIncomingPackets && existingConnection != null)
            {
                throw new Exception("Unable to listen for incoming packets if an existing client has been provided. This is to prevent possible multiple accidently listens on the same client.");
            }

            if (existingConnection == null)
            {
                if (connectionInfo.RemoteIPEndPoint.Address.Equals(IPAddress.Any) || connectionInfo.RemoteIPEndPoint.Address.Equals(IPAddress.IPv6Any))
                {
#if WINDOWS_PHONE || NETFX_CORE
                    //We are creating an unbound endPoint, this is currently the rogue UDP sender and listeners only
                    socket = new DatagramSocket();

                    if (listenForIncomingPackets)
                    {
                        socket.MessageReceived += socket_MessageReceived;
                    }

                    socket.BindEndpointAsync(new HostName(ConnectionInfo.LocalIPEndPoint.Address.ToString()), ConnectionInfo.LocalIPEndPoint.Port.ToString()).AsTask().Wait();
#else
                    //We are creating an unbound endPoint, this is currently the rogue UDP sender and listeners only
                    udpClient = new UdpClientWrapper(new UdpClient(ConnectionInfo.LocalIPEndPoint));
#endif
                }
                else
                {
                    //If this is a specific connection we link to a default end point here
                    isIsolatedUDPConnection = true;

#if WINDOWS_PHONE || NETFX_CORE
                    if (ConnectionInfo.LocalEndPoint == null ||
                        (ConnectionInfo.LocalIPEndPoint.Address == IPAddress.Any && connectionInfo.LocalIPEndPoint.Port == 0) ||
                        (ConnectionInfo.LocalIPEndPoint.Address == IPAddress.IPv6Any && connectionInfo.LocalIPEndPoint.Port == 0))
                    {
                        socket = new DatagramSocket();

                        if (listenForIncomingPackets)
                        {
                            socket.MessageReceived += socket_MessageReceived;
                        }

                        socket.ConnectAsync(new HostName(ConnectionInfo.RemoteIPEndPoint.Address.ToString()), ConnectionInfo.RemoteIPEndPoint.Port.ToString()).AsTask().Wait();
                    }
                    else
                    {
                        socket = new DatagramSocket();

                        if (listenForIncomingPackets)
                        {
                            socket.MessageReceived += socket_MessageReceived;
                        }

                        EndpointPair pair = new EndpointPair(new HostName(ConnectionInfo.LocalIPEndPoint.Address.ToString()), ConnectionInfo.LocalIPEndPoint.Port.ToString(),
                                                             new HostName(ConnectionInfo.RemoteIPEndPoint.Address.ToString()), ConnectionInfo.RemoteIPEndPoint.Port.ToString());

                        socket.ConnectAsync(pair).AsTask().Wait();
                    }
#else
                    if (ConnectionInfo.LocalEndPoint == null)
                    {
                        udpClient = new UdpClientWrapper(new UdpClient(ConnectionInfo.RemoteEndPoint.AddressFamily));
                    }
                    else
                    {
                        udpClient = new UdpClientWrapper(new UdpClient(ConnectionInfo.LocalIPEndPoint));
                    }

                    //By calling connect we discard packets from anything other then the provided remoteEndPoint on our localEndPoint
                    udpClient.Connect(ConnectionInfo.RemoteIPEndPoint);
#endif
                }

#if !WINDOWS_PHONE && !NETFX_CORE
                //NAT traversal does not work in .net 2.0
                //Mono does not seem to have implemented AllowNatTraversal method and attempting the below method call will throw an exception
                //if (Type.GetType("Mono.Runtime") == null)
                //Allow NAT traversal by default for all udp clients
                //    udpClientThreadSafe.AllowNatTraversal(true);

                if (listenForIncomingPackets)
                {
                    StartIncomingDataListen();
                }
#endif
            }
            else
            {
                if (!existingConnection.ConnectionInfo.RemoteIPEndPoint.Address.Equals(IPAddress.Any))
                {
                    throw new Exception("If an existing udpClient is provided it must be unbound to a specific remoteEndPoint");
                }

#if WINDOWS_PHONE || NETFX_CORE
                //Using an exiting client allows us to send from the same port as for the provided existing connection
                this.socket = existingConnection.socket;
#else
                //Using an exiting client allows us to send from the same port as for the provided existing connection
                this.udpClient = existingConnection.udpClient;
#endif
            }

            IPEndPoint localEndPoint;
#if WINDOWS_PHONE || NETFX_CORE
            localEndPoint = new IPEndPoint(IPAddress.Parse(socket.Information.LocalAddress.DisplayName.ToString()), int.Parse(socket.Information.LocalPort));
#else
            localEndPoint = udpClient.LocalIPEndPoint;
#endif

            //We can update the localEndPoint so that it is correct
            if (!ConnectionInfo.LocalEndPoint.Equals(localEndPoint))
            {
                //We should now be able to set the connectionInfo localEndPoint
                NetworkComms.UpdateConnectionReferenceByEndPoint(this, ConnectionInfo.RemoteIPEndPoint, localEndPoint);
                ConnectionInfo.UpdateLocalEndPointInfo(localEndPoint);
            }
        }