/// <summary> /// Socket transmit thread /// </summary> public void TxThread() { // Execute until a kill event occurs while (!m_transmitThreadInfo.m_pKill.WaitOne(5, false)) { try { // Check the reliable message queue for retransmits Byte[] pReliableData = m_reliableMessageHandler.GetRetransmitPacket(); // If a packet is found if (pReliableData.Length > 0) { // Add the message to the transmit queue TransmitPacket(pReliableData); } if (m_pTransmitQueue.Count != 0) { // Check if there is more than one packet if (m_pTransmitQueue.Count > 1) { // Create a clustered packet ClusteredPacket packetCluster = new ClusteredPacket(); while (m_pTransmitQueue.Count > 0) { // Get the next packet Byte[] nextPacket = (Byte[])(m_pTransmitQueue[0]); if (nextPacket != null) { // If the packet is too big to cluster if (nextPacket.Length > 256) { // Encrypt and transmit the packet EncryptAndTransmitPacket(nextPacket); } else { // Add the next packet to the cluster packetCluster.AddPacket(nextPacket); if (packetCluster.ClusterLength > 256) { // Encrypt and transmit the packet EncryptAndTransmitPacket(packetCluster.Packet); } } } // Remove the item from the queue m_pTransmitQueue.RemoveAt(0); } if (packetCluster.ClusterLength > 0) { // Encrypt and transmit the packet EncryptAndTransmitPacket(packetCluster.Packet); } } else { // Encrypt and transmit the packet EncryptAndTransmitPacket((Byte[])(m_pTransmitQueue[0])); // Remove the item from the queue m_pTransmitQueue.RemoveAt(0); } } } catch (Exception e) { Console.WriteLine(e); m_receiveThreadInfo.m_pKill.Set(); m_transmitThreadInfo.m_pKill.Set(); } } try { // Send any outstanding messages while (m_pTransmitQueue.Count > 0) { // Get the next packet to transmit Byte[] pData = (Byte[])(m_pTransmitQueue[0]); // Encrypt the next packet pData = m_packetEncryption.Encrypt(pData); // Send the packet to the server m_pSocket.Send(pData, pData.Length); // Remove the item from the queue m_pTransmitQueue.RemoveAt(0); } } catch (Exception e) { Console.WriteLine(e); } // Reset the kill event m_transmitThreadInfo.m_pKill.Reset(); // Set the thread dead event m_transmitThreadInfo.m_pDead.Set(); }
/// <summary> /// Receive a packet from the server /// </summary> /// <returns>Received packet data</returns> public Byte[] ReceivePacket() { ReliablePacket pReliablePacket = new ReliablePacket(); AcknowlegePacket pAckPacket = new AcknowlegePacket(); Byte[] pData = new Byte[0]; ClusteredPacket pClusteredPacket = new ClusteredPacket(); ChunkBodyPacket pChunkBodyPacket = new ChunkBodyPacket(); ChunkTailPacket pChunkTailPacket = new ChunkTailPacket(); LargeChunkPacket pLargeChunkPacket = new LargeChunkPacket(); // Check if there are any elements on the queue if (m_pReceiveQueue.Count > 0) { // Get the next element from the receive queue pData = (Byte[])(m_pReceiveQueue.Dequeue()); if (pData != null) { // Write the data to the packet loggers m_packetLogger(PacketDirection.Receive, pData); // Check if the message is reliable if (pData[0] == 0x00) { switch (pData[1]) { case 0x03: // Set the packet information pReliablePacket.Packet = pData; // Extract the message pData = pReliablePacket.Message; // Increment the reliable receive counter m_nReliablePacketsReceived++; // Set the acknowlege transaction identifier and transmit pAckPacket.TransactionId = pReliablePacket.TransactionId; TransmitPacket(pAckPacket.Packet); break; case 0x04: // Set the acknowlegement packet data pAckPacket.Packet = pData; // Handle the Acknowlege packet m_reliableMessageHandler.HandleAcknowlegement(pAckPacket.TransactionId); break; } // Check if the packet is a chunk body packet if ((pData[0] == 0x00) && (pData[1] == 0x08)) { // Set the chunk data packet pChunkBodyPacket.Packet = pData; // Get the message packet from the buffer pData = pChunkBodyPacket.Message; // Append the data to the buffer m_chunkBuffer.Write(pData, 0, pData.Length); // Clear the returned data pData = new Byte[0]; } // Check if the packet is a chunk tail packet else if ((pData[0] == 0x00) && (pData[1] == 0x09)) { // Set the chunk data packet pChunkTailPacket.Packet = pData; // Get the message packet from the buffer pData = pChunkTailPacket.Message; // Append the data to the chunk buffer m_chunkBuffer.Write(pData, 0, pData.Length); // return the full data packet pData = m_chunkBuffer.ToArray(); // Clear the chunk buffer m_chunkBuffer.Position = 0; } // Check if the packet is a large chunk packet else if ((pData[0] == 0x00) && (pData[1] == 0x0A)) { // Set the large chunk packet pLargeChunkPacket.Packet = pData; // Get the message packet from the buffer pData = pLargeChunkPacket.Message; // Append the message to the large buffer m_largeBuffer.Write(pData, 0, pData.Length); // Check if the packet is complete if (m_largeBuffer.Length == pLargeChunkPacket.TotalLength) { // return the full data packet pData = m_largeBuffer.ToArray(); // Clear the chunk buffer m_largeBuffer.Position = 0; } else { // Clear the returned data pData = new Byte[0]; } } // Check if the packet is a clustered packet else if ((pData[0] == 0x00) && (pData[1] == 0x0E)) { // Set the clustered packet data pClusteredPacket.Packet = pData; // Get the enumerator for the packet list IEnumerator pEnum = pClusteredPacket.Packets.GetEnumerator(); while (pEnum.MoveNext()) { // Add the next element to the receive queue m_pReceiveQueue.Enqueue((Byte[])pEnum.Current); } // Clear the returned data pData = new Byte[0]; } } } } return(pData); }