source: network-game/server/server.cpp@ 8e540f4

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

Created a separate function for processing error messages, began capitalizing class names and class-related file names, and fixed the include guard in message,h

  • Property mode set to 100644
File size: 7.5 KB
RevLine 
[e084950]1#include "../common/compiler.h"
2
[2488852]3#include <cstdlib>
[e3535b3]4#include <unistd.h>
[2488852]5#include <string>
[e3535b3]6#include <netdb.h>
[2488852]7#include <cstdio>
[e3535b3]8#include <iostream>
[2488852]9#include <vector>
10#include <algorithm>
[e3535b3]11
[73f75c1]12#include <sys/socket.h>
13#include <netinet/in.h>
14#include <arpa/inet.h>
15
[e3535b3]16#include <mysql/mysql.h>
17
18#include <openssl/bio.h>
19#include <openssl/ssl.h>
20#include <openssl/err.h>
21
[8e540f4]22#include "Player.h"
[2488852]23#include "../common/message.h"
[d2b411a]24
25/*
26 Protocol Design
27
28 Client sends a login message
29 Server replies with client's position in the world and positions of
30 oall other logged in players
31 Merver sends player ids along with locations
32 This means a newly logged in client will need to know which id is
33 assigned to it
34 So server needs to send an id message, wait for an ack, and then send
35 the location messages
36 When a client shuts down, it sends a message to indicate this so the
37 server can remove it from the list of connected clients
38 Eventually, there'll need to be a way to detect timeouts from clients
39 (if they crashed or otherwise failed to send the logout message)
40*/
41
[e3535b3]42using namespace std;
43
[8e540f4]44void processMessage(const NETWORK_MSG &clientMsg, const struct sockaddr_in &from, vector<Player> &vctPlayers, int &num, NETWORK_MSG &serverMsg);
45
[73f75c1]46// this should probably go somewhere in the common folder
[e3535b3]47void error(const char *msg)
48{
49 perror(msg);
50 exit(0);
51}
52
[8e540f4]53Player *findPlayerByName(vector<Player> &vec, string name)
[2488852]54{
[8e540f4]55 vector<Player>::iterator it;
[2488852]56
57 for (it = vec.begin(); it != vec.end(); it++)
58 {
59 if ( it->name.compare(name) == 0 )
60 return &(*it);
61 }
62
63 return NULL;
64}
65
[73f75c1]66// not sure if we actually need this function
67// when I made it, I thought we did
[8e540f4]68Player *findPlayerByAddr(vector<Player> &vec, const sockaddr_in &addr)
[73f75c1]69{
[8e540f4]70 vector<Player>::iterator it;
[73f75c1]71
72 for (it = vec.begin(); it != vec.end(); it++)
73 {
74 if ( it->addr.sin_addr.s_addr == addr.sin_addr.s_addr &&
75 it->addr.sin_port == addr.sin_port )
76 return &(*it);
77 }
78
79 return NULL;
80}
81
[e3535b3]82int main(int argc, char *argv[])
83{
84 int sock, length, n;
85 struct sockaddr_in server;
[73f75c1]86 struct sockaddr_in from; // holds the info on the connected client
[e084950]87 NETWORK_MSG clientMsg, serverMsg;
[8e540f4]88 vector<Player> vctPlayers;
[e084950]89
90 srand(time(NULL));
91 int num = (rand() % 1000) + 1;
92
93 cout << "num: " << num << endl;
[e3535b3]94
95 SSL_load_error_strings();
96 ERR_load_BIO_strings();
97 OpenSSL_add_all_algorithms();
98
99 if (argc < 2) {
[73f75c1]100 cerr << "ERROR, no port provided" << endl;
101 exit(1);
[e3535b3]102 }
103
104 sock=socket(AF_INET, SOCK_DGRAM, 0);
105 if (sock < 0) error("Opening socket");
106 length = sizeof(server);
107 bzero(&server,length);
108 server.sin_family=AF_INET;
109 server.sin_port=htons(atoi(argv[1]));
[2488852]110 server.sin_addr.s_addr=INADDR_ANY;
111 if ( bind(sock, (struct sockaddr *)&server, length) < 0 )
[e084950]112 error("binding");
[73f75c1]113
[cb1f288]114 while (true) {
[2488852]115 // if n == 0, means the client disconnected. may want to check this
[e084950]116 n = receiveMessage(&clientMsg, sock, &from);
117 if (n < 0)
118 error("recieveMessage");
[8e540f4]119
120 processMessage(clientMsg, from, vctPlayers, num, serverMsg);
121
122 cout << "msg: " << serverMsg.buffer << endl;
123
124 n = sendMessage(&serverMsg, sock, &from);
125 if (n < 0)
126 error("sendMessage");
127 }
128 return 0;
129}
130
131void processMessage(const NETWORK_MSG &clientMsg, const struct sockaddr_in &from, vector<Player> &vctPlayers, int &num, NETWORK_MSG &serverMsg)
132{
133 cout << "ip address: " << inet_ntoa(from.sin_addr) << endl;
134 cout << "port: " << from.sin_port << endl;
135 cout << "MSG: type: " << clientMsg.type << endl;
136 cout << "MSG contents: " << clientMsg.buffer << endl;
137
138 // Check that if an invalid message is sent, the client will correctly
139 // receive and display the response. Maybe make a special error msg type
140 switch(clientMsg.type)
141 {
142 case MSG_TYPE_REGISTER:
[d2b411a]143 {
[8e540f4]144 string username(clientMsg.buffer);
145 string password(strchr(clientMsg.buffer, '\0')+1);
[d2b411a]146
[8e540f4]147 cout << "username: " << username << endl;
148 cout << "password: " << password << endl;
[d2b411a]149
[8e540f4]150 strcpy(serverMsg.buffer, "Registration test");
151
152 serverMsg.type = MSG_TYPE_REGISTER;
[d2b411a]153
[8e540f4]154 break;
155 }
156 case MSG_TYPE_LOGIN:
157 {
158 string username(clientMsg.buffer);
159 cout << "Player logging in: " << username << endl;
160
161 Player *p = findPlayerByName(vctPlayers, username);
[d2b411a]162
[8e540f4]163 if (p == NULL)
164 {
165 vctPlayers.push_back(Player(username, from));
166 strcpy(serverMsg.buffer, "I'm thinking of a number between 1 and 1000. Guess what it is.");
[07028b9]167 }
[8e540f4]168 else
[07028b9]169 {
[8e540f4]170 strcpy(serverMsg.buffer, "Player has already logged in.");
171 }
[07028b9]172
[8e540f4]173 serverMsg.type = MSG_TYPE_LOGIN;
[07028b9]174
[8e540f4]175 break;
176 }
177 case MSG_TYPE_LOGOUT:
178 {
179 string name(clientMsg.buffer);
180 cout << "Player logging out: " << name << endl;
181
182 Player *p = findPlayerByName(vctPlayers, name);
[633f42a]183
[8e540f4]184 if (p == NULL)
185 {
186 strcpy(serverMsg.buffer, "That player is not logged in. This is either a bug, or you're trying to hack the server.");
[07028b9]187 }
[8e540f4]188 else if( p->addr.sin_addr.s_addr != from.sin_addr.s_addr ||
189 p->addr.sin_port != from.sin_port )
[07028b9]190 {
[8e540f4]191 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.");
[2488852]192 }
[8e540f4]193 else
[2488852]194 {
[8e540f4]195 vctPlayers.erase((vector<Player>::iterator)p);
196 strcpy(serverMsg.buffer, "You have successfully logged out. You may quit the game.");
197 }
[07028b9]198
[8e540f4]199 break;
200 }
201 case MSG_TYPE_CHAT:
202 {
203 Player *p = findPlayerByAddr(vctPlayers, from);
[07028b9]204
[8e540f4]205 if (p == NULL)
206 {
207 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]208 }
[8e540f4]209 else
210 {
211 int guess = atoi(clientMsg.buffer);
212
213 cout << "guess: " << guess << endl;
214
215 if (guess < 1 || guess > 1000) {
216 strcpy(serverMsg.buffer, "You must guess a number between 1 and 1000");
217 }else if(guess > num)
218 strcpy(serverMsg.buffer, "The number I'm thinking of is less than that.");
219 else if(guess < num)
220 strcpy(serverMsg.buffer, "The number I'm thinking of is greater than that.");
221 else if(guess == num) {
222 strcpy(serverMsg.buffer, "Congratulations! I will now think of a new number.");
223 num = (rand() % 1000) + 1;
224 }
225 }
226
227 serverMsg.type = MSG_TYPE_CHAT;
228
229 break;
[e084950]230 }
[8e540f4]231 default:
232 {
233 strcpy(serverMsg.buffer, "Server error occured. Report this please.");
[e084950]234
[8e540f4]235 serverMsg.type = MSG_TYPE_CHAT;
[e084950]236
[8e540f4]237 break;
238 }
[e3535b3]239 }
240}
241
242int dbtest()
243{
244 MYSQL *connection, mysql;
245 MYSQL_RES *result;
246 MYSQL_ROW row;
247 int query_state;
248
249 mysql_init(&mysql);
250
251 connection = mysql_real_connect(&mysql,"localhost","pythonAdmin","pyMaster09*","pythondb",0,0,0);
252
253 if (connection == NULL) {
254 cout << mysql_error(&mysql) << endl;
255 return 1;
256 }else
257 cout << "Connection successful" << endl;
258
259 query_state = mysql_query(connection, "SELECT * FROM users");
260
261 if (query_state !=0) {
262 cout << mysql_error(connection) << endl;
263 return 1;
264 }
265
266 result = mysql_store_result(connection);
267
268 while ( ( row = mysql_fetch_row(result)) != NULL ) {
269 cout << row[0] << ", " << row[1] << ", " << row[2] << endl;
270 }
271
272 mysql_free_result(result);
273 mysql_close(connection);
274
275 cout << "Test finished" << endl;
276
277 return 0;
278}
Note: See TracBrowser for help on using the repository browser.