aboutsummaryrefslogtreecommitdiff
path: root/src/old/connectionmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/old/connectionmanager.cpp')
-rw-r--r--src/old/connectionmanager.cpp397
1 files changed, 397 insertions, 0 deletions
diff --git a/src/old/connectionmanager.cpp b/src/old/connectionmanager.cpp
new file mode 100644
index 0000000..ea60b2b
--- /dev/null
+++ b/src/old/connectionmanager.cpp
@@ -0,0 +1,397 @@
1#include <time.h>
2#include <string.h>
3#include <stdio.h>
4#include <errno.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <sys/types.h>
8#include <sys/socket.h>
9#include <termios.h>
10#include <netinet/in.h>
11#include <netdb.h>
12#include <arpa/inet.h>
13#include "connectionmanager.h"
14#include <fcntl.h>
15
16ConnectionManager::ConnectionManager( int nInitPool ) :
17 xLog( MultiLog::getInstance() )
18{
19 //nMasterSocket = -1;
20 pMonitor = NULL;
21 for( int j = 0; j < nInitPool; j++ )
22 {
23 lInactive.insert( lInactive.begin(), new Connection() );
24 }
25 FD_ZERO (&fdActive);
26 FD_ZERO (&fdRead);
27 FD_ZERO (&fdWrite);
28 FD_ZERO (&fdException);
29}
30
31ConnectionManager::~ConnectionManager()
32{
33 std::list<Connection *>::const_iterator i;
34 for( i = lActive.begin(); i != lActive.end(); i++ )
35 {
36 delete (*i);
37 }
38 for( i = lInactive.begin(); i != lInactive.end(); i++ )
39 {
40 delete (*i);
41 }
42}
43
44bool ConnectionManager::startServer( int nPort )
45{
46 /* Create the socket and set it up to accept connections. */
47 struct sockaddr_in name;
48
49 /* Give the socket a name. */
50 name.sin_family = AF_INET;
51 name.sin_port = htons( nPort );
52
53 // I think this specifies who we will accept connections from,
54 // a good thing to make configurable later on
55 name.sin_addr.s_addr = htonl( INADDR_ANY );
56
57 return startServer( name );
58}
59
60bool ConnectionManager::startServer( const char *sAddr, int nPort )
61{
62 /* Create the socket and set it up to accept connections. */
63 struct sockaddr_in name;
64
65 /* Give the socket a name. */
66 name.sin_family = AF_INET;
67 name.sin_port = htons( nPort );
68
69 inet_aton( sAddr, &name.sin_addr );
70
71 return startServer( name );
72}
73
74bool ConnectionManager::startServer( struct sockaddr_in &name )
75{
76 /* Create the socket. */
77 int nMasterSocket = socket (PF_INET, SOCK_STREAM, 0);
78 if (nMasterSocket < 0)
79 {
80 xLog.LineLog( MultiLog::LError, "Couldn't create a listen socket.");
81 return false;
82 }
83
84 int opt = 1;
85 setsockopt(
86 nMasterSocket,
87 SOL_SOCKET,
88 SO_REUSEADDR,
89 (char *)&opt,
90 sizeof(opt)
91 );
92
93 if (bind (nMasterSocket, (struct sockaddr *) &name, sizeof (name)) < 0)
94 {
95 xLog.LineLog( MultiLog::LError, "Couldn't bind to the listen socket.");
96 return false;
97 }
98
99 if (listen (nMasterSocket, 40) < 0)
100 {
101 xLog.LineLog( MultiLog::LError, "Couldn't begin listening to the server socket.");
102 return false;
103 }
104
105 /* Initialize the set of active sockets. */
106 FD_SET (nMasterSocket, &fdActive);
107
108 sMasterSocket[nMasterSocket] = name.sin_port;
109
110 return true;
111}
112
113bool ConnectionManager::startServer( int nPort, int nNumTries, int nTimeout )
114{
115 struct timeval xTimeout;
116
117 for( int j = 0; j < nNumTries; j++ )
118 {
119 xLog.LineLog( MultiLog::LStatus, "Attempting to create server socket (attempt [%d/%d])...", j+1, nNumTries );
120 if( startServer( nPort ) == true )
121 {
122 return true;
123 }
124 else if( j < nNumTries-1 )
125 {
126 xLog.LineLog( MultiLog::LStatus, "Waiting for %d secconds to allow port to clear...", nTimeout );
127 xTimeout.tv_sec = nTimeout;
128 xTimeout.tv_usec = 0;
129 if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) {
130 xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while.");
131 }
132 usleep( nTimeout );
133 }
134 }
135
136 return false;
137}
138
139bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout )
140{
141 struct timeval xTimeout;
142
143 xTimeout.tv_sec = nTimeout / 1000000;
144 xTimeout.tv_usec = nTimeout % 1000000;
145
146 /* Block until input arrives on one or more active sockets. */
147 fdRead = fdActive;
148 fdWrite = fdActive;
149 fdException = fdActive;
150
151 // We removed the write checking because it just checks to see if you *can*
152 // write...that's stupid, they're all open, so it always exits immediately
153 // if there are ANY connections there...
154 if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, (fd_set *)0/*&fdWrite*/, &fdException, &xTimeout ) ) < 0 )
155 {
156 xLog.LineLog( MultiLog::LError, "Error attempting to scan open connections.");
157 perror("ConnectionManager");
158 return false;
159 }
160 // Now we use select to sleep as well as to scan for connections, now we
161 // just need to fix the fact that if there are no connections, the seccond
162 // select call doesn't return until there is a connection...
163 if( bForceTimeout )
164 {
165 if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) {
166 xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while.");
167 }
168 }
169
170 /* Service all the sockets with input pending. */
171 for( int i = 0; i < FD_SETSIZE; ++i )
172 {
173 if( FD_ISSET( i, &fdRead ) )
174 {
175 if( sMasterSocket.find( i ) != sMasterSocket.end() )
176 {
177 addConnection( i );
178 }
179 else
180 {
181 Connection *pCon = findActiveConnection( i );
182 if( pCon == NULL )
183 {
184 xLog.LineLog( MultiLog::LError, "A connection object was lost, or never created!");
185 return false;
186 }
187
188 /* Data arriving on an already-connected socket. */
189 if( pCon->readInput() == 0 )
190 {
191 xLog.LineLog( MultiLog::LStatus, "Closing connection due to disconnect.");
192 close( i );
193 FD_CLR( i, &fdActive );
194 pMonitor->onClosedConnection( pCon );
195 pCon->close();
196 }
197 else
198 {
199 // We actually read something...but the connection handles
200 // protocol notification, so we don't need to do anything
201 // here...
202 }
203 }
204 }
205 }
206 std::list<Connection *>::iterator i;
207 for( i = lActive.begin(); i != lActive.end(); i++ )
208 {
209 if( (*i)->isActive() == false )
210 {
211 std::list<Connection *>::iterator l = i;
212 i--;
213 lInactive.insert( lInactive.end(), *l );
214 lActive.erase( l );
215 continue;
216 }
217 (*i)->getProtocol()->poll();
218 if( (*i)->hasOutput() )
219 {
220 (*i)->writeOutput();
221 }
222 if( (*i)->needDisconnect() && !(*i)->hasOutput() )
223 {
224 int prt = (*i)->getSocket();
225 close( prt );
226 FD_CLR( prt, &fdActive );
227 pMonitor->onClosedConnection( *i );
228 (*i)->close();
229 lInactive.insert( lInactive.end(), *i );
230 std::list<Connection *>::iterator l = i;
231 i--;
232 lActive.erase( l );
233 xLog.LineLog( MultiLog::LStatus, "Closing connection due to server request.");
234 }
235 }
236
237 return true;
238}
239
240bool ConnectionManager::shutdownServer()
241{
242 while( !lActive.empty() )
243 {
244 Connection *i = *(lActive.begin());
245 if( i->isActive() )
246 {
247 pMonitor->onClosedConnection( i );
248 i->close();
249 lInactive.insert( lInactive.end(), i );
250 lActive.erase( lActive.begin() );
251 }
252 }
253/*
254 for( int i = 0; i < nPoolSize; i++ )
255 {
256
257 int prt = axConPool[i].getSocket();
258 close( prt );
259// FD_CLR( prt, &fdActive );
260 pMonitor->onClosedConnection( &axConPool[i] );
261 axConPool[i].close();
262 }
263*/
264 std::map<int,int>::iterator i;
265 for( i = sMasterSocket.begin(); i != sMasterSocket.end(); i++ )
266 {
267 int nSocket = (*i).first;
268 shutdown( nSocket, SHUT_RDWR );
269 close( nSocket );
270 }
271
272 return true;
273}
274
275bool ConnectionManager::broadcastMessage( const char *lpData, int nExcludeSocket )
276{
277 std::list<Connection *>::const_iterator i;
278 for( i = lActive.begin(); i != lActive.end(); i++ )
279 {
280 if( (*i)->isActive() &&
281 (*i)->getSocket() != nExcludeSocket )
282 {
283 (*i)->appendOutput( lpData );
284 }
285 }
286
287 return true;
288}
289
290bool ConnectionManager::addConnection( int nSocket )
291{
292 struct sockaddr_in clientname;
293 size_t size;
294 int newSocket;
295
296 size = sizeof( clientname );
297#ifdef __CYGWIN__
298 newSocket = accept( nSocket, (struct sockaddr *) &clientname, (int *)&size );
299#else
300 newSocket = accept( nSocket, (struct sockaddr *) &clientname, &size );
301#endif
302 if( newSocket < 0 )
303 {
304 xLog.LineLog( MultiLog::LError, "Error accepting a new connection!" );
305 return false;
306 }
307// char *tmpa = inet_ntoa(clientname.sin_addr);
308 char tmpa[20];
309 inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 );
310 xLog.LineLog( MultiLog::LStatus, "New connection from host %s, port %hd.", tmpa, ntohs (clientname.sin_port) );
311/*
312 int nCnt = 0;
313 for( int j = 0; j < nPoolSize; j++ )
314 {
315 if( axConPool[j].isActive() )
316 {
317 nCnt++;
318 }
319 }
320 xLog.LineLog( MultiLog::LStatus, "Connections %d/%d.", nCnt, nPoolSize );
321 */
322// free( tmpa );
323 FD_SET( newSocket, &fdActive );
324
325 //void nonblock(socket_t s)
326 {
327 int flags;
328
329 flags = fcntl(newSocket, F_GETFL, 0);
330 flags |= O_NONBLOCK;
331 if (fcntl(newSocket, F_SETFL, flags) < 0)
332 {
333 return false;
334 }
335 }
336
337 Connection *pCon = getInactiveConnection();
338 pCon->open( newSocket );
339
340 pMonitor->onNewConnection( pCon, (*sMasterSocket.find(nSocket)).second );
341 if( pCon->getProtocol() )
342 pCon->getProtocol()->onNewConnection();
343
344 lActive.insert( lActive.end(), pCon );
345
346 return true;
347}
348
349void ConnectionManager::connect(
350 const char *lpAddress,
351 int nPort,
352 int nProtocolPort,
353 Protocol *pNewProto
354 )
355{
356 Connection *pCon = getInactiveConnection();
357 pCon->open( lpAddress, nPort );
358 int nSocket = pCon->getSocket();
359 FD_SET( nSocket, &fdActive );
360
361 pCon->setProtocol( pNewProto );
362 pMonitor->onNewClientConnection( pCon, nProtocolPort );
363 if( pCon->getProtocol() )
364 pCon->getProtocol()->onNewClientConnection();
365
366 lActive.insert( lActive.end(), pCon );
367}
368
369Connection *ConnectionManager::getInactiveConnection()
370{
371 if( lInactive.empty() )
372 {
373 return new Connection();
374 }
375 Connection *pCon = *(lInactive.begin());
376 lInactive.erase( lInactive.begin() );
377 return pCon;
378}
379
380Connection *ConnectionManager::findActiveConnection( int nSocket )
381{
382 std::list<Connection *>::const_iterator i;
383 for( i = lActive.begin(); i != lActive.end(); i++ )
384 {
385 if( (*i)->getSocket() == nSocket )
386 {
387 return *i;
388 }
389 }
390
391 return NULL;
392}
393
394void ConnectionManager::setConnectionMonitor( ConnectionMonitor *pNewMonitor )
395{
396 pMonitor = pNewMonitor;
397}