Beispiel #1
0
 public void messageReceived(SpreadMessage msg)
 {
     if (this.InvokeRequired)
     {
         AddTextDel del = new AddTextDel(this.messageReceived);
         object[] args = new object[] { msg };
         this.Invoke(del, args);
     }
     else
         this.DisplayMessage(msg);
 }
Beispiel #2
0
        private void AsyncReceive(IAsyncResult ar)
        {
            bool readAsync = false;
            do
            {
                if (receiveState == INIT_RECEIVE)
                {
                    buffer = new byte[48];
                    receivedLength = 0;
                    receiveState = HEADER_RECEIVE;
                    receivedMessage = new SpreadMessage();
                }
                else
                {
                    if (receivedLength != buffer.Length)
                    {
                        int size = stream.EndRead(ar);
                        if (size == 0)
                            throw new SpreadException("Connection closed while reading");
                        receivedLength += size;
                    }
                    if (receivedLength == buffer.Length)
                        switch (receiveState)
                        {
                            case HEADER_RECEIVE:
                                byte[] header = buffer;

                                int headerIndex = 0;
                                // Get service type.
                                ////////////////////
                                receivedMessage.ServiceType = toInt(header, headerIndex);
                                headerIndex += 4;

                                // Get the sender.
                                //////////////////
                                ///
                                receivedMessage.Sender = toGroup(header, headerIndex);
                                headerIndex += MAX_GROUP_NAME;

                                // Get the number of groups.
                                ////////////////////////////
                                numGroups = toInt(header, headerIndex);
                                headerIndex += 4;

                                // Get the hint/type.
                                /////////////////////
                                int hint = toInt(header, headerIndex);
                                headerIndex += 4;

                                // Get the data length.
                                ///////////////////////
                                int dataLen = toInt(header, headerIndex);
                                headerIndex += 4;

                                // Does the header need to be flipped?
                                // (Checking for a daemon server endian-mismatch)
                                /////////////////////////////////////////////////

                                if (sameEndian(receivedMessage.ServiceType) == false)
                                {
                                    // Flip them.
                                    /////////////
                                    receivedMessage.ServiceType = flip(receivedMessage.ServiceType);
                                    numGroups = flip(numGroups);
                                    dataLen = flip(dataLen);

                                    // The daemon endian-mismatch.
                                    //////////////////////////////
                                    daemonEndianMismatch = true;
                                }
                                else
                                {
                                    // The daemon endian-mismatch.
                                    //////////////////////////////
                                    daemonEndianMismatch = false;
                                }

                                receivedMessage.Data = new byte[dataLen];

                                // Is this a regular message?
                                /////////////////////////////
                                if (receivedMessage.IsRegular || receivedMessage.IsReject)
                                {
                                    // Does the hint need to be flipped?
                                    // (Checking for a sender endian-mismatch)
                                    //////////////////////////////////////////
                                    if (sameEndian(hint) == false)
                                    {
                                        hint = flip(hint);
                                        receivedMessage.EndianMismatch = true;
                                    }
                                    else
                                    {
                                        receivedMessage.EndianMismatch = false;
                                    }

                                    // Get the type from the hint.
                                    //////////////////////////////
                                    hint = clearEndian(hint);
                                    hint >>= 8;
                                    hint &= 0x0000FFFF;
                                    receivedMessage.Type = (short)hint;
                                }
                                else
                                {
                                    // This is not a regular message.
                                    /////////////////////////////////
                                    receivedMessage.Type = -1;
                                    receivedMessage.EndianMismatch = false;
                                }
                                if (receivedMessage.IsReject)
                                {
                                    buffer = new byte[4];
                                    receivedLength = 0;
                                    receiveState = OLD_TYPE_RECEIVE;
                                }
                                else
                                {
                                    buffer = new byte[numGroups * MAX_GROUP_NAME];
                                    receivedLength = 0;
                                    receiveState = GROUPS_RECEIVE;
                                }
                                break;
                            case OLD_TYPE_RECEIVE:
                                int oldType = toInt(buffer, 0);
                                if (sameEndian(receivedMessage.ServiceType) == false)
                                    oldType = flip(oldType);
                                receivedMessage.ServiceType = (SpreadMessage.REJECT_MESS | oldType);
                                buffer = new byte[numGroups * MAX_GROUP_NAME];
                                receivedLength = 0;
                                receiveState = GROUPS_RECEIVE;
                                break;
                            case GROUPS_RECEIVE:
                                // Clear the endian type.
                                /////////////////////////
                                receivedMessage.ServiceType = clearEndian(receivedMessage.ServiceType);

                                // Get the groups from the buffer.
                                //////////////////////////////////
                                for (int bufferIndex = 0; bufferIndex < buffer.Length; bufferIndex += MAX_GROUP_NAME)
                                {
                                    // Translate the name into a group and add it to the vector.
                                    ////////////////////////////////////////////////////////////
                                    receivedMessage.AddGroup(toGroup(buffer, bufferIndex));
                                }
                                buffer = receivedMessage.Data;
                                receivedLength = 0;
                                receiveState = DATA_RECEIVE;
                                break;
                            case DATA_RECEIVE:
                                // Is it a membership message?
                                //////////////////////////////
                                if (receivedMessage.IsMembership)
                                {
                                    // Create a membership info object.
                                    ///////////////////////////////////
                                    receivedMessage.membershipInfo = new MembershipInfo(this, receivedMessage, daemonEndianMismatch);

                                    // Is it a regular membership message?
                                    //////////////////////////////////////
                                    if (receivedMessage.membershipInfo.IsRegularMembership)
                                    {
                                        // Find which of these groups is the local connection.
                                        //////////////////////////////////////////////////////
                                        receivedMessage.Type = (short)receivedMessage.groups.IndexOf(PrivateGroup);
                                    }
                                }
                                else
                                {
                                    // There's no membership info.
                                    //////////////////////////////
                                    receivedMessage.membershipInfo = null;
                                }
                                if (OnRegularMessage != null && receivedMessage.IsRegular)
                                    OnRegularMessage(receivedMessage);
                                else if (OnMembershipMessage != null && receivedMessage.IsMembership)
                                    OnMembershipMessage(receivedMessage);
                                else
                                {
                                    lock (rsynchro)
                                    {
                                        messageWaiting = true;
                                        Monitor.Pulse(rsynchro);
                                        Monitor.Wait(rsynchro);
                                    }
                                }
                                buffer = new byte[48];
                                receivedLength = 0;
                                receiveState = HEADER_RECEIVE;
                                receivedMessage = new SpreadMessage();
                                break;
                        }
                }
                try
                {
                    // read sync if data available
                    while (stream.DataAvailable && receivedLength < buffer.Length)
                    {
                        int size = stream.Read(buffer, receivedLength, buffer.Length - receivedLength);
                        if (size == 0)
                            throw new SpreadException("Connection closed while reading");
                        receivedLength += size;
                    }
                    if (receivedLength != buffer.Length)
                    {
                        // no more data - continue async read
                        stream.BeginRead(buffer, receivedLength, buffer.Length - receivedLength, new AsyncCallback(AsyncReceive), null);
                        readAsync = true;
                    }
                }
                catch (Exception e)
                {
                    throw new SpreadException("BeginRead(): " + e);
                }
            } while (!readAsync);
        }
