public static void WriteHeader(this WBitStream bitStream, RemoteConnection remoteConnection, uint packetCode)
 {
     bitStream.Write((byte) 83);
     bitStream.Write((ushort) remoteConnection);
     bitStream.Write(packetCode);
     bitStream.Write((byte) 0);
 }
Ejemplo n.º 2
0
        public static RemoteConnection CreateConnection(uint timeout)
        {
            RemoteConnection socket;

            if (connectionStorage.Count > 0)
                socket = connectionStorage.Dequeue();
            else
                socket = new RemoteConnection();

            socket.Connect(endpoint, port);
            return socket;
        }
Ejemplo n.º 3
0
        /**
         * Used by an agent to open a remote connection to another agent. Remote
         * connections are bi-directional and this routine, along with its pair,
         * ConfirmRemoteConnection, are used to resolve all handshaking. Remote
         * connections are used by Agents to work on Tasks for Jobs they're
         * managing on behalf of a LocalConnection.
         */
        public Int32 OpenRemoteConnection( string RequestingAgentName, Int32 ConnectionHandle, ELogFlags LoggingFlags, bool IsAssigned, DateTime AssignedTimestamp )
        {
            // Always wait until the agent is fully initialized
            Initialized.WaitOne();

            Int32 RemoteConnectionHandle = Constants.INVALID;

            CreateTimings( LoggingFlags );
            StartTiming( "OpenRemoteConn-Internal", true );

            // Make sure we only have one thread in here at a time
            lock( Connections )
            {
                // Reject any incoming remote connection if:
                // we're in standalone mode
                // of if the CPU is already busy
                // or if a restart/exit has been requested
                if( ( AgentApplication.Options.EnableStandaloneMode ) ||
                    ( CurrentState == AgentState.Busy ) ||
                    ( AgentIsShuttingDown ) )
                {
                    return Constants.INVALID;
                }
                else
                {
                    // Determine if this is a request for a connection or an assignment
                    if( IsAssigned )
                    {
                        // Make sure the assignment isn't stale
                        if( AssignedTimestamp <= LastAssignedTime )
                        {
                            return Constants.INVALID;
                        }
                        if( Connections.Count != 0 )
                        {
                            // If there are any active jobs running in which the owner is the instigator,
                            // meaning that this agent is connected directly to the instigator, reject
                            foreach( AgentJob Job in ActiveJobs.Values )
                            {
                                if( Job.OwnerIsInstigator )
                                {
                                    return Constants.INVALID;
                                }
                            }

                            // Close any existing remote connections in favor of this incoming one
                            foreach( Connection ExistingConnection in Connections.Values )
                            {
                                if( ExistingConnection is RemoteConnection )
                                {
                                    Log( EVerbosityLevel.Informative, ELogColour.Orange, "[Connection] Detected incoming assigned remote connection, closing existing remote connection" );
                                    Hashtable OldInParameters = null;
                                    Hashtable OldOutParameters = null;
                                    CloseConnection( ExistingConnection.Handle, OldInParameters, ref OldOutParameters );
                                }
                            }
                        }
                    }
                    else
                    {
                        // For connection requests, any other connection at all will cause a rejection
                        if( Connections.Count != 0 )
                        {
                            return Constants.INVALID;
                        }
                    }
                }

                // First, ping the remote host to make sure we can talk to it,
                // starting with verifying the Agent with the Coordinator
                try
                {
                    if( ( Coordinator != null ) &&
                        ( CoordinatorResponding ) &&
                        ( AgentApplication.Options.EnableStandaloneMode == false ) )
                    {
                        AgentInfo RequestingAgentInfo = null;

                        Hashtable RequestedConfiguration = new Hashtable();
                        RequestedConfiguration["Version"] = new Version( 0, 0, 0, 0 );
                        RequestedConfiguration["RequestingAgentName"] = Environment.MachineName;
                        List<AgentInfo> PotentialRemoteAgents = Coordinator.GetAvailableAgents( RequestedConfiguration );
                        foreach( AgentInfo NextAgentInfo in PotentialRemoteAgents )
                        {
                            if( NextAgentInfo.Name == RequestingAgentName )
                            {
                                RequestingAgentInfo = NextAgentInfo;
                                break;
                            }
                        }

                        if( RequestingAgentInfo != null )
                        {
                            Debug.Assert( RequestingAgentInfo.Configuration.ContainsKey( "IPAddress" ) );
                            string RequestingAgentIPAddress = RequestingAgentInfo.Configuration["IPAddress"].ToString();

                            ValidateHostName(RequestingAgentIPAddress);

                            // Now, ping the Agent
                            if( PingRemoteHost( RequestingAgentName, RequestingAgentIPAddress ) )
                            {
                                // Get the remote agent's interface object and wrap it
                                string RemoteAgentURL = String.Format( "tcp://{0}:{1}/SwarmAgent",
                                    RequestingAgentIPAddress,
                                    Properties.Settings.Default.AgentRemotingPort.ToString() );

                                Agent RequestingAgentInterface = ( Agent )Activator.GetObject( typeof( Agent ), RemoteAgentURL );
                                RemoteConnectionInterfaceWrapper WrappedRequestingAgentInterface = new RemoteConnectionInterfaceWrapper( ConnectionHandle, RequestingAgentName, RequestingAgentIPAddress, RequestingAgentInterface );
                                Log( EVerbosityLevel.Informative, ELogColour.Green, "[Connect] Remote agent connection object obtained: " + RequestingAgentName );

                                // Confirm the connection
                                try
                                {
                                    // Send the connection GUID back to the requesting agent as
                                    // confirmation that we've received the request and plan to
                                    // accept it after the handshaking is complete
                                    RemoteConnectionHandle = WrappedRequestingAgentInterface.ConfirmRemoteConnection( ConnectionHandle );
                                    if( RemoteConnectionHandle >= 0 )
                                    {
                                        // Create the new remote connection object
                                        RemoteConnection NewRemoteConnection = new RemoteConnection( ConnectionHandle,
                                                                                                     RequestingAgentInfo,
                                                                                                     WrappedRequestingAgentInterface );

                                        // There are times we want to ensure no new connections are coming online
                                        // where we'll lock the Connections dictionary (see MaintainCache). Note
                                        // that we're already in the lock above...
                                        Connections.Add( ConnectionHandle, NewRemoteConnection );
                                        NewRemoteConnection.CurrentState = ConnectionState.CONNECTED;

                                        // Update our state and ping the coordinator
                                        CurrentState = AgentState.Working;
                                        WorkingFor = RequestingAgentName;
                                        if( IsAssigned )
                                        {
                                            // Successful assignment
                                            LastAssignedTime = AssignedTimestamp;
                                        }
                                        PingCoordinator( true );

                                        Log( EVerbosityLevel.Informative, ELogColour.Green, "[Connect] Remote agent connection confirmed: " + RequestingAgentName );
                                    }
                                }
                                catch( Exception Ex )
                                {
                                    Log( EVerbosityLevel.Informative, ELogColour.Red, "[Connect] OpenRemoteConnection: " + Ex.ToString() );
                                    RemoteConnectionHandle = Constants.ERROR_EXCEPTION;
                                }
                            }
                            else
                            {
                                // Failed to ping, simply return with an appropriate error code
                                Log( EVerbosityLevel.Informative, ELogColour.Red, "[Connect] Failed to ping " + RequestingAgentName + " at " + RequestingAgentIPAddress + " to confirm the remote connection" );
                                RemoteConnectionHandle = Constants.ERROR_CONNECTION_NOT_FOUND;
                            }
                        }
                        else
                        {
                            // Failed to find the Agent info for the requesting Agent, simply return with an appropriate error code
                            Log( EVerbosityLevel.Informative, ELogColour.Red, "[Connect] Failed to lookup " + RequestingAgentName + " in the Coordinator" );
                            RemoteConnectionHandle = Constants.ERROR_CONNECTION_NOT_FOUND;
                        }
                    }
                    else
                    {
                        // Could not contact the Coordinator, simply return with an appropriate error code
                        Log( EVerbosityLevel.Informative, ELogColour.Red, "[Connect] Failed to contact the Coordinator" );
                        RemoteConnectionHandle = Constants.ERROR_CONNECTION_NOT_FOUND;
                    }
                }
                catch( Exception Ex )
                {
                    Log( EVerbosityLevel.Verbose, ELogColour.Red, "[Connect] Remote agent connection failed: " + RequestingAgentName );
                    Log( EVerbosityLevel.Verbose, ELogColour.Red, "[Connect] Exception details: " + Ex.ToString() );
                }

                if( RemoteConnectionHandle < 0 )
                {
                    // If we get here, we have failed to create the connection
                    Log( EVerbosityLevel.Informative, ELogColour.Red, "[Connect] Remote agent connection failed: " + RequestingAgentName );
                }

                StopTiming();
            }
            return RemoteConnectionHandle;
        }
