librnr  1.14.5
RoadNarrows Robotics Common Library 1
sock.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: RoadNarrows Robotics Common Library 1
4 //
5 // Library: librnr
6 //
7 // File: sock.c
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2012-07-10 12:37:42 -0600 (Tue, 10 Jul 2012) $
12  * $Rev: 2078 $
13  *
14  * \brief Socket services definitions.
15  *
16  * These socket functions were inspired by the camserv socket.c functions
17  * written by Jon Travis (see below).
18  *
19  * \todo Socket_T *SocketOpenUnix(int ipPortUdp, int nType)
20  * \todo Socket_T *SocketOpenUnixPair(int nType)
21  * \todo fix cygwin shortcommings.
22  *
23  * \author Robin Knight (robin.knight@roadnarrows.com)
24  *
25  * \pkgcopyright{2005-2018,RoadNarrows LLC.,http://www.roadnarrows.com}
26  *
27  * <hr>
28  * \par Original Source and Copyright:
29  *
30  * \par Original Author:
31  * Jon Travis (jtravis@p00p.org)
32  *
33  * <hr>
34  */
35 // Permission is hereby granted, without written agreement and without
36 // license or royalty fees, to use, copy, modify, and distribute this
37 // software and its documentation for any purpose, provided that
38 // (1) The above copyright notice and the following two paragraphs
39 // appear in all copies of the source code and (2) redistributions
40 // including binaries reproduces these notices in the supporting
41 // documentation. Substantial modifications to this software may be
42 // copyrighted by their authors and need not follow the licensing terms
43 // described here, provided that the new terms are clearly indicated in
44 // all files where they apply.
45 //
46 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
47 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
48 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
49 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
50 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
51 // THE POSSIBILITY OF SUCH DAMAGE.
52 //
53 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
54 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
55 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
56 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
57 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
58 //
59 ////////////////////////////////////////////////////////////////////////////////
60 
61 #define USE_IPV6 ///< enable IPV6 (Cygwin)
62 
63 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <sys/un.h>
66 #include <netinet/in.h>
67 #include <netdb.h>
68 #include <arpa/inet.h>
69 #include <unistd.h>
70 #include <fcntl.h>
71 #include <errno.h>
72 #include <string.h>
73 
74 #include "rnr/rnrconfig.h"
75 #include "rnr/sock.h"
76 #include "rnr/simplebuf.h"
77 #include "rnr/log.h"
78 #include "rnr/new.h"
79 
80 
81 // ---------------------------------------------------------------------------
82 // Private Interface
83 // ---------------------------------------------------------------------------
84 
85 #ifndef HOST_NAME_MAX
86 #define HOST_NAME_MAX 64 ///< maximum host name length
87 #endif
88 
89 PRAGMA_IGNORED(sign-conversion)
90 /*!
91  * \brief FD_SET() wrapper with no annoying warnings.
92  * \param fd File descriptor to add to set.
93  * \param pset Pointer to fd set.
94  */
95 static inline void fdset_nowarn(int fd, fd_set *pset)
96 {
97  FD_SET(fd, pset);
98 }
99 PRAGMA_WARNING(sign-conversion)
100 
101 PRAGMA_IGNORED(conversion)
102 /*!
103  * \brief ntohs() wrapper with no annoying warnings.
104  * \param huShort Unsigned short integer.
105  * \return Host byte order.
106  */
107 static inline ushort_t ntohs_nowarn(ushort_t huShort)
108 {
109  return ntohs(huShort);
110 }
111 
112 /*!
113  * \brief htons() wrapper with no annoying warnings.
114  * \param huShort Unsigned short integer.
115  * \return Network byte order.
116  */
117 static inline ushort_t htons_nowarn(ushort_t huShort)
118 {
119  return htons(huShort);
120 }
121 PRAGMA_WARNING(conversion)
122 
123 
124 /*!
125  * Special Host Names
126  */
127 const char *SockStrClosed = "** Closed **"; ///< closed socket
128 const char *SockStrDisconnected = "** Disconnected **"; ///< disconnected
129 const char *SockStrAnyHost = "ANYHOST"; ///< any host
130 const char *SockStrLocalHost = "LOCALHOST"; ///< local host
131 const char *SockStrUnknownHost = "UNKNOWNHOST"; ///< unknown host
132 
133 /*!
134  * Socket Structure
135  */
136 struct socket_t
137 {
138  int m_sd; ///< (open) socket descriptor
139  int m_ipPort; ///< socket port
140  SockFlavor m_eFlavor; ///< socket type
141  char *m_sLocalName; ///< local name
142  char *m_sRemoteName; ///< remote name
143  SimpleBuf_T *m_pIOBuf[SOCK_IO_NUMOF]; ///< read/write buffers
144  void *m_pClientData; ///< client data
145 };
146 
147 /*!
148  * \brief Resolve host name into IP address (IPV4 only).
149  *
150  * \param sHostName Host name in dotted or DNS network format.
151  * \param pAddrInet IP address
152  *
153  * \return Returns 0 on success, -1 on failure.
154  */
155 static int SockResolveHostName(const char *sHostName, struct in_addr *pAddrInet)
156 {
157  struct hostent *pHostEntry;
158  struct in_addr addrInet;
159 
160  // hostname: "www.xxx.yyy.zzz" (IPv4)
161  if( inet_aton(sHostName, &addrInet) != 0 )
162  {
163  memcpy(pAddrInet, &addrInet, sizeof(addrInet));
164  }
165  // hostname: "www.xxx.yyy.zzz" (IPv4) or "networkname" (may use DNS)
166  else if( (pHostEntry = gethostbyname(sHostName)) != NULL )
167  {
168  memcpy(pAddrInet, pHostEntry->h_addr, (size_t)pHostEntry->h_length);
169  }
170  else
171  {
172  LOGERROR("gethostbyname(%s): %s", sHostName, hstrerror(h_errno));
173  return -1;
174  }
175 
176  return OK;
177 }
178 
179 /*!
180  * \brief Allocate formated internet name (IPV4, IPV6).
181  *
182  * \par Generated Name Format:
183  * \verbatim
184  * addrname_inet:
185  * hostname '('dottedaddr')'
186  * hostname '('dottedaddr port')'
187  * hostname:
188  * given
189  * lookup
190  * dottedaddr
191  * dottedaddr:
192  * ipv4_format
193  * ipv6_format
194  * port:
195  * ':' number
196  * \endverbatim
197  *
198  * \param af Internet socket protocol family.
199  * \param pAddr Socket address.
200  * \param sHostName Host name. NULLL to force lookup.
201  *
202  * \return Returns pointer to allocated name string.
203  */
204 static char *SocketAddrNameInet(int af,
205  struct sockaddr *pAddr,
206  const char *sHostName)
207 {
208  void *pAddrIn;
209  size_t nAddrSize;
210  char bufAddr[INET6_ADDRSTRLEN];
211  uint_t uPort;
212  char bufPort[16];
213  char bufHost[NI_MAXHOST];
214  char *sHost;
215  char *sAddrName;
216 
217  bufAddr[0] = 0;
218  bufPort[0] = 0;
219  bufHost[0] = 0;
220 
221  // ipv4
222  if( af == AF_INET )
223  {
224  nAddrSize = sizeof(struct sockaddr_in);
225  pAddrIn = &(((struct sockaddr_in *)pAddr)->sin_addr);
226  uPort = (uint_t)(((struct sockaddr_in *)pAddr)->sin_port);
227  }
228  // ipv6
229  else if( af == AF_INET6 )
230  {
231  nAddrSize = sizeof(struct sockaddr_in6);
232  pAddrIn = &(((struct sockaddr_in6 *)pAddr)->sin6_addr);
233  uPort = (uint_t)(((struct sockaddr_in6 *)pAddr)->sin6_port);
234  }
235  // bug
236  else
237  {
238  return NULL;
239  }
240 
241  // dotted address
242  if( inet_ntop(af, pAddrIn, bufAddr, (socklen_t)sizeof(bufAddr)) != NULL )
243  {
244  if( uPort != 0 )
245  {
246  snprintf(bufPort, sizeof(bufPort), ":%hu", ntohs_nowarn((ushort_t)uPort));
247  bufPort[sizeof(bufPort)-1] = 0;
248  }
249  }
250  else
251  {
252  LOGSYSERROR("inet_ntop(%d, ...)", af);
253  strcpy(bufAddr, "ADDR???");
254  }
255 
256  // use given hostname
257  if( sHostName != NULL )
258  {
259  sHost = (char *)sHostName;
260  }
261 
262  // any host address
263  else if( (af == AF_INET)
264  && (((struct in_addr *)pAddrIn)->s_addr == INADDR_ANY) )
265  {
266  sHost = (char *)SockStrAnyHost;
267  }
268 
269  // lookup hostname (makes dotted if cannot find)
270  else
271  {
272  sHost = bufHost;
273  getnameinfo(pAddr, (socklen_t)nAddrSize,
274  bufHost, (socklen_t)sizeof(bufHost),
275  NULL, (socklen_t)0, NI_NOFQDN);
276  }
277 
278  sAddrName = NEWSTR(strlen(sHost)+strlen(bufAddr)+strlen(bufPort)+3);
279 
280  sprintf(sAddrName, "%s(%s%s)", sHost, bufAddr, bufPort);
281 
282  return sAddrName;
283 }
284 
285 /*!
286  * \brief Allocate formated UNIX name.
287  *
288  * \par Generated Name Format:
289  * \verbatim
290  * addrname_unix:
291  * hostname '('unixpath')'
292  * hostname:
293  * given
294  * localhost
295  * "LOCALHOST"
296  * \endverbatim
297  *
298  * \param pAddrUnix UNIX socket address.
299  * \param sHostName Host name. NULLL to force lookup.
300  *
301  * \return Returns pointer to allocated name string.
302  */
303 static char *SocketAddrNameUnix(struct sockaddr_un *pAddrUnix,
304  const char *sHostName)
305 {
306  char bufHost[NI_MAXHOST];
307  char *sHost;
308  char *sAddrName;
309 
310  // use given hostname
311  if( sHostName != NULL )
312  {
313  sHost = (char *)sHostName;
314  }
315  // lookup local hostname
316  else if( gethostname(bufHost, sizeof(bufHost)) < 0 )
317  {
318  sHost = bufHost;
319  }
320  else
321  {
322  sHost = (char *)SockStrLocalHost;
323  }
324 
325  sAddrName = NEWSTR(strlen(sHost)+strlen(pAddrUnix->sun_path)+3);
326 
327  sprintf(sAddrName, "%s(%s)", sHost, pAddrUnix->sun_path);
328 
329  return sAddrName;
330 }
331 
332 /*!
333  * \brief Allocate formated address name.
334  *
335  * \par Generated Name Format:
336  * \verbatim
337  * addrname:
338  * addrname_inet
339  * addrname_unix
340  * \endverbatim
341  *
342  * \param pAddr Socket address.
343  * \param sHostName Host name. NULLL to force lookup.
344  *
345  * \return Returns pointer to allocated name string.
346  */
347 static char *SocketAddrName(struct sockaddr *pAddr, const char *sHostName)
348 {
349  int af;
350 
351  af = pAddr->sa_family;
352 
353  switch(af)
354  {
355  case AF_INET:
356  case AF_INET6:
357  return SocketAddrNameInet(af, pAddr, sHostName);
358  case AF_UNIX:
359  return SocketAddrNameUnix((struct sockaddr_un *)pAddr, sHostName);
360  default:
361  return new_strdup("AF???");
362  }
363 }
364 
365 
366 // ---------------------------------------------------------------------------
367 // Public Interface
368 // ---------------------------------------------------------------------------
369 
370 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
371 // Socket Utilities
372 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
373 
374 /*!
375  * \brief Get the host string name of this network node (computer).
376  *
377  * \return Returns pointer to allocated name string.
378  */
380 {
381  char sHostName[HOST_NAME_MAX];
382  char sAddr[INET6_ADDRSTRLEN];
383  struct hostent *pHostEntry;
384  char *p;
385 
386  // get the host name of this processor
387  if( gethostname(sHostName, sizeof(sHostName)) == -1 )
388  {
389  LOGSYSERROR("gethostname(...)");
391  }
392  sHostName[sizeof(sHostName)-1] = 0;
393 
394  // get this host entry info
395  if( (pHostEntry = gethostbyname(sHostName)) == NULL )
396  {
397  LOGERROR("gethostbyname(%s): %s", sHostName, hstrerror(h_errno));
398  return new_strdup(sHostName);
399  }
400 
401  // dotted address to string
402  if( pHostEntry->h_addr_list && pHostEntry->h_addr_list[0] )
403  {
404  if( inet_ntop(pHostEntry->h_addrtype, pHostEntry->h_addr_list[0],
405  sAddr, (socklen_t)sizeof(sAddr)) == NULL )
406  {
407  LOGSYSERROR("inet_ntop(%d, ...)", pHostEntry->h_addrtype);
408  strcpy(sAddr, "ADDR???");
409  }
410  }
411  else
412  {
413  strcpy(sAddr, "ADDR???");
414  }
415  sAddr[sizeof(sAddr)-1] = 0;
416 
417  p = NEWSTR(strlen(sHostName)+strlen(sAddr)+2);
418  sprintf(p, "%s(%s)", sHostName, sAddr);
419 
420  return p;
421 }
422 
423 
424 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
425 // Socket New/Delete Functions
426 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
427 
428 /*!
429  * \brief Allocate a new, unconnected socket.
430  *
431  * \return Returns pointer to allocated Socket_T *.
432  */
434 {
435  Socket_T *pSocket = NEW(Socket_T);
436 
437  pSocket->m_sd = SOCK_SD_CLOSED;
438  pSocket->m_ipPort = SOCK_PORT_NONE;
439  pSocket->m_eFlavor = SockFlavorUndef;
440 
443 
444  pSocket->m_pIOBuf[SOCK_IO_READ] = SimpleBufNew();
445  pSocket->m_pIOBuf[SOCK_IO_WRITE] = SimpleBufNew();
446 
447  pSocket->m_pClientData = NULL;
448 
449  return pSocket;
450 }
451 
452 /*!
453  * \brief Delate an allocated socket.
454  *
455  * \warning Socket should be closed.
456  */
457 void SocketDelete(Socket_T *pSocket)
458 {
459  if( pSocket == NULL )
460  {
461  return;
462  }
463 
464  delete(pSocket->m_sLocalName);
465  delete(pSocket->m_sRemoteName);
468  delete(pSocket);
469 }
470 
471 
472 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
473 // Socket Buffer Functions
474 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
475 
476 /*!
477  * \brief Allocate a socket buffer and attach to Socket.
478  *
479  * \param pSocket Pointer to Socket.
480  * \param eIOBuf One of: \ref SOCK_IO_READ \ref SOCK_IO_WRITE.
481  * \param nBufSize Buffer size (bytes).
482  *
483  * \return Returns pointer to newly allocated buffer.
484  */
485 SimpleBuf_T *SocketBufNewBuf(Socket_T *pSocket, int eIOBuf, size_t nBufSize)
486 {
487  CHKPTR(pSocket, NULL);
488  SOCK_CHK_IO(eIOBuf, NULL);
489 
490  SimpleBufDelete(pSocket->m_pIOBuf[eIOBuf]);
491  pSocket->m_pIOBuf[eIOBuf] = SimpleBufNewWithBuf(nBufSize);
492  return pSocket->m_pIOBuf[eIOBuf];
493 }
494 
495 /*!
496  * \brief Attach a buffer to Socket.
497  *
498  * \param pSocket Pointer to Socket.
499  * \param eIOBuf One of: \ref SOCK_IO_READ \ref SOCK_IO_WRITE.
500  * \param pBuf Pointer to buffer.
501  * \param nBufSize Buffer size (bytes).
502  *
503  * \return Returns pointer to buffer.
504  */
506  int eIOBuf,
507  byte_t *pBuf,
508  size_t nBufSize)
509 {
510  CHKPTR(pSocket, NULL);
511  SOCK_CHK_IO(eIOBuf, NULL);
512 
513  SimpleBufSetBuf(pSocket->m_pIOBuf[eIOBuf], pBuf, nBufSize, (size_t)0);
514  return pSocket->m_pIOBuf[eIOBuf];
515 }
516 
517 /*!
518  * \brief Get Socket buffer.
519  *
520  * \param pSocket Pointer to Socket.
521  * \param eIOBuf One of: \ref SOCK_IO_READ \ref SOCK_IO_WRITE.
522  *
523  * \return Returns pointer to simplebuffer.
524  */
525 SimpleBuf_T *SocketBufGetBuf(Socket_T *pSocket, int eIOBuf)
526 {
527  CHKPTR(pSocket, NULL);
528  SOCK_CHK_IO(eIOBuf, NULL);
529 
530  return pSocket->m_pIOBuf[eIOBuf];
531 }
532 
533 /*!
534  * \brief Get Socket raw buffer.
535  *
536  * \param pSocket Pointer to Socket.
537  * \param eIOBuf One of: \ref SOCK_IO_READ \ref SOCK_IO_WRITE.
538  *
539  * \return Returns pointer to byte buffer.
540  */
541 byte_t *SocketBufGetRawBuf(Socket_T *pSocket, int eIOBuf)
542 {
543  CHKPTR(pSocket, NULL);
544  SOCK_CHK_IO(eIOBuf, NULL);
545 
546  return pSocket->m_pIOBuf[eIOBuf]->m_pRWBuf;
547 }
548 
549 /*!
550  * \brief Get Socket buffer size.
551  *
552  * \param pSocket Pointer to Socket.
553  * \param eIOBuf One of: \ref SOCK_IO_READ \ref SOCK_IO_WRITE.
554  *
555  * \return Returns size of buffer in bytes.
556  */
557 size_t SocketBufGetSize(Socket_T *pSocket, int eIOBuf)
558 {
559  CHKPTR(pSocket, (size_t)0);
560  SOCK_CHK_IO(eIOBuf, (size_t)0);
561 
562  return SimpleBufHasSize(pSocket->m_pIOBuf[eIOBuf]);
563 }
564 
565 /*!
566  * \brief Get number of bytes in Socket buffer.
567  *
568  * \param pSocket Pointer to Socket.
569  * \param eIOBuf One of: \ref SOCK_IO_READ \ref SOCK_IO_WRITE.
570  *
571  * \return Returns number of bytes currently in buffer.
572  */
573 size_t SocketBufGetLen(Socket_T *pSocket, int eIOBuf)
574 {
575  CHKPTR(pSocket, (size_t)0);
576  SOCK_CHK_IO(eIOBuf, (size_t)0);
577 
578  return SimpleBufHasLen(pSocket->m_pIOBuf[eIOBuf]);
579 }
580 
581 /*!
582  * \brief Clear a Socket buffer.
583  *
584  * \param pSocket Pointer to Socket.
585  * \param eIOBuf One of: \ref SOCK_IO_READ \ref SOCK_IO_WRITE.
586  */
587 void SocketBufClear(Socket_T *pSocket, int eIOBuf)
588 {
589  CHKPTR(pSocket);
590  SOCK_CHK_IO(eIOBuf);
591 
592  SimpleBufClear(pSocket->m_pIOBuf[eIOBuf]);
593 }
594 
595 
596 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
597 // Socket Attribute Access Functions
598 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
599 
600 /*!
601  * \brief Get Socket client user data.
602  *
603  * \param pSocket Pointer to Socket.
604  *
605  * \return Returns pointer to user defined data.
606  */
608 {
609  CHKPTR(pSocket, NULL);
610  return pSocket->m_pClientData;
611 }
612 
613 /*!
614  * \brief Get Socket client user data.
615  *
616  * \param pSocket Pointer to Socket.
617  * \param pClientData User defined data.
618  */
619 void SocketAttrSetClientData(Socket_T *pSocket, void *pClientData)
620 {
621  CHKPTR(pSocket);
622  pSocket->m_pClientData = pClientData;
623 }
624 
625 /*!
626  * \brief Get Socket local name.
627  *
628  * \param pSocket Pointer to Socket.
629  *
630  * \return Returns string.
631  */
632 const char *SocketAttrGetLocalName(Socket_T *pSocket)
633 {
634  CHKPTR(pSocket, NULL);
635  return pSocket->m_sLocalName;
636 }
637 
638 /*!
639  * \brief Set Socket local name.
640  *
641  * \param pSocket Pointer to Socket.
642  * \param sHostName Local host name string.
643  */
644 void SocketAttrSetLocalName(Socket_T *pSocket, const char *sHostName)
645 {
646  struct sockaddr_un addr; // largest address size (is there a better way?)
647  socklen_t sizAddr;
648 
649  CHKPTR(pSocket);
650 
651  delete(pSocket->m_sLocalName);
652 
653  sizAddr = (socklen_t)sizeof(addr);
654 
655  // closed
656  if( !SocketStateIsOpen(pSocket) )
657  {
659  }
660 
661  // error leg - simply use host name
662  else if( getsockname(pSocket->m_sd, (struct sockaddr *)&addr, &sizAddr) < 0 )
663  {
664  LOGSYSERROR("getsockname(%d, ...)", pSocket->m_sd);
665  pSocket->m_sLocalName = new_strdup(sHostName);
666  }
667 
668  // get local address
669  else
670  {
671  pSocket->m_sLocalName = SocketAddrName((struct sockaddr *)&addr, sHostName);
672  }
673 }
674 
675 /*!
676  * \brief Get Socket remote name.
677  *
678  * \param pSocket Pointer to Socket.
679  *
680  * \return Returns string.
681  */
682 const char *SocketAttrGetRemoteName(Socket_T *pSocket)
683 {
684  CHKPTR(pSocket, NULL);
685  return pSocket->m_sRemoteName;
686 }
687 
688 /*!
689  * \brief Set Socket remote name.
690  *
691  * \param pSocket Pointer to Socket.
692  * \param pAddr Socket address.
693  * \param sHostName Remote host name string.
694  */
696  struct sockaddr *pAddr,
697  const char *sHostName)
698 {
699  CHKPTR(pSocket);
700 
701  delete(pSocket->m_sRemoteName);
702 
703  // closed
704  if( !SocketStateIsOpen(pSocket) )
705  {
707  }
708 
709  // set preferred address named
710  else if( pAddr != NULL )
711  {
712  pSocket->m_sRemoteName = SocketAddrName(pAddr, sHostName);
713  }
714 
715  // simply use host name
716  else if( sHostName != NULL )
717  {
718  pSocket->m_sRemoteName = new_strdup(sHostName);
719  }
720 
721  // error
722  else
723  {
725  }
726 }
727 
728 /*!
729  * \brief Get Socket socket (file) descriptor.
730  *
731  * \param pSocket Pointer to Socket.
732  *
733  * \return Returns socket descriptor.
734  */
736 {
737  CHKPTR(pSocket, SOCK_SD_CLOSED);
738  return pSocket->m_sd;
739 }
740 
741 /*!
742  * \brief Set Socket socket (file) descriptor.
743  *
744  * \param pSocket Pointer to Socket.
745  * \param sd Socket descriptor.
746  */
747 void SocketAttrSetSd(Socket_T *pSocket, int sd)
748 {
749  CHKPTR(pSocket);
750  if( (pSocket->m_sd = sd) < 0 )
751  {
752  SocketClose(pSocket);
753  }
754 }
755 
756 /*!
757  * \brief Get Socket port number.
758  *
759  * \param pSocket Pointer to Socket.
760  *
761  * \return Returns port number.
762  */
764 {
765  CHKPTR(pSocket, SOCK_PORT_NONE);
766  return pSocket->m_ipPort;
767 }
768 
769 /*!
770  * \brief Set Socket port number.
771  *
772  * \param pSocket Pointer to Socket.
773  * \param ipPort Port number.
774  */
775 void SocketAttrSetPort(Socket_T *pSocket, int ipPort)
776 {
777  CHKPTR(pSocket);
778  pSocket->m_ipPort = ipPort;
779 }
780 
781 /*!
782  * \brief Get Socket flavor.
783  *
784  * \param pSocket Pointer to Socket.
785  *
786  * \return Returns flavor enumeration.
787  */
789 {
790  CHKPTR(pSocket, SockFlavorUndef);
791  return pSocket->m_eFlavor;
792 }
793 
794 /*!
795  * \brief Set Socket flavor.
796  *
797  * \param pSocket Pointer to Socket.
798  * \param eFlavor Flavor enumeration.
799  */
800 void SocketAttrSetFlavor(Socket_T *pSocket, SockFlavor eFlavor)
801 {
802  CHKPTR(pSocket);
803  pSocket->m_eFlavor = eFlavor;
804 }
805 
806 /*!
807  * \brief Check if Socket has an assigned flavor.
808  *
809  * \param pSocket Pointer to Socket.
810  * \param nMask Flavor mask of relevant bits.
811  * \param nFlavor Flavor bits.
812  *
813  * \return Returns true or false.
814  */
815 bool_t SocketAttrHasFlavor(Socket_T *pSocket, int nMask, int nFlavor)
816 {
817  CHKPTR(pSocket, false);
818 
819  // flavors only apply to open sockets
820  if( pSocket->m_sd == SOCK_SD_CLOSED )
821  {
822  return false;
823  }
824  else
825  {
826  return ((int)(pSocket->m_eFlavor) & nMask) == nFlavor? true: false;
827  }
828 }
829 
830 /*!
831  * \brief Set Socket for non-blockiong I/O.
832  *
833  * \param pSocket Pointer to Socket.
834  *
835  * \return Returns 0 on success, \h_lt 0 on failure.
836  */
838 {
839  CHKPTR(pSocket, -1);
840 
841  if( fcntl(pSocket->m_sd, F_SETFL, O_NONBLOCK) < 0 )
842  {
843  LOGSYSERROR("fcntl(%d,F_SETFL,O_NONBLOCK)", pSocket->m_sd);
844  return -1;
845  }
846  return OK;
847 }
848 
849 #if 0 // RDK TODO
850 
851 /*!
852  * \brief Set Socket for non-blockiong I/O.
853  *
854  * \param pSocket Pointer to Socket.
855  *
856  * \return Returns 0 on success, \h_lt 0 on failure.
857  */
858 int SocketAttrSetRcvTimeOut(Socket_T *pSocket, uint_t uSec)
859 {
860  int rc;
861 
862  CHKPTR(pSocket, -1);
863 
864  if( (rc = getsockopt(pSocket->m_sd, SO_RCVTIMEO, &tv)) < 0 )
865  {
866  LOGSYSERROR("getsockopt(%d,SO_RCVTIMEO,...)", pSocket->m_sd);
867  return -1;
868  }
869 
870  LOGDIAG3(x, y);
871 
872  return OK;
873 }
874 #endif // RDK
875 
876 
877 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
878 // Socket State Functions
879 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
880 
881 /*!
882  * \brief Check if Socket is open.
883  *
884  * \param pSocket Pointer to Socket.
885  *
886  * \return Returns true or false.
887  */
889 {
890  if( pSocket == NULL )
891  {
892  return false;
893  }
894  else
895  {
896  return pSocket->m_sd == SOCK_SD_CLOSED? false: true;
897  }
898 }
899 
900 /*!
901  * \brief Check if Socket is in some kind of errored state.
902  *
903  * The fcntl() non-blocking function is used to test the socket.
904  *
905  * \param pSocket Pointer to Socket.
906  *
907  * \return Returns true or false.
908  */
910 {
911  int fopts = 0;
912 
913  if( (pSocket == NULL) || (pSocket->m_sd == SOCK_SD_CLOSED) )
914  {
915  return false;
916  }
917  else if( fcntl(pSocket->m_sd, F_GETFL, &fopts) >= 0 )
918  {
919  return false;
920  }
921  else
922  {
923  return true;
924  }
925 }
926 
927 
928 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
929 // Socket Open/Close Functions
930 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
931 
932 /*!
933  * \brief Create and open a new TCP/IP passive listener socket on this host.
934  *
935  * \param ipPortListener Port number to listen on.
936  * \param sLocalHostName String name of local host to bind to. If NULL, then
937  * this host will automatically choose the IP address.
938  *
939  * \return:
940  * Returns a new listener Socket_T pointer on success, NULL on failure.
941  */
942 Socket_T *SocketOpenTcpListener(int ipPortListener, const char *sLocalHostName)
943 {
944  int sd;
945  struct sockaddr_in addrInet;
946  int backlog = 8;
947  int nVal;
948  Socket_T *pSocket;
949 
950  LOGDIAG4CALL(_TINT(ipPortListener), _TSTR(sLocalHostName));
951 
952  //
953  // Create socket in protocal familiy INET (IPv4), of type STREAM (TCP).
954  //
955  if( (sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 )
956  {
957  LOGSYSERROR("socket(%d,%d,%d)", PF_INET, SOCK_STREAM, IPPROTO_TCP);
958  return NULL;
959  }
960 
961  //
962  // Disallow binding if another local task already listening on this address.
963  // After socking binding and listen, then this sock option will disallow
964  // binding from any task to this port on any local address.
965  // Note: Non-critacal, so continue on errors.
966  //
967  nVal = 1;
968  if( setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
969  &nVal, (socklen_t)sizeof(nVal)) < 0 )
970  {
971  LOGSYSERROR("setsockopt(%d,SOL_SOCKET,SO_REUSEADDR)", sd);
972  }
973 
974  //
975  // Enable sending of keep-alive messages on connection-oriented sockets.
976  // Note: Non-critacal, so continue on errors.
977  //
978  nVal = 1;
979  if( setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE,
980  &nVal, (socklen_t)sizeof(nVal)) < 0 )
981  {
982  LOGSYSERROR("setsockopt(%d,SOL_SOCKET,SO_KEEPALIVE)", sd);
983  }
984 
985  //
986  // Bind this socket to application family INET (IP) at the given port.
987  //
988  addrInet.sin_family = AF_INET; // ip application family
989  addrInet.sin_port = htons_nowarn((uint16_t)ipPortListener);
990  // listen port number
991 
992  //
993  // Let bind() automatically fill in the IP address of the machine where
994  // the calling process is running on.
995  //
996  if( sLocalHostName == NULL )
997  {
998  addrInet.sin_addr.s_addr = htonl(INADDR_ANY);
999  }
1000 
1001  //
1002  // Bind to a specific local address
1003  //
1004  else if( SockResolveHostName(sLocalHostName, &(addrInet.sin_addr)) < 0 )
1005  {
1006  LOGERROR("SockResolveHostName() failed");
1007  close(sd);
1008  return NULL;
1009  }
1010 
1011  //
1012  // Bind socket to the address.
1013  //
1014  if( bind(sd, (struct sockaddr *)&addrInet, (socklen_t)sizeof(addrInet)) < 0 )
1015  {
1016  LOGSYSERROR("bind(%d, ...)", sd);
1017  close(sd);
1018  return NULL;
1019  }
1020 
1021  //
1022  // Mark this bound socket as a listener for new incoming connections that
1023  // can then be accepted. The backlog is the maximum queue length of pending
1024  // connection requests.
1025  //
1026  if( listen(sd, backlog) < 0 )
1027  {
1028  LOGSYSERROR("listen(%d,%d)", sd, backlog);
1029  close(sd);
1030  return NULL;
1031  }
1032 
1033  //
1034  // Now create a new socket and set the appropriate attributes
1035  //
1036  pSocket = SocketNew();
1037 
1038  SocketAttrSetSd(pSocket, sd);
1039  SocketAttrSetFlavor(pSocket,
1041  SocketAttrSetLocalName(pSocket, NULL);
1043 
1044  LOGDIAG4("Opened Socket Listener on %s", SocketAttrGetLocalName(pSocket));
1045 
1046  return pSocket;
1047 }
1048 
1049 /*!
1050  * \brief Create and open a new TCP/IP socket to the given remote host and
1051  * port.
1052  *
1053  * \param sRemoteHostName Dotted address or network name.
1054  * \param ipPortRemote Remote port number.
1055  *
1056  * \return
1057  * Returns a new TCP Socket_T pointer on success, NULL on failure.
1058  */
1059 Socket_T *SocketOpenTcpConnection(const char *sRemoteHostName, int ipPortRemote)
1060 {
1061  int sd;
1062  struct sockaddr_in addrInet;
1063  Socket_T *pSocket;
1064 
1065  //
1066  // Create socket in protocal familiy INET (IPv4), of type STREAM (TCP).
1067  //
1068  if( (sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 )
1069  {
1070  LOGSYSERROR("socket(%d,%d,%d)", PF_INET, SOCK_STREAM, IPPROTO_TCP);
1071  return NULL;
1072  }
1073 
1074  //
1075  // Set IPv4 address of remote
1076  //
1077  addrInet.sin_family = AF_INET; // ip application family
1078  addrInet.sin_port = htons_nowarn((ushort_t)ipPortRemote);
1079  // remote port number
1080 
1081  if( SockResolveHostName(sRemoteHostName, &(addrInet.sin_addr)) < 0 )
1082  {
1083  LOGERROR("SockResolveHostName() failed");
1084  close(sd);
1085  return NULL;
1086  }
1087 
1088  //
1089  // Connect to remote end
1090  //
1091  if(connect(sd, (struct sockaddr *)&addrInet, (socklen_t)sizeof(addrInet)) < 0)
1092  {
1093  LOGSYSERROR("connect(%d, ...)", sd);
1094  close(sd);
1095  return NULL;
1096  }
1097 
1098  //
1099  // Now create a new socket and set the appropriate attributes
1100  //
1101  pSocket = SocketNew();
1102 
1103  SocketAttrSetSd(pSocket, sd);
1104  SocketAttrSetFlavor(pSocket,
1106  SocketAttrSetLocalName(pSocket, NULL);
1107  SocketAttrSetRemoteName(pSocket, (struct sockaddr *)&addrInet,
1108  sRemoteHostName);
1109 
1110  LOGDIAG4("Opened Connection %s", SocketAttrGetRemoteName(pSocket));
1111 
1112  return pSocket;
1113 }
1114 
1115 /*!
1116  * \brief Create and open a new UDP/IP connectionless socket.
1117  * port.
1118  *
1119  * \param ipPortUdp Binding UDP port number.
1120  * \param sLocalHostName String name of local host to bind to. If NULL, then
1121  * this host will automatically choose the IP address.
1122  *
1123  * \return
1124  * Returns a new UDP Socket_T pointer on success, NULL on failure.
1125  */
1126 Socket_T *SocketOpenUdp(int ipPortUdp, const char *sLocalHostName)
1127 {
1128  int sd;
1129  struct sockaddr_in addrInet;
1130  Socket_T *pSocket;
1131 
1132  LOGDIAG4CALL(_TINT(ipPortUdp), _TSTR(sLocalHostName));
1133 
1134  //
1135  // Create socket in protocal familiy INET (IPv4), of type DateGram (UDP).
1136  //
1137  if( (sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0 )
1138  {
1139  LOGSYSERROR("socket(%d,%d,%d)", PF_INET, SOCK_DGRAM, IPPROTO_UDP);
1140  return NULL;
1141  }
1142 
1143  //
1144  // Bind this socket to application family INET (IP) at the given port.
1145  //
1146  memset((void*)&addrInet, 0, sizeof(addrInet));
1147  addrInet.sin_family = AF_INET; // ip application family
1148  addrInet.sin_port = htons_nowarn((ushort_t)ipPortUdp);
1149  // listen port number
1150 
1151 
1152  //
1153  // Let bind() automatically fill in the IP address of the machine where
1154  // the calling process is running on.
1155  //
1156  if( sLocalHostName == NULL )
1157  {
1158  addrInet.sin_addr.s_addr = htonl(INADDR_ANY);
1159  }
1160 
1161  //
1162  // Bind to a specific local address
1163  //
1164  else if( SockResolveHostName(sLocalHostName, &(addrInet.sin_addr)) < 0 )
1165  {
1166  LOGERROR("SockResolveHostName() failed");
1167  close(sd);
1168  return NULL;
1169  }
1170 
1171  //
1172  // Bind socket to the address.
1173  //
1174  if( bind(sd, (struct sockaddr *)&addrInet, (socklen_t)sizeof(addrInet)) < 0 )
1175  {
1176  LOGSYSERROR("bind(%d, ...)", sd);
1177  close(sd);
1178  return NULL;
1179  }
1180 
1181  //
1182  // Now create a new socket and set the appropriate attributes
1183  //
1184  pSocket = SocketNew();
1185 
1186  SocketAttrSetSd(pSocket, sd);
1187  SocketAttrSetFlavor(pSocket,
1189  SocketAttrSetLocalName(pSocket, NULL);
1191 
1192  LOGDIAG4("Opened UDP Socket %s", SocketAttrGetLocalName(pSocket));
1193 
1194  return pSocket;
1195 }
1196 
1197 /*!
1198  * \brief Create and open a new UNIX connectionless socket.
1199  *
1200  * \todo Create and open a new UNIX connectionless socket.
1201  *
1202  * \param ipPortUdp Binding UDP port number.
1203  * \param nType Type of...
1204  *
1205  * \return
1206  * Returns a new UNIX Socket_T pointer on success, NULL on failure.
1207  */
1208 Socket_T *SocketOpenUnix(int ipPortUdp, int nType)
1209 {
1210  return NULL;
1211 }
1212 
1213 /*!
1214  * \brief Create and open a new UNIX pair socket.
1215  *
1216  * \todo Create and open a new UNIX pair socket.
1217  *
1218  * \param nType Type of...
1219  *
1220  * \return
1221  * Returns a new UNIX Socket_T pointer on success, NULL on failure.
1222  */
1224 {
1225  return NULL;
1226 }
1227 
1228 /*!
1229  * \brief Accept a client connection requst from the listener socket.
1230  *
1231  * The new socket will be set to non-blocking I/O mode if requested.
1232  *
1233  * \param pSocketListener Pointer to open listener socket.
1234  * \param bNonBlock Do [not] set socket to non-blocking.
1235  *
1236  * Return Value:
1237  * Newly allocated and accepted open Socket_T pointer on success,
1238  * NULL on failure.
1239  */
1240 Socket_T *SocketAccept(Socket_T *pSocketListener, bool_t bNonBlock)
1241 {
1242  int sd;
1243  struct sockaddr saddr;
1244  unsigned int addrlen = sizeof(saddr);
1245  Socket_T *pSocket;
1246 
1247  LOGDIAG4CALL("pSocketListener->%s", pSocketListener->m_sLocalName);
1248 
1249  // accept incoming connection
1250  if((sd = accept(pSocketListener->m_sd, &saddr, (socklen_t *)&addrlen)) == -1)
1251  {
1252  LOGSYSERROR("accept(%d,...)", pSocketListener->m_sd);
1253  return NULL;
1254  }
1255 
1256  //
1257  // Now create a new socket and set the appropriate attributes
1258  //
1259  pSocket = SocketNew();
1260 
1261  SocketAttrSetSd(pSocket, sd);
1262  SocketAttrSetPort(pSocket, ((struct sockaddr_in*)&saddr)->sin_port);
1263  SocketAttrSetFlavor(pSocket,
1265  SocketAttrSetLocalName(pSocket, NULL);
1266  SocketAttrSetRemoteName(pSocket, &saddr, NULL);
1267 
1268  // set non-blocking
1269  if( bNonBlock )
1270  {
1271  if( SocketAttrSetNonBlocking(pSocket) == -1 )
1272  {
1273  LOGERROR("SockAttrSetNonBlocking() failed");
1274  SocketClose(pSocket);
1275  SocketDelete(pSocket);
1276  return NULL;
1277  }
1278  }
1279 
1280  LOGDIAG4("Accepted connection from %s", SocketAttrGetRemoteName(pSocket));
1281 
1282  return pSocket;
1283 }
1284 
1285 /*!
1286  * \brief Close a Socket.
1287  *
1288  * \param pSocket Pointer to Socket.
1289  *
1290  * \return Returns 0 on success, \h_lt 0 on failure.
1291  */
1292 int SocketClose(Socket_T *pSocket)
1293 {
1294  CHKPTR(pSocket, -1);
1295 
1296  if( pSocket->m_sd != SOCK_SD_CLOSED )
1297  {
1298  shutdown(pSocket->m_sd, SHUT_RDWR);
1299 
1300  if( close(pSocket->m_sd) < 0 )
1301  {
1302  LOGSYSERROR("close(%d)", pSocket->m_sd);
1303  }
1304 
1305  if( SocketAttrIsConnection(pSocket) )
1306  {
1307  LOGDIAG4("Closed Connection %s", SocketAttrGetRemoteName(pSocket));
1308  }
1309  else
1310  {
1311  LOGDIAG4("Closed Socket %s", SocketAttrGetLocalName(pSocket));
1312  }
1313 
1314  SocketAttrSetSd(pSocket, SOCK_SD_CLOSED);
1318  }
1319 
1320  return 0;
1321 }
1322 
1323 
1324 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
1325 // Socket Read/Write Functions
1326 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
1327 
1328 /*!
1329  * \brief Reads the next available bytes from the Socket into in the Socket's
1330  * read buffer.
1331  *
1332  * \note Read are from the connection to the read buffer.
1333  *
1334  * \param pSocket Pointer to Socket.
1335  *
1336  * \returns
1337  * Number of bytes read on success (may be zero if a timeout or an interupt
1338  * occurred). Returns \h_lt 0 (RC_SOCK_E*) return code on error.
1339  */
1340 ssize_t SocketRead(Socket_T *pSocket)
1341 {
1342  SimpleBuf_T *pBuf;
1343  size_t nBytes;
1344  ssize_t nRead;
1345 
1346  CHKPTR(pSocket, SOCK_RC_EBADSOCK);
1347 
1348  // socket isn't open
1349  if( !SocketStateIsOpen(pSocket) )
1350  {
1351  LOGERROR("Socket %s is not open for reading", pSocket->m_sLocalName);
1352  return SOCK_RC_EBADSD;
1353  }
1354 
1355  // socket's simple read buffer
1356  pBuf = pSocket->m_pIOBuf[SOCK_IO_READ];
1357 
1358  // no read buffer present
1359  CHKPTR(pBuf, SOCK_RC_ENOBUF);
1360  CHKPTR(pBuf->m_pRWBuf, SOCK_RC_ENOBUF);
1361 
1362  // bytes remaining available in buffer
1363  nBytes = SimpleBufHasAvail(pBuf);
1364 
1365  // read buffer is full
1366  if( nBytes == 0 )
1367  {
1368  return SOCK_RC_EBUFFULL;
1369  }
1370 
1371  // read
1372  nRead = read(pSocket->m_sd, SimpleBufGetWritePtr(pBuf), nBytes);
1373 
1374  LOGDIAG4("SocketRead: read()=%d", nRead);
1375 
1376  // system error occurred - interpret
1377  if( nRead < 0 )
1378  {
1379  switch(errno)
1380  {
1381  case EAGAIN: // non-blocking, but read would have caused blocking
1382  case EINTR: // read was interrupted
1383  return 0;
1384  default:
1385  LOGSYSERROR("read()");
1386  return SOCK_RC_ESYSERR;
1387  }
1388  }
1389 
1390  SimpleBufWriteSeek(pBuf, (size_t)nRead, SIMPLEBUF_REL);
1391 
1392  return nRead;
1393 }
1394 
1395 /*!
1396  * \brief Writes the bytes from the Socket's write buffer to the Socket
1397  * connection.
1398  *
1399  * Only one write attempt is made.
1400  *
1401  * \note Writes are from the Socket write buffer.
1402  *
1403  * \param pSocket Pointer to Socket.
1404  *
1405  * \returns
1406 // Number of bytes written on success (may be zero if a timeout or an interupt
1407 // occurred). Returns \h_lt 0 (RC_SOCK_E*) return code on error.
1408  */
1409 ssize_t SocketWrite(Socket_T *pSocket)
1410 {
1411  SimpleBuf_T *pBuf;
1412  size_t nBytes;
1413  ssize_t nWritten;
1414 
1415  CHKPTR(pSocket, SOCK_RC_EBADSOCK);
1416 
1417  // socket isn't open
1418  if( !SocketStateIsOpen(pSocket) )
1419  {
1420  LOGERROR("Socket is not open for writing");
1421  return SOCK_RC_EBADSD;
1422  }
1423 
1424  // socket's simple read buffer
1425  pBuf = pSocket->m_pIOBuf[SOCK_IO_WRITE];
1426 
1427  // no write buffer present
1428  CHKPTR(pBuf, SOCK_RC_ENOBUF);
1429  CHKPTR(pBuf->m_pRWBuf, SOCK_RC_ENOBUF);
1430 
1431  // bytes in buffer
1432  nBytes = SimpleBufHasLen(pBuf);
1433 
1434  // read buffer is empty - finished writing this buffer
1435  if( nBytes == 0 )
1436  {
1437  return SOCK_RC_IODONE;
1438  }
1439 
1440  // write
1441  nWritten = write(pSocket->m_sd, SimpleBufGetReadPtr(pBuf), nBytes);
1442 
1443  // system error occurred - interpret
1444  if( nWritten < 0 )
1445  {
1446  switch(errno)
1447  {
1448  case EAGAIN: // non-blocking, but write would have caused blocking
1449  case EINTR: // write was interrupted
1450  return 0;
1451  default:
1452  LOGSYSERROR("write()");
1453  return SOCK_RC_ESYSERR;
1454  }
1455  }
1456 
1457  SimpleBufReadSeek(pBuf, (size_t)nWritten, SIMPLEBUF_REL);
1458 
1459  return nWritten;
1460 }
1461 
1462 /*!
1463  * \brief Writes all of the bytes from the socket's write buffer until
1464  * no more bytes or error.
1465  *
1466  * \param pSocket Pointer to Socket.
1467  *
1468  * \return
1469  * Number of bytes written on success.
1470  * Returns \h_lt 0 (RC_SOCK_E*) return code on error.
1471  */
1472 ssize_t SocketWriteAll(Socket_T *pSocket)
1473 {
1474  ssize_t n, nWritten=0;
1475 
1476  // write all of the bytes in the buffer
1477  while( (n = SocketWrite(pSocket)) >= 0 )
1478  {
1479  nWritten += n;
1480  }
1481 
1482  // all bytes have been
1483  if( n == SOCK_RC_IODONE )
1484  {
1485  return nWritten;
1486  }
1487 
1488  // error occurred
1489  else
1490  {
1491  return n;
1492  }
1493 }
1494 
1495 #ifdef debugSockUTest
1496 
1497 /*!
1498  * \brief Socket Unit Tester.
1499  */
1500 void SocketUTest()
1501 {
1502  Socket_T *pSocket;
1503 
1504  LOGDIAG4("SocketUTest: SocketOpenTcpListener(9192, ANYHOST)");
1505  if( (pSocket = SocketOpenTcpListener(9192, NULL))
1506  == NULL )
1507  {
1508  LOGERROR("SocketOpenTcpListener() failed");
1509  }
1510  else
1511  {
1512  LOGDIAG4(" LocalName='%s'", SocketAttrGetLocalName(pSocket));
1513  LOGDIAG4(" RemoteName='%s'", SocketAttrGetRemoteName(pSocket));
1514  SocketClose(pSocket);
1515  SocketDelete(pSocket);
1516  }
1517 
1518  LOGDIAG4("SocketUTest: SocketOpenTcpListener(9192, nouturn)");
1519  if( (pSocket = SocketOpenTcpListener(9192, "nouturn"))
1520  == NULL )
1521  {
1522  LOGERROR("SocketOpenTcpListener() failed");
1523  }
1524  else
1525  {
1526  LOGDIAG4(" LocalName='%s'", SocketAttrGetLocalName(pSocket));
1527  LOGDIAG4(" RemoteName='%s'", SocketAttrGetRemoteName(pSocket));
1528  SocketClose(pSocket);
1529  SocketDelete(pSocket);
1530  }
1531 
1532  LOGDIAG4("SocketUTest: SocketOpenTcpConnection(pedxing, 21)");
1533  if( (pSocket = SocketOpenTcpConnection("pedxing", 21)) == NULL )
1534  {
1535  LOGERROR("SocketOpenTcpConnection() failed");
1536  }
1537  else
1538  {
1539  LOGDIAG4(" LocalName='%s'", SocketAttrGetLocalName(pSocket));
1540  LOGDIAG4(" RemoteName='%s'", SocketAttrGetRemoteName(pSocket));
1541  SocketClose(pSocket);
1542  SocketDelete(pSocket);
1543  }
1544 
1545  LOGDIAG4("SocketUTest: SocketOpenUdp(9193, ANYHOST)");
1546  if( (pSocket = SocketOpenUdp(9193, NULL)) == NULL )
1547  {
1548  LOGERROR("SocketOpenUdp() failed");
1549  }
1550  else
1551  {
1552  LOGDIAG4(" LocalName='%s'", SocketAttrGetLocalName(pSocket));
1553  LOGDIAG4(" RemoteName='%s'", SocketAttrGetRemoteName(pSocket));
1554  SocketClose(pSocket);
1555  SocketDelete(pSocket);
1556  }
1557 
1558  LOGDIAG4("SocketUTest: SocketOpenUdp(9193, 192.168.1.2)");
1559  if( (pSocket = SocketOpenUdp(9193, "192.168.2.2")) == NULL )
1560  {
1561  LOGERROR("SocketOpenUdp() failed");
1562  }
1563  else
1564  {
1565  LOGDIAG4(" LocalName='%s'", SocketAttrGetLocalName(pSocket));
1566  LOGDIAG4(" RemoteName='%s'", SocketAttrGetRemoteName(pSocket));
1567  SocketClose(pSocket);
1568  SocketDelete(pSocket);
1569  }
1570 }
1571 
1572 #endif // debugSockUTest
void * m_pClientData
client data
Definition: sock.c:144
Socket_T * SocketNew()
Allocate a new, unconnected socket.
Definition: sock.c:433
static byte_t * SimpleBufGetReadPtr(SimpleBuf_T *pBuf)
Returns pointer to internal I/O buffer at the current read position.
Definition: simplebuf.h:202
SimpleBuf_T * SimpleBufNew()
Allocate a new simple buffer with no internal buffer allocation.
Definition: simplebuf.c:70
#define _TINT(var)
int (decimal)
Definition: log.h:582
const char * SocketAttrGetRemoteName(Socket_T *pSocket)
Get Socket remote name.
Definition: sock.c:682
#define NEWSTR(len)
Allocate new string buffer of length len+1.
Definition: new.h:64
#define SOCK_IO_READ
read index
Definition: sock.h:130
INLINE_IN_H bool_t SocketAttrIsConnection(Socket_T *pSocket)
Test if socket is connection flavor.
Definition: sock.h:252
static size_t SimpleBufHasSize(SimpleBuf_T *pBuf)
Returns size of buffer.
Definition: simplebuf.h:142
void SocketDelete(Socket_T *pSocket)
Delate an allocated socket.
Definition: sock.c:457
connection/connectionless
Definition: sock.h:105
static void fdset_nowarn(int fd, fd_set *pset)
FD_SET() wrapper with no annoying warnings.
Definition: sock.c:95
char * new_strdup(const char *s)
Duplicate a string.
Definition: new.c:176
#define SOCK_RC_IODONE
finished current I/O
Definition: sock.h:120
Socket_T * SocketOpenUnixPair(int nType)
Create and open a new UNIX pair socket.
Definition: sock.c:1223
bool_t SocketAttrHasFlavor(Socket_T *pSocket, int nMask, int nFlavor)
Check if Socket has an assigned flavor.
Definition: sock.c:815
#define SIMPLEBUF_REL
relative
Definition: simplebuf.h:53
SimpleBuf_T * m_pIOBuf[SOCK_IO_NUMOF]
read/write buffers
Definition: sock.c:143
#define CHKPTR(p,...)
Checks validity of pointer.
Definition: log.h:651
#define LOGDIAG3(fmt,...)
Standard Diagnostic Level 3 logging.
Definition: log.h:393
byte_t * m_pRWBuf
internal read/write buffer
Definition: simplebuf.h:60
char * SocketThisHostName()
Get the host string name of this network node (computer).
Definition: sock.c:379
#define SOCK_RC_EBADSD
bad/closed socket descriptor
Definition: sock.h:124
void SocketAttrSetRemoteName(Socket_T *pSocket, struct sockaddr *pAddr, const char *sHostName)
Set Socket remote name.
Definition: sock.c:695
#define OK
Okay.
Definition: rnrconfig.h:301
#define NULL
null pointer
Definition: rnrconfig.h:199
int SocketAttrSetNonBlocking(Socket_T *pSocket)
Set Socket for non-blockiong I/O.
Definition: sock.c:837
static size_t SimpleBufHasLen(SimpleBuf_T *pBuf)
Returns number of bytes currently in buffer.
Definition: simplebuf.h:178
Memory allocation and deallocation declarations.
#define SOCK_PORT_NONE
no port number specified
Definition: sock.h:145
#define SOCK_RC_ENOBUF
no buffer
Definition: sock.h:123
const char * SockStrUnknownHost
unknown host
Definition: sock.c:131
u32_t uint_t
32-bit unsigned integer
Definition: rnrconfig.h:181
ssize_t SocketRead(Socket_T *pSocket)
Reads the next available bytes from the Socket into in the Socket&#39;s read buffer.
Definition: sock.c:1340
SimpleBuf_T * SimpleBufNewWithBuf(size_t nBufSize)
Allocate a new simple buffer with internal buffer of nBufSize.
Definition: simplebuf.c:91
Socket_T * SocketOpenTcpConnection(const char *sRemoteHostName, int ipPortRemote)
Create and open a new TCP/IP socket to the given remote host and port.
Definition: sock.c:1059
void SocketAttrSetSd(Socket_T *pSocket, int sd)
Set Socket socket (file) descriptor.
Definition: sock.c:747
#define SOCK_RC_EBUFFULL
buffer is full
Definition: sock.h:121
SockFlavor
< unit tests
Definition: sock.h:88
void SimpleBufDelete(SimpleBuf_T *pBuf)
Delete a simple buffer along with the internal buffer.
Definition: simplebuf.c:111
void SocketAttrSetFlavor(Socket_T *pSocket, SockFlavor eFlavor)
Set Socket flavor.
Definition: sock.c:800
#define PRAGMA_IGNORED(filter)
Disable compiler warnings on the diagnostics filter.
Definition: rnrconfig.h:358
#define LOGSYSERROR(fmt,...)
Standard System Error logging.
Definition: log.h:509
const char * SocketAttrGetLocalName(Socket_T *pSocket)
Get Socket local name.
Definition: sock.c:632
#define HOST_NAME_MAX
maximum host name length
Definition: sock.c:86
ssize_t SocketWriteAll(Socket_T *pSocket)
Writes all of the bytes from the socket&#39;s write buffer until no more bytes or error.
Definition: sock.c:1472
SimpleBuf_T * SocketBufSetBuf(Socket_T *pSocket, int eIOBuf, byte_t *pBuf, size_t nBufSize)
Attach a buffer to Socket.
Definition: sock.c:505
listener socket
Definition: sock.h:104
UDP (DGRAM)
Definition: sock.h:100
const char * SockStrClosed
closed socket
Definition: sock.c:127
static size_t SimpleBufHasAvail(SimpleBuf_T *pBuf)
Returns number of bytes available in buffer for writing.
Definition: simplebuf.h:190
void SocketAttrSetLocalName(Socket_T *pSocket, const char *sHostName)
Set Socket local name.
Definition: sock.c:644
void SocketAttrSetClientData(Socket_T *pSocket, void *pClientData)
Get Socket client user data.
Definition: sock.c:619
static char * SocketAddrNameUnix(struct sockaddr_un *pAddrUnix, const char *sHostName)
Allocate formated UNIX name.
Definition: sock.c:303
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
char * m_sLocalName
local name
Definition: sock.c:141
ssize_t SocketWrite(Socket_T *pSocket)
Writes the bytes from the Socket&#39;s write buffer to the Socket connection.
Definition: sock.c:1409
#define LOGDIAG4(fmt,...)
Standard Diagnostic Level 4 logging.
Definition: log.h:386
void * SocketAttrGetClientData(Socket_T *pSocket)
Get Socket client user data.
Definition: sock.c:607
size_t SocketBufGetSize(Socket_T *pSocket, int eIOBuf)
Get Socket buffer size.
Definition: sock.c:557
bool_t SocketStateIsOpen(Socket_T *pSocket)
Check if Socket is open.
Definition: sock.c:888
#define NEW(T)
Allocate new type.
Definition: new.h:49
Socket services declarations.
static char * SocketAddrName(struct sockaddr *pAddr, const char *sHostName)
Allocate formated address name.
Definition: sock.c:347
const char * SockStrLocalHost
local host
Definition: sock.c:130
#define SOCK_RC_EBADSOCK
socket is bad
Definition: sock.h:122
Socket_T * SocketOpenTcpListener(int ipPortListener, const char *sLocalHostName)
Create and open a new TCP/IP passive listener socket on this host.
Definition: sock.c:942
void SimpleBufSetBuf(SimpleBuf_T *pBuf, byte_t *pRWBuf, size_t nBufSize, size_t nLen)
Set simple buffer&#39;s internal read/write buffer.
Definition: simplebuf.c:134
#define SOCK_CHK_IO(io,...)
Check I/O index.
Definition: sock.h:138
int SocketAttrGetSd(Socket_T *pSocket)
Get Socket socket (file) descriptor.
Definition: sock.c:735
void SocketAttrSetPort(Socket_T *pSocket, int ipPort)
Set Socket port number.
Definition: sock.c:775
int bool_t
"boolean" T/F
Definition: rnrconfig.h:187
SockFlavor m_eFlavor
socket type
Definition: sock.c:140
RoadNarrows Robotics common configuration file.
const char * SockStrAnyHost
any host
Definition: sock.c:129
Socket_T * SocketAccept(Socket_T *pSocketListener, bool_t bNonBlock)
Accept a client connection requst from the listener socket.
Definition: sock.c:1240
u8_t byte_t
8-bit byte
Definition: rnrconfig.h:177
static char * SocketAddrNameInet(int af, struct sockaddr *pAddr, const char *sHostName)
Allocate formated internet name (IPV4, IPV6).
Definition: sock.c:204
#define _TSTR(var)
string variable
Definition: log.h:578
#define SOCK_RC_ESYSERR
system error occurred
Definition: sock.h:125
Definition: sock.c:136
#define SOCK_SD_CLOSED
closed socket descriptor value
Definition: sock.h:144
Socket_T * SocketOpenUdp(int ipPortUdp, const char *sLocalHostName)
Create and open a new UDP/IP connectionless socket. port.
Definition: sock.c:1126
SimpleBuf_T * SocketBufNewBuf(Socket_T *pSocket, int eIOBuf, size_t nBufSize)
Allocate a socket buffer and attach to Socket.
Definition: sock.c:485
static size_t SimpleBufWriteSeek(SimpleBuf_T *pBuf, size_t wpos, int how)
Seek buffer write head to the new write position.
Definition: simplebuf.h:125
SimpleBuf_T * SocketBufGetBuf(Socket_T *pSocket, int eIOBuf)
Get Socket buffer.
Definition: sock.c:525
int SocketClose(Socket_T *pSocket)
Close a Socket.
Definition: sock.c:1292
#define LOGDIAG4CALL(...)
Standard Diagnostic Level 4 function call tracing.
Definition: log.h:442
#define PRAGMA_WARNING(filter)
Enable compiler warnings on the diagnostics filter.
Definition: rnrconfig.h:365
static size_t SimpleBufReadSeek(SimpleBuf_T *pBuf, size_t rpos, int how)
Seek buffer read head to the new read position.
Definition: simplebuf.h:105
const char * SockStrDisconnected
disconnected
Definition: sock.c:128
int m_sd
(open) socket descriptor
Definition: sock.c:138
int m_ipPort
socket port
Definition: sock.c:139
u16_t ushort_t
16-bit unsigned integer
Definition: rnrconfig.h:179
SockFlavor SocketAttrGetFlavor(Socket_T *pSocket)
Get Socket flavor.
Definition: sock.c:788
static ushort_t htons_nowarn(ushort_t huShort)
htons() wrapper with no annoying warnings.
Definition: sock.c:117
void SocketBufClear(Socket_T *pSocket, int eIOBuf)
Clear a Socket buffer.
Definition: sock.c:587
Socket_T * SocketOpenUnix(int ipPortUdp, int nType)
Create and open a new UNIX connectionless socket.
Definition: sock.c:1208
static ushort_t ntohs_nowarn(ushort_t huShort)
ntohs() wrapper with no annoying warnings.
Definition: sock.c:107
undefined
Definition: sock.h:90
#define SOCK_IO_NUMOF
number of indices
Definition: sock.h:132
bool_t SocketStateIsErrored(Socket_T *pSocket)
Check if Socket is in some kind of errored state.
Definition: sock.c:909
static int SockResolveHostName(const char *sHostName, struct in_addr *pAddrInet)
Resolve host name into IP address (IPV4 only).
Definition: sock.c:155
byte_t * SocketBufGetRawBuf(Socket_T *pSocket, int eIOBuf)
Get Socket raw buffer.
Definition: sock.c:541
Logger declarations.
size_t SocketBufGetLen(Socket_T *pSocket, int eIOBuf)
Get number of bytes in Socket buffer.
Definition: sock.c:573
int SocketAttrGetPort(Socket_T *pSocket)
Get Socket port number.
Definition: sock.c:763
#define SOCK_IO_WRITE
write index
Definition: sock.h:131
Simple [io] buffer declarations and operations.
static void SimpleBufClear(SimpleBuf_T *pBuf)
Clear contents of buffer.
Definition: simplebuf.h:89
char * m_sRemoteName
remote name
Definition: sock.c:142
static byte_t * SimpleBufGetWritePtr(SimpleBuf_T *pBuf)
Returns pointer to internal I/O buffer at the current write position.
Definition: simplebuf.h:214