Beispiel #3
0
 // Receives numMessages new messages.
 /////////////////////////////////////
 /**
  * Receives <code>numMessages</code> messages on the connection and returns them in an array.
  * If there are not <code>numMessages</code> messages waiting, the call will block until there are
  * enough messages available.
  *
  * @param  numMessages  the number of messages to receive
  * @return an array of messages
  * @throws  SpreadException  if there is no connection or if there is any error reading the messages
  */
 public SpreadMessage[] Receive(int numMessages)
 {
     // Allocate the messages array.
     ///////////////////////////////
     SpreadMessage[] messages = new SpreadMessage[numMessages];
     for (int i = 0; i < numMessages; i++)
     {
         messages[i] = Receive();
     }
     // Return the array.
     ////////////////////
     return messages;
 }
Beispiel #4
0
        // Sends the message.
        /////////////////////
        /**
             * mcasts a message.  The message will be sent to all the groups specified in
             * the message.
             *
             * @param  message  the message to mcast
             * @throws  SpreadException  if there is no connection or if there is any error sending the message
             */
        public void Multicast(SpreadMessage message)
        {
            // Check if we're connected.
            ////////////////////////////
            if (connected == false)
            {
                throw new SpreadException("Not connected.");
            }

            // The groups this message is going to.
            ///////////////////////////////////////
            SpreadGroup[] groups = message.Groups;

            // The message data.
            ////////////////////
            byte[] data = message.Data;

            // Calculate the total number of bytes.
            ///////////////////////////////////////
            int numBytes = 16;  // serviceType, numGroups, type/hint, dataLen
            numBytes += MAX_GROUP_NAME;  // private group
            numBytes += (MAX_GROUP_NAME * groups.Length);  // groups

            if (numBytes + data.Length > MAX_MESSAGE_LENGTH)
            {
                throw new SpreadException("Message is too long for a Spread Message");
            }
            // Allocate the send buffer.
            ////////////////////////////
            byte[] buffer = new byte[numBytes];
            int bufferIndex = 0;

            // The service type.
            ////////////////////
            toBytes(message.ServiceType, buffer, bufferIndex);
            bufferIndex += 4;

            // The private group.
            /////////////////////
            toBytes(group, buffer, bufferIndex);
            bufferIndex += MAX_GROUP_NAME;

            // The number of groups.
            ////////////////////////
            toBytes(groups.Length, buffer, bufferIndex);
            bufferIndex += 4;

            // The service type and hint.
            /////////////////////////////
            toBytes(((int)message.Type << 8) & 0x00FFFF00, buffer, bufferIndex);
            bufferIndex += 4;

            // The data length.
            ///////////////////
            toBytes(data.Length, buffer, bufferIndex);
            bufferIndex += 4;

            // The group names.
            ///////////////////
            for (int i = 0; i < groups.Length; i++)
            {
                toBytes(groups[i], buffer, bufferIndex);
                bufferIndex += MAX_GROUP_NAME;
            }

            try
            {
                stream.Write(buffer, 0, buffer.Length);
                stream.Write(data, 0, data.Length);
            }
            catch (Exception e)
            {
                throw new SpreadException("Write(): " + e.ToString());
            }
        }
