1 /*******************************************************************************
2 * File Name : HLH_Sock.cpp
5 * Created Time : 2009-10-8 13:56:06
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
60 ******************************************************************************/
64 // Init member variables
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
81 ******************************************************************************/
82 HLH_Sock::~HLH_Sock ()
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
)
112 // Lock before process
113 m_zhmMainMutex
.Lock ();
116 // Unlock after process
117 m_zhmMainMutex
.Unlock ();
118 HLH_DEBUG ( HLH_DEBUG_MAIN
, ("already created") );
119 return HLH_SOCK_ERR_ALREADY_CREATED
;
123 switch (zhsSockType
) {
124 case HLH_SOCK_TYPE_STREAM
:
125 m_fdSocket
= socket (AF_INET
, SOCK_STREAM
, 0);
128 case HLH_SOCK_TYPE_DGRAM
:
129 m_fdSocket
= socket (AF_INET
, SOCK_DGRAM
, 0);
133 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("sock type not supported") );
137 if (m_fdSocket
< 0) {
138 HLH_DEBUG ( HLH_DEBUG_MAIN
, ("can't create socket") );
142 // Set Nonblocking if request
144 nFlags
= fcntl (m_fdSocket
, F_GETFL
, 0);
145 nRetVal
= fcntl (m_fdSocket
, F_SETFL
, nFlags
|O_NONBLOCK
);
148 HLH_DEBUG ( HLH_DEBUG_MAIN
, ("can't set nonblock") );
153 // Bind on specific address
154 nRetVal
= bind ( m_fdSocket
, zhsSockAddr
.GetAddrPointer (),
155 zhsSockAddr
.GetAddrLen () );
158 HLH_DEBUG ( HLH_DEBUG_MAIN
, ("can't bind on address") );
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
174 // Unlock after process
175 m_zhmMainMutex
.Unlock ();
180 // Close socket if failed after create
181 if (m_fdSocket
>= 0) {
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
)
206 // Lock before process
207 m_zhmMainMutex
.Lock ();
210 // Unlock after process
211 m_zhmMainMutex
.Unlock ();
212 HLH_DEBUG ( HLH_DEBUG_MAIN
, ("already created") );
213 return HLH_SOCK_ERR_ALREADY_CREATED
;
218 // Set Nonblocking if request
220 nFlags
= fcntl (m_fdSocket
, F_GETFL
, 0);
221 nRetVal
= fcntl (m_fdSocket
, F_SETFL
, nFlags
|O_NONBLOCK
);
224 HLH_DEBUG ( HLH_DEBUG_MAIN
, ("can't set nonblock") );
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
242 // Unlock after process
243 m_zhmMainMutex
.Unlock ();
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
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
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
292 // Unlock operations other than read/write
293 m_zhmMainMutex
.Unlock ();
295 // Unlock send operations
296 m_zhmSendMutex
.Unlock ();
304 /******************************************************************************
305 * Func : HLH_Sock::IsCreated
306 * Desc : Whether this socket created
308 * Outs : If created return true, otherwise return false
309 ******************************************************************************/
310 bool HLH_Sock::IsCreated ()
314 m_zhmMainMutex
.Lock ();
315 bCreated
= m_bCreated
;
316 m_zhmMainMutex
.Unlock ();
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
)
334 // Lock before process
335 m_zhmMainMutex
.Lock ();
337 // Can't listen on socket which is not created
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
);
348 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("listen failed") );
352 // Unlock after process
353 m_zhmMainMutex
.Unlock ();
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
)
375 // Lock before process
376 m_zhmMainMutex
.Lock ();
378 // Can't Connect on socket which is not created
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 () );
391 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("connect failed") );
395 // Unlock after process
396 m_zhmMainMutex
.Unlock ();
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
)
421 // Lock before process
422 m_zhmMainMutex
.Lock ();
424 // Can't Accept on socket which is not created
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
);
437 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("accept failed") );
441 // Unlock after process
442 m_zhmMainMutex
.Unlock ();
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
)
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
475 // Unlock after process
476 m_zhmMainMutex
.Unlock ();
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 ();
489 nRetVal
= send (m_fdSocket
, pvBuf
, unLen
, unFlags
/*|MSG_NOSIGNAL*/);
491 // Unlock send mutex after send
492 m_zhmSendMutex
.Unlock ();
495 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("send failed") );
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
)
520 // Lock before Receiving
521 m_zhmRecvMutex
.Lock ();
523 // Lock before process
524 m_zhmMainMutex
.Lock ();
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 ();
546 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("receive 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
)
572 // Lock the send mutex
573 m_zhmSendMutex
.Lock ();
575 // Lock before process
576 m_zhmMainMutex
.Lock ();
579 // Unlock after process
580 m_zhmMainMutex
.Unlock ();
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 ();
593 nRetVal
= sendto ( m_fdSocket
, pvBuf
, unLen
, unFlags
,
594 zhsSockAddr
.GetAddrPointer (), zhsSockAddr
.GetAddrLen () );
596 // Unlock send mutex after send
597 m_zhmSendMutex
.Unlock ();
600 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("sendto 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
)
627 // Lock before Receiving
628 m_zhmRecvMutex
.Lock ();
630 // Lock before process
631 m_zhmMainMutex
.Lock ();
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 ();
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
656 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("recvfrom 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
)
691 UINT32 unPollTypeNew
;
693 // Lock before process
694 m_zhmMainMutex
.Lock ();
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
,
721 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("select failed") );
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
;
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
)
769 UINT32 unPollTypeNew
;
771 struct timeval tvTime
;
773 // Lock before process
774 m_zhmMainMutex
.Lock ();
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
,
802 HLH_DEBUG ( HLH_DEBUG_UTILS
, ("select failed") );
806 // Return the time left
807 zhtTime
.SetTime (tvTime
);
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
;
833 return HLH_SOCK_ERR_FAILED
;