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

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

#1 apply reuseaddr

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