Beispiel #5
0
 // Sends the array of messages.
 ///////////////////////////////
 /**
  * mcasts an array of messages.  Each message will be sent to all the groups specified in
  * the message.
  *
  * @param  messages  the messages to mcast
  * @throws  SpreadException  if there is no connection or if there is any error sending the messages
  */
 public void Multicast(SpreadMessage[] messages)
 {
     // Go through the array.
     ////////////////////////
     for (int i = 0; i < messages.Length; i++)
     {
         // Send this message.
         /////////////////////
         Multicast(messages[i]);
     }
 }
Beispiel #6
0
        // Disconnects from the spread daemon.
        //////////////////////////////////////
        /**
         * Disconnects the connection to the daemon.  Nothing else should be done with this connection
         * after disconnecting it.
         *
         * @throws  SpreadException  if there is no connection or there is an error disconnecting
         * @see  SpreadConnection#connect(InetAddress, int, String, boolean, boolean)
         */
        public void Disconnect()
        {
            // Check if we're connected.
            ////////////////////////////
            if (connected == false)
            {
                throw new SpreadException("Not connected.");
            }

            // Get a new message.
            /////////////////////
            SpreadMessage killMessage = new SpreadMessage();

            // Send it to our private group.
            ////////////////////////////////
            killMessage.AddGroup(group);

            // Set the service type.
            ////////////////////////
            killMessage.ServiceType = SpreadMessage.KILL_MESS;

            // Send the message.
            ////////////////////
            Multicast(killMessage);

            // Close the socket.
            ////////////////////
            try
            {
                socket.Close();
            }
            catch (Exception e)
            {
                throw new SpreadException("close(): " + e);
            }
        }
Beispiel #7
0
        public void Leave()
        {
            // Check if we can leave.
            /////////////////////////
            if (connection == null)
            {
                throw new SpreadException("No group to leave.");
            }

            // Get a new message.
            /////////////////////
            SpreadMessage leaveMessage = new SpreadMessage();

            // Set the group we're sending to.
            //////////////////////////////////
            leaveMessage.AddGroup(name);

            // Set the service type.
            ////////////////////////
            leaveMessage.ServiceType = SpreadMessage.LEAVE_MESS;

            // Send the message.
            ////////////////////
            connection.Multicast(leaveMessage);

            // No longer connected.
            ///////////////////////
            connection = null;
        }
