sources/network/rconsession.cpp

changeset 10
3874575d924d
child 11
cffa2777d917
equal deleted inserted replaced
9:e7a09ceb4505 10:3874575d924d
1 #include "rconsession.h"
2
3 // -------------------------------------------------------------------------------------------------
4 //
5 RCONSession::RCONSession() :
6 m_state (RCON_DISCONNECTED),
7 m_lastPing (0)
8 {
9 if (not m_socket.set_blocking (false))
10 {
11 // TODO: find a better way to deal with errors
12 fprintf (stderr, "unable to set socket as non-blocking: %s\n",
13 m_socket.error_string().chars());
14 }
15 }
16
17 // -------------------------------------------------------------------------------------------------
18 //
19 RCONSession::~RCONSession() {}
20
21 // -------------------------------------------------------------------------------------------------
22 //
23 METHOD
24 RCONSession::connect (IPAddress address) -> void
25 {
26 m_address = address;
27 m_state = RCON_CONNECTING;
28 }
29
30 // -------------------------------------------------------------------------------------------------
31 //
32 METHOD
33 RCONSession::disconnect() -> void
34 {
35 if (m_state == RCON_CONNECTED)
36 {
37 // Say goodbye to remote
38 Bytestream packet;
39 packet.write_byte (CLRC_DISCONNECT);
40 this->send (packet);
41 }
42
43 m_state = RCON_DISCONNECTED;
44 }
45
46 // -------------------------------------------------------------------------------------------------
47 //
48 METHOD
49 RCONSession::send (const Bytestream& packet) -> void
50 {
51 m_socket.send (m_address, packet);
52 }
53
54 // -------------------------------------------------------------------------------------------------
55 //
56 METHOD
57 RCONSession::tick() -> void
58 {
59 time_t now;
60 time (&now);
61
62 if (m_lastPing < now)
63 {
64 if (m_state == RCON_CONNECTING)
65 {
66 send_hello();
67 }
68 else if (m_state == RCON_AUTHENTICATING)
69 {
70 send_password();
71 }
72 else if (m_state == RCON_CONNECTED and m_lastPing + 5 < now)
73 {
74 Bytestream packet;
75 packet.write_byte (CLRC_PONG);
76 send (packet);
77 bump_last_ping();
78 }
79 }
80
81 for (Datagram datagram; m_socket.read (datagram);)
82 handle_packet (datagram.data, datagram.from);
83 }
84
85 // -------------------------------------------------------------------------------------------------
86 //
87 METHOD
88 RCONSession::handle_packet (Bytestream& packet, const IPAddress& from) -> void
89 {
90 print ("Handling packet of %1 bytes\n", packet.written_length());
91 bool ok = true;
92
93 while (packet.bytes_left() > 0)
94 {
95 print ("%1/%2 bytes left\n", packet.bytes_left(), packet.written_length());
96 int header = packet.read_byte (&ok);
97 print ("recieved HEADER with %1\n", header);
98
99 switch (ServerResponse (header))
100 {
101 case SVRC_OLDPROTOCOL:
102 fprintf (stderr, "wrong version\n");
103 m_state = RCON_DISCONNECTED;
104 break;
105
106 case SVRC_BANNED:
107 fprintf (stderr, "you're banned\n");
108 m_state = RCON_DISCONNECTED;
109 break;
110
111 case SVRC_SALT:
112 {
113 String salt = packet.read_string();
114 m_salt = salt;
115 m_state = RCON_AUTHENTICATING;
116 send_password();
117 }
118 break;
119
120 case SVRC_LOGGEDIN:
121 fprintf (stderr, "login successful\n");
122 m_state = RCON_CONNECTED;
123 break;
124
125 case SVRC_INVALIDPASSWORD:
126 fprintf (stderr, "bad password\n");
127 m_state = RCON_DISCONNECTED;
128 break;
129
130 case SVRC_MESSAGE:
131 {
132 String message = packet.read_string();
133 print_to (stderr, "message: %1\n", message);
134 }
135 break;
136
137 case SVRC_UPDATE:
138 switch (RCONUpdateType (packet.read_byte (&ok)))
139 {
140 case SVRCU_PLAYERDATA:
141 {
142 int numplayers = packet.read_byte (&ok);
143 Vector<String> players;
144
145 while (numplayers--)
146 players << packet.read_string (&ok);
147
148 print_to (stderr, "players: %1\n", players);
149 }
150 break;
151
152 case SVRCU_ADMINCOUNT:
153 print_to (stderr, "num admins: %1\n", packet.read_byte (&ok));
154 break;
155
156 case SVRCU_MAP:
157 print_to (stderr, "new map: %1\n", packet.read_string (&ok));
158 break;
159 }
160
161 break;
162 }
163
164 if (not ok)
165 print_to (stderr, "error while reading packet\n");
166 }
167 }
168
169 // -------------------------------------------------------------------------------------------------
170 //
171 METHOD
172 RCONSession::socket() -> UDPSocket*
173 {
174 return &m_socket;
175 }
176
177 // -------------------------------------------------------------------------------------------------
178 //
179 METHOD
180 RCONSession::send_hello() -> void
181 {
182 print ("connecting to %1...\n", m_address.to_string (IP_WITH_PORT));
183 Bytestream packet;
184 packet.write_byte (CLRC_BEGINCONNECTION);
185 packet.write_byte (RCON_PROTOCOL_VERSION);
186 send (packet);
187 bump_last_ping();
188 }
189
190 // -------------------------------------------------------------------------------------------------
191 //
192 METHOD
193 RCONSession::send_password() -> void
194 {
195 print ("sending password...\n");
196 Bytestream packet;
197 packet.write_byte (CLRC_PASSWORD);
198 packet.write_string ((m_salt + m_password).md5());
199 send (packet);
200 bump_last_ping();
201 }
202
203 // -------------------------------------------------------------------------------------------------
204 //
205 METHOD
206 RCONSession::set_password (const String& password) -> void
207 {
208 m_password = password;
209 }
210
211 // -------------------------------------------------------------------------------------------------
212 //
213 METHOD
214 RCONSession::bump_last_ping() -> void
215 {
216 time_t now;
217 time (&now);
218 m_lastPing = now;
219 }

mercurial