aboutsummaryrefslogtreecommitdiff
path: root/src/serversocket.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2007-07-03 00:28:59 +0000
committerMike Buland <eichlan@xagasoft.com>2007-07-03 00:28:59 +0000
commitac517a2b7625e0aa0862679e961c6349f859ea3b (patch)
treee3e27a6b9bd5e2be6150088495c91fc91786ad9d /src/serversocket.cpp
parentf8d4301e9fa4f3709258505941e37fab2eadadc6 (diff)
parentbd865cee5f89116c1f054cd0e5c275e97c2d0a9b (diff)
downloadlibbu++-ac517a2b7625e0aa0862679e961c6349f859ea3b.tar.gz
libbu++-ac517a2b7625e0aa0862679e961c6349f859ea3b.tar.bz2
libbu++-ac517a2b7625e0aa0862679e961c6349f859ea3b.tar.xz
libbu++-ac517a2b7625e0aa0862679e961c6349f859ea3b.zip
The reorg is being put in trunk, I think it's ready. Now we just get to find
out how many applications won't work anymore :)
Diffstat (limited to 'src/serversocket.cpp')
-rw-r--r--src/serversocket.cpp158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/serversocket.cpp b/src/serversocket.cpp
new file mode 100644
index 0000000..1424630
--- /dev/null
+++ b/src/serversocket.cpp
@@ -0,0 +1,158 @@
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 <fcntl.h>
14#include "serversocket.h"
15#include "exceptions.h"
16
17Bu::ServerSocket::ServerSocket( int nPort, int nPoolSize ) :
18 nPort( nPort )
19{
20 /* Create the socket and set it up to accept connections. */
21 struct sockaddr_in name;
22
23 /* Give the socket a name. */
24 name.sin_family = AF_INET;
25 name.sin_port = htons( nPort );
26
27 // I think this specifies who we will accept connections from,
28 // a good thing to make configurable later on
29 name.sin_addr.s_addr = htonl( INADDR_ANY );
30
31 startServer( name, nPoolSize );
32}
33
34Bu::ServerSocket::ServerSocket(const FString &sAddr,int nPort, int nPoolSize) :
35 nPort( nPort )
36{
37 /* Create the socket and set it up to accept connections. */
38 struct sockaddr_in name;
39
40 /* Give the socket a name. */
41 name.sin_family = AF_INET;
42 name.sin_port = htons( nPort );
43
44 inet_aton( sAddr.getStr(), &name.sin_addr );
45
46 startServer( name, nPoolSize );
47}
48
49Bu::ServerSocket::~ServerSocket()
50{
51}
52
53void Bu::ServerSocket::startServer( struct sockaddr_in &name, int nPoolSize )
54{
55 /* Create the socket. */
56 nServer = socket( PF_INET, SOCK_STREAM, 0 );
57 if( nServer < 0 )
58 {
59 throw Bu::SocketException("Couldn't create a listen socket.");
60 }
61
62 int opt = 1;
63 setsockopt(
64 nServer,
65 SOL_SOCKET,
66 SO_REUSEADDR,
67 (char *)&opt,
68 sizeof( opt )
69 );
70
71 if( bind( nServer, (struct sockaddr *) &name, sizeof(name) ) < 0 )
72 {
73 throw Bu::SocketException("Couldn't bind to the listen socket.");
74 }
75
76 if( listen( nServer, nPoolSize ) < 0 )
77 {
78 throw Bu::SocketException(
79 "Couldn't begin listening to the server socket."
80 );
81 }
82
83 FD_ZERO( &fdActive );
84 /* Initialize the set of active sockets. */
85 FD_SET( nServer, &fdActive );
86}
87
88int Bu::ServerSocket::getSocket()
89{
90 return nServer;
91}
92
93int Bu::ServerSocket::accept( int nTimeoutSec, int nTimeoutUSec )
94{
95 fd_set fdRead = fdActive;
96
97 struct timeval xT;
98
99 xT.tv_sec = nTimeoutSec;
100 xT.tv_usec = nTimeoutUSec;
101
102 if( TEMP_FAILURE_RETRY(select( nServer+1, &fdRead, NULL, NULL, &xT )) < 0 )
103 {
104 throw SocketException(
105 "Error scanning for new connections: %s", strerror( errno )
106 );
107 }
108
109 if( FD_ISSET( nServer, &fdRead ) )
110 {
111 struct sockaddr_in clientname;
112 size_t size;
113 int nClient;
114
115 size = sizeof( clientname );
116#ifdef __CYGWIN__
117 nClient = ::accept( nServer, (struct sockaddr *)&clientname,
118 (int *)&size
119 );
120#else
121 nClient = ::accept( nServer, (struct sockaddr *)&clientname, &size );
122#endif
123 if( nClient < 0 )
124 {
125 throw SocketException(
126 "Error accepting a new connection: %s", strerror( errno )
127 );
128 }
129 char tmpa[20];
130 inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 );
131 //"New connection from host %s, port %hd.",
132 // tmpa, ntohs (clientname.sin_port) );
133
134 {
135 int flags;
136
137 flags = fcntl( nClient, F_GETFL, 0 );
138 flags |= O_NONBLOCK;
139 if( fcntl( nClient, F_SETFL, flags ) < 0)
140 {
141 throw SocketException(
142 "Error setting option on client socket: %s",
143 strerror( errno )
144 );
145 }
146 }
147
148 return nClient;
149 }
150
151 return -1;
152}
153
154int Bu::ServerSocket::getPort()
155{
156 return nPort;
157}
158