예제 #1
0
      internal static Transaction Create(bool reply, int transactionId, int taskNumber, int errorCode,
                                         byte[] transactionData, out Transaction replyTo)
      {
         replyTo = null;
         try
         {
            // Figure out what type is associated with the given ID number.
            // The default for unknown ID values is the base class.
            Type transType;
            if (s_idMap.TryGetValue(transactionId, out transType) == false)
            {
               s_log.InfoFormat("Unknown Transaction ID {0}", transactionId);
               transType = typeof(Transaction);
            }

            // Create an instance of that Type.
            Transaction transaction = (Transaction)Activator.CreateInstance(transType);

            // Configure the base instance with the fields we have.
            transaction.Configure(reply, transactionId, taskNumber, errorCode);

            // Have the transaction parse its own details.
            transaction.ParseObjects(transactionData);

            // Look up the transaction that this is a reply to.
            replyTo = Transaction.GetSourceTransaction(taskNumber);

            // Return the finished transaction.
            return transaction;
         }
         catch (Exception e)
         {
            s_log.ErrorFormat("Exception generating Transaction ID {0}: {1}", transactionId, e.Message);
            return null;
         }
      }
예제 #2
0
 public TransactionEventArgs(Transaction incomingTransaction, Transaction replyToTransaction)
 {
    m_incomingTransaction = incomingTransaction;
    m_replyToTransaction = replyToTransaction;
 }
예제 #3
0
      internal Status SendTransaction(Transaction transaction)
      {
         //TODO: Check socket state for being disconnected.

         // Validate transaction
         if (transaction == null)
         {
            s_log.ErrorFormat("Cannot send null package.");
            return Status.Failure;
         }

         // Enqueue Package.
         lock (m_sendQueue)
         {
            m_sendQueue.Enqueue(transaction);
         }

         // Notify other thread.
         m_sendEvent.Set();

         // Start other thread if necessary.
         if (m_sendThread == null)
         {
            m_sendThread = new Thread(SendLoop);
            m_sendThread.Name = "Transaction Sending";
            m_sendThread.Start();
         }

         return Status.Success;
      }
예제 #4
0
      public static Status TryParse(ref List<byte> potentialTransaction,
                                    out Transaction outTransaction,
                                    out Transaction replyToTransaction)
      {
         outTransaction = null;
         replyToTransaction = null;

         s_log.InfoFormat("Parsing Transaction from {0} bytes.", potentialTransaction.Count);
         DataUtils.DumpBytes("Parsing received bytes:", potentialTransaction);

         byte[] transArray = potentialTransaction.ToArray();
         int arrayIndex = 0;

         try
         {
            // Parse bytes enough to run the appropriate creator,
            // followed by a generic data object parser for the details.
            // Then a factory should be able to make the right transaction.
            int transactionClass = DataUtils.ReadShort(transArray, ref arrayIndex);
            bool reply = (transactionClass != 0); // If class is "0", this is not a reply.

            int transactionId = DataUtils.ReadShort(transArray, ref arrayIndex);
            int taskNumber = DataUtils.ReadLong(transArray, ref arrayIndex);
            int errorCode = DataUtils.ReadLong(transArray, ref arrayIndex);
            int dataLength1 = DataUtils.ReadLong(transArray, ref arrayIndex); // Total transaction size
            int dataLength2 = DataUtils.ReadLong(transArray, ref arrayIndex); // Size of this part

            s_log.InfoFormat("Parsed header for Transaction ID {0}", transactionId);

            if (errorCode != 0)
               s_log.ErrorFormat("Error code: {0}", errorCode);

            if (dataLength1 != dataLength2)
            {
               s_log.ErrorFormat("Multi-part transactions not supported! ({0},{1})", dataLength1, dataLength2);
               return Status.Failure;
            }

            // Read the exact amount of bytes specified by the header.
            byte[] transactionData = DataUtils.ReadLength(transArray, ref arrayIndex, dataLength1);

            // Shuttle off the Transaction data to the factory for more specific parsing.
            outTransaction = TransactionFactory.Create(reply, transactionId, taskNumber, errorCode,
                                                       transactionData, out replyToTransaction);

            // Any additional data in the array needs to be left in the original list.
            potentialTransaction = DataUtils.CopyRemainder(transArray, ref arrayIndex);

            return Status.Success;
         }
         catch (Exception e)
         {
            s_log.ErrorFormat("Exception parsing Transaction: {0}", e.Message);
            return Status.Failure;
         }
      }
