source: network-game/server/server.cpp@ 60b77d2

Last change on this file since 60b77d2 was b128109, checked in by dportnoy <dmp1488@…>, 12 years ago

Added MSG_TYPE_PLAYER_MOVE, which allows players to tell the server where they want to move

  • Property mode set to 100644
File size: 9.1 KB
Line 
1#include <cstdlib>
2#include <cstdio>
3#include <unistd.h>
4#include <string>
5#include <iostream>
6#include <sstream>
7#include <cstring>
8
9#include <vector>
10#include <map>
11
12#include <sys/socket.h>
13#include <netdb.h>
14#include <netinet/in.h>
15#include <arpa/inet.h>
16
17#include <crypt.h>
18
19/*
20#include <openssl/bio.h>
21#include <openssl/ssl.h>
22#include <openssl/err.h>
23*/
24
25#include "../common/Compiler.h"
26#include "../common/Common.h"
27#include "../common/Message.h"
28#include "../common/Player.h"
29
30#include "DataAccess.h"
31
32using namespace std;
33
34bool processMessage(const NETWORK_MSG &clientMsg, const struct sockaddr_in &from, map<unsigned int, Player>& mapPlayers, unsigned int& unusedId, NETWORK_MSG &serverMsg);
35
36void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers);
37
38// this should probably go somewhere in the common folder
39void error(const char *msg)
40{
41 perror(msg);
42 exit(0);
43}
44
45Player *findPlayerByName(map<unsigned int, Player> &m, string name)
46{
47 map<unsigned int, Player>::iterator it;
48
49 for (it = m.begin(); it != m.end(); it++)
50 {
51 if ( it->second.name.compare(name) == 0 )
52 return &(it->second);
53 }
54
55 return NULL;
56}
57
58Player *findPlayerByAddr(map<unsigned int, Player> &m, const sockaddr_in &addr)
59{
60 map<unsigned int, Player>::iterator it;
61
62 for (it = m.begin(); it != m.end(); it++)
63 {
64 if ( it->second.addr.sin_addr.s_addr == addr.sin_addr.s_addr &&
65 it->second.addr.sin_port == addr.sin_port )
66 return &(it->second);
67 }
68
69 return NULL;
70}
71
72void broadcastPlayerPositions(map<unsigned int, Player> &m, int sock)
73{
74 map<unsigned int, Player>::iterator it, it2;
75 NETWORK_MSG serverMsg;
76
77 serverMsg.type = MSG_TYPE_PLAYER;
78
79 for (it = m.begin(); it != m.end(); it++)
80 {
81 it->second.serialize(serverMsg.buffer);
82
83 for (it2 = m.begin(); it2 != m.end(); it2++)
84 {
85 if ( sendMessage(&serverMsg, sock, &(it2->second.addr)) < 0 )
86 error("sendMessage");
87 }
88 }
89}
90
91int main(int argc, char *argv[])
92{
93 int sock, length, n;
94 struct sockaddr_in server;
95 struct sockaddr_in from; // info of client sending the message
96 NETWORK_MSG clientMsg, serverMsg;
97 map<unsigned int, Player> mapPlayers;
98 unsigned int unusedId = 1;
99
100 //SSL_load_error_strings();
101 //ERR_load_BIO_strings();
102 //OpenSSL_add_all_algorithms();
103
104 if (argc < 2) {
105 cerr << "ERROR, no port provided" << endl;
106 exit(1);
107 }
108
109 sock = socket(AF_INET, SOCK_DGRAM, 0);
110 if (sock < 0) error("Opening socket");
111 length = sizeof(server);
112 bzero(&server,length);
113 server.sin_family=AF_INET;
114 server.sin_port=htons(atoi(argv[1]));
115 server.sin_addr.s_addr=INADDR_ANY;
116 if ( bind(sock, (struct sockaddr *)&server, length) < 0 )
117 error("binding");
118
119 set_nonblock(sock);
120
121 bool broadcastResponse;
122 while (true) {
123
124 usleep(5000);
125
126 n = receiveMessage(&clientMsg, sock, &from);
127
128 if (n >= 0) {
129 cout << "Got a message" << endl;
130
131 broadcastResponse = processMessage(clientMsg, from, mapPlayers, unusedId, serverMsg);
132
133 // probably replace this with a function that prints based on the
134 // message type
135 cout << "msg: " << serverMsg.buffer << endl;
136 cout << "broadcastResponse: " << broadcastResponse << endl;
137 if (broadcastResponse)
138 {
139 cout << "Should be broadcasting the message" << endl;
140
141 map<unsigned int, Player>::iterator it;
142
143 for (it = mapPlayers.begin(); it != mapPlayers.end(); it++)
144 {
145 if ( sendMessage(&serverMsg, sock, &(it->second.addr)) < 0 )
146 error("sendMessage");
147 }
148 }
149 else
150 {
151 cout << "Should be sending back the message" << endl;
152
153 if ( sendMessage(&serverMsg, sock, &from) < 0 )
154 error("sendMessage");
155 }
156
157 broadcastPlayerPositions(mapPlayers, sock);
158 }
159 }
160
161 return 0;
162}
163
164bool processMessage(const NETWORK_MSG& clientMsg, const struct sockaddr_in& from, map<unsigned int, Player>& mapPlayers, unsigned int& unusedId, NETWORK_MSG& serverMsg)
165{
166 DataAccess da;
167
168 cout << "ip address: " << inet_ntoa(from.sin_addr) << endl;
169 cout << "port: " << from.sin_port << endl;
170 cout << "MSG: type: " << clientMsg.type << endl;
171 cout << "MSG contents: " << clientMsg.buffer << endl;
172
173 // maybe we should make a message class and have this be a member
174 bool broadcastResponse = false;
175
176 // Check that if an invalid message is sent, the client will correctly
177 // receive and display the response. Maybe make a special error msg type
178 switch(clientMsg.type)
179 {
180 case MSG_TYPE_REGISTER:
181 {
182 string username(clientMsg.buffer);
183 string password(strchr(clientMsg.buffer, '\0')+1);
184
185 cout << "username: " << username << endl;
186 cout << "password: " << password << endl;
187
188 int error = da.insertPlayer(username, password);
189
190 if (!error)
191 strcpy(serverMsg.buffer, "Registration successful.");
192 else
193 strcpy(serverMsg.buffer, "Registration failed. Please try again.");
194
195 serverMsg.type = MSG_TYPE_REGISTER;
196
197 break;
198 }
199 case MSG_TYPE_LOGIN:
200 {
201 string username(clientMsg.buffer);
202 string password(strchr(clientMsg.buffer, '\0')+1);
203
204 Player* p = da.getPlayer(username);
205
206 if (p == NULL || !da.verifyPassword(password, p->password))
207 {
208 strcpy(serverMsg.buffer, "Incorrect username or password");
209 }
210 else if(findPlayerByName(mapPlayers, username) != NULL)
211 {
212 strcpy(serverMsg.buffer, "Player has already logged in.");
213 }
214 else
215 {
216 p->setAddr(from);
217 updateUnusedId(unusedId, mapPlayers);
218 p->id = unusedId;
219 mapPlayers[unusedId] = *p;
220
221 // sendd back the new player info to the user
222 p->serialize(serverMsg.buffer);
223 }
224
225 serverMsg.type = MSG_TYPE_LOGIN;
226
227 delete(p);
228
229 break;
230 }
231 case MSG_TYPE_LOGOUT:
232 {
233 string name(clientMsg.buffer);
234 cout << "Player logging out: " << name << endl;
235
236 Player *p = findPlayerByName(mapPlayers, name);
237
238 if (p == NULL)
239 {
240 strcpy(serverMsg.buffer, "That player is not logged in. This is either a bug, or you're trying to hack the server.");
241 cout << "Player not logged in" << endl;
242 }
243 else if ( p->addr.sin_addr.s_addr != from.sin_addr.s_addr ||
244 p->addr.sin_port != from.sin_port )
245 {
246 strcpy(serverMsg.buffer, "That player is logged in using a differemt connection. This is either a bug, or you're trying to hack the server.");
247 cout << "Player logged in using a different connection" << endl;
248 }
249 else
250 {
251 if (p->id < unusedId)
252 unusedId = p->id;
253 mapPlayers.erase(p->id);
254 strcpy(serverMsg.buffer, "You have successfully logged out.");
255 cout << "Player logged out successfuly" << endl;
256 }
257
258 // should really be serverMsg.type = MSG_TYPE_LOGOUT;
259 serverMsg.type = MSG_TYPE_LOGIN;
260
261 break;
262 }
263 case MSG_TYPE_CHAT:
264 {
265 cout << "Got a chat message" << endl;
266
267 Player *p = findPlayerByAddr(mapPlayers, from);
268
269 if (p == NULL)
270 {
271 strcpy(serverMsg.buffer, "No player is logged in using this connection. This is either a bug, or you're trying to hack the server.");
272 }
273 else
274 {
275 broadcastResponse = true;
276
277 ostringstream oss;
278 oss << p->name << ": " << clientMsg.buffer;
279
280 strcpy(serverMsg.buffer, oss.str().c_str());
281 }
282
283 serverMsg.type = MSG_TYPE_CHAT;
284
285 break;
286 }
287 case MSG_TYPE_PLAYER_MOVE:
288 {
289 istringstream iss;
290 iss.str(clientMsg.buffer);
291
292 cout << "PLAYER_MOVE" << endl;
293
294 int id, x, y;
295
296 memcpy(&id, clientMsg.buffer, 4);
297 memcpy(&x, clientMsg.buffer+4, 4);
298 memcpy(&y, clientMsg.buffer+8, 4);
299
300 cout << "x: " << x << endl;
301 cout << "y: " << y << endl;
302 cout << "id: " << id << endl;
303
304 if ( mapPlayers[id].addr.sin_addr.s_addr == from.sin_addr.s_addr &&
305 mapPlayers[id].addr.sin_port == from.sin_port )
306 {
307 memcpy(&mapPlayers[id].pos.x, clientMsg.buffer+4, 4);
308 memcpy(&mapPlayers[id].pos.y, clientMsg.buffer+8, 4);
309
310 serverMsg.type = MSG_TYPE_PLAYER_MOVE;
311 memcpy(serverMsg.buffer, clientMsg.buffer, 12);
312
313 broadcastResponse = true;
314 }
315 else // nned to send back a message indicating failure
316 cout << "Player id (" << id << ") doesn't match sender" << endl;
317
318 break;
319 }
320 default:
321 {
322 strcpy(serverMsg.buffer, "Server error occured. Report this please.");
323
324 serverMsg.type = MSG_TYPE_CHAT;
325
326 break;
327 }
328 }
329
330 return broadcastResponse;
331}
332
333void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers)
334{
335 while (mapPlayers.find(id) != mapPlayers.end())
336 id++;
337}
Note: See TracBrowser for help on using the repository browser.