Reads packets from the network or loopback.
()
| 625 | * Reads packets from the network or loopback. |
| 626 | */ |
| 627 | void SV_ReadPackets() { |
| 628 | while (true) { |
| 629 | NetworkPacket networkPacket = NET.receiveNetworkPacket( |
| 630 | NET.ip_sockets[NS_SERVER], |
| 631 | NET.ip_channels[NS_SERVER], |
| 632 | NET.loopbacks[NS_SERVER], |
| 633 | true); |
| 634 | |
| 635 | if (networkPacket == null) |
| 636 | break; |
| 637 | |
| 638 | if (networkPacket.isConnectionless()) { |
| 639 | SV_ConnectionlessPacket(networkPacket.from, networkPacket.connectionlessMessage); |
| 640 | continue; |
| 641 | } |
| 642 | |
| 643 | // Match incoming packet with the existing client. |
| 644 | // todo: get client by address (hashmap?) |
| 645 | for (client_t cl: clients) { |
| 646 | if (cl.state == ClientStates.CS_FREE) |
| 647 | continue; |
| 648 | if (!networkPacket.from.CompareBaseAdr(cl.netchan.remote_address)) |
| 649 | continue; |
| 650 | if (cl.netchan.qport != networkPacket.qport) |
| 651 | continue; |
| 652 | if (cl.netchan.remote_address.port != networkPacket.from.port) { |
| 653 | Com.Printf("SV_ReadPackets: fixing up a translated port\n"); |
| 654 | cl.netchan.remote_address.port = networkPacket.from.port; |
| 655 | } |
| 656 | |
| 657 | if (cl.netchan.accept(networkPacket)) { |
| 658 | // this is a valid, sequenced packet, so process it |
| 659 | if (cl.state != ClientStates.CS_ZOMBIE) { |
| 660 | cl.lastmessage = games.get(cl.gameName).realtime; // don't timeout |
| 661 | Collection<ClientMessage> body = networkPacket.parseBodyFromClient(cl.netchan.incoming_sequence); |
| 662 | if (body == null) |
| 663 | SV_DropClient(cl); |
| 664 | else |
| 665 | SV_ExecuteClientMessage(cl, body); |
| 666 | } |
| 667 | } |
| 668 | break; |
| 669 | } |
| 670 | |
| 671 | } |
| 672 | } |
| 673 | |
| 674 | /* |
| 675 | * =================== SV_ExecuteClientMessage |
no test coverage detected