Ejemplo n.º 4
0
        /**
         * Used internally to try to open connections to remote agents
         */
        public Int32 TryOpenRemoteConnection( LocalConnection ParentConnection, AgentInfo RemoteAgentInfo, bool IsAssigned, DateTime AssignedTimestamp, out RemoteConnection OpenedRemoteConnection )
        {
            // Initialize the return values
            Int32 ErrorCode = Constants.INVALID;
            OpenedRemoteConnection = null;

            string RemoteAgentName = RemoteAgentInfo.Name;
            string RemoteAgentIPAddress = RemoteAgentInfo.Configuration["IPAddress"].ToString();

            Log( EVerbosityLevel.Verbose, ELogColour.Green, "[Connect] Trying to open a remote connection to " + RemoteAgentName + " at " + RemoteAgentIPAddress );

            bool bHostNameValid = true;
            try
            {
                ValidateHostName(RemoteAgentIPAddress);
            }
            catch (Exception)
            {
                ErrorCode = Constants.ERROR_EXCEPTION;
                bHostNameValid = false;
            }

            // First, ping the remote host to make sure we can talk to it
            if (bHostNameValid && PingRemoteHost(RemoteAgentName, RemoteAgentIPAddress))
            {
                // Get the new unique handle that this connection will be known by
                Int32 NewConnectionHandle = GetUniqueHandle();

                // Get the remote Agent interface object
                string RemoteAgentURL = String.Format( "tcp://{0}:{1}/SwarmAgent",
                    RemoteAgentIPAddress,
                    Properties.Settings.Default.AgentRemotingPort.ToString() );

                Agent RemoteAgentInterface = ( Agent )Activator.GetObject( typeof( Agent ), RemoteAgentURL );
                RemoteConnectionInterfaceWrapper WrappedRemoteAgentInterface = new RemoteConnectionInterfaceWrapper( NewConnectionHandle, RemoteAgentName, RemoteAgentIPAddress, RemoteAgentInterface );
                Log( EVerbosityLevel.Verbose, ELogColour.Green, "[Connect] Remote agent interface object obtained for " + RemoteAgentName + " at " + RemoteAgentIPAddress );

                // With the interface in hand, try to open a bi-directional connection.

                // Create the new RemoteConnection object and add it to the set
                // of pending connections, waiting for the incoming confirmation
                // which will move it to the active connection set. See
                // ConfirmRemoteConnection for where this happens.
                RemoteConnection NewRemoteConnection = new RemoteConnection( NewConnectionHandle,
                                                                             RemoteAgentInfo,
                                                                             WrappedRemoteAgentInterface );
                PendingConnections.Add( NewConnectionHandle, NewRemoteConnection );

                // Try to open the connection
                try
                {
                    // Send the connection handle and the machine name that will
                    // be used to construct the return URL for bi-directional
                    // connection
                    if( WrappedRemoteAgentInterface.OpenRemoteConnection( Environment.MachineName, NewConnectionHandle, LoggingFlags, IsAssigned, AssignedTimestamp ) >= 0 )
                    {
                        // Successful confirmation, double check that the connection has moved
                        if( PendingConnections.ContainsKey( NewConnectionHandle ) == false )
                        {
                            if( Connections.ContainsKey( NewConnectionHandle ) )
                            {
                                // Connection was successfully moved to the active connection set
                                // thus the bi-directional communication link is established
                                Log( EVerbosityLevel.Informative, ELogColour.Green, "[Connect] Successfully opened a remote connection with " + RemoteAgentName );

                                // Establish the parent-child relationship
                                NewRemoteConnection.Parent = ParentConnection;
                                NewRemoteConnection.Job = ParentConnection.Job;
                                ParentConnection.RemoteChildren.Add( NewConnectionHandle, NewRemoteConnection );
                                ParentConnection.RemoteChildrenSeen++;
                                ParentConnection.ChildrenSeen++;

                                // Update the visualizer indicating that another remote connection is online
                                if( NewRemoteConnection.Job.OwnerIsInstigator )
                                {
                                    AgentApplication.UpdateMachineState( RemoteAgentName, -1, EProgressionState.RemoteConnected );
                                }

                                // Return the new handle for this connection
                                OpenedRemoteConnection = NewRemoteConnection;
                                ErrorCode = Constants.SUCCESS;
                            }
                            else
                            {
                                // Woah. Bad news.
                            }
                        }
                    }
                    else
                    {
                        // The connection failed to open, but didn't timeout and die, so it's likely just busy.
                        // Return with a success code, but with no remote agent, signaling that it's possible
                        // to try this one again later.
                        ErrorCode = Constants.SUCCESS;
                    }
                }
                catch( Exception Ex )
                {
                    Log( EVerbosityLevel.Verbose, ELogColour.Red, "[Connect] Exception: " + RemoteAgentName + ": " + Ex.ToString() );
                    ErrorCode = Constants.ERROR_EXCEPTION;
                }

                if( ErrorCode < 0 )
                {
                    Log( EVerbosityLevel.Verbose, ELogColour.Red, "[Connect] Failed to open a remote connection with " + RemoteAgentName );
                }

                // Regardless of how we got here, make sure the connection has been removed
                // from the pending set (this is a safe call to make anytime)
                PendingConnections.Remove( NewConnectionHandle );
            }
            else
            {
                // Failed to ping, simply return with an appropriate error code
                ErrorCode = Constants.ERROR_CONNECTION_NOT_FOUND;
            }

            return ErrorCode;
        }
