source: cheroxy/trunk/src/CRXSocket.cpp@ 57

Last change on this file since 57 was 57, checked in by cheese, 11 years ago

#1 add reuseaddr option to server socket and linger option to client socket

File size: 10.1 KB
RevLine 
[6]1/**
2 * CRXSocket.cpp
3 */
4#include "CRXSocket.h"
5
6#include <string.h>
7
8#ifdef _WIN32
9# pragma comment (lib, "ws2_32.lib")
10# define close(__socket) closesocket(__socket)
11#endif
12
13bool CRXSocket::mInitialized = false;
14
15CRXSocket::CRXSocket (int aSocket)
16 : mSocket (aSocket)
17{
18 /*----------------------------------------------------------------*/
[24]19 CRXSocket::Initialize ();
20
[14]21 memset ((void *)&mAddress, 0x0, sizeof (struct sockaddr_in));
[6]22 /*----------------------------------------------------------------*/
23}
24
25CRXSocket::~CRXSocket (void)
26{
27 /*----------------------------------------------------------------*/
28 Close ();
29 /*----------------------------------------------------------------*/
30}
31
32void
33CRXSocket::Attach (int aSocket)
34{
35 /*----------------------------------------------------------------*/
36 mSocket = aSocket;
37 /*----------------------------------------------------------------*/
38}
39
40int
41CRXSocket::Detach (void)
42{
43 int aSocket = mSocket;
44
45 /*----------------------------------------------------------------*/
46 mSocket = 0;
47
48 /*----------------------------------------------------------------*/
49 return aSocket;
50}
51
52void
53CRXSocket::Close (void)
54{
55 /*----------------------------------------------------------------*/
56 if (mSocket <= 0)
57 return ;
58
59 close (mSocket);
60 mSocket = 0;
61 /*----------------------------------------------------------------*/
62}
63
64CRXSocket::operator int (void) const
65{
66 /*----------------------------------------------------------------*/
67 /*----------------------------------------------------------------*/
68 return mSocket;
69}
70
71CRXSocket &
72CRXSocket::operator = (int aSocket)
73{
74 /*----------------------------------------------------------------*/
75 Attach (aSocket);
76 /*----------------------------------------------------------------*/
77 return *this;
78}
79
80int
[24]81CRXSocket::SetTimeout (const int aTimeout)
82{
83 int aResult = 0;
84
85#ifndef _WIN32
86 struct timeval aTimeVal;
87 aTimeVal.tv_sec = aTimeout;
88 aTimeVal.tv_usec= 0;
89#else
90 int aTimeMilliSec = aTimeout * 1000;
91#endif
92
93 /*----------------------------------------------------------------*/
94 if (!IsReady ())
95 return ERROR_TCPSOCKET_NOT_READY;
96
97 if (aTimeout == TCPSOCKET_NO_TIMEOUT)
98 return 0;
99
100 aResult = setsockopt (mSocket,
101 SOL_SOCKET,
102 SO_RCVTIMEO,
103#ifdef _WIN32
104 (char *) &aTimeMilliSec,
105#else
106 &aTimeVal,
[57]107#endif
[24]108 (socklen_t) sizeof (aTimeVal));
109 if (aResult < 0)
110 {
[57]111 aResult = ERROR_TCPSOCKET_FAILED_TO_SET_SOCKOPT;
[35]112 CRX_ERROR_SET (aResult, "Failed to set socket option.");
[24]113 }
114 /*----------------------------------------------------------------*/
115
116 return aResult;
117}
118
119int
[6]120CRXSocket::Initialize (void)
121{
122 int aResult = 0;
123
124 /*----------------------------------------------------------------*/
125 if (CRXSocket::IsInitialized ())
126 return aResult;
127
128#ifdef WIN32
129 WSADATA aWinSockData;
130
131 aResult = WSAStartup (MAKEWORD (2, 0), &aWinSockData);
132 if (aResult != 0)
133 {
[18]134 aResult = ERROR_TCPSOCKET_FAILED_TO_INITIALIZE;
135 return aResult;
[6]136 }
137#endif
138
139 mInitialized = true;
140
141 /*----------------------------------------------------------------*/
142 return aResult;
143}
144
145void
146CRXSocket::Finalize (void)
147{
148 /*----------------------------------------------------------------*/
149#ifdef WIN32
150 WSACleanup ();
151#endif
152 /*----------------------------------------------------------------*/
153}
154
155bool
156CRXSocket::IsInitialized (void)
157{
158 /*----------------------------------------------------------------*/
159 /*----------------------------------------------------------------*/
160 return mInitialized;
161}
162
163bool
164CRXSocket::IsReady (void) const
165{
166 /*----------------------------------------------------------------*/
167 /*----------------------------------------------------------------*/
168 return IsInitialized () && IsCreated ();
169}
170
171bool
172CRXSocket::IsCreated (void) const
173{
174 /*----------------------------------------------------------------*/
175 /*----------------------------------------------------------------*/
176 return mSocket > 0 ? true : false;
177}
178
179int
180CRXSocket::CreateSocket (void)
181{
182 int aResult = -1;
183
184 /*----------------------------------------------------------------*/
185 if (!IsInitialized () || IsCreated ())
[18]186 {
187 aResult = ERROR_TCPSOCKET_ALREADY_IN_USE;
[35]188 CRX_ERROR_SET (aResult, "Already in use.");
[18]189 return aResult;
190 }
[6]191
192 aResult = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
193 if (aResult < 0)
194 {
[18]195 aResult = ERROR_TCPSOCKET_FAILED_TO_CREATE_SOCKET;
[35]196 CRX_ERROR_SET (aResult, "Failed to create socket(%d).", GetSystemErrorCode ());
[18]197 return aResult;
[6]198 }
199
200 mSocket = aResult;
201
202 /*----------------------------------------------------------------*/
203 return aResult;
204}
205
206int
[14]207CRXSocket::Connect (const std::string aUrl,
208 const unsigned short aPort,
209 const int aTimeout)
[6]210{
211 int aResult = -1;
212 struct hostent * aHostEnt;
[57]213 struct linger aLinger;
[6]214
215 /*----------------------------------------------------------------*/
216 aResult = CreateSocket ();
217 if (aResult < 0)
218 {
[24]219 aResult = ERROR_TCPSOCKET_FAILED_TO_CREATE_SOCKET;
[35]220 CRX_ERROR_SET (aResult, "Failed to create socket(%d).", GetSystemErrorCode ());
[6]221 return aResult;
222 }
223
224 mAddress.sin_family = AF_INET;
225 mAddress.sin_port = htons (aPort);
226 mAddress.sin_addr.s_addr = inet_addr (aUrl.c_str ());
227
228 if (mAddress.sin_addr.s_addr == (unsigned int)-1)
229 {
230 aHostEnt = gethostbyname (aUrl.c_str ());
231 if (aHostEnt == NULL)
232 {
[18]233 aResult = ERROR_TCPSOCKET_FAILED_TO_GET_HOSTNAME;
[35]234 CRX_ERROR_SET (aResult, "Failed to get hostname.");
[18]235 return aResult;
[6]236 }
237 mAddress.sin_family = aHostEnt->h_addrtype;
238 memcpy (&(mAddress.sin_addr.s_addr), aHostEnt->h_addr, aHostEnt->h_length);
239 }
240
[57]241 aLinger.l_onoff = 1;
242 aLinger.l_linger = 0;
243 aResult = setsockopt (mSocket,
244 SOL_SOCKET,
245 SO_LINGER,
246#ifdef _WIN32
247 (char *) &aLinger,
248#else
249 &aLinger,
250#endif
251 (socklen_t) sizeof (aLinger));
252 if (aResult < 0)
253 {
254 aResult = ERROR_TCPSOCKET_FAILED_TO_SET_SOCKOPT;
255 CRX_ERROR_SET (aResult, "Failed to set socket option (linger).");
256 }
257
[24]258 aResult = SetTimeout (aTimeout);
259 if (aResult < 0)
[14]260 {
[57]261 aResult = ERROR_TCPSOCKET_FAILED_TO_SET_TIMEOUT;
[35]262 CRX_ERROR_SET (aResult, "Failed to set timeout (%d).", GetSystemErrorCode ());
[24]263 return aResult;
[14]264 }
265
266 aResult = connect (mSocket, (struct sockaddr*) &mAddress, sizeof (mAddress));
[6]267 if (aResult < 0)
268 {
[18]269 aResult = ERROR_TCPSOCKET_FAILED_TO_CONNECT;
[35]270 CRX_ERROR_SET (aResult, "Failed to connect (%d).", GetSystemErrorCode ());
[6]271 }
272
273 /*----------------------------------------------------------------*/
274 return aResult;
275}
276
277int
[14]278CRXSocket::CreateServer (const unsigned short aPort,
279 const int aBacklog,
280 struct sockaddr_in * aAddress)
[6]281{
282 int aResult = -1;
283
[57]284 int aReuseAddress = 1;
285
[6]286 /*----------------------------------------------------------------*/
287 aResult = CreateSocket ();
288 if (aResult < 0)
289 {
[24]290 aResult = ERROR_TCPSOCKET_FAILED_TO_CREATE_SOCKET;
[35]291 CRX_ERROR_SET (aResult, "Failed to create socket(%d).", GetSystemErrorCode ());
[6]292 return aResult;
293 }
294
[57]295 aResult = setsockopt (mSocket,
296 SOL_SOCKET,
297 SO_REUSEADDR,
298#ifdef _WIN32
299 (char *) &aReuseAddress,
300#else
301 &aReuseAddress,
302#endif
303 (socklen_t) sizeof (aReuseAddress));
304 if (aResult < 0)
305 {
306 aResult = ERROR_TCPSOCKET_FAILED_TO_SET_SOCKOPT;
307 CRX_ERROR_SET (aResult, "Failed to set socket option (reuseaddr).");
308 }
309
[6]310 mAddress.sin_family = AF_INET;
311 mAddress.sin_addr.s_addr= htonl (INADDR_ANY);
312 mAddress.sin_port = htons (aPort);
313
[14]314 aResult = bind (mSocket, (struct sockaddr *)&mAddress, sizeof (struct sockaddr));
[6]315 if (aResult < 0)
316 {
[18]317 aResult = ERROR_TCPSOCKET_FAILED_TO_BIND;
[35]318 CRX_ERROR_SET (aResult, "Failed to bind(%d).", GetSystemErrorCode ());
[18]319 return aResult;
[6]320 }
321
322 aResult = listen (mSocket, aBacklog);
323 if (aResult < 0)
324 {
[18]325 aResult = ERROR_TCPSOCKET_FAILED_TO_LISTEN;
[35]326 CRX_ERROR_SET (aResult, "Failed to listen(%d).", GetSystemErrorCode ());
[18]327 return aResult;
[6]328 }
329
330 if (aAddress != NULL)
331 {
[14]332 memset ((void *)aAddress, 0x0, sizeof (struct sockaddr_in));
333 memcpy ((void *)aAddress, (void *)&mAddress, sizeof (struct sockaddr_in));
[6]334 }
335
336 /*----------------------------------------------------------------*/
337 return aResult;
338}
339
340int
[14]341CRXSocket::Accept (struct sockaddr_in * aRemoteAddress,
342 int * aAddressLength)
[6]343{
[14]344 int aResult = -1;
[6]345
[14]346 struct sockaddr_in aAddress;
347 socklen_t aLength = sizeof (aAddress);
[6]348
349 /*----------------------------------------------------------------*/
[24]350 if (!IsReady ())
351 return ERROR_TCPSOCKET_NOT_READY;
[6]352
[14]353 aResult = accept (mSocket, (struct sockaddr *) &aAddress, &aLength);
[6]354 if (aResult < 0)
355 {
[18]356 aResult = ERROR_TCPSOCKET_FAILED_TO_ACCEPT;
[35]357 CRX_ERROR_SET (aResult, "Failed to accept(%d).", GetSystemErrorCode ());
[6]358 return aResult;
359 }
360
361 if (aRemoteAddress != NULL)
362 {
[14]363 memset ((void *)aRemoteAddress, 0x0, sizeof (struct sockaddr_in));
364 memcpy ((void *)aRemoteAddress, (void *)&aAddress, sizeof (struct sockaddr_in));
[6]365 }
366
367 if (aAddressLength != NULL)
368 *aAddressLength = aLength;
369
370 /*----------------------------------------------------------------*/
371 return aResult;
372}
373
374int
[24]375CRXSocket::Send (const char * aBuffer,
376 int aSize)
[6]377{
378 int aResult = -1;
379
380 /*----------------------------------------------------------------*/
[24]381 if (!IsReady ())
382 return ERROR_TCPSOCKET_NOT_READY;
[6]383
384 aResult = send (mSocket, aBuffer, aSize, 0);
385 if (aResult != aSize)
386 {
[18]387 aResult = ERROR_TCPSOCKET_FAILED_TO_SEND;
[35]388 CRX_ERROR_SET (aResult, "Failed to send(%d).", GetSystemErrorCode ());
[18]389 return aResult;
[6]390 }
391
392 /*----------------------------------------------------------------*/
393 return aResult;
394}
395
396int
397CRXSocket::Receive (char * aBuffer,
398 int aSize)
399{
400 int aResult = -1;
401
402 /*----------------------------------------------------------------*/
[24]403 if (!IsReady ())
404 return ERROR_TCPSOCKET_NOT_READY;
[6]405
406 aResult = recv (mSocket, aBuffer, aSize, 0);
407 if (aResult < 0)
408 {
[18]409 aResult = ERROR_TCPSOCKET_FAILED_TO_RECEIVE;
[35]410 CRX_ERROR_SET (aResult, "Failed to receive(%d).", GetSystemErrorCode ());
[18]411 return aResult;
[6]412 }
413
414 /*----------------------------------------------------------------*/
415 return aResult;
416}
Note: See TracBrowser for help on using the repository browser.