aboutsummaryrefslogtreecommitdiff
path: root/src/stable/serversockettcp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/serversockettcp.cpp')
-rw-r--r--src/stable/serversockettcp.cpp254
1 files changed, 254 insertions, 0 deletions
diff --git a/src/stable/serversockettcp.cpp b/src/stable/serversockettcp.cpp
new file mode 100644
index 0000000..c3750b2
--- /dev/null
+++ b/src/stable/serversockettcp.cpp
@@ -0,0 +1,254 @@
1/*
2 * Copyright (C) 2007-2019 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/config.h"
9
10#ifndef WIN32
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <netdb.h>
14 #include <arpa/inet.h>
15#endif
16
17#include <time.h>
18#include <string.h>
19#include <stdio.h>
20#include <errno.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <sys/types.h>
24//#include <termios.h>
25#include <fcntl.h>
26#include "bu/serversockettcp.h"
27#include "bu/sockettcp.h"
28
29namespace Bu { subExceptionDef( ServerSocketTcpException ) }
30
31Bu::ServerSocketTcp::ServerSocketTcp( int iPort, int nPoolSize ) :
32 iPort( iPort )
33{
34#ifdef WIN32
35 Bu::Winsock2::getInstance();
36#endif
37
38 /* Create the socket and set it up to accept connections. */
39 struct sockaddr_in name;
40
41 /* Give the socket a name. */
42 name.sin_family = AF_INET;
43 name.sin_port = bu_htons( iPort );
44
45 // I think this specifies who we will accept connections from,
46 // a good thing to make configurable later on
47 name.sin_addr.s_addr = bu_htonl( INADDR_ANY );
48
49 startServer( name, nPoolSize );
50}
51
52Bu::ServerSocketTcp::ServerSocketTcp(const String &sAddr,int iPort, int nPoolSize) :
53 iPort( iPort )
54{
55#ifdef WIN32
56 Bu::Winsock2::getInstance();
57#endif
58
59 /* Create the socket and set it up to accept connections. */
60 struct sockaddr_in name;
61
62 /* Give the socket a name. */
63 name.sin_family = AF_INET;
64
65 name.sin_port = bu_htons( iPort );
66
67#ifdef WIN32
68 name.sin_addr.s_addr = bu_inet_addr( sAddr.getStr() );
69#else
70 inet_aton( sAddr.getStr(), &name.sin_addr );
71#endif
72
73 startServer( name, nPoolSize );
74}
75
76Bu::ServerSocketTcp::ServerSocketTcp( socket_t iSocket, bool bInit, int nPoolSize ) :
77 iSocket( iSocket ),
78 iPort( 0 )
79{
80#ifdef WIN32
81 Bu::Winsock2::getInstance();
82#endif
83
84 if( bInit )
85 {
86 struct sockaddr name;
87 socklen_t namelen = sizeof(name);
88 getpeername( iSocket, &name, &namelen );
89
90 initServer( *((sockaddr_in *)&name), nPoolSize );
91 }
92 else
93 {
94 FD_ZERO( &fdActive );
95 FD_SET( iSocket, &fdActive );
96 }
97}
98
99Bu::ServerSocketTcp::ServerSocketTcp( const ServerSocketTcp &rSrc )
100{
101#ifdef WIN32
102 Bu::Winsock2::getInstance();
103#endif
104
105 iSocket = dup( rSrc.iSocket );
106 iPort = rSrc.iPort;
107 FD_ZERO( &fdActive );
108 FD_SET( iSocket, &fdActive );
109}
110
111Bu::ServerSocketTcp::~ServerSocketTcp()
112{
113#ifdef WIN32
114 if( iSocket != INVALID_SOCKET )
115#else
116 if( iSocket > -1 )
117#endif
118 ::close( iSocket );
119}
120
121void Bu::ServerSocketTcp::startServer( struct sockaddr_in &name, int nPoolSize )
122{
123 /* Create the socket. */
124 iSocket = bu_socket( PF_INET, SOCK_STREAM, 0 );
125
126#ifdef WIN32
127 if( iSocket == INVALID_SOCKET )
128#else
129 if( iSocket < 0 )
130#endif
131 {
132 throw Bu::ServerSocketTcpException("Couldn't create a listen socket.");
133 }
134
135 int opt = 1;
136 bu_setsockopt(
137 iSocket,
138 SOL_SOCKET,
139 SO_REUSEADDR,
140 (char *)&opt,
141 sizeof( opt )
142 );
143
144 initServer( name, nPoolSize );
145}
146
147void Bu::ServerSocketTcp::initServer( struct sockaddr_in &name, int nPoolSize )
148{
149 if( bu_bind( iSocket, (struct sockaddr *) &name, sizeof(name) ) < 0 )
150 {
151 throw Bu::ServerSocketTcpException("Couldn't bind to the listen socket.");
152 }
153
154 if( bu_listen( iSocket, nPoolSize ) < 0 )
155 {
156 throw Bu::ServerSocketTcpException(
157 "Couldn't begin listening to the server socket."
158 );
159 }
160
161 FD_ZERO( &fdActive );
162 /* Initialize the set of active sockets. */
163 FD_SET( iSocket, &fdActive );
164}
165
166Bu::Socket *Bu::ServerSocketTcp::accept( int nTimeoutSec, int nTimeoutUSec )
167{
168 fd_set fdRead = fdActive;
169
170 struct timeval xT;
171
172 xT.tv_sec = nTimeoutSec;
173 xT.tv_usec = nTimeoutUSec;
174
175 if( TEMP_FAILURE_RETRY(
176 bu_select( iSocket+1, &fdRead, NULL, NULL, &xT )) < 0 )
177 {
178 throw Bu::ServerSocketTcpException(
179 "Error scanning for new connections: %s", strerror( errno )
180 );
181 }
182
183 if( FD_ISSET( iSocket, &fdRead ) )
184 {
185 struct sockaddr_in clientname;
186 socklen_t size;
187 int nClient;
188
189 size = sizeof( clientname );
190#ifdef WIN32
191 nClient = bu_accept( iSocket, (struct sockaddr *)&clientname, &size);
192#else /* not-WIN32 */
193#ifdef __CYGWIN__
194 nClient = ::accept( iSocket, (struct sockaddr *)&clientname,
195 (int *)&size
196 );
197#else /* not-cygwin */
198#ifdef __APPLE__
199 nClient = ::accept( iSocket, (struct sockaddr *)&clientname, (socklen_t*)&size );
200#else /* linux */
201 nClient = ::accept( iSocket, (struct sockaddr *)&clientname, &size );
202#endif /* __APPLE__ */
203#endif /* __CYGWIN__ */
204#endif /* WIN32 */
205 if( nClient < 0 )
206 {
207 throw Bu::ServerSocketTcpException(
208 "Error accepting a new connection: %s", strerror( errno )
209 );
210 }
211
212#ifndef WIN32
213 char tmpa[20];
214 inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 );
215 //"New connection from host %s, port %hd.",
216 // tmpa, ntohs (clientname.sin_port) );
217#endif
218
219 {
220#ifndef WIN32
221 int flags;
222 flags = fcntl( nClient, F_GETFL, 0 );
223 flags |= O_NONBLOCK;
224 if( fcntl( nClient, F_SETFL, flags ) < 0)
225 {
226 throw Bu::ServerSocketTcpException(
227 "Error setting option on client socket: %s",
228 strerror( errno )
229 );
230 }
231#else
232 //-------------------------
233 // Set the socket I/O mode: In this case FIONBIO
234 // enables or disables the blocking mode for the
235 // socket based on the numerical value of iMode.
236 // If iMode = 0, blocking is enabled;
237 // If iMode != 0, non-blocking mode is enabled.
238 u_long iMode = 1;
239 bu_ioctlsocket(nClient, FIONBIO, &iMode);
240#endif
241 }
242
243 return new SocketTcp( nClient );
244 }
245
246 return NULL;
247}
248
249bool Bu::ServerSocketTcp::getFd( int &rFdOut ) const
250{
251 rFdOut = iSocket;
252 return true;
253}
254