Ejemplo n.º 5
0
        public void Open()
        {
            // connect to one of our specified hosts
            baseStream = new RemoteConnection();
            baseStream.Connect(MySqlConnection.CurrentStringBuilder.ServerEndPoint, MySqlConnection.CurrentStringBuilder.ServerPort);

            int maxSinglePacket = 255 * 255 * 255;
            stream = new MySqlStream(baseStream, Encoding, false);

            stream.ResetTimeout((int)Settings.ConnectionTimeout * 1000);

            // read off the welcome packet and parse out it's values
            packet = stream.ReadPacket();
            int protocol = packet.ReadByte();
            string versionString = packet.ReadString();
            version = DBVersion.Parse(versionString);
            if (!version.isAtLeast(5, 0, 0))
                throw new NotSupportedException(Resources.ServerTooOld);
            threadId = packet.ReadInteger(4);
            encryptionSeed = packet.ReadString();

            maxSinglePacket = (256 * 256 * 256) - 1;

            // read in Server capabilities if they are provided
            ClientFlags serverCaps = 0;
            if (packet.HasMoreData)
                serverCaps = (ClientFlags)packet.ReadInteger(2);

            /* New protocol with 16 bytes to describe server characteristics */
            owner.ConnectionCharSetIndex = (int)packet.ReadByte();

            serverStatus = (ServerStatusFlags)packet.ReadInteger(2);

            // Since 5.5, high bits of server caps are stored after status.
            // Previously, it was part of reserved always 0x00 13-byte filler.
            uint serverCapsHigh = (uint)packet.ReadInteger(2);
            serverCaps |= (ClientFlags)(serverCapsHigh << 16);

            packet.Position += 11;
            string seedPart2 = packet.ReadString();
            encryptionSeed += seedPart2;

            string authenticationMethod = "";
            if ((serverCaps & ClientFlags.PLUGIN_AUTH) != 0)
            {
                authenticationMethod = packet.ReadString();
            }
            else
            {
                // Some MySql versions like 5.1, don't give name of plugin, default to native password.
                authenticationMethod = "mysql_native_password";
            }

            // based on our settings, set our connection flags
            SetConnectionFlags(serverCaps);

            packet.Clear();
            packet.WriteInteger((int)connectionFlags, 4);

            packet.WriteInteger(maxSinglePacket, 4);
            packet.WriteByte(8);
            packet.Write(new byte[23]);

            Authenticate(authenticationMethod, false);

            // if we are using compression, then we use our CompressedStream class
            // to hide the ugliness of managing the compression
            if ((connectionFlags & ClientFlags.COMPRESS) != 0)
                stream = new MySqlStream(baseStream, Encoding, true);

            // give our stream the server version we are connected to.
            // We may have some fields that are read differently based
            // on the version of the server we are connected to.
            packet.Version = version;
            stream.MaxBlockSize = maxSinglePacket;
        }
        private void ExecuteInsertGameData(DbGame game)
        {
            game.IsSynchronised = true;
            LocalConnection.Update(game);

            Guid gameId = game.Id;

            List <DbAttackGoal>    goals    = new List <DbAttackGoal>();
            List <DbAttack>        attacks  = new List <DbAttack>();
            List <DbAttackRebound> rebounds = new List <DbAttackRebound>();
            List <DbAttackShot>    shots    = new List <DbAttackShot>();

            MySqlCommand     remoteCommand = new MySqlCommand();
            MySqlTransaction transaction   = RemoteConnection.BeginTransaction();

            remoteCommand.Transaction = transaction;
            try {
                var           localAttacks = LocalConnection;
                string        query        = "SELECT * FROM Attack WHERE GameId = ?";
                SQLiteCommand command      = LocalConnection.CreateCommand(query, gameId);
                attacks = command.ExecuteQuery <DbAttack>();

                string getGoalsQuery = "SELECT ag.* FROM Attack a" +
                                       " JOIN AttackGoal ag" +
                                       " on a.GoalId = ag.Id" +
                                       " WHERE a.GameId = ? AND a.IsSynchronised = 0";
                command = LocalConnection.CreateCommand(getGoalsQuery, gameId);
                goals   = command.ExecuteQuery <DbAttackGoal>();

                string insertGoalsQuery = CreateInsertStatement(goals, "Attack_Goal");

                string insertAttacksQuery = CreateInsertStatement(attacks, "Attack");


                string localShotsQuery = "SELECT ash.* FROM Attack a" +
                                         " join AttackShot ash" +
                                         " on a.Id = ash.AttackId" +
                                         " WHERE a.GameId = ? AND a.IsSynchronised = 0";

                command = LocalConnection.CreateCommand(localShotsQuery, gameId);
                shots   = command.ExecuteQuery <DbAttackShot>();
                string insertShotsQuery = CreateInsertStatement(shots, "Attack_Shot");

                string localReboundsQuery = "SELECT ash.* FROM Attack a" +
                                            " join AttackShot ash " +
                                            " on a.Id = ash.AttackId" +
                                            " WHERE a.GameId = ? AND a.IsSynchronised = 0";

                command  = LocalConnection.CreateCommand(localReboundsQuery, gameId);
                rebounds = command.ExecuteQuery <DbAttackRebound>();
                string insertReboundsQuery = CreateInsertStatement(rebounds, "Attack_Rebound");

                remoteCommand.Connection = RemoteConnection;

                remoteCommand.CommandText = insertGoalsQuery;
                remoteCommand.ExecuteNonQuery();

                remoteCommand.CommandText = insertAttacksQuery;
                remoteCommand.ExecuteNonQuery();

                remoteCommand.CommandText = insertReboundsQuery;
                remoteCommand.ExecuteNonQuery();

                remoteCommand.CommandText = insertShotsQuery;
                remoteCommand.ExecuteNonQuery();

                transaction.Commit();

                goals.ForEach(g => g.IsSynchronised    = true);
                attacks.ForEach(a => a.IsSynchronised  = true);
                rebounds.ForEach(r => r.IsSynchronised = true);
                shots.ForEach(s => s.IsSynchronised    = true);

                LocalConnection.UpdateAll(goals);
                LocalConnection.UpdateAll(attacks);
                LocalConnection.UpdateAll(rebounds);
                LocalConnection.UpdateAll(shots);
            } catch (Exception e)
            {
                transaction.Rollback();
                throw new Exception(e.Message);
            }
        }
 private void Initialize()
 {
     RemoteConnection.Establish();
     CommunicationDirectory.WaitForServiceReady(DiscoveryServiceName, null, DefaultConnectionTimeout);
 }
        public void InsertAttack(IAttack attack)
        {
            bool   isGoal           = attack.Goal != null;
            string attackGoalInsert = string.Empty;

            if (isGoal)
            {
                attackGoalInsert = CreateInsertStatement(attack.Goal, "Attack_Goal");
            }
            bool insertShot = attack.Shots.Count > 0;

            string attackInsert     = CreateInsertStatement(attack.DbAttack, "Attack");
            string attackShotInsert = string.Empty;

            if (insertShot)
            {
                attackShotInsert = CreateInsertStatement(attack.Shots, "Attack_Shot");
            }

            string attackReboundInsert = string.Empty;
            bool   insertRebounds      = attack.Rebounds.Count > 0;

            if (insertRebounds)
            {
                CreateInsertStatement(attack.Rebounds, "Attack_Rebound");
            }

            MySqlCommand command = new MySqlCommand();

            command.Connection = RemoteConnection;

            MySqlTransaction transaction = RemoteConnection.BeginTransaction();

            command.Transaction = transaction;
            try
            {
                if (isGoal)
                {
                    command.CommandText = attackGoalInsert;
                    command.ExecuteNonQuery();
                }
                command.CommandText = attackInsert;
                command.ExecuteNonQuery();
                if (insertShot)
                {
                    command.CommandText = attackShotInsert;
                    command.ExecuteNonQuery();
                }
                if (insertRebounds)
                {
                    command.CommandText = attackReboundInsert;
                    command.ExecuteNonQuery();
                }

                transaction.Commit();
            } catch (Exception e)
            {
                transaction.Rollback();
                Console.WriteLine(e.Message);
            }
        }
