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
RevLine 
[2488852]1#include <cstdlib>
[371ce29]2#include <cstdio>
[e3535b3]3#include <unistd.h>
[2488852]4#include <string>
[e3535b3]5#include <iostream>
[3b1efcc]6#include <sstream>
[edfd1d0]7#include <cstring>
[371ce29]8
[01d0d00]9#include <vector>
10#include <map>
11
[73f75c1]12#include <sys/socket.h>
[371ce29]13#include <netdb.h>
[73f75c1]14#include <netinet/in.h>
15#include <arpa/inet.h>
16
[b128109]17#include <crypt.h>
18
[edfd1d0]19/*
[e3535b3]20#include <openssl/bio.h>
21#include <openssl/ssl.h>
22#include <openssl/err.h>
[edfd1d0]23*/
[e3535b3]24
[b53c6b3]25#include "../common/Compiler.h"
[3b1efcc]26#include "../common/Common.h"
[edfd1d0]27#include "../common/Message.h"
28#include "../common/Player.h"
[b53c6b3]29
[36082e8]30#include "DataAccess.h"
[d2b411a]31
[e3535b3]32using namespace std;
33
[01d0d00]34bool processMessage(const NETWORK_MSG &clientMsg, const struct sockaddr_in &from, map<unsigned int, Player>& mapPlayers, unsigned int& unusedId, NETWORK_MSG &serverMsg);
35
[1106210]36void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers);
[8e540f4]37
[73f75c1]38// this should probably go somewhere in the common folder
[e3535b3]39void error(const char *msg)
40{
41 perror(msg);
42 exit(0);
43}
44
[01d0d00]45Player *findPlayerByName(map<unsigned int, Player> &m, string name)
[2488852]46{
[01d0d00]47 map<unsigned int, Player>::iterator it;
[2488852]48
[01d0d00]49 for (it = m.begin(); it != m.end(); it++)
[2488852]50 {
[01d0d00]51 if ( it->second.name.compare(name) == 0 )
52 return &(it->second);
[2488852]53 }
54
55 return NULL;
56}
57
[01d0d00]58Player *findPlayerByAddr(map<unsigned int, Player> &m, const sockaddr_in &addr)
[73f75c1]59{
[01d0d00]60 map<unsigned int, Player>::iterator it;
[73f75c1]61
[01d0d00]62 for (it = m.begin(); it != m.end(); it++)
[73f75c1]63 {
[01d0d00]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);
[73f75c1]67 }
68
69 return NULL;
70}
71
[01d0d00]72void broadcastPlayerPositions(map<unsigned int, Player> &m, int sock)
[edfd1d0]73{
[01d0d00]74 map<unsigned int, Player>::iterator it, it2;
[edfd1d0]75 NETWORK_MSG serverMsg;
76
77 serverMsg.type = MSG_TYPE_PLAYER;
78
[01d0d00]79 for (it = m.begin(); it != m.end(); it++)
[edfd1d0]80 {
[01d0d00]81 it->second.serialize(serverMsg.buffer);
[edfd1d0]82
[01d0d00]83 for (it2 = m.begin(); it2 != m.end(); it2++)
[edfd1d0]84 {
[01d0d00]85 if ( sendMessage(&serverMsg, sock, &(it2->second.addr)) < 0 )
[edfd1d0]86 error("sendMessage");
87 }
88 }
89}
90
[e3535b3]91int main(int argc, char *argv[])
92{
93 int sock, length, n;
94 struct sockaddr_in server;
[3b1efcc]95 struct sockaddr_in from; // info of client sending the message
[e084950]96 NETWORK_MSG clientMsg, serverMsg;
[01d0d00]97 map<unsigned int, Player> mapPlayers;
[1106210]98 unsigned int unusedId = 1;
[e084950]99
[edfd1d0]100 //SSL_load_error_strings();
101 //ERR_load_BIO_strings();
102 //OpenSSL_add_all_algorithms();
[e3535b3]103
104 if (argc < 2) {
[73f75c1]105 cerr << "ERROR, no port provided" << endl;
106 exit(1);
[e3535b3]107 }
[41ad8ed]108
[371ce29]109 sock = socket(AF_INET, SOCK_DGRAM, 0);
[e3535b3]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]));
[2488852]115 server.sin_addr.s_addr=INADDR_ANY;
116 if ( bind(sock, (struct sockaddr *)&server, length) < 0 )
[e084950]117 error("binding");
[73f75c1]118
[371ce29]119 set_nonblock(sock);
120
[da692b9]121 bool broadcastResponse;
[cb1f288]122 while (true) {
[371ce29]123
124 usleep(5000);
125
[e084950]126 n = receiveMessage(&clientMsg, sock, &from);
[8e540f4]127
[371ce29]128 if (n >= 0) {
129 cout << "Got a message" << endl;
[8e540f4]130
[01d0d00]131 broadcastResponse = processMessage(clientMsg, from, mapPlayers, unusedId, serverMsg);
[371ce29]132
[b128109]133 // probably replace this with a function that prints based on the
134 // message type
[371ce29]135 cout << "msg: " << serverMsg.buffer << endl;
[b128109]136 cout << "broadcastResponse: " << broadcastResponse << endl;
[da692b9]137 if (broadcastResponse)
[3b1efcc]138 {
[da692b9]139 cout << "Should be broadcasting the message" << endl;
140
[01d0d00]141 map<unsigned int, Player>::iterator it;
[3b1efcc]142
[01d0d00]143 for (it = mapPlayers.begin(); it != mapPlayers.end(); it++)
[3b1efcc]144 {
[01d0d00]145 if ( sendMessage(&serverMsg, sock, &(it->second.addr)) < 0 )
[3b1efcc]146 error("sendMessage");
147 }
148 }
149 else
150 {
[da692b9]151 cout << "Should be sending back the message" << endl;
152
[3b1efcc]153 if ( sendMessage(&serverMsg, sock, &from) < 0 )
154 error("sendMessage");
155 }
[8e540f4]156
[01d0d00]157 broadcastPlayerPositions(mapPlayers, sock);
[edfd1d0]158 }
[8e540f4]159 }
[371ce29]160
[8e540f4]161 return 0;
162}
163
[01d0d00]164bool processMessage(const NETWORK_MSG& clientMsg, const struct sockaddr_in& from, map<unsigned int, Player>& mapPlayers, unsigned int& unusedId, NETWORK_MSG& serverMsg)
[8e540f4]165{
[41ad8ed]166 DataAccess da;
167
[8e540f4]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
[da692b9]173 // maybe we should make a message class and have this be a member
[3b1efcc]174 bool broadcastResponse = false;
175
[8e540f4]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:
[d2b411a]181 {
[8e540f4]182 string username(clientMsg.buffer);
183 string password(strchr(clientMsg.buffer, '\0')+1);
[d2b411a]184
[8e540f4]185 cout << "username: " << username << endl;
186 cout << "password: " << password << endl;
[d2b411a]187
[3b1efcc]188 int error = da.insertPlayer(username, password);
[41ad8ed]189
[3b1efcc]190 if (!error)
191 strcpy(serverMsg.buffer, "Registration successful.");
192 else
193 strcpy(serverMsg.buffer, "Registration failed. Please try again.");
[8e540f4]194
195 serverMsg.type = MSG_TYPE_REGISTER;
[d2b411a]196
[8e540f4]197 break;
198 }
199 case MSG_TYPE_LOGIN:
200 {
201 string username(clientMsg.buffer);
[41ad8ed]202 string password(strchr(clientMsg.buffer, '\0')+1);
[8e540f4]203
[41ad8ed]204 Player* p = da.getPlayer(username);
[d2b411a]205
[b128109]206 if (p == NULL || !da.verifyPassword(password, p->password))
[41ad8ed]207 {
208 strcpy(serverMsg.buffer, "Incorrect username or password");
209 }
[01d0d00]210 else if(findPlayerByName(mapPlayers, username) != NULL)
[41ad8ed]211 {
212 strcpy(serverMsg.buffer, "Player has already logged in.");
213 }
214 else
[8e540f4]215 {
[01d0d00]216 p->setAddr(from);
[1106210]217 updateUnusedId(unusedId, mapPlayers);
[01d0d00]218 p->id = unusedId;
219 mapPlayers[unusedId] = *p;
[59061f6]220
[594d2e9]221 // sendd back the new player info to the user
222 p->serialize(serverMsg.buffer);
[07028b9]223 }
224
[8e540f4]225 serverMsg.type = MSG_TYPE_LOGIN;
[41ad8ed]226
227 delete(p);
[07028b9]228
[8e540f4]229 break;
230 }
231 case MSG_TYPE_LOGOUT:
232 {
233 string name(clientMsg.buffer);
234 cout << "Player logging out: " << name << endl;
235
[01d0d00]236 Player *p = findPlayerByName(mapPlayers, name);
[633f42a]237
[8e540f4]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.");
[8a3ef42]241 cout << "Player not logged in" << endl;
[07028b9]242 }
[01d0d00]243 else if ( p->addr.sin_addr.s_addr != from.sin_addr.s_addr ||
244 p->addr.sin_port != from.sin_port )
[07028b9]245 {
[8e540f4]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.");
[8a3ef42]247 cout << "Player logged in using a different connection" << endl;
[2488852]248 }
[8e540f4]249 else
[2488852]250 {
[01d0d00]251 if (p->id < unusedId)
252 unusedId = p->id;
253 mapPlayers.erase(p->id);
[41ad8ed]254 strcpy(serverMsg.buffer, "You have successfully logged out.");
[8a3ef42]255 cout << "Player logged out successfuly" << endl;
[8e540f4]256 }
[07028b9]257
[8a3ef42]258 // should really be serverMsg.type = MSG_TYPE_LOGOUT;
259 serverMsg.type = MSG_TYPE_LOGIN;
260
[8e540f4]261 break;
262 }
263 case MSG_TYPE_CHAT:
264 {
[da692b9]265 cout << "Got a chat message" << endl;
266
[01d0d00]267 Player *p = findPlayerByAddr(mapPlayers, from);
[07028b9]268
[8e540f4]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.");
[2488852]272 }
[8e540f4]273 else
274 {
[3b1efcc]275 broadcastResponse = true;
276
[b128109]277 ostringstream oss;
278 oss << p->name << ": " << clientMsg.buffer;
[3b1efcc]279
[b128109]280 strcpy(serverMsg.buffer, oss.str().c_str());
[8e540f4]281 }
282
283 serverMsg.type = MSG_TYPE_CHAT;
284
285 break;
[e084950]286 }
[b128109]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 }
[8e540f4]320 default:
321 {
322 strcpy(serverMsg.buffer, "Server error occured. Report this please.");
[e084950]323
[8e540f4]324 serverMsg.type = MSG_TYPE_CHAT;
[e084950]325
[8e540f4]326 break;
327 }
[e3535b3]328 }
[da692b9]329
330 return broadcastResponse;
[e3535b3]331}
[da692b9]332
[1106210]333void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers)
[01d0d00]334{
[1106210]335 while (mapPlayers.find(id) != mapPlayers.end())
336 id++;
[01d0d00]337}
Note: See TracBrowser for help on using the repository browser.