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
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 CRXSocket::mInitialized = false;
14
15CRXSocket::CRXSocket (int aSocket)
16 : mSocket (aSocket)
17{
18 /*----------------------------------------------------------------*/
19 CRXSocket::Initialize ();
20
21 memset ((void *)&mAddress, 0x0, sizeof (struct sockaddr_in));
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
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,
107#endif
108 (socklen_t) sizeof (aTimeVal));
109 if (aResult < 0)
110 {
111 aResult = ERROR_TCPSOCKET_FAILED_TO_SET_SOCKOPT;
112 CRX_ERROR_SET (aResult, "Failed to set socket option.");
113 }
114 /*----------------------------------------------------------------*/
115
116 return aResult;
117}
118
119int
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 {
134 aResult = ERROR_TCPSOCKET_FAILED_TO_INITIALIZE;
135 return aResult;
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 ())
186 {
187 aResult = ERROR_TCPSOCKET_ALREADY_IN_USE;
188 CRX_ERROR_SET (aResult, "Already in use.");
189 return aResult;
190 }
191
192 aResult = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
193 if (aResult < 0)
194 {
195 aResult = ERROR_TCPSOCKET_FAILED_TO_CREATE_SOCKET;
196 CRX_ERROR_SET (aResult, "Failed to create socket(%d).", GetSystemErrorCode ());
197 return aResult;
198 }
199
200 mSocket = aResult;
201
202 /*----------------------------------------------------------------*/
203 return aResult;
204}
205
206int
207CRXSocket::Connect (const std::string aUrl,
208 const unsigned short aPort,
209 const int aTimeout)
210{
211 int aResult = -1;
212 struct hostent * aHostEnt;
213 struct linger aLinger;
214
215 /*----------------------------------------------------------------*/
216 aResult = CreateSocket ();
217 if (aResult < 0)
218 {
219 aResult = ERROR_TCPSOCKET_FAILED_TO_CREATE_SOCKET;
220 CRX_ERROR_SET (aResult, "Failed to create socket(%d).", GetSystemErrorCode ());
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 {
233 aResult = ERROR_TCPSOCKET_FAILED_TO_GET_HOSTNAME;
234 CRX_ERROR_SET (aResult, "Failed to get hostname.");
235 return aResult;
236 }
237 mAddress.sin_family = aHostEnt->h_addrtype;
238 memcpy (&(mAddress.sin_addr.s_addr), aHostEnt->h_addr, aHostEnt->h_length);
239 }
240
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
258 aResult = SetTimeout (aTimeout);
259 if (aResult < 0)
260 {
261 aResult = ERROR_TCPSOCKET_FAILED_TO_SET_TIMEOUT;
262 CRX_ERROR_SET (aResult, "Failed to set timeout (%d).", GetSystemErrorCode ());
263 return aResult;
264 }
265
266 aResult = connect (mSocket, (struct sockaddr*) &mAddress, sizeof (mAddress));
267 if (aResult < 0)
268 {
269 aResult = ERROR_TCPSOCKET_FAILED_TO_CONNECT;
270 CRX_ERROR_SET (aResult, "Failed to connect (%d).", GetSystemErrorCode ());
271 }
272
273 /*----------------------------------------------------------------*/
274 return aResult;
275}
276
277int
278CRXSocket::CreateServer (const unsigned short aPort,
279 const int aBacklog,
280 struct sockaddr_in * aAddress)
281{
282 int aResult = -1;
283
284 int aReuseAddress = 1;
285
286 /*----------------------------------------------------------------*/
287 aResult = CreateSocket ();
288 if (aResult < 0)
289 {
290 aResult = ERROR_TCPSOCKET_FAILED_TO_CREATE_SOCKET;
291 CRX_ERROR_SET (aResult, "Failed to create socket(%d).", GetSystemErrorCode ());
292 return aResult;
293 }
294
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
310 mAddress.sin_family = AF_INET;
311 mAddress.sin_addr.s_addr= htonl (INADDR_ANY);
312 mAddress.sin_port = htons (aPort);
313
314 aResult = bind (mSocket, (struct sockaddr *)&mAddress, sizeof (struct sockaddr));
315 if (aResult < 0)
316 {
317 aResult = ERROR_TCPSOCKET_FAILED_TO_BIND;
318 CRX_ERROR_SET (aResult, "Failed to bind(%d).", GetSystemErrorCode ());
319 return aResult;
320 }
321
322 aResult = listen (mSocket, aBacklog);
323 if (aResult < 0)
324 {
325 aResult = ERROR_TCPSOCKET_FAILED_TO_LISTEN;
326 CRX_ERROR_SET (aResult, "Failed to listen(%d).", GetSystemErrorCode ());
327 return aResult;
328 }
329
330 if (aAddress != NULL)
331 {
332 memset ((void *)aAddress, 0x0, sizeof (struct sockaddr_in));
333 memcpy ((void *)aAddress, (void *)&mAddress, sizeof (struct sockaddr_in));
334 }
335
336 /*----------------------------------------------------------------*/
337 return aResult;
338}
339
340int
341CRXSocket::Accept (struct sockaddr_in * aRemoteAddress,
342 int * aAddressLength)
343{
344 int aResult = -1;
345
346 struct sockaddr_in aAddress;
347 socklen_t aLength = sizeof (aAddress);
348
349 /*----------------------------------------------------------------*/
350 if (!IsReady ())
351 return ERROR_TCPSOCKET_NOT_READY;
352
353 aResult = accept (mSocket, (struct sockaddr *) &aAddress, &aLength);
354 if (aResult < 0)
355 {
356 aResult = ERROR_TCPSOCKET_FAILED_TO_ACCEPT;
357 CRX_ERROR_SET (aResult, "Failed to accept(%d).", GetSystemErrorCode ());
358 return aResult;
359 }
360
361 if (aRemoteAddress != NULL)
362 {
363 memset ((void *)aRemoteAddress, 0x0, sizeof (struct sockaddr_in));
364 memcpy ((void *)aRemoteAddress, (void *)&aAddress, sizeof (struct sockaddr_in));
365 }
366
367 if (aAddressLength != NULL)
368 *aAddressLength = aLength;
369
370 /*----------------------------------------------------------------*/
371 return aResult;
372}
373
374int
375CRXSocket::Send (const char * aBuffer,
376 int aSize)
377{
378 int aResult = -1;
379
380 /*----------------------------------------------------------------*/
381 if (!IsReady ())
382 return ERROR_TCPSOCKET_NOT_READY;
383
384 aResult = send (mSocket, aBuffer, aSize, 0);
385 if (aResult != aSize)
386 {
387 aResult = ERROR_TCPSOCKET_FAILED_TO_SEND;
388 CRX_ERROR_SET (aResult, "Failed to send(%d).", GetSystemErrorCode ());
389 return aResult;
390 }
391
392 /*----------------------------------------------------------------*/
393 return aResult;
394}
395
396int
397CRXSocket::Receive (char * aBuffer,
398 int aSize)
399{
400 int aResult = -1;
401
402 /*----------------------------------------------------------------*/
403 if (!IsReady ())
404 return ERROR_TCPSOCKET_NOT_READY;
405
406 aResult = recv (mSocket, aBuffer, aSize, 0);
407 if (aResult < 0)
408 {
409 aResult = ERROR_TCPSOCKET_FAILED_TO_RECEIVE;
410 CRX_ERROR_SET (aResult, "Failed to receive(%d).", GetSystemErrorCode ());
411 return aResult;
412 }
413
414 /*----------------------------------------------------------------*/
415 return aResult;
416}
Note: See TracBrowser for help on using the repository browser.