root / trunk / code / projects / colonet / ColonetServer / ColonetServer.cpp @ 24
History | View | Annotate | Download (7.82 KB)
1 | 11 | emarinel | /** @file ColonetServer.cpp
|
---|---|---|---|
2 | *
|
||
3 | * @brief colonet_server - primary server application for Colonet
|
||
4 | *
|
||
5 | * @author Jason Knichel
|
||
6 | * @author Eugene Marinelli
|
||
7 | * @date 10/31/06
|
||
8 | */
|
||
9 | |||
10 | #include <colonet_wireless.h> |
||
11 | #include <sys/select.h> |
||
12 | #include <sys/socket.h> |
||
13 | #include <netinet/in.h> |
||
14 | #include <errno.h> |
||
15 | #include <arpa/inet.h> |
||
16 | |||
17 | 23 | jknichel | #include <fcntl.h> |
18 | |||
19 | 20 | jknichel | #include <colonet_wireless.h> |
20 | |||
21 | #include "includes/ColonetServer.h" |
||
22 | 11 | emarinel | #include "includes/ConnectionPool.h" |
23 | #include "includes/client.h" |
||
24 | #include "includes/options.h" |
||
25 | #include "includes/Logging.h" |
||
26 | |||
27 | #define LISTEN_BACKLOG 5 |
||
28 | #define LOG_BUFFER_LENGTH 128 |
||
29 | |||
30 | 20 | jknichel | ConnectionPool * connection_pool; |
31 | 22 | jknichel | ColonetWireless* wireless; |
32 | 20 | jknichel | |
33 | ColonetServer::ColonetServer(): logger("logFile.txt") {
|
||
34 | 24 | jknichel | listen_socket = 0;
|
35 | 20 | jknichel | } |
36 | |||
37 | ColonetServer::~ColonetServer() { |
||
38 | } |
||
39 | |||
40 | int ColonetServer::initialize_server(int argc, char * argv[]) { |
||
41 | printf("Initializing Server...\n");
|
||
42 | |||
43 | parseCmdLine(argc, argv); |
||
44 | |||
45 | if (initConnection(optionsG.listen_port) < 0) |
||
46 | return -1; |
||
47 | |||
48 | 22 | jknichel | if (initialize_wireless() < 0) { |
49 | 20 | jknichel | fprintf(stderr, "%s: initWireless failed\n", __FUNCTION__);
|
50 | return -1; |
||
51 | } |
||
52 | |||
53 | return 0; |
||
54 | } |
||
55 | |||
56 | 22 | jknichel | |
57 | 20 | jknichel | int ColonetServer::log_error(char * error_message) { |
58 | return logger.logMessage(LOG_TYPE_ERROR, error_message);
|
||
59 | } |
||
60 | |||
61 | int ColonetServer::log_message(char * message) { |
||
62 | return logger.logMessage(LOG_TYPE_MESSAGE, message);
|
||
63 | } |
||
64 | |||
65 | 24 | jknichel | int ColonetServer::run_server() {
|
66 | 20 | jknichel | connection_pool.set_listen_socket_in_ready_set(listen_socket); |
67 | |||
68 | //TODO: why is all of this in that if statement and not just conn_pool.maxfd = listen_socket ?
|
||
69 | if (listen_socket > connection_pool.get_max_file_descriptor()) {
|
||
70 | connection_pool.set_max_file_descriptor(listen_socket); |
||
71 | |||
72 | 11 | emarinel | int acceptSocket = 0; |
73 | struct sockaddr_in clientAddr;
|
||
74 | socklen_t clen = sizeof(clientAddr);
|
||
75 | struct timeval selectTimeout;
|
||
76 | |||
77 | memset(&selectTimeout,0,sizeof(selectTimeout)); |
||
78 | |||
79 | 20 | jknichel | logger.logMessage(LOG_TYPE_MESSAGE, "Server initialized. About to start listening for connections");
|
80 | 11 | emarinel | |
81 | while(1) { |
||
82 | 20 | jknichel | connection_pool.perform_select(listen_socket, &selectTimeout); |
83 | 11 | emarinel | |
84 | //either no descriptors are ready or there was an error
|
||
85 | //TODO: check for specific errors
|
||
86 | if (connection_pool.get_number_clients_ready() <= 0) { |
||
87 | continue;
|
||
88 | } |
||
89 | |||
90 | 20 | jknichel | if (connection_pool.is_socket_ready_to_read(listen_socket)) {
|
91 | 11 | emarinel | printf("Something is trying to connect...\n");
|
92 | 20 | jknichel | if ((acceptSocket = accept(listen_socket, (struct sockaddr*) &clientAddr, &clen)) < 0) { |
93 | 11 | emarinel | if (errno == EMFILE) {
|
94 | printf("\tWhen attempting to accept a connection, "
|
||
95 | "reached the per process limit of file descriptors."
|
||
96 | " Dropping the new connection.\n");
|
||
97 | continue;
|
||
98 | } else {
|
||
99 | printf("\tThere was an error when attempting to accept a "
|
||
100 | "connection");
|
||
101 | } |
||
102 | continue;
|
||
103 | } |
||
104 | |||
105 | char logBuffer[LOG_BUFFER_LENGTH];
|
||
106 | snprintf(logBuffer, LOG_BUFFER_LENGTH, "Client at address %s attempting to connect.", inet_ntoa(clientAddr.sin_addr));
|
||
107 | 20 | jknichel | logger.logMessage(LOG_TYPE_CONNECT, logBuffer); |
108 | 11 | emarinel | |
109 | //TODO: remove this
|
||
110 | //printf("Attempting to add a client.\n");
|
||
111 | |||
112 | |||
113 | if (connection_pool.add_client(acceptSocket) < 0) { |
||
114 | printf("\tThere was an error when trying to add a client to the "
|
||
115 | "connection pool.");
|
||
116 | continue;
|
||
117 | } |
||
118 | |||
119 | snprintf(logBuffer, LOG_BUFFER_LENGTH, "Client at address %s successfully added to connection pool.", inet_ntoa(clientAddr.sin_addr));
|
||
120 | 20 | jknichel | logger.logMessage(LOG_TYPE_CONNECT, logBuffer); |
121 | 11 | emarinel | |
122 | } |
||
123 | |||
124 | 22 | jknichel | if (connection_pool.check_clients(wireless) < 0) { |
125 | 11 | emarinel | printf("\tThere was an error trying to update the clients.");
|
126 | continue;
|
||
127 | } |
||
128 | } |
||
129 | } |
||
130 | |||
131 | 20 | jknichel | return 0; |
132 | 11 | emarinel | } |
133 | 20 | jknichel | |
134 | ConnectionPool * ColonetServer::get_connection_pool_pointer() { |
||
135 | return &connection_pool;
|
||
136 | } |
||
137 | 22 | jknichel | |
138 | 24 | jknichel | int ColonetServer::get_listen_socket() {
|
139 | return listen_socket;
|
||
140 | } |
||
141 | |||
142 | 23 | jknichel | int ColonetServer::initialize_wireless()
|
143 | { |
||
144 | char* log_filename = NULL; |
||
145 | 22 | jknichel | |
146 | 23 | jknichel | if (optionsG.logging_enabled) {
|
147 | log_filename = optionsG.log_filename; |
||
148 | } |
||
149 | |||
150 | wireless = new ColonetWireless(optionsG.wireless_port,
|
||
151 | wirelessMessageHandler, log_filename, |
||
152 | /*!optionsG.listener_mode*/false, true); |
||
153 | //Note: last arg set to true ignores token ring; in general, this should
|
||
154 | //probably be false (changed for demo purposes)
|
||
155 | |||
156 | if (!wireless->run_listener_thread()) {
|
||
157 | return -1; |
||
158 | } |
||
159 | |||
160 | return 0; |
||
161 | } |
||
162 | |||
163 | int ColonetServer::initConnection(int port) |
||
164 | { |
||
165 | printf("Initializing connection that will be used to listen for "
|
||
166 | "clients...\n");
|
||
167 | int opts = 1; |
||
168 | struct sockaddr_in my_addr;
|
||
169 | |||
170 | //get a socket fd
|
||
171 | 24 | jknichel | if ((listen_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
172 | 23 | jknichel | printf("\tThere was an error creating a socket\n");
|
173 | return -1; |
||
174 | } |
||
175 | |||
176 | //set up the address struct
|
||
177 | memset(&my_addr,'\0',sizeof(my_addr)); |
||
178 | my_addr.sin_family = AF_INET; |
||
179 | my_addr.sin_addr.s_addr = htonl(INADDR_ANY); |
||
180 | my_addr.sin_port = htons(port); |
||
181 | |||
182 | 24 | jknichel | setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opts, sizeof(opts));
|
183 | 23 | jknichel | |
184 | //get the current socket options
|
||
185 | 24 | jknichel | if ((opts = fcntl(listen_socket, F_GETFL)) < 0) { |
186 | 23 | jknichel | printf("\tThere was an error getting the socket options.\n");
|
187 | return -1; |
||
188 | } |
||
189 | |||
190 | //set the socket to non blocking
|
||
191 | opts = (opts | O_NONBLOCK); |
||
192 | 24 | jknichel | if (fcntl(listen_socket, F_SETFL, opts) < 0) { |
193 | 23 | jknichel | printf("\tThere was an error setting the socket to be non blocking.\n");
|
194 | return -1; |
||
195 | } |
||
196 | |||
197 | //bind the socket to listen on the specified port
|
||
198 | 24 | jknichel | if (bind(listen_socket, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) { |
199 | 23 | jknichel | printf("\tThere was an error binding the socket\n");
|
200 | return -1; |
||
201 | } |
||
202 | |||
203 | return 0; |
||
204 | } |
||
205 | |||
206 | 24 | jknichel | int main(int argc, char** argv) { |
207 | ColonetServer colonet_server; |
||
208 | |||
209 | connection_pool = colonet_server.get_connection_pool_pointer(); |
||
210 | |||
211 | if (colonet_server.initialize_server(argc, argv) < 0) { |
||
212 | colonet_server.log_error("\t\nThere was an error initializing the server. "
|
||
213 | "Terminating server...\n");
|
||
214 | return -1; |
||
215 | } |
||
216 | |||
217 | if (listen(colonet_server.get_listen_socket(), LISTEN_BACKLOG) < 0) { |
||
218 | colonet_server.log_error("\t\nThere was an error telling the socket to "
|
||
219 | "listen for connections from clients. Terminating Server...\n");
|
||
220 | return -1; |
||
221 | } |
||
222 | |||
223 | colonet_server.run_server(); |
||
224 | |||
225 | return 0; |
||
226 | } |
||
227 | |||
228 | 23 | jknichel | //this is old code that was commented out that I didn't want to delete yet
|
229 | /*
|
||
230 | int parseCommandLine(int argc, char * argv[], commandParams_t * params)
|
||
231 | {
|
||
232 | printf("Parsing Command Line...\n");
|
||
233 | if (!params)
|
||
234 | return -1;
|
||
235 | |||
236 | //if no command line parameters were specified, set to defaults
|
||
237 | if (argc == 1) {
|
||
238 | printf("No port was specified for listening for client connections."
|
||
239 | " Defaulting to %d\n", DEFAULTPORT);
|
||
240 | params->listenPort = DEFAULTPORT;
|
||
241 | }
|
||
242 | |||
243 | if (!argv)
|
||
244 | return -1;
|
||
245 | |||
246 | int i;
|
||
247 | for (i = 1; i < argc; i++) {
|
||
248 | char * temp = argv[i];
|
||
249 | if (temp[0] != '-')
|
||
250 | {
|
||
251 | printUsage(argv[0]);
|
||
252 | return -1;
|
||
253 | }
|
||
254 | |||
255 | switch(temp[1])
|
||
256 | {
|
||
257 | case 'h': printUsage(argv[0]);
|
||
258 | break;
|
||
259 | case 'p':
|
||
260 | {
|
||
261 | if (i >= argc-1)
|
||
262 | {
|
||
263 | printUsage(argv[0]);
|
||
264 | return -1;
|
||
265 | }
|
||
266 | i++;
|
||
267 | char * portString = argv[i];
|
||
268 | char * endptr = NULL;
|
||
269 | int port = strtol(portString, &endptr, 10);
|
||
270 | if (*endptr != '\0')
|
||
271 | {
|
||
272 | printf("Invalid port specified...%s, %d\n", endptr, port);
|
||
273 | return -1;
|
||
274 | }
|
||
275 | if (port < SMALLEST_POSS_LISTEN_PORT)
|
||
276 | {
|
||
277 | printf("You cannot listen on a port less than %d.\n",
|
||
278 | SMALLEST_POSS_LISTEN_PORT);
|
||
279 | return -1;
|
||
280 | }
|
||
281 | params->listenPort = port;
|
||
282 | printf("Setting port to listen on to %d.\n", params->listenPort);
|
||
283 | }
|
||
284 | break;
|
||
285 | default: printUsage(argv[0]);
|
||
286 | return -1;
|
||
287 | break;
|
||
288 | }
|
||
289 | }
|
||
290 | |||
291 | return 0;
|
||
292 | }
|
||
293 | */
|