Ejemplo n.º 9
0
 private static void OnBeforeChildProcessLaunch(object sender, Chromium.Event.CfxOnBeforeChildProcessLaunchEventArgs e)
 {
     if(e.CommandLine.HasSwitch("type") && e.CommandLine.GetSwitchValue("type") == "renderer") {
         var pipeName = "cfx" + Guid.NewGuid().ToString().Replace("-", string.Empty);
         var pipeIn = PipeFactory.Instance.CreateServerPipeInputStream(pipeName + "si");
         var pipeOut = PipeFactory.Instance.CreateServerPipeOutputStream(pipeName + "so");
         var connection = new RemoteConnection(pipeIn, pipeOut, false);
         connections.Add(connection);
         e.CommandLine.AppendSwitchWithValue("cfxremote", pipeName);
     }
 }
Ejemplo n.º 10
0
        /**
         * Actual work performed by SendMessage happens here
         */
        public Int32 SendMessageInternal(Connection Sender, AgentMessage NewMessage)
        {
            Int32 ErrorCode = Constants.INVALID;

            // We assume the message is valid, but if somewhere below we change our
            // mind, this value will be set to false and we'll eat the message
            bool bMessageIsValid = true;

            // Logic for the setting of the To and From fields (if not already set)
            //
            // All connections sending messages are implicitly sending them to the
            // Instigator of the Job they're working on. Depending on where the
            // message is coming from, we might need to patch up the To field a
            // little bit to ensure it's heading to a Local connection when it
            // needs to be. The only case this applies is when we receive a message
            // from a Remote connection, directed toward a Remote connection, which
            // happens when we get a message from a Remote Agent from an even more
            // Remote connection (i.e. a Job connection on the remote machine):
            //
            // To Local, From Local -> routing of main message and replies are ok
            // To Local, From Remote -> routing of main message and replies are ok
            // To Remote, From Local -> routing of main message and replies are ok
            // To Remote, From Remote -> routing of replies is ok, but the main
            //      message is in trouble if it's not completely handled within the
            //      Agent's ProcessMessages routine. It would be forwarded on to the
            //      To field connection which is Remote and we'd end up bouncing the
            //      message back and forth forever. Need to adjust the To field to
            //      point to the parent of the To connection (which is where it's
            //      intended to go anyway). See further below for where we handle
            //      this case.

            // If the From field is not set, give it the connection handle value by
            // default so that any response message will automatically be routed back
            // to it whether it's the sender or the recipient
            if (NewMessage.From == Constants.INVALID)
            {
                NewMessage.From = Sender.Handle;
            }
            // If the connection used to send the message is Remote, check for the
            // Remote -> Remote case described above
            else if (Sender is RemoteConnection)
            {
                // If the From field is already set, see if we've already registered
                // the connection this message is being sent from
                Connection FromConnection;
                if (!Connections.TryGetValue(NewMessage.From, out FromConnection))
                {
                    // This is a new one - make it an alias for the sender so that any
                    // responses will be directed back via its sending interface
                    RemoteConnection RemoteSender = Sender as RemoteConnection;
                    RemoteSender.Aliases.Add(NewMessage.From);
                    // There are times we want to ensure no new connections are coming online
                    // where we'll lock the Connections dictionary (see MaintainCache)
                    lock ( Connections )
                    {
                        Connections.Add(NewMessage.From, RemoteSender);
                    }
                    FromConnection = RemoteSender;

                    string LogMessage = String.Format("[SendMessage] Added alias for remote connection: {0:X8} is an alias for {1:X8}",
                                                      NewMessage.From,
                                                      Sender.Handle);
                    Log(EVerbosityLevel.Informative, ELogColour.Green, LogMessage);
                }

                // If this is a Remote -> Remote situation, the proper place to route
                // the message to the parent of the remote connection since the Agents
                // generally act as glue between connections
                if (FromConnection is RemoteConnection)
                {
                    Debug.Assert(NewMessage.To != Constants.INVALID);

                    Connection ToConnection;
                    if ((Connections.TryGetValue(NewMessage.To, out ToConnection)) &&
                        (ToConnection is RemoteConnection))
                    {
                        Connection ToConnectionParent = ToConnection.Parent;
                        if (ToConnectionParent != null)
                        {
                            NewMessage.To = ToConnectionParent.Handle;
                        }
                    }
                }
            }

            // If the To field is not set, assign it based on the message type
            if (NewMessage.To == Constants.INVALID)
            {
                // TODO: As we add additional versions, convert to a switch rather than if-else.
                // For now, just use a simple if since we only have one version and a switch is
                // overkill.
                if (NewMessage.Version == ESwarmVersionValue.VER_1_0)
                {
                    // The default is for messages to be ultimately routed to the Instigator
                    // unless the message is one of a certain set of types that route
                    // directly to the connection specified
                    switch (NewMessage.Type)
                    {
                    // These message types need to be routed to the connection specified
                    // either because they are meant to be simple round-trip messages or
                    // because they are sent from within Swarm directly to the connection
                    // and should not be routed anywhere else

                    case EMessageType.QUIT:
                    case EMessageType.PING:
                    case EMessageType.SIGNAL:
                        NewMessage.To = Sender.Handle;
                        break;

                    // These message types need to be routed eventually to the Instigator
                    // connection, which is the ultimate ancestor up the parent chain, so
                    // simply assign the most senior parent we have

                    case EMessageType.INFO:
                    case EMessageType.ALERT:
                    case EMessageType.TIMING:
                    case EMessageType.TASK_REQUEST:
                    case EMessageType.TASK_STATE:
                    case EMessageType.JOB_STATE:
                        // By default, make the sender the recipient for these cases, in
                        // case the parent is no longer active
                        NewMessage.To = Sender.Handle;
                        Connection SenderParent = Sender.Parent;
                        if (SenderParent != null)
                        {
                            // If we have a parent connection and it's active, then
                            // assign it as the recipient
                            if (SenderParent.CurrentState == ConnectionState.CONNECTED)
                            {
                                NewMessage.To = SenderParent.Handle;
                            }
                        }
                        break;

                    // These message types are not expected and are each error cases

                    case EMessageType.NONE:                                                     // Should never be set to this
                    case EMessageType.JOB_SPECIFICATION:                                        // Only used for messages going directly into OpenJob
                    case EMessageType.TASK_REQUEST_RESPONSE:                                    // Should always have the To field set already
                    default:
                        Log(EVerbosityLevel.Informative,ELogColour.Orange,"SendMessage: Invalid message type received, ignoring " + NewMessage.Type.ToString());
                        break;
                    }

                    // If still no assigned To field, consider it an error
                    if (NewMessage.To == Constants.INVALID)
                    {
                        Log(EVerbosityLevel.Informative, ELogColour.Orange, "SendMessage: No proper recipient found, ignoring " + NewMessage.Type.ToString());
                        bMessageIsValid = false;
                    }
                }
            }

            // If the message remains valid, post it to the queue
            if (bMessageIsValid)
            {
                lock ( MessageQueueLock )
                {
                    Debug.Assert(NewMessage != null);
                    MessageQueueSM.Enqueue(NewMessage);

                    string NewLogMessage = String.Format("Step 1 of N for message: ({0:X8} -> {1:X8}), {2}, Message Count {3} (Agent)",
                                                         NewMessage.To,
                                                         NewMessage.From,
                                                         NewMessage.Type,
                                                         MessageQueueSM.Count);

                    Log(EVerbosityLevel.SuperVerbose, ELogColour.Green, NewLogMessage);

                    MessageQueueReady.Set();
                }
                ErrorCode = Constants.SUCCESS;
            }
            else
            {
                Log(EVerbosityLevel.Informative, ELogColour.Orange, String.Format("SendMessage: Discarded message \"{0}\"", NewMessage.Type));
            }

            return(ErrorCode);
        }