Beispiel #8
0
        public void Join(SpreadConnection c, string groupName)
        {
            // Check if this group has already been joined.
            ///////////////////////////////////////////////
            if (this.connection != null)
            {
                throw new SpreadException("Already joined.");
            }

            // Set member variables.
            ////////////////////////
            this.connection = c;
            this.name = groupName;

            // Error check the name.
            ////////////////////////
            byte[] bytes;
            try
            {
                bytes = System.Text.Encoding.ASCII.GetBytes(name);
            }
            catch (Exception e)
            {
                throw new SpreadException("Encoding not supported: " + e);
            }
            for (int i = 0; i < bytes.Length; i++)
            {
                // Make sure the byte (character) is within the valid range.
                ////////////////////////////////////////////////////////////
                if ((bytes[i] < 36) || (bytes[i] > 126))
                {
                    throw new SpreadException("Illegal character in group name.");
                }
            }

            // Get a new message.
            /////////////////////
            SpreadMessage joinMessage = new SpreadMessage();

            // Set the group we're sending to.
            //////////////////////////////////
            joinMessage.AddGroup(name);

            // Set the service type.
            ////////////////////////
            joinMessage.ServiceType = SpreadMessage.JOIN_MESS;

            // Send the message.
            ////////////////////
            connection.Multicast(joinMessage);
        }
Beispiel #9
0
        // Constructor.
        ///////////////
        internal MembershipInfo(SpreadConnection connection, SpreadMessage message, bool daemonEndianMismatch)
        {
            // Set local variables.
            ///////////////////////
            this.serviceType = message.ServiceType;
            this.group = message.Sender;
            this.members = message.Groups;

            // Is this a regular membership message.
            ////////////////////////////////////////
            if (IsRegularMembership)
            {
                // Extract the groupID.
                ///////////////////////
                int dataIndex = 0;
                int[] id = new int[3];
                id[0] = SpreadConnection.toInt(message.Data, dataIndex);
                dataIndex += 4;
                id[1] = SpreadConnection.toInt(message.Data, dataIndex);
                dataIndex += 4;
                id[2] = SpreadConnection.toInt(message.Data, dataIndex);
                dataIndex += 4;
                // Endian-flip?
                ///////////////
                if (daemonEndianMismatch)
                {
                    id[0] = SpreadConnection.flip(id[0]);
                    id[1] = SpreadConnection.flip(id[1]);
                    id[2] = SpreadConnection.flip(id[2]);
                }

                // Create the group ID.
                ///////////////////////
                this.groupID = new GroupID(id[0], id[1], id[2]);

                // Get the number of groups.
                ////////////////////////////
                int numGroups = SpreadConnection.toInt(message.Data, dataIndex);
                if (daemonEndianMismatch)
                {
                    numGroups = SpreadConnection.flip(numGroups);
                }
                dataIndex += 4;

                // Get the groups.
                //////////////////
                this.groups = new SpreadGroup[numGroups];
                for (int i = 0; i < numGroups; i++)
                {
                    this.groups[i] = connection.toGroup(message.Data, dataIndex);
                    dataIndex += SpreadConnection.MAX_GROUP_NAME;
                }
            }
        }
