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); }
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); }
// 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; }
// 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()); } }
// 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]); } }
// 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); } }
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; }
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); }
// 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; } } }
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); } }
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); } }