예제 #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);
            }
        }
예제 #2
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;
            }
        }
예제 #4
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;
        }
예제 #5
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);
        }