Ejemplo n.º 11
0
        /**
         * Takes messages off the internal message queue and handles them by either
         * sending responses, forwarding the message on, or processing it internally
         */
        private void ProcessMessagesThreadProc()
        {
            // A response message queue used to send messages back to the one which sent it
            Queue <AgentMessage> ResponseMessageQueue = new Queue <AgentMessage>();

            while (AgentHasShutDown == false)
            {
                StartTiming("ProcessMessage-Internal", true);

                lock ( MessageQueueLock )
                {
                    // Swap the SM and PM message queue to keep things moving at full speed
                    Queue <AgentMessage> Temp = MessageQueuePM;
                    MessageQueuePM = MessageQueueSM;
                    MessageQueueSM = Temp;
                }

                // Process all messages currently in the queue
                while (MessageQueuePM.Count > 0)
                {
                    Debug.Assert(ResponseMessageQueue.Count == 0);

                    // Get and process the next message
                    AgentMessage NextMessage = MessageQueuePM.Dequeue();
                    Debug.Assert(NextMessage != null);

                    bool bMessageHandled = false;
                    switch (NextMessage.Type)
                    {
                    case EMessageType.SIGNAL:
                    {
                        if (NextMessage is DisconnectionSignalMessage)
                        {
                            // Mark the connection as inactive
                            DisconnectionSignalMessage DisconnectMessage = NextMessage as DisconnectionSignalMessage;
                            Log(EVerbosityLevel.Informative,ELogColour.Green,String.Format("[CloseConnection] Connection disconnected {0:X8}",DisconnectMessage.ConnectionToDisconnect.Handle));
                            DisconnectMessage.ConnectionToDisconnect.CurrentState     = ConnectionState.DISCONNECTED;
                            DisconnectMessage.ConnectionToDisconnect.DisconnectedTime = DateTime.UtcNow;
                        }

                        // Signal the message and move on
                        AgentSignalMessage SignalMessage = NextMessage as AgentSignalMessage;
                        SignalMessage.ResetEvent.Set();
                        bMessageHandled = true;
                    }
                    break;

                    case EMessageType.TIMING:
                    {
                        Connection FromConnection;
                        if ((Connections.TryGetValue(NextMessage.From,out FromConnection)))
                        {
                            Connection ToConnection;
                            if ((Connections.TryGetValue(NextMessage.To,out ToConnection)) &&
                                (ToConnection is LocalConnection))
                            {
                                // Handle message
                                AgentTimingMessage TimingMessage = NextMessage as AgentTimingMessage;
                                AgentApplication.UpdateMachineState(MachineNameFromConnection(FromConnection),TimingMessage.ThreadNum,TimingMessage.State);
                                bMessageHandled = true;
                            }
                        }
                    }
                    break;

                    case EMessageType.TASK_REQUEST:
                    {
                        // Look up the requesting connection
                        Debug.Assert(NextMessage.From != Constants.INVALID);
                        Connection RequestingConnection;
                        if (Connections.TryGetValue(NextMessage.From,out RequestingConnection))
                        {
                            // Look up the specified Job
                            AgentJob JobToAskForTasks = RequestingConnection.Job;
                            if (JobToAskForTasks != null)
                            {
                                // If we get a valid response back, add it to the queue
                                AgentTaskRequestResponse Response = JobToAskForTasks.GetNextTask(RequestingConnection);
                                if (Response != null)
                                {
                                    ResponseMessageQueue.Enqueue(Response);

                                    // Specifications and releases are always handled here, but
                                    // reservations are special in that we will send a reservation
                                    // back to local connections but we'll need to make sure the
                                    // message continues on to remote connections.
                                    if ((Response.ResponseType == ETaskRequestResponseType.SPECIFICATION) ||
                                        (Response.ResponseType == ETaskRequestResponseType.RELEASE) ||
                                        ((Response.ResponseType == ETaskRequestResponseType.RESERVATION) &&
                                         (JobToAskForTasks.Owner is LocalConnection)))
                                    {
                                        bMessageHandled = true;
                                    }
                                }
                            }
                            else
                            {
                                // Unable to find the Job, just send back a release message
                                Log(EVerbosityLevel.Verbose,ELogColour.Orange,"[ProcessMessage] Unable to find Job for Task Request; may have been closed");
                                //ResponseMessageQueue.Enqueue( new AgentTaskRequestResponse( RequestingConnection.Job.JobGuid,
                                //															ETaskRequestResponseType.RELEASE ) );
                                bMessageHandled = true;
                            }
                        }
                        else
                        {
                            // Unable to find the connection, swallow the request
                            Log(EVerbosityLevel.Verbose,ELogColour.Orange,"[ProcessMessage] Unable to find owning Connection for Task Request");
                            bMessageHandled = true;
                        }
                    }
                    break;

                    case EMessageType.TASK_STATE:
                    {
                        // Look up the sending connection
                        Debug.Assert(NextMessage.From != Constants.INVALID);
                        Connection SendingConnection;
                        if ((Connections.TryGetValue(NextMessage.From,out SendingConnection)) &&
                            (SendingConnection.Job != null))
                        {
                            // Look up the specified Job
                            AgentJob UpdatedJob;
                            if (ActiveJobs.TryGetValue(SendingConnection.Job.JobGuid,out UpdatedJob))
                            {
                                AgentTaskState UpdatedTaskState = NextMessage as AgentTaskState;
                                UpdatedJob.UpdateTaskState(UpdatedTaskState);

                                if (UpdatedJob.Owner is LocalConnection)
                                {
                                    // If the Task state change is of a type potentially interesting to
                                    // the Instigator, return it
                                    switch (UpdatedTaskState.TaskState)
                                    {
                                    case EJobTaskState.TASK_STATE_INVALID:
                                    case EJobTaskState.TASK_STATE_COMPLETE_SUCCESS:
                                    case EJobTaskState.TASK_STATE_COMPLETE_FAILURE:
                                        // For these message types, allow the message to continue on
                                        break;

                                    default:
                                        // Nothing to do otherwise, mark the message as handled
                                        bMessageHandled = true;
                                        break;
                                    }
                                }
                                else
                                {
                                    // Always send messages on for remote connections
                                }
                            }
                            else
                            {
                                // Unable to find the Job, swallow the request
                                Log(EVerbosityLevel.Verbose,ELogColour.Orange,"[ProcessMessage] Unable to find Job for Task Request");
                                bMessageHandled = true;
                            }
                        }
                        else
                        {
                            // Unable to find the connection, swallow the request
                            Log(EVerbosityLevel.Verbose,ELogColour.Orange,"[ProcessMessage] Unable to find owning Connection for Task Request");
                            bMessageHandled = true;
                        }
                    }
                    break;
                    }

                    // If the message was not handled completely, send it on
                    if (bMessageHandled == false)
                    {
                        // Look up who the message is being sent to and make sure they're
                        // still active and if not, ignore the message
                        Connection Recipient;
                        Debug.Assert(NextMessage.To != Constants.INVALID);
                        if (Connections.TryGetValue(NextMessage.To,out Recipient))
                        {
                            if (Recipient is LocalConnection)
                            {
                                // If the recipient is local, place it in the proper queue
                                // and signal that a message is ready
                                LocalConnection LocalRecipient = Recipient as LocalConnection;
                                lock (LocalRecipient.MessageQueue)
                                {
                                    LocalRecipient.MessageQueue.Enqueue(NextMessage);

                                    string NewLogMessage = String.Format("Step 2 of 4 for message: ({0:X8} -> {1:X8}), {2}, Message Count {3} (Local Connection)",
                                                                         NextMessage.To,
                                                                         NextMessage.From,
                                                                         NextMessage.Type,
                                                                         LocalRecipient.MessageQueue.Count);

                                    Log(EVerbosityLevel.SuperVerbose,ELogColour.Green,NewLogMessage);

                                    LocalRecipient.MessageAvailableSignal();
                                }
                            }
                            else
                            {
                                Debug.Assert(Recipient is RemoteConnection);

                                // If the recipient is remote, send the message via SendMessage
                                // unless the message is a Task being sent back, which is sent
                                // via the dedicated Task API
                                RemoteConnection RemoteRecipient = Recipient as RemoteConnection;
                                if (NextMessage is AgentTaskSpecification)
                                {
                                    // All new Tasks are sent via the dedicated Task API
                                    AgentTaskSpecification TaskSpecification = NextMessage as AgentTaskSpecification;

                                    Hashtable RemoteInParameters = new Hashtable();
                                    RemoteInParameters["Version"]       = ESwarmVersionValue.VER_1_0;
                                    RemoteInParameters["Specification"] = TaskSpecification;
                                    Hashtable RemoteOutParameters = null;

                                    Int32 Error = RemoteRecipient.Interface.AddTask(RemoteRecipient.Handle,RemoteInParameters,ref RemoteOutParameters);
                                    if (Error >= 0)
                                    {
                                        // Perhaps we should be sending an accept message back?
                                    }
                                    else
                                    {
                                        AgentTaskState UpdateMessage;
                                        if (Error == Constants.ERROR_CONNECTION_DISCONNECTED)
                                        {
                                            // Special case of the connection dropping while we're adding the
                                            // task, say it's been killed to requeue
                                            UpdateMessage = new AgentTaskState(TaskSpecification.JobGuid,
                                                                               TaskSpecification.TaskGuid,
                                                                               EJobTaskState.TASK_STATE_KILLED);
                                        }
                                        else
                                        {
                                            // All other error cases will be rejections
                                            UpdateMessage = new AgentTaskState(TaskSpecification.JobGuid,
                                                                               TaskSpecification.TaskGuid,
                                                                               EJobTaskState.TASK_STATE_REJECTED);
                                        }
                                        AgentJob Job;
                                        if (ActiveJobs.TryGetValue(TaskSpecification.JobGuid,out Job))
                                        {
                                            Job.UpdateTaskState(UpdateMessage);
                                        }
                                    }
                                }
                                else
                                {
                                    // All standard messages are sent via the SendMessage API
                                    Hashtable RemoteInParameters = new Hashtable();
                                    RemoteInParameters["Version"] = ESwarmVersionValue.VER_1_0;
                                    RemoteInParameters["Message"] = NextMessage;
                                    Hashtable RemoteOutParameters = null;

                                    RemoteRecipient.Interface.SendMessage(NextMessage.To,RemoteInParameters,ref RemoteOutParameters);
                                }

                                string NewLogMessage = String.Format("Step 2 of 2 for message: ({0:X8} -> {1:X8}), {2}, (Remote Connection)",
                                                                     NextMessage.To,
                                                                     NextMessage.From,
                                                                     NextMessage.Type);

                                Log(EVerbosityLevel.SuperVerbose,ELogColour.Green,NewLogMessage);
                            }
                        }
                        else
                        {
                            Log(EVerbosityLevel.Informative,ELogColour.Orange,"ProcessMessage: Message sent to invalid connection, ignoring: " + NextMessage.Type.ToString());
                        }
                    }

                    // If there are any responses to the message, send them
                    if (ResponseMessageQueue.Count > 0)
                    {
                        foreach (AgentMessage NextResponse in ResponseMessageQueue)
                        {
                            // For each one of the messages, set the routing fields properly
                            NextResponse.To   = NextMessage.From;
                            NextResponse.From = NextMessage.To;

                            // And then queue the message back up immediately
                            MessageQueuePM.Enqueue(NextResponse);
                        }
                        ResponseMessageQueue.Clear();
                    }
                }

                StopTiming();

                // Wait for a message to become available and once unlocked, swap the queues
                // and check for messages to process. Set a timeout, so we'll wake up every
                // now and then to check for a quit signal at least
                MessageQueueReady.WaitOne(500);
            }
        }
Ejemplo n.º 12
0
 internal CfxRemoteCallContext(RemoteConnection connection, int threadId)
 {
     this.connection = connection;
     ThreadId        = threadId;
 }
Ejemplo n.º 13
0
		public MySqlStream(RemoteConnection baseStream, Encoding encoding, bool compress)
			: this(encoding)
		{
			this.connection = baseStream;
		}