// 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(); // } }
// 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); }
// 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; } } }
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; } }
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; }
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); }
// 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()); } }
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); } }
private void membershipMsgReceived(SpreadMessage pMessage) { extMembershipMessageHandler(pMessage.Sender.ToString(), pMessage.Data); }