1 /*
2 * serverscanner/ServerScannerNetwork.cpp
3 *
4 * This file is part of Leges Motus, a networked, 2D shooter set in zero gravity.
5 *
6 * Copyright 2009-2010 Andrew Ayer, Nathan Partlan, Jeffrey Pfau
7 *
8 * Leges Motus is free and open source software. You may redistribute it and/or
9 * modify it under the terms of version 2, or (at your option) version 3, of the
10 * GNU General Public License (GPL), as published by the Free Software Foundation.
11 *
12 * Leges Motus is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14 * PARTICULAR PURPOSE. See the full text of the GNU General Public License for
15 * further detail.
16 *
17 * For a full copy of the GNU General Public License, please see the COPYING file
18 * in the root of the source code tree. You may also retrieve a copy from
19 * <http://www.gnu.org/licenses/gpl-2.0.txt>, or request a copy by writing to the
20 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 * 02111-1307 USA
22 *
23 */
24
25 #include <string>
26 #include "ServerScannerNetwork.hpp"
27 #include "ServerScanner.hpp"
28 #include "common/network.hpp"
29 #include "common/PacketWriter.hpp"
30 #include "common/PacketReader.hpp"
31 #include "common/PacketHeader.hpp"
32 #include "common/UDPPacket.hpp"
33 #include "common/UDPSocket.hpp"
34 #include "common/IPAddress.hpp"
35 #include "common/timer.hpp"
36 #include <iostream>
37
38 using namespace LM;
39 using namespace std;
40
41 uint32_t ServerScannerNetwork::next_connection_id = 1;
42
ServerScannerNetwork(ServerScanner & controller)43 ServerScannerNetwork::ServerScannerNetwork(ServerScanner& controller) : m_controller(controller) {
44 m_is_connected = false;
45 m_last_packet_time = 0;
46 }
47
connect(const char * hostname,unsigned int portno)48 bool ServerScannerNetwork::connect(const char* hostname, unsigned int portno) {
49 disconnect();
50
51 if (!resolve_hostname(m_server_address, hostname, portno)) {
52 return false;
53 }
54
55 m_ack_manager.clear();
56 m_is_connected = true;
57 m_last_packet_time = 0;
58 return true;
59 }
60
connect(const IPAddress & address)61 bool ServerScannerNetwork::connect(const IPAddress& address) {
62 disconnect();
63 m_ack_manager.clear();
64 m_server_address = address;
65 m_is_connected = true;
66 m_last_packet_time = 0;
67 return true;
68 }
69
disconnect()70 void ServerScannerNetwork::disconnect() {
71 m_is_connected = false;
72 m_server_peer.init(next_connection_id++);
73 m_server_peer.packet_queue.set_max_size(1024);
74 }
75
76
send_reliable_packet(const PacketWriter & packet)77 void ServerScannerNetwork::send_reliable_packet(const PacketWriter& packet) {
78 if (!is_connected()) {
79 return;
80 }
81
82 PacketHeader header(packet.packet_type(), m_server_peer.next_sequence_no++, m_server_peer.connection_id);
83 send_packet_to(m_server_address, header, packet.packet_data());
84 m_ack_manager.add_packet(m_server_address, header, packet.packet_data());
85 }
86
87
send_packet(const PacketHeader & packet_header,const std::string & packet_data)88 void ServerScannerNetwork::send_packet(const PacketHeader& packet_header, const std::string& packet_data) {
89 if (is_connected()) {
90 send_packet_to(m_server_address, packet_header, packet_data);
91 }
92 }
93
94
broadcast_packet(unsigned int portno,const PacketWriter & packet)95 void ServerScannerNetwork::broadcast_packet(unsigned int portno, const PacketWriter& packet) {
96 send_packet_to(IPAddress(htonl(INADDR_BROADCAST), htons(portno)), packet);
97 }
98
receive_packets(uint32_t timeout)99 bool ServerScannerNetwork::receive_packets(uint32_t timeout) {
100 UDPPacket raw_packet(MAX_PACKET_LENGTH);
101 // Block until packets are received, timeout has elapsed, or a signal has been received.
102 bool has_packets = m_socket.has_packets(timeout);
103 // Keep receiving packets for as long as we can.
104 while (receive_raw_packet(raw_packet)) {
105 process_unbound_packet(raw_packet);
106 }
107
108 return has_packets;
109 }
110
process_unbound_packet(const UDPPacket & raw_packet)111 void ServerScannerNetwork::process_unbound_packet(const UDPPacket& raw_packet) {
112 PacketReader reader(raw_packet);
113
114 switch (reader.packet_type()) {
115 case INFO_PACKET:
116 m_controller.server_info(raw_packet.get_address(), reader);
117 break;
118 case UPGRADE_AVAILABLE_PACKET:
119 m_controller.upgrade_available(raw_packet.get_address(), reader);
120 break;
121 case HOLE_PUNCH_PACKET:
122 m_controller.hole_punch_packet(raw_packet.get_address(), reader);
123 break;
124 }
125 }
126
get_last_packet_time()127 uint64_t ServerScannerNetwork::get_last_packet_time() {
128 return m_last_packet_time;
129 }
130
131