Пример #1
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);
            }
        }
        private void regularMsgReceived(SpreadMessage pMessage)
        {
            //TODO: test if selfDiscarded messages would be actually sent back by spread deamon
            extRegularMessageHandler(pMessage.Sender.ToString(), pMessage.Data);

            //			if (pMessage.Sender == me) {
            //				SyncLock.Pulse();
            //			}
        }
Пример #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);
        }
Пример #4
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;
                }
            }
        }
Пример #5
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);
        }
        //------------------------------ Private ----------------------------------------
        private void send(string pToGroup, string pMessage, bool pIsSelfDiscard)
        {
            SpreadMessage _spreadMsg = new SpreadMessage();

            _spreadMsg.IsAgreed      = true;            //  _spreadMsg.IsSafe = true;
            _spreadMsg.IsSelfDiscard = pIsSelfDiscard;
            _spreadMsg.AddGroup(pToGroup);
            _spreadMsg.Data = System.Text.Encoding.ASCII.GetBytes(pMessage);

            // Send msg and wait for response
            try {
                connection.Multicast(_spreadMsg);
                //				if ( ! pIsSelfDiscard) {
                //					SyncLock.Wait();
                //				}
            }
            catch (Exception _ex) {
                T.LogStatus("Multicast Exception: " + _ex);
                throw;
            }
        }
Пример #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;
        }
Пример #8
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);
        }
Пример #9
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());
            }
        }
Пример #10
0
        private void display(SpreadMessage msg)
        {
            try {
                if (msg.IsRegular)
                {
                    T.LogDebug("Received a ");
                    if (msg.IsUnreliable)
                    {
                        T.LogDebug("UNRELIABLE");
                    }
                    else if (msg.IsReliable)
                    {
                        T.LogDebug("RELIABLE");
                    }
                    else if (msg.IsFifo)
                    {
                        T.LogDebug("FIFO");
                    }
                    else if (msg.IsCausal)
                    {
                        T.LogDebug("CAUSAL");
                    }
                    else if (msg.IsAgreed)
                    {
                        T.LogDebug("AGREED");
                    }
                    else if (msg.IsSafe)
                    {
                        T.LogDebug("SAFE");
                    }
                    T.LogDebug(" message.");

                    T.LogDebug("Sent by  " + msg.Sender + ".");

                    T.LogDebug("Type is " + msg.Type + ".");

                    if (msg.EndianMismatch == true)
                    {
                        T.LogDebug("There is an endian mismatch.");
                    }
                    else
                    {
                        T.LogDebug("There is no endian mismatch.");
                    }

                    SpreadGroup[] groups = msg.Groups;
                    T.LogDebug("To " + groups.Length + " groups.");

                    byte[] data = msg.Data;
                    T.LogDebug("The data is " + data.Length + " bytes.");

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

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

                        T.LogDebug("Received a REGULAR membership.");
                        T.LogDebug("For group " + info.Group + ".");
                        T.LogDebug("With " + groups.Length + " members.");
                        T.LogDebug("I am member " + msg.Type + ".");
                        for (int i = 0; i < groups.Length; i++)
                        {
                            T.LogDebug("  " + groups[i]);
                        }

                        T.LogDebug("Group ID is " + info.GroupID);

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

                    T.LogDebug("Sent by  " + msg.Sender + ".");

                    T.LogDebug("Type is " + msg.Type + ".");

                    if (msg.EndianMismatch == true)
                    {
                        T.LogDebug("There is an endian mismatch.");
                    }
                    else
                    {
                        T.LogDebug("There is no endian mismatch.");
                    }

                    SpreadGroup[] groups = msg.Groups;
                    T.LogDebug("To " + groups.Length + " groups.");

                    byte[] data = msg.Data;
                    T.LogDebug("The data is " + data.Length + " bytes.");

                    T.LogDebug("The message is: " + System.Text.Encoding.ASCII.GetString(data));
                }
                else
                {
                    T.LogDebug("Message is of unknown type: " + msg.ServiceType);
                }
            }
            catch (Exception e) {
                T.LogDebug("Exception: " + e);
                Environment.Exit(1);
            }
        }
Пример #11
0
 private void membershipMsgReceived(SpreadMessage pMessage)
 {
     extMembershipMessageHandler(pMessage.Sender.ToString(), pMessage.Data);
 }