예제 #5
0
      private void HandleGotUserInfo(Transaction userInfoTransaction)
      {
         s_log.InfoFormat("Received GetUserInfo response.");
         if (userInfoTransaction == null)
            return;

         Message msg = (Message)ObjectFactory.FindObject(userInfoTransaction.Objects, typeof(Message));
         Nick nick = (Nick)ObjectFactory.FindObject(userInfoTransaction.Objects, typeof(Nick));

         if (msg == null || nick == null)
            return;

         string formattedMsg = String.Format("*** User Details for {0}: ***\n\n{1}",
                                             nick.Value.Value, msg.Value.Value);

         // Raise the event.
         OnUserInfoReceived(new UserInfoEventArgs(formattedMsg));
      }
예제 #6
0
      /// <summary>
      /// Handler for a Transaction response listing the complete userlist.
      /// NOTE: It is not the responsibility of the Server class to decide how
      /// the response data is displayed to the user.  That is, do NOT
      /// automatically make this a chat message!
      /// </summary>
      private void HandleGetUserList(Transaction userList)
      {
         s_log.InfoFormat("Received userlist response.");
         if (userList == null)
            return;

         // Create a new userlist from scratch.
         List<User> addList = new List<User>();

         foreach (HotlineObject obj in userList.Objects)
         {
            UserListEntry ule = obj as UserListEntry;
            if (ule == null)
               continue;

            User user = new User(ule);
            addList.Add(user);
         }

         // Send the new full user list as a non-delta list of "adds".
         OnUserListUpdate(new UserListUpdateEventArgs(addList, null, false));
      }
예제 #7
0
      private void HandleLoginResponse(Transaction loginResponse)
      {
         s_log.InfoFormat("Received login response: {0}", loginResponse.ErrorCode);

         if (loginResponse.ErrorCode != 0)
         {
            OnDisconnected(new DisconnectedEventArgs("Login failed."));
            Disconnect();
         }
         else
         {
            // If the error code is zero, the login was succesful.
            // Some servers return a ServerName object, so print it if found.
            ServerName serverName = (ServerName)ObjectFactory.FindObject(loginResponse.Objects, typeof(ServerName));
            if (ChatReceived != null)
            {
               if (serverName == null)
               {
                  OnConnected(new ConnectedEventArgs("*** Login complete. ***"));
               }
               else
               {
                  string text = String.Format("*** Server Name: {0} ***", serverName.Value.Value);
                  OnConnected(new ConnectedEventArgs(text));
               }
            }
         }
      }
예제 #8
0
 private void HandleError(Transaction inTransaction)
 {
    s_log.InfoFormat("Received error transaction: {0}", inTransaction.ErrorCode);
    ErrorMessage errMsg = (ErrorMessage)ObjectFactory.FindObject(inTransaction.Objects, typeof(ErrorMessage));
    string text = String.Format("*** Error: {0} ***", errMsg.Value.Value);
    OnChatReceived(new ChatReceivedEventArgs(text));
 }
예제 #9
0
      public Status SendTransaction(Transaction tx)
      {
         if (m_channel == null)
         {
            s_log.ErrorFormat("Not connected to server.");
            return Status.Failure;
         }

         if (tx == null)
         {
            s_log.ErrorFormat("Null transaction provided.  Not sending.");
            return Status.Failure;
         }

         // Returns Success if the transaction was successfully queued.
         return m_channel.SendTransaction(tx);
      }
예제 #10
0
 public static void AddActiveTransaction(int taskNumber, Transaction transaction)
 {
    lock (s_activeTransactions)
    {
       s_activeTransactions.Add(taskNumber, transaction);
    }
 }