Beispiel #1
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();
            }
        }