private void SendPacketRaw(ServerPacket packet) { Socket socket = SocketManager.GetSocket(); if (packet.Header.Sequence == 0) { socket = SocketManager.GetSocket(0); } byte[] payload = packet.GetPayload(); if (packetLog.IsDebugEnabled) { System.Net.IPEndPoint listenerEndpoint = (System.Net.IPEndPoint)socket.LocalEndPoint; StringBuilder sb = new StringBuilder(); sb.AppendLine(String.Format("[{5}] Sending Packet (Len: {0}) [{1}:{2}=>{3}:{4}]", payload.Length, listenerEndpoint.Address, listenerEndpoint.Port, session.EndPoint.Address, session.EndPoint.Port, session.Id)); sb.AppendLine(payload.BuildPacketString()); packetLog.Debug(sb.ToString()); } socket.SendTo(payload, session.EndPoint); }
private void SendPacketRaw(ServerPacket packet) { Socket socket = SocketManager.GetMainSocket(); byte[] payload = packet.GetPayload(); #if NETDIAG payload = NetworkSyntheticTesting.SyntheticCorruption_S2C(payload); #endif if (packetLog.IsDebugEnabled) { var listenerEndpoint = (System.Net.IPEndPoint)socket.LocalEndPoint; var sb = new StringBuilder(); sb.AppendLine(String.Format("[{5}] Sending Packet (Len: {0}) [{1}:{2}=>{3}:{4}]", payload.Length, listenerEndpoint.Address, listenerEndpoint.Port, session.EndPoint.Address, session.EndPoint.Port, session.Network.ClientId)); sb.AppendLine(payload.BuildPacketString()); packetLog.Debug(sb.ToString()); } try { socket.SendTo(payload, session.EndPoint); } catch (SocketException ex) { // Unhandled Exception: System.Net.Sockets.SocketException: A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself // at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName) // at System.Net.Sockets.Socket.SendTo(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint remoteEP) var listenerEndpoint = (System.Net.IPEndPoint)socket.LocalEndPoint; var sb = new StringBuilder(); sb.AppendLine(ex.ToString()); sb.AppendLine(String.Format("[{5}] Sending Packet (Len: {0}) [{1}:{2}=>{3}:{4}]", payload.Length, listenerEndpoint.Address, listenerEndpoint.Port, session.EndPoint.Address, session.EndPoint.Port, session.Network.ClientId)); log.Error(sb.ToString()); session.State = Enum.SessionState.NetworkTimeout; // This will force WorldManager to drop the session } }
/// <summary> /// request retransmission of lost sequences /// </summary> /// <param name="rcvdSeq">the sequence of the packet that was just received.</param> private void DoRequestForRetransmission(uint rcvdSeq) { var desiredSeq = lastReceivedPacketSequence + 1; List <uint> needSeq = new List <uint>(); needSeq.Add(desiredSeq); uint bottom = desiredSeq + 1; if (rcvdSeq - bottom > CryptoSystem.MaximumEffortLevel) { session.Terminate(SessionTerminationReason.AbnormalSequenceReceived); return; } for (uint a = bottom; a < rcvdSeq; a++) { if (!outOfOrderPackets.ContainsKey(a)) { needSeq.Add(a); } } ServerPacket reqPacket = new ServerPacket(); byte[] reqData = new byte[4 + (needSeq.Count * 4)]; MemoryStream msReqData = new MemoryStream(reqData, 0, reqData.Length, true, true); msReqData.Write(BitConverter.GetBytes((uint)needSeq.Count), 0, 4); needSeq.ForEach(k => msReqData.Write(BitConverter.GetBytes(k), 0, 4)); reqPacket.Data = msReqData; reqPacket.Header.Flags = PacketHeaderFlags.RequestRetransmit; EnqueueSend(reqPacket); LastRequestForRetransmitTime = DateTime.Now; packetLog.DebugFormat("[{0}] Requested retransmit of {1}", session.LoggingIdentifier, needSeq.Select(k => k.ToString()).Aggregate((a, b) => a + ", " + b)); NetworkStatistics.S2C_RequestsForRetransmit_Aggregate_Increment(); }
/// <summary> /// This function handles turning a bundle of messages (representing all messages accrued in a timeslice), /// into 1 or more packets, combining multiple messages into one packet or spliting large message across /// several packets as needed. /// </summary> /// <param name="bundle"></param> private void SendBundle(NetworkBundle bundle, GameMessageGroup group) { packetLog.DebugFormat("[{0}] Sending Bundle", session.LoggingIdentifier); bool writeOptionalHeaders = true; List <MessageFragment> fragments = new List <MessageFragment>(); // Pull all messages out and create MessageFragment objects while (bundle.HasMoreMessages) { var message = bundle.Dequeue(); var fragment = new MessageFragment(message, ConnectionData.FragmentSequence++); fragments.Add(fragment); } packetLog.DebugFormat("[{0}] Bundle Fragment Count: {1}", session.LoggingIdentifier, fragments.Count); // Loop through while we have fragements while (fragments.Count > 0 || writeOptionalHeaders) { ServerPacket packet = new ServerPacket(); PacketHeader packetHeader = packet.Header; if (fragments.Count > 0) { packetHeader.Flags |= PacketHeaderFlags.BlobFragments; } if (bundle.EncryptedChecksum) { packetHeader.Flags |= PacketHeaderFlags.EncryptedChecksum; } int availableSpace = ServerPacket.MaxPacketSize; // Pull first message and see if it is a large one var firstMessage = fragments.FirstOrDefault(); if (firstMessage != null) { // If a large message send only this one, filling the whole packet if (firstMessage.DataRemaining >= availableSpace) { packetLog.DebugFormat("[{0}] Sending large fragment", session.LoggingIdentifier); ServerPacketFragment spf = firstMessage.GetNextFragment(); packet.Fragments.Add(spf); availableSpace -= spf.Length; if (firstMessage.DataRemaining <= 0) { fragments.Remove(firstMessage); } } // Otherwise we'll write any optional headers and process any small messages that will fit else { if (writeOptionalHeaders) { writeOptionalHeaders = false; WriteOptionalHeaders(bundle, packet); if (packet.Data != null) { availableSpace -= (int)packet.Data.Length; } } // Create a list to remove completed messages after iterator List <MessageFragment> removeList = new List <MessageFragment>(); foreach (MessageFragment fragment in fragments) { // Is this a large fragment and does it have a tail that needs sending? if (!fragment.TailSent && availableSpace >= fragment.TailSize) { packetLog.DebugFormat("[{0}] Sending tail fragment", session.LoggingIdentifier); ServerPacketFragment spf = fragment.GetTailFragment(); packet.Fragments.Add(spf); availableSpace -= spf.Length; } // Otherwise will this message fit in the remaining space? else if (availableSpace >= fragment.NextSize) { packetLog.DebugFormat("[{0}] Sending small message", session.LoggingIdentifier); ServerPacketFragment spf = fragment.GetNextFragment(); packet.Fragments.Add(spf); availableSpace -= spf.Length; } // If message is out of data, set to remove it if (fragment.DataRemaining <= 0) { removeList.Add(fragment); } } // Remove all completed messages fragments.RemoveAll(x => removeList.Contains(x)); } } // If no messages, write optional headers else { packetLog.DebugFormat("[{0}] No messages, just sending optional headers", session.LoggingIdentifier); if (writeOptionalHeaders) { writeOptionalHeaders = false; WriteOptionalHeaders(bundle, packet); if (packet.Data != null) { availableSpace -= (int)packet.Data.Length; } } } EnqueueSend(packet); } }
public void Terminate(SessionTerminationReason reason, GameMessage message = null, ServerPacket packet = null, string extraReason = "") { // TODO: graceful SessionTerminationReason.AccountBooted handling if (packet != null) { Network.EnqueueSend(packet); } if (message != null) { Network.EnqueueSend(message); } PendingTermination = new SessionTerminationDetails() { ExtraReason = extraReason, Reason = reason }; }