00001 #ifndef SERVER_H
00002 #define SERVER_H
00003 #include <stdio.h>
00004 #include <list>
00005 #include <string>
00006 #include <stdlib.h>
00007 #include <sys/types.h>
00008 #include <sys/time.h>
00009 #include <sys/socket.h>
00010 #include <sys/resource.h>
00011 #include <unistd.h>
00012 #include <netinet/in.h>
00013 #include <sys/ioctl.h>
00014 #include <signal.h>
00015 #include <arpa/inet.h>
00016 #include <errno.h>
00017
00018 #include "engine/loop_thread_obj.h"
00019 #include "tools/conf.h"
00020 #include "tools/log.h"
00021
00022 template <class A>
00023 class Server : public FastLoopThreadObj
00024 {
00025 std::list<A*> clients;
00026 int fd;
00027 fd_set sock_set;
00028 int port;
00029
00030 public :
00031 Server(std::string name);
00032 ~Server();
00033 void Loop();
00034 void OnStop();
00035 };
00036
00037 template <class A>
00038 Server<A>::Server(std::string name) : FastLoopThreadObj(name)
00039 {
00040
00041
00042 if( signal(SIGPIPE, SIG_IGN) == SIG_ERR )
00043 log(LogPanic, "Could not ignore SIGPIPE");
00044
00045 fd = -1;
00046
00047 Config conf;
00048 if(!conf.Get(name + "_port", port))
00049 {
00050 std::string conf_port = name + "_port";
00051 log(LogPanic, "Couldn't find configuration option %s", conf_port.c_str());
00052 }
00053
00054 log(LogInfo, "Starting server listening on port %i", port);
00055
00056 fd = socket(AF_INET, SOCK_STREAM, 0);
00057 int on = 1;
00058 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
00059
00060 struct sockaddr_in address;
00061 address.sin_family = AF_INET;
00062 address.sin_addr.s_addr = htonl(INADDR_ANY);
00063 address.sin_port = htons(port);
00064
00065 if ( bind(fd, (struct sockaddr*) &address, sizeof(address)) == -1 )
00066 log(LogPanic, "Could not bind to port %i : %s", port, strerror(errno));
00067
00068
00069
00070
00071 if ( listen(fd, 128) == -1 )
00072 log(LogPanic, "Unable to socket's queue size...\n");
00073
00074
00075 memset(&sock_set, 0, sizeof(sock_set));
00076 FD_ZERO(&sock_set);
00077 FD_SET(fd, &sock_set);
00078 }
00079
00080 template <class A>
00081 Server<A>::~Server()
00082 {
00083 }
00084
00085 template <class A>
00086 void Server<A>::Loop()
00087 {
00088 if(fd == -1)
00089 return;
00090
00091 struct timeval timeout;
00092 fd_set acting_socket;
00093 memset(&timeout, 0, sizeof(struct timeval));
00094
00095 timeout.tv_sec = 0;
00096 timeout.tv_usec = 100000;
00097
00098 acting_socket = sock_set;
00099
00100 if ( select(fd + 1, &acting_socket, NULL, NULL, &timeout) < 0)
00101 {
00102 if(timeout.tv_sec != 0 && timeout.tv_usec != 0)
00103 log(LogPanic, "Error during select");
00104 }
00105
00106
00107 if( FD_ISSET(fd, &acting_socket) )
00108 {
00109 int client_fd;
00110 struct sockaddr_in client_address;
00111 socklen_t addr_size = sizeof(client_address);
00112
00113 client_fd = accept(fd, (struct sockaddr*)&client_address, &addr_size);
00114
00115 if(client_fd == -1)
00116 {
00117 log(LogError, "Unable to accept client..");
00118 return;
00119 }
00120
00121 FD_SET(client_fd, &sock_set);
00122
00123
00124 const int buflen = 256;
00125 char buf[buflen];
00126 char buf2[buflen];
00127
00128 if(inet_ntop(AF_INET, &client_address.sin_addr.s_addr, buf, buflen) == NULL)
00129 strcpy(buf, "Unknown address");
00130 snprintf(buf2, buflen, "%s:%i", buf, ntohs(client_address.sin_port));
00131
00132 log(LogInfo, "New client from %s", buf2);
00133
00134 A* c = new A(buf2, client_fd);
00135 c->Start();
00136 clients.push_back(c);
00137 }
00138
00139 typename std::list<A*>::iterator c = clients.begin();
00140 while(c != clients.end())
00141 {
00142 if(!(*c)->IsConnected())
00143 {
00144 (*c)->Stop();
00145 delete (*c);
00146 c = clients.erase(c);
00147 }
00148 else
00149 ++c;
00150 }
00151 }
00152
00153 template <class A>
00154 void Server<A>::OnStop()
00155 {
00156 if(fd == -1)
00157 return;
00158
00159 typename std::list<A*>::iterator c = clients.begin();
00160 while(c != clients.end())
00161 {
00162 (*c)->Disconnect();
00163 (*c)->Stop();
00164 delete (*c);
00165 ++c;
00166 }
00167 FD_ZERO(&sock_set);
00168 close(fd);
00169 }
00170
00171 #endif