public void Setup(int length, NetworkMessageType sendType) { this.networkMessage = NetworkMessage.Create(-4, length, sendType); //Number of chunks needed receivePartsLength = (length + 4) / 500; if ((length + 4) % 500 > 0) { receivePartsLength++; } //Check the send array can fit the chunks if (receiveParts == null || receiveParts.Length < receivePartsLength) { int createLength = 128; while (receivePartsLength > createLength) { createLength = createLength * 4; } receiveParts = new bool[createLength]; } receivePartsLeft = receivePartsLength; for (int i = 0; i < receivePartsLength; i++) { receiveParts[i] = false; } }
private void HandleOrdered(ByteArray data, Connection <T> connection) { if (data.Length < 12) { return; } int orderID = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.data, 0)); int distance = orderID - connection.receiveOrderID; bool orderOK = false; //Normal case if ((distance < (Int32.MaxValue / 4)) && distance > 0) { orderOK = true; } //Wrap around case if (distance < -(Int32.MaxValue / 4)) { orderOK = true; } if (orderOK) { connection.receiveOrderID = orderID; int messageType = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.data, 4)); int messageLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.data, 8)); NetworkMessage handleOrdered = NetworkMessage.Create(messageType, messageLength, NetworkMessageType.ORDERED_UNRELIABLE); if (messageLength > 0 && messageLength == (data.Length + 12)) { Array.Copy(data.data, 12, handleOrdered.data.data, 0, messageLength); } Handle(handleOrdered, connection); } }
private NetworkMessage ConvertOrderedUnreliableMessage(NetworkMessage input, Connection <T> connection) { if (input.sendType != NetworkMessageType.ORDERED_UNRELIABLE) { return(input); } int newSize = 12; if (input.data != null) { newSize += input.data.Length; } NetworkMessage converted = NetworkMessage.Create(-3, newSize, NetworkMessageType.UNORDERED_UNRELIABLE); DarkUtils.WriteInt32ToByteArray(connection.sendOrderID++, converted.data.data, 0); if (connection.sendOrderID == Int32.MaxValue) { connection.sendOrderID = 0; } DarkUtils.WriteInt32ToByteArray(input.type, converted.data.data, 4); DarkUtils.WriteInt32ToByteArray(newSize - 8, converted.data.data, 8); if (input.data != null) { Array.Copy(input.data.data, 0, converted.data.data, 12, input.data.Length); } input.Destroy(); return(input); }
internal void HandleRaw(byte[] data, int length, IPEndPoint endPoint) { if (length < 12) { return; } //Magic header, DARK if (data[0] != 68 || data[1] != 65 || data[2] != 82 || data[3] != 75) { return; } Connection <T> connection = null; Guid messageOwner = DarkUtils.GuidFromIPEndpoint(endPoint); if (!connections.ContainsKey(messageOwner)) { if (connection == null) { connection = new Connection <T>(); connection.handler = this; connection.reliableMessageHandler = new ReliableMessageHandler <T>(connection, this); if (network.clientMode && serverConnection == null) { serverConnection = connection; } } connection.lastReceiveTime = DateTime.UtcNow.Ticks; connection.remoteEndpoint = endPoint; lock (connections) { connections.Add(messageOwner, connection); } if (connectCallback != null) { connection.state = connectCallback(connection); } } connection = connections[messageOwner]; int messageType = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 4)); int messageLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 8)); if (length < messageLength + 12) { //Malformed message return; } NetworkMessage nm = NetworkMessage.Create(messageType, messageLength, NetworkMessageType.UNORDERED_UNRELIABLE); if (nm.data != null && nm.data.Length > 0) { Array.Copy(data, 12, nm.data.data, 0, nm.data.Length); } Handle(nm, connection); }
private void HandleHeartbeat(ByteArray data, Connection <T> connection) { if (data.Length != 8) { return; } NetworkMessage nm = NetworkMessage.Create(-2, 8, NetworkMessageType.UNORDERED_UNRELIABLE); Array.Copy(data.data, 0, nm.data.data, 0, data.Length); SendMessageWithHighPriority(nm, connection); }
public NetworkMessage Copy() { NetworkMessage retVal = null; if (data != null) { retVal = NetworkMessage.Create(type, data.size, sendType); Array.Copy(data.data, 0, retVal.data.data, 0, data.Length); } else { retVal = NetworkMessage.Create(type, 0, sendType); } return(retVal); }
internal void SendHeartbeat() { lock (connections) { long currentTime = DateTime.UtcNow.Ticks; foreach (KeyValuePair <Guid, Connection <T> > c in connections) { if (currentTime > c.Value.lastReceiveTime + TimeSpan.TicksPerSecond * 20) { disconnectList.Add(c.Key); } if (currentTime > (c.Value.lastHeartbeatTime + TimeSpan.TicksPerSecond)) { c.Value.lastHeartbeatTime = currentTime; NetworkMessage nm = NetworkMessage.Create(-1, 8, NetworkMessageType.UNORDERED_UNRELIABLE); DarkUtils.WriteInt64ToByteArray(DateTime.UtcNow.Ticks, nm.data.data, 0); SendMessageWithHighPriority(nm, c.Value); } RateControl <T> .Update(c.Value); c.Value.reliableMessageHandler.Send(); } foreach (Guid disconnectConnectionGuid in disconnectList) { Connection <T> disconnectConnection = connections[disconnectConnectionGuid]; if (disconnectCallback != null) { disconnectCallback(disconnectConnection); } disconnectConnection.reliableMessageHandler.ReleaseAllObjects(); network.ReleaseAllObjects(disconnectConnection); connections.Remove(disconnectConnectionGuid); } disconnectList.Clear(); } }
public NetworkMessage GetMessage(int id, Connection <T> connection) { if (finished) { return(null); } int checkedThisRound = 0; //Always assume at least 10ms lag long latency = connection.latency; if (latency < 10 * TimeSpan.TicksPerMillisecond) { latency = 10 * TimeSpan.TicksPerMillisecond; } //Resend message if it has been 2 RTT's long checkTime = DateTime.UtcNow.Ticks - (latency * 2); bool found = false; while (!found) { if (sendParts[nextSendPart] >= 0 && checkTime > sendParts[nextSendPart]) { found = true; } else { nextSendPart++; if (nextSendPart == sendPartsLength) { nextSendPart = 0; } checkedThisRound++; if (checkedThisRound == sendPartsLength) { //We checked to see if we could send any chunks and didn't find any. break; } } } if (found) { int totalSize = 4; if (networkMessage.data != null) { totalSize += networkMessage.data.Length; } int thisSendSize = 500; if (nextSendPart == (sendPartsLength - 1)) { thisSendSize = totalSize % 500; } //This is a retransmit, count the lost data if (sendParts[nextSendPart] != 0) { connection.dataLoss += thisSendSize; } connection.dataSent += thisSendSize; NetworkMessage sendMessage = NetworkMessage.Create(-4, 12 + thisSendSize, NetworkMessageType.UNORDERED_UNRELIABLE); DarkUtils.WriteInt32ToByteArray(id, sendMessage.data.data, 0); DarkUtils.WriteInt32ToByteArray(nextSendPart, sendMessage.data.data, 4); //Don't include the header in the message length, we know it's there DarkUtils.WriteInt32ToByteArray(totalSize - 4, sendMessage.data.data, 8); if (nextSendPart == 0) { DarkUtils.WriteInt32ToByteArray(networkMessage.type, sendMessage.data.data, 12); if (networkMessage.data != null && networkMessage.data.Length > 0) { Array.Copy(networkMessage.data.data, 0, sendMessage.data.data, 16, thisSendSize - 4); } } else { Array.Copy(networkMessage.data.data, (nextSendPart * 500) - 4, sendMessage.data.data, 12, thisSendSize); } sendParts[nextSendPart] = -2; nextSendPart++; if (nextSendPart == sendPartsLength) { nextSendPart = 0; } return(sendMessage); } return(null); }
public void Handle(ByteArray data, Connection <T> connection) { if (connection.destroyed) { return; } if (data.Length < 12) { return; } int recvSendingID = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.data, 0)); int recvPartID = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.data, 4)); int recvLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.data, 8)); //Always send an ACK back immediately NetworkMessage nm = NetworkMessage.Create(-5, 8, NetworkMessageType.UNORDERED_UNRELIABLE); Array.Copy(data.data, 0, nm.data.data, 0, 8); handler.SendMessageWithHighPriority(nm, connection); ReliableMessageReceiveTracking rmrt = null; if (receivingMessages.ContainsKey(recvSendingID)) { rmrt = receivingMessages[recvSendingID]; } //Received either a new chunk or a duplicate, if the messageID is higher than what we have received, it's new. if (rmrt == null) { if (recvSendingID > 0) { int distance = recvSendingID - unorderedReceiveID; //A message in the past (doesn't detect wrap around) bool fromThePast = distance <= 0; //A future message received before we have wrapped around bool massivelyInPast = -distance > (Int32.MaxValue / 4); //A past message received when we have wrapped around bool massivelyInFuture = distance > (Int32.MaxValue / 4); if (fromThePast && !massivelyInPast || massivelyInFuture) { return; } while (recvSendingID != unorderedReceiveID) { if (unorderedReceiveID == Int32.MaxValue) { unorderedReceiveID = 0; } unorderedReceiveID++; rmrt = ReliableMessageReceiveTracking.Create(); lock (receivingMessages) { receivingMessages.Add(unorderedReceiveID, rmrt); } } } else { int distance = -recvSendingID - orderedReceiveID; //A message in the past (doesn't detect wrap around) bool fromThePast = distance <= 0; //A future message received before we have wrapped around bool massivelyInPast = -distance > (Int32.MaxValue / 4); //A past message received when we have wrapped around bool massivelyInFuture = distance > (Int32.MaxValue / 4); if (fromThePast && !massivelyInPast || massivelyInFuture) { return; } while (-recvSendingID != orderedReceiveID) { if (orderedReceiveID == Int32.MaxValue) { orderedReceiveID = 0; } orderedReceiveID++; rmrt = ReliableMessageReceiveTracking.Create(); lock (receivingMessages) { receivingMessages.Add(-orderedReceiveID, rmrt); } } } rmrt = receivingMessages[recvSendingID]; } //Fist setup if needed if (rmrt.networkMessage == null) { if (recvSendingID > 0) { rmrt.Setup(recvLength, NetworkMessageType.UNORDERED_RELIABLE); } else { rmrt.Setup(recvLength, NetworkMessageType.ORDERED_RELIABLE); } } //Handle incoming data rmrt.Handle(recvPartID, recvLength, data); //We have all the parts if (rmrt.receivePartsLeft == 0) { if (recvSendingID > 0) { handler.Handle(rmrt.networkMessage, connection); } else { //This message is received in order if (-recvSendingID == orderedHandleID) { orderedHandleID++; if (orderedHandleID == Int32.MaxValue) { orderedHandleID = 0; } handler.Handle(rmrt.networkMessage, connection); } else { //This message is received out of order and we need to hold onto it orderedHandleMessages.Add(-recvSendingID, rmrt.networkMessage); } //If a message fills the missing hole this can play out. while (orderedHandleMessages.ContainsKey(orderedHandleID)) { NetworkMessage handleMessage = orderedHandleMessages[orderedHandleID]; orderedHandleMessages.Remove(orderedHandleID); handler.Handle(handleMessage, connection); orderedHandleID++; if (orderedHandleID == Int32.MaxValue) { orderedHandleID = 0; } } } rmrt.Destroy(); lock (receivingMessages) { receivingMessages.Remove(recvSendingID); } } }