add HLH_Ref
[HLH_utils.git] / HLH_Sock.cpp
blob76b5372a47d6d3dcf2826912e59efa867424d14f
1 /*******************************************************************************
2 * File Name : HLH_Sock.cpp
3 *
4 * Author : Henry He
5 * Created Time : 2009-10-8 13:56:06
6 * Description :
7 ******************************************************************************/
10 /*******************************************************************************
11 * Desc : Includes Files
12 ******************************************************************************/
15 #include "HLH_utils/typedef.h"
16 #include "HLH_utils/HLH_Sock.h"
19 /*******************************************************************************
20 * Desc : Macro Definations
21 ******************************************************************************/
24 /*******************************************************************************
25 * Desc : Type Definations
26 ******************************************************************************/
29 /*******************************************************************************
30 * Desc : Global Variables
31 ******************************************************************************/
34 /*******************************************************************************
35 * Desc : File Variables
36 ******************************************************************************/
41 /******************************************************************************
42 * Desc : Member Functions
43 ******************************************************************************/
49 /******************************************************************************
50 * Desc : Constructor / Deconstructor
51 ******************************************************************************/
55 /******************************************************************************
56 * Func : HLH_Sock::HLH_Sock
57 * Desc : Constructor of HLH_Sock
58 * Args : NONE
59 * Outs : NONE
60 ******************************************************************************/
61 HLH_Sock::HLH_Sock ()
64 // Init member variables
65 m_fdSocket = -1;
66 m_bCreated = false;
68 // Init Mutexs
69 m_zhmMainMutex.Init ();
70 m_zhmSendMutex.Init ();
71 m_zhmRecvMutex.Init ();
76 /******************************************************************************
77 * Func : HLH_Sock::~HLH_Sock
78 * Desc : Deconstructor of HLH_Sock
79 * Args : NONE
80 * Outs : NONE
81 ******************************************************************************/
82 HLH_Sock::~HLH_Sock ()
84 Destroy ();
89 /******************************************************************************
90 * Desc : Common Operations
91 ******************************************************************************/
97 /******************************************************************************
98 * Func : HLH_Sock::Create
99 * Desc : Initialize the socket and bind it
100 * Args : zhsSockType socket type
101 * zhsSockAddr address to be binded
102 * bNonblocking whether create this socket nonblocking
103 * (default is blocking)
104 * Outs : if success, return 0, otherwise return error code
105 ******************************************************************************/
106 int HLH_Sock::Create (HLH_SockType zhsSockType,
107 const HLH_SockAddr &zhsSockAddr, bool bNonblocking)
109 int nRetVal;
110 int nFlags;
112 // Lock before process
113 m_zhmMainMutex.Lock ();
115 if (m_bCreated) {
116 // Unlock after process
117 m_zhmMainMutex.Unlock ();
118 HLH_DEBUG ( HLH_DEBUG_MAIN, ("already created") );
119 return HLH_SOCK_ERR_ALREADY_CREATED;
122 // Create socket
123 switch (zhsSockType) {
124 case HLH_SOCK_TYPE_STREAM:
125 m_fdSocket = socket (AF_INET, SOCK_STREAM, 0);
126 break;
128 case HLH_SOCK_TYPE_DGRAM:
129 m_fdSocket = socket (AF_INET, SOCK_DGRAM, 0);
130 break;
132 default:
133 HLH_DEBUG ( HLH_DEBUG_UTILS, ("sock type not supported") );
134 goto failed;
137 if (m_fdSocket < 0) {
138 HLH_DEBUG ( HLH_DEBUG_MAIN, ("can't create socket") );
139 goto failed;
142 // Set Nonblocking if request
143 if (bNonblocking) {
144 nFlags = fcntl (m_fdSocket, F_GETFL, 0);
145 nRetVal = fcntl (m_fdSocket, F_SETFL, nFlags|O_NONBLOCK);
147 if (nRetVal < 0) {
148 HLH_DEBUG ( HLH_DEBUG_MAIN, ("can't set nonblock") );
149 goto failed;
153 // Bind on specific address
154 nRetVal = bind ( m_fdSocket, zhsSockAddr.GetAddrPointer (),
155 zhsSockAddr.GetAddrLen () );
157 if (nRetVal < 0) {
158 HLH_DEBUG ( HLH_DEBUG_MAIN, ("can't bind on address") );
159 goto failed;
162 // Prepare fd_set for poll
163 FD_ZERO (&m_fsReadSet);
164 FD_ZERO (&m_fsWriteSet);
165 FD_ZERO (&m_fsErrorSet);
167 FD_SET (m_fdSocket, &m_fsReadSet);
168 FD_SET (m_fdSocket, &m_fsWriteSet);
169 FD_SET (m_fdSocket, &m_fsErrorSet);
171 // Notify that this socket has been create
172 m_bCreated = true;
174 // Unlock after process
175 m_zhmMainMutex.Unlock ();
176 return 0;
178 failed:
180 // Close socket if failed after create
181 if (m_fdSocket >= 0) {
182 close (m_fdSocket);
183 m_fdSocket = -1;
186 // Unlock after process
187 m_zhmMainMutex.Unlock ();
189 return HLH_SOCK_ERR_CANT_CREATE;
194 /******************************************************************************
195 * Func : HLH_Sock::Create
196 * Desc : Initialize the socket from a initialized socket file descriptor
197 * Args : fdSock file descriptor to create from
198 * Outs : if success return 0, otherwise return error code
199 ******************************************************************************/
200 int HLH_Sock::Create (int fdSock, bool bNonblocking)
203 int nRetVal;
204 int nFlags;
206 // Lock before process
207 m_zhmMainMutex.Lock ();
209 if (m_bCreated) {
210 // Unlock after process
211 m_zhmMainMutex.Unlock ();
212 HLH_DEBUG ( HLH_DEBUG_MAIN, ("already created") );
213 return HLH_SOCK_ERR_ALREADY_CREATED;
216 m_fdSocket = fdSock;
218 // Set Nonblocking if request
219 if (bNonblocking) {
220 nFlags = fcntl (m_fdSocket, F_GETFL, 0);
221 nRetVal = fcntl (m_fdSocket, F_SETFL, nFlags|O_NONBLOCK);
223 if (nRetVal < 0) {
224 HLH_DEBUG ( HLH_DEBUG_MAIN, ("can't set nonblock") );
225 goto failed;
230 // Prepare fd_set for poll
231 FD_ZERO (&m_fsReadSet);
232 FD_ZERO (&m_fsWriteSet);
233 FD_ZERO (&m_fsErrorSet);
235 FD_SET (m_fdSocket, &m_fsReadSet);
236 FD_SET (m_fdSocket, &m_fsWriteSet);
237 FD_SET (m_fdSocket, &m_fsErrorSet);
239 // Notify that this socket has been created
240 m_bCreated = true;
242 // Unlock after process
243 m_zhmMainMutex.Unlock ();
245 return 0;
247 failed:
249 // Unlock after process
250 m_zhmMainMutex.Unlock ();
252 return HLH_SOCK_ERR_CANT_CREATE;
257 /******************************************************************************
258 * Func : HLH_Sock::Destroy
259 * Desc : Destroy the socket, will wait for send/pollwait operations
260 * Args : NONE
261 * Outs : If success, return 0, otherwise return error code
262 ******************************************************************************/
263 int HLH_Sock::Destroy ()
266 // Wait for send operations
267 m_zhmSendMutex.Lock ();
269 // Wait for operations other than read/write
270 m_zhmMainMutex.Lock ();
272 // if not create, can't close
273 if (!m_bCreated) {
274 // Unlock operations other than read/write
275 m_zhmMainMutex.Unlock ();
277 // Unlock send operations
278 m_zhmSendMutex.Unlock ();
280 return HLH_SOCK_ERR_NOT_CREATED;
284 // Receive operations won't be waited
286 // Close the socket now
287 close (m_fdSocket);
288 m_fdSocket = -1;
289 m_bCreated = false;
292 // Unlock operations other than read/write
293 m_zhmMainMutex.Unlock ();
295 // Unlock send operations
296 m_zhmSendMutex.Unlock ();
298 return 0;
304 /******************************************************************************
305 * Func : HLH_Sock::IsCreated
306 * Desc : Whether this socket created
307 * Args : NONE
308 * Outs : If created return true, otherwise return false
309 ******************************************************************************/
310 bool HLH_Sock::IsCreated ()
312 bool bCreated;
314 m_zhmMainMutex.Lock ();
315 bCreated = m_bCreated;
316 m_zhmMainMutex.Unlock ();
318 return bCreated;
324 /******************************************************************************
325 * Func : HLH_Sock::Listen
326 * Desc : Listen for socket connections and limit the queue of incoming connections
327 * Args : unQueue length of listen queue
328 * Outs : if success, return 0, otherwise return error code
329 ******************************************************************************/
330 int HLH_Sock::Listen (UINT32 unQueue)
332 int nRetVal;
334 // Lock before process
335 m_zhmMainMutex.Lock ();
337 // Can't listen on socket which is not created
338 if (!m_bCreated) {
339 // Unlock after process
340 m_zhmMainMutex.Unlock ();
342 HLH_DEBUG ( HLH_DEBUG_UTILS, ("not created") );
343 return HLH_SOCK_ERR_NOT_CREATED;
346 nRetVal = listen (m_fdSocket, unQueue);
347 if (nRetVal < 0) {
348 HLH_DEBUG ( HLH_DEBUG_UTILS, ("listen failed") );
349 goto failed;
352 // Unlock after process
353 m_zhmMainMutex.Unlock ();
355 return 0;
357 failed:
358 // Unlock after process
359 m_zhmMainMutex.Unlock ();
361 return HLH_SOCK_ERR_FAILED;
365 /******************************************************************************
366 * Func : HLH_Sock::Connect
367 * Desc : Requests a connection to be made on a socket
368 * Args : zhsPeekAddr address to connect
369 * Outs : if success, return 0, otherwise return error code
370 ******************************************************************************/
371 int HLH_Sock::Connect (const HLH_SockAddr &zhsPeekAddr)
373 int nRetVal;
375 // Lock before process
376 m_zhmMainMutex.Lock ();
378 // Can't Connect on socket which is not created
379 if (!m_bCreated) {
380 // Unlock after process
381 m_zhmMainMutex.Unlock ();
383 HLH_DEBUG ( HLH_DEBUG_UTILS, ("not created") );
384 return HLH_SOCK_ERR_NOT_CREATED;
387 // Connect to specific address
388 nRetVal = connect ( m_fdSocket, zhsPeekAddr.GetAddrPointer (),
389 zhsPeekAddr.GetAddrLen () );
390 if (nRetVal < 0) {
391 HLH_DEBUG ( HLH_DEBUG_UTILS, ("connect failed") );
392 goto failed;
395 // Unlock after process
396 m_zhmMainMutex.Unlock ();
398 return 0;
400 failed:
401 // Unlock after process
402 m_zhmMainMutex.Unlock ();
404 return HLH_SOCK_ERR_FAILED;
408 /******************************************************************************
409 * Func : HLH_Sock::Accept
410 * Desc : Extracts the first connection on the queue of pending connections,
411 * creates a new socket with the same socket type protocol and address family as the specified socket,
412 * and allocates a new file descriptor for that socket
413 * Args : zhsPeerAddr address of peer comming in
414 * Outs : if success, return 0, otherwise return error code
415 ******************************************************************************/
416 int HLH_Sock::Accept (HLH_SockAddr &zhsPeerAddr)
418 int nRetVal;
419 socklen_t slLen;
421 // Lock before process
422 m_zhmMainMutex.Lock ();
424 // Can't Accept on socket which is not created
425 if (!m_bCreated) {
426 // Unlock after process
427 m_zhmMainMutex.Unlock ();
429 HLH_DEBUG ( HLH_DEBUG_UTILS, ("not created") );
430 return HLH_SOCK_ERR_NOT_CREATED;
433 // Wait and accept connections
434 slLen = zhsPeerAddr.GetAddrLen ();
435 nRetVal = accept ( m_fdSocket, zhsPeerAddr.GetAddrPointer(), &slLen );
436 if (nRetVal < 0) {
437 HLH_DEBUG ( HLH_DEBUG_UTILS, ("accept failed") );
438 goto failed;
441 // Unlock after process
442 m_zhmMainMutex.Unlock ();
444 return nRetVal;
446 failed:
447 // Unlock after process
448 m_zhmMainMutex.Unlock ();
450 return HLH_SOCK_ERR_FAILED;
454 /******************************************************************************
455 * Func : HLH_Sock::Send
456 * Desc : Initiates transmission of a message from the specified socket to its peer
457 * Args : pvBuf pointer of buffer
458 * unLen length of buffer
459 * unFlags flags used by send ()
460 * Outs : if success return the length of data send, otherwise error code
461 ******************************************************************************/
462 int HLH_Sock::Send (const void *pvBuf, UINT32 unLen, UINT32 unFlags)
464 int nRetVal;
466 // Lock the send mutex
467 m_zhmSendMutex.Lock ();
469 // Lock before process
470 m_zhmMainMutex.Lock ();
472 // Can't send on socket not created
473 if (!m_bCreated) {
475 // Unlock after process
476 m_zhmMainMutex.Unlock ();
478 // Unlock send mutex
479 m_zhmSendMutex.Unlock ();
481 HLH_DEBUG ( HLH_DEBUG_UTILS, ("not created") );
482 return HLH_SOCK_ERR_NOT_CREATED;
485 // Unlock after process
486 m_zhmMainMutex.Unlock ();
488 // Send the data now
489 nRetVal = send (m_fdSocket, pvBuf, unLen, unFlags/*|MSG_NOSIGNAL*/);
491 // Unlock send mutex after send
492 m_zhmSendMutex.Unlock ();
494 if (nRetVal < 0) {
495 HLH_DEBUG ( HLH_DEBUG_UTILS, ("send failed") );
496 goto failed;
499 return nRetVal;
500 failed:
501 // Unlock send mutex
502 m_zhmSendMutex.Unlock ();
504 return HLH_SOCK_ERR_FAILED;
508 /******************************************************************************
509 * Func : HLH_Sock::Recv
510 * Desc : Receives a message from a connection-mode or connectionless-mode socket
511 * Args : pvBuf pointer to buffer
512 * unLen length of buffer
513 * unFlags flags used by recv ()
514 * Outs : if success, return length of data received, otherwise return error code
515 ******************************************************************************/
516 int HLH_Sock::Recv (void *pvBuf, UINT32 unLen, UINT32 unFlags)
518 int nRetVal;
520 // Lock before Receiving
521 m_zhmRecvMutex.Lock ();
523 // Lock before process
524 m_zhmMainMutex.Lock ();
525 if (!m_bCreated) {
527 // Unlock receive mutex
528 m_zhmRecvMutex.Unlock ();
530 // Unlock after process
531 m_zhmMainMutex.Unlock ();
533 HLH_DEBUG ( HLH_DEBUG_UTILS, ("not created") );
534 return HLH_SOCK_ERR_NOT_CREATED;
537 // Unlock after process
538 m_zhmMainMutex.Unlock ();
540 nRetVal = recv (m_fdSocket, pvBuf, unLen, unFlags/*|MSG_NOSIGNAL*/);
542 // Unlock after receiving
543 m_zhmRecvMutex.Unlock ();
545 if (nRetVal < 0) {
546 HLH_DEBUG ( HLH_DEBUG_UTILS, ("receive failed") );
547 goto failed;
550 return nRetVal;
552 failed:
553 return HLH_SOCK_ERR_FAILED;
558 /******************************************************************************
559 * Func : HLH_Sock::SendTo
560 * Desc : Sends a message through a connection-mode or connectionless-mode socket
561 * Args : pvBuf pointer of buffer
562 * unLen length of buffer
563 * zhsSockAddr address of peer
564 * unFlags flags used by send ()
565 * Outs : if success return the length of data send, otherwise error code
566 ******************************************************************************/
567 int HLH_Sock::SendTo (const void *pvBuf, UINT32 unLen,
568 const HLH_SockAddr &zhsSockAddr, UINT32 unFlags)
570 int nRetVal;
572 // Lock the send mutex
573 m_zhmSendMutex.Lock ();
575 // Lock before process
576 m_zhmMainMutex.Lock ();
578 if (!m_bCreated) {
579 // Unlock after process
580 m_zhmMainMutex.Unlock ();
582 // Unlock send mutex
583 m_zhmSendMutex.Unlock ();
585 HLH_DEBUG ( HLH_DEBUG_UTILS, ("not created") );
586 return HLH_SOCK_ERR_NOT_CREATED;
589 // Unlock after process
590 m_zhmMainMutex.Unlock ();
592 // Send the data now
593 nRetVal = sendto ( m_fdSocket, pvBuf, unLen, unFlags,
594 zhsSockAddr.GetAddrPointer (), zhsSockAddr.GetAddrLen () );
596 // Unlock send mutex after send
597 m_zhmSendMutex.Unlock ();
599 if (nRetVal < 0) {
600 HLH_DEBUG ( HLH_DEBUG_UTILS, ("sendto failed") );
601 goto failed;
604 return nRetVal;
606 failed:
607 return HLH_SOCK_ERR_FAILED;
612 /******************************************************************************
613 * Func : HLH_Sock::RecvFrom
614 * Desc : Receives a message from a connection-mode or connectionless-mode socket
615 * Args : pvBuf pointer to buffer
616 * unLen length of buffer
617 * zhsPeerAddr used to store peer address
618 * unFlags flags used by recv ()
619 * Outs : if success, return length of data received, otherwise return error code
620 ******************************************************************************/
621 int HLH_Sock::RecvFrom (void *pvBuf, UINT32 unLen,
622 HLH_SockAddr &zhsPeekAddr, UINT32 unFlags)
624 int nRetVal;
625 socklen_t slLen;
627 // Lock before Receiving
628 m_zhmRecvMutex.Lock ();
630 // Lock before process
631 m_zhmMainMutex.Lock ();
632 if (!m_bCreated) {
633 // Unlock after process
634 m_zhmMainMutex.Unlock ();
636 // Unlock after Receiving
637 m_zhmRecvMutex.Unlock ();
639 HLH_DEBUG ( HLH_DEBUG_UTILS, ("not created") );
640 return HLH_SOCK_ERR_NOT_CREATED;
643 // Unlock after process
644 m_zhmMainMutex.Unlock ();
646 // Send the data now
647 slLen = zhsPeekAddr.GetAddrLen ();
648 nRetVal = recvfrom (m_fdSocket, pvBuf, unLen, unFlags,
649 zhsPeekAddr.GetAddrPointer (), &slLen);
651 // Unlock after receiving
652 m_zhmRecvMutex.Unlock ();
654 // Format return value
655 if (nRetVal < 0) {
656 HLH_DEBUG ( HLH_DEBUG_UTILS, ("recvfrom failed") );
657 goto failed;
660 return nRetVal;
662 failed:
663 return HLH_SOCK_ERR_FAILED;
671 /******************************************************************************
672 * Desc : Poll Operations
673 ******************************************************************************/
678 /******************************************************************************
679 * Func : HLH_Sock::Poll
680 * Desc : Poll for specific events
681 * Args : unPollType poll type
682 * Outs : if success return number of events, otherwise return error code
683 ******************************************************************************/
684 int HLH_Sock::Poll (UINT32 &unPollType)
686 fd_set fsReadSet;
687 fd_set fsWriteSet;
688 fd_set fsErrorSet;
690 int nRetVal;
691 UINT32 unPollTypeNew;
693 // Lock before process
694 m_zhmMainMutex.Lock ();
696 if (!m_bCreated) {
697 // Unlock after process
698 m_zhmMainMutex.Unlock ();
700 HLH_DEBUG ( HLH_DEBUG_UTILS, ("not created") );
701 return HLH_SOCK_ERR_NOT_CREATED;
704 memcpy ( &fsReadSet, &m_fsReadSet, sizeof (fd_set) );
705 memcpy ( &fsWriteSet, &m_fsWriteSet, sizeof (fd_set) );
706 memcpy ( &fsErrorSet, &m_fsErrorSet, sizeof (fd_set) );
708 // Unlock after process,
709 // Unlock before poll as we may want to close before poll successed
710 m_zhmMainMutex.Unlock ();
712 // Poll for specific event
713 nRetVal = select ( m_fdSocket + 1,
714 unPollType & HLH_SOCK_POLL_READ ? &fsReadSet : NULL,
715 unPollType & HLH_SOCK_POLL_WRITE ? &fsWriteSet : NULL,
716 unPollType & HLH_SOCK_POLL_ERROR ? &fsErrorSet : NULL,
717 NULL
720 if (nRetVal < 0) {
721 HLH_DEBUG ( HLH_DEBUG_UTILS, ("select failed") );
722 goto failed;
725 // Set return value
727 unPollTypeNew = 0;
729 if ( ( unPollType & HLH_SOCK_POLL_READ )
730 && FD_ISSET (m_fdSocket, &fsReadSet) ) {
731 unPollTypeNew |= HLH_SOCK_POLL_READ;
734 if ( ( unPollType & HLH_SOCK_POLL_WRITE )
735 && FD_ISSET (m_fdSocket, &fsWriteSet) ) {
736 unPollTypeNew |= HLH_SOCK_POLL_WRITE;
739 if ( ( unPollType & HLH_SOCK_POLL_ERROR )
740 && FD_ISSET (m_fdSocket, &fsErrorSet) ) {
741 unPollTypeNew |= HLH_SOCK_POLL_ERROR;
744 unPollType = unPollTypeNew;
746 return nRetVal;
748 failed:
750 return HLH_SOCK_ERR_FAILED;
754 /******************************************************************************
755 * Func : HLH_Sock::PollWait
756 * Desc : Poll for specific events until time eclipsed
757 * Args : unPollType poll type
758 * zhtTime time to wait before poll success
759 * Outs : if success return number of events, otherwise return error code
760 * if failed, the time left will return in zhtTime
761 ******************************************************************************/
762 int HLH_Sock::PollWait (UINT32 &unPollType, HLH_Time &zhtTime)
764 fd_set fsReadSet;
765 fd_set fsWriteSet;
766 fd_set fsErrorSet;
768 int nRetVal;
769 UINT32 unPollTypeNew;
771 struct timeval tvTime;
773 // Lock before process
774 m_zhmMainMutex.Lock ();
776 if (!m_bCreated) {
777 // Unlock after process
778 m_zhmMainMutex.Unlock ();
780 HLH_DEBUG ( HLH_DEBUG_UTILS, ("not created") );
781 return HLH_SOCK_ERR_NOT_CREATED;
784 memcpy ( &fsReadSet, &m_fsReadSet, sizeof (fd_set) );
785 memcpy ( &fsWriteSet, &m_fsWriteSet, sizeof (fd_set) );
786 memcpy ( &fsErrorSet, &m_fsErrorSet, sizeof (fd_set) );
788 // Poll for specific event
789 tvTime = zhtTime.GetTimeVal ();
791 // Unlock after process
792 m_zhmMainMutex.Unlock ();
794 nRetVal = select ( m_fdSocket + 1,
795 unPollType & HLH_SOCK_POLL_READ ? &fsReadSet : NULL,
796 unPollType & HLH_SOCK_POLL_WRITE ? &fsWriteSet : NULL,
797 unPollType & HLH_SOCK_POLL_ERROR ? &fsErrorSet : NULL,
798 &tvTime
801 if (nRetVal < 0) {
802 HLH_DEBUG ( HLH_DEBUG_UTILS, ("select failed") );
803 goto failed;
806 // Return the time left
807 zhtTime.SetTime (tvTime);
809 // Set return value
811 unPollTypeNew = 0;
813 if ( ( unPollType & HLH_SOCK_POLL_READ )
814 && FD_ISSET (m_fdSocket, &fsReadSet) ) {
815 unPollTypeNew |= HLH_SOCK_POLL_READ;
818 if ( ( unPollType & HLH_SOCK_POLL_WRITE )
819 && FD_ISSET (m_fdSocket, &fsWriteSet) ) {
820 unPollTypeNew |= HLH_SOCK_POLL_WRITE;
823 if ( ( unPollType & HLH_SOCK_POLL_ERROR )
824 && FD_ISSET (m_fdSocket, &fsErrorSet) ) {
825 unPollTypeNew |= HLH_SOCK_POLL_ERROR;
828 unPollType = unPollTypeNew;
830 return nRetVal;
832 failed:
833 return HLH_SOCK_ERR_FAILED;