/// <summary> /// Fragments the given message into a number of smaller messages for sending over the network /// </summary> /// <returns>An array of network mesages belonging which are the fragments of the given message</returns> public NetworkMessage[] Fragment(NetworkMessage message) { List<byte[]> fragments = new List<byte[]>(); NetworkMessage[] messages; int numRead = 1; using (MemoryStream ms = new MemoryStream(message.GzData)) { while (numRead > 0) { byte[] readBytes = new byte[FragmentSize]; numRead = ms.Read(readBytes, 0, FragmentSize); if (numRead > 0) { if (numRead < FragmentSize) { byte[] fragData = new byte[numRead]; Array.Copy(readBytes, fragData, numRead); fragments.Add(fragData); } else { fragments.Add(readBytes); } } } messages = new NetworkMessage[fragments.Count]; for (int i = 0; i < fragments.Count; i++) { NetworkMessage fragmentMessage = new NetworkMessage(message.SenderID, message.DestinationID, message.MessageID, message.Type, fragments[i], i, fragments.Count, message.Lifetime); messages[i] = fragmentMessage; } } return messages; }
/// <summary> /// Stores a message fragment, if all the fragments of a message are stored MessageDefragmented event is fired /// </summary> public void Defragment(NetworkMessage message) { NetworkMessage[] buffer; List<int> fragmentsNeededList = null; Debug.WriteLine("Fragment: " + message.FragmentNumber + " size: " + message.Data.Length); if (incomingFragmentBuffer.ContainsKey(message.MessageID)) { // first fragment has already been received so add to existing buffer buffer = (NetworkMessage[])incomingFragmentBuffer[message.MessageID]; } else { // This is the first fragement of a message received, so create a new buffer buffer = new NetworkMessage[message.FragmentTotal]; messageFragmentsRequired[message.MessageID] = new List<int>(message.FragmentTotal); for (int i = 0; i < message.FragmentTotal; i++) { ((List<int>) messageFragmentsRequired[message.MessageID]).Add(i); } messageExpiryTimes.Add(new TickGuid(message.MessageID, message.Lifetime)); } fragmentsNeededList = (List<int>) messageFragmentsRequired[message.MessageID]; buffer[message.FragmentNumber] = message; incomingFragmentBuffer[message.MessageID] = buffer; fragmentsNeededList.Remove(message.FragmentNumber); if (fragmentsNeededList.Count == 0) { byte[] messageData; using (MemoryStream ms = new MemoryStream()) { for (int j = 0; j < buffer.Length; j++) { ms.Write(buffer[j].Data, 0, buffer[j].Data.Length); } messageData = new byte[ms.Length]; messageData = ms.ToArray(); } MessageDefragmented(this, new MessageDefragmentedEventArgs(buffer[0].DestinationID, buffer[0].SenderID, buffer[0].MessageID, messageData)); incomingFragmentBuffer.Remove(message.MessageID); messageFragmentsRequired.Remove(message.MessageID); } else { startMessageLifetimeTimer(); } }
private void MessageLifetimeTimerTimeout(object ob) { Debug.WriteLine("MessageLifetimeTimerTimeout happened"); lock (messageExpiryTimes) { List<TickGuid> expired = messageExpiryTimes.FindAll(earlierThanNow); Guid[] guids = new Guid[expired.Count]; foreach (TickGuid item in expired) { // check if it's fragments being sent in messageCache if (outgoingFragments.ContainsKey(item.id)) { Debug.WriteLine(String.Format("Expiring from fragment store {0}", item.id)); outgoingFragments.Remove(item.id); } if (incomingFragmentBuffer.ContainsKey(item.id)) { NetworkMessage[] messageFragments = (NetworkMessage[])incomingFragmentBuffer[item.id]; for (int i = 0; i < messageFragments.Length; i++) { if (messageFragments[i] == null) { Debug.WriteLine(String.Format("Need to request resend of message {0} fragment {1}", item.id, i)); NetworkMessage message = new NetworkMessage(localID, Guid.Empty, Guid.NewGuid(), NetworkMessageType.FragmentRequest, item.id.ToByteArray(), i, 1, 5000); sendMessage(message); } } } messageExpiryTimes.Remove(item); //Schedule next time to try messageExpiryTimes.Add(new TickGuid(item.id, 5000)); } } if (messageExpiryTimes.Count == 0) { if (messageLifetimeTimer != null) { messageLifetimeTimer.Dispose(); messageLifetimeTimer = null; } } }
public MessageEventArgs(NetworkMessage message) { this.gzData = message.GzData; this.senderID = message.SenderID; this.destinationID = message.DestinationID; }
public void FireMessageReceived(NetworkMessage message) { if (this.MessageReceived != null) { MessageReceived(this, new MessageEventArgs(message)); } }
private void sendMessage(NetworkMessage message) { SendQueue.Enqueue(message); messageToSendEvent.Set(); }
private void ReceiveThread() { try { udpReceiveClient = new UdpClient(port, AddressFamily.InterNetwork); IPEndPoint receivedFrom = new IPEndPoint(IPAddress.Any, 0); byte[] receivedBytes = new byte[100000]; while (keepRecieving) { receivedBytes = udpReceiveClient.Receive(ref receivedFrom); int receivedLength = receivedBytes.Length; if (receivedLength > 36) { NetworkMessage message = new NetworkMessage(receivedBytes); Debug.WriteLine(String.Format("Received {0} from {1}", message.Type, receivedFrom)); switch (message.Type) { case NetworkMessageType.Message: ReceiveQueue.Enqueue(message); messageReceivedEvent.Set(); break; case NetworkMessageType.DirectRequest: if (message.DestinationID == this.localID) { Debug.WriteLine("Received direct request for " + message.DestinationID.ToString()); NetworkMessage replyMessage = new NetworkMessage(this.localID, message.SenderID, Guid.NewGuid(), NetworkMessageType.DirectReply, message.Data, 1, 1, 50000); sendMessage(replyMessage); } break; case NetworkMessageType.DirectReply: if (message.DestinationID == localID) { Debug.WriteLine("Recieved reply for " + message.DestinationID.ToString()); MessageRequest messageReq = new MessageRequest(); messageReq.Address = receivedFrom.Address; messageReq.MessageID = new Guid(message.Data); messageReq.Fragment = -1; directUdpTargets.Enqueue(messageReq); directUdpEvent.Set(); } break; case NetworkMessageType.FragmentRequest: if (message.SenderID != localID) { Guid messageRequestID = new Guid(message.Data); Debug.WriteLine(String.Format("Request for resend of message {0} fragment {1}", messageRequestID, message.FragmentNumber)); MessageRequest fragmentReq = new MessageRequest(); fragmentReq.Address = receivedFrom.Address; fragmentReq.MessageID = new Guid(message.Data); fragmentReq.Fragment = message.FragmentNumber; directUdpTargets.Enqueue(fragmentReq); directUdpEvent.Set(); Thread.Sleep(0); } break; } } } } catch (SocketException ex) { Debug.WriteLine(String.Format("SocketException: {0} {1}\r\n{2}", ex.ErrorCode, ex.Message, ex.StackTrace)); } }
public void SendFragments(byte[] data, Guid destinationID) { Guid messageID = Guid.NewGuid(); Debug.WriteLine("Created message " + messageID.ToString()); // Make the lifetime of the message 30 seconds NetworkMessage largeMessage = new NetworkMessage(localID, destinationID, messageID, NetworkMessageType.Message, data, 1,1, 300000); NetworkMessage[] fragments = this.Fragment(largeMessage); outgoingFragments[largeMessage.MessageID] = fragments; //double the lifetime in send cache so that receivers have a chance to request fragments within one timespan before it's expired messageExpiryTimes.Add(new TickGuid(largeMessage.MessageID, (largeMessage.Lifetime*2))); Debug.WriteLine("Message fragmented in " + fragments.Length + " fragments."); foreach (NetworkMessage message in fragments) { sendMessage(message); Thread.Sleep(0); } startMessageLifetimeTimer(); }
public void SendDirect(byte[] data, Guid destinationID) { Guid messageID = Guid.NewGuid(); NetworkMessage[] fragments = null; TickGuid expiryTime = new TickGuid(); expiryTime.id = messageID; NetworkMessage message = new NetworkMessage(localID, destinationID, messageID, NetworkMessageType.Message, data, 1, 1, 10000); if (message.GzData.Length > FragmentSize) { message.Lifetime = 30000; //Break the message up if it's large fragments = this.Fragment(message); expiryTime.SetExpityTime(message.Lifetime); } else { fragments = new NetworkMessage[1]; fragments[0] = message; expiryTime.SetExpityTime(message.Lifetime); } Debug.WriteLine(String.Format("Adding {0} to store in {1} fragments", messageID, fragments.Length)); outgoingFragments[messageID] = fragments; messageExpiryTimes.Add(expiryTime); // make the lifetime of the direct request message 5 seconds NetworkMessage directRequestMessage = new NetworkMessage(localID, destinationID, Guid.NewGuid(), NetworkMessageType.DirectRequest, messageID.ToByteArray(), 1, 1, 5000); sendMessage(directRequestMessage); startMessageLifetimeTimer(); }
public void Send(byte[] bytes, Guid destinationID) { NetworkMessage message = new NetworkMessage(localID, destinationID, Guid.NewGuid(), NetworkMessageType.Message, bytes, 1, 1, 50000); if (message.GzData.Length > FragmentSize) { // This is a large message, break into fragments SendFragments(bytes, destinationID); } else { Debug.WriteLine("Created message " + message.MessageID.ToString()); sendMessage(message); } }
public MessageDefragmentedEventArgs(NetworkMessage message) : base(message) { this.gzData = message.Data; }