Beispiel #10
0
        private void DisplayMessage(SpreadMessage msg)
        {
            try
            {
                richTextBox1.AppendText("--------------\n");
                string str = null;
                if (msg.IsRegular)
                {
                    str="Received a ";
                    if (msg.IsUnreliable)
                        str+="UNRELIABLE";
                    else if (msg.IsReliable)
                        str+="RELIABLE";
                    else if (msg.IsFifo)
                        str+="FIFO";
                    else if (msg.IsCausal)
                        str+="CAUSAL";
                    else if (msg.IsAgreed)
                        str+="AGREED";
                    else if (msg.IsSafe)
                        str+="SAFE";
                    str+=" message.";
                    richTextBox1.AppendText(str+"\n");
                    //richTextBox1.AppendText("Type is " + msg.Type + ".\n");
                    richTextBox1.AppendText("Sent by  " + msg.Sender + ".");

                    //if (msg.EndianMismatch == true)
                    //    richTextBox1.AppendText("There is an endian mismatch.\n");
                    //else
                    //    richTextBox1.AppendText("There is no endian mismatch.\n");

                    SpreadGroup[] groups = msg.Groups;
                    richTextBox1.AppendText("To " + groups.Length + " groups.\n");

                    byte[] data = msg.Data;
                    richTextBox1.AppendText("The Size is " + data.Length + " bytes.\n");

                    richTextBox1.AppendText("The message is: " + System.Text.Encoding.ASCII.GetString(data)+"\n");
                }
                else if (msg.IsMembership)
                {
                    MembershipInfo info = msg.MembershipInfo;

                    if (info.IsRegularMembership)
                    {
                        SpreadGroup[] groups = msg.Groups;

                        richTextBox1.AppendText("Received a REGULAR membership.\n");
                        richTextBox1.AppendText("For group " + info.Group + ", ID=" + info.GroupID.ToString() + "\n");
                        richTextBox1.AppendText("with " + groups.Length + " members:\n");
                        //richTextBox1.AppendText("Members: ");
                        for (int i = 0; i < groups.Length; i++)
                            richTextBox1.AppendText("  " + groups[i]);
                        richTextBox1.AppendText("\n");

                        richTextBox1.AppendText("Due to ");
                        if (info.IsCausedByJoin)
                        {
                            richTextBox1.AppendText("the JOIN of " + info.Joined + "."+"\n");
                        }
                        else if (info.IsCausedByLeave)
                        {
                            richTextBox1.AppendText("the LEAVE of " + info.Left + "."+"\n");
                        }
                        else if (info.IsCausedByDisconnect)
                        {
                            richTextBox1.AppendText("the DISCONNECT of " + info.Disconnected + "."+"\n");
                        }
                        else if (info.IsCausedByNetwork)
                        {
                            SpreadGroup[] stayed = info.Stayed;
                            richTextBox1.AppendText("NETWORK change."+"\n");
                            richTextBox1.AppendText("VS set has " + stayed.Length + " members:"+"\n");
                            for (int i = 0; i < stayed.Length; i++)
                                richTextBox1.AppendText("  " + stayed[i]+"\n");
                        }
                    }
                    else if (info.IsTransition)
                    {
                        richTextBox1.AppendText("Received a TRANSITIONAL membership for group " + info.Group+"\n");
                    }
                    else if (info.IsSelfLeave)
                    {
                        richTextBox1.AppendText("Received a SELF-LEAVE message for group " + info.Group+"\n");
                    }
                }
                else if (msg.IsReject)
                {
                    // Received a Reject message
                    richTextBox1.AppendText("Received a ");
                    if (msg.IsUnreliable)
                        richTextBox1.AppendText("UNRELIABLE");
                    else if (msg.IsReliable)
                        richTextBox1.AppendText("RELIABLE");
                    else if (msg.IsFifo)
                        richTextBox1.AppendText("FIFO");
                    else if (msg.IsCausal)
                        richTextBox1.AppendText("CAUSAL");
                    else if (msg.IsAgreed)
                        richTextBox1.AppendText("AGREED");
                    else if (msg.IsSafe)
                        richTextBox1.AppendText("SAFE");

                    richTextBox1.AppendText(" REJECTED message."+"\n");

                    richTextBox1.AppendText("Sent by  " + msg.Sender + ".");

                    richTextBox1.AppendText("Type is " + msg.Type + "."+"\n");

                    //if (msg.EndianMismatch == true)
                    //    richTextBox1.AppendText("There is an endian mismatch."+"\n");
                    //else
                    //    richTextBox1.AppendText("There is no endian mismatch."+"\n");

                    SpreadGroup[] groups = msg.Groups;
                    richTextBox1.AppendText("To " + groups.Length + " groups."+"\n");

                    byte[] data = msg.Data;
                    richTextBox1.AppendText("The Size is " + data.Length + " bytes."+"\n");

                    richTextBox1.AppendText("The message is: " + System.Text.Encoding.ASCII.GetString(data)+"\n");
                }
                else
                {
                    richTextBox1.AppendText("Message is of unknown type: " + msg.ServiceType+"\n");
                }
                richTextBox1.AppendText("\n");
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);

            }
        }
Beispiel #11
0
 private void button3_Click(object sender, EventArgs e)
 {
     SpreadMessage msg;
     try
     {
         msg = new SpreadMessage();
         msg.IsSafe = true;
         msg.AddGroup(comboBox1.Text);
         msg.Data = System.Text.Encoding.ASCII.GetBytes(textBox3.Text);
         // Send it
         connection.Multicast(msg);
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.Message);
     }
 }