PAPI  5.0.1.0
pit_server.c File Reference
Include dependency graph for pit_server.c:

Go to the source code of this file.

Defines

#define DFLT_SERVICE   "PIT" /* Programmable Interdimensional Timer */
#define INVALID_DESC   -1 /* Invalid file descriptor. */
#define MAXCONNQLEN   3 /* Max nbr of connection requests to queue. */
#define MAXTCPSCKTS   2 /* One TCP socket for IPv4 & one for IPv6. */
#define MAXUDPSCKTS   2 /* One UDP socket for IPv4 & one for IPv6. */
#define VALIDOPTS   "vh:p:" /* Valid command options. */
#define USAGE
#define CHK(expr)

Functions

static int openSckt (const char *service, const char *protocol, int desc[], size_t *descSize)
static void pit (int tSckt[], size_t tScktSize, int uSckt[], size_t uScktSize)
int main (int argc, char *argv[])

Variables

int false = 0
int true = 1
static char hostBfr [NI_MAXHOST]
static const char * pgmName
static char servBfr [NI_MAXSERV]
static int verbose = 0
struct timeval tm
char timeStr [40]
char service_name [20]
int need

Define Documentation

#define CHK (   expr)
Value:
do                                                          \
        {                                                           \
           if ( (expr) == -1 )                                      \
           {                                                        \
              fprintf( stderr,                                      \
                       "%s (line %d): System call ERROR - %s.\n",   \
                       pgmName,                                     \
                       __LINE__,                                    \
                       strerror( errno ) );                         \
              exit( 1 );                                            \
           }   /* End IF system call failed. */                     \
        } while ( false )

Definition at line 102 of file pit_server.c.

#define DFLT_SERVICE   "PIT" /* Programmable Interdimensional Timer */

Definition at line 54 of file pit_server.c.

#define INVALID_DESC   -1 /* Invalid file descriptor. */

Definition at line 56 of file pit_server.c.

#define MAXCONNQLEN   3 /* Max nbr of connection requests to queue. */

Definition at line 57 of file pit_server.c.

#define MAXTCPSCKTS   2 /* One TCP socket for IPv4 & one for IPv6. */

Definition at line 58 of file pit_server.c.

#define MAXUDPSCKTS   2 /* One UDP socket for IPv4 & one for IPv6. */

Definition at line 59 of file pit_server.c.

#define USAGE
Value:
{                                           \
           fprintf( stderr,                         \
                    "Usage: %s [-v] -p service \n",   \
                    pgmName );                      \
           exit( 127 );                             \
        }  /* End USAGE macro. */

Definition at line 91 of file pit_server.c.

#define VALIDOPTS   "vh:p:" /* Valid command options. */

Definition at line 60 of file pit_server.c.


Function Documentation

int main ( int  argc,
char *  argv[] 
)

Definition at line 129 of file pit_server.c.

{
   int         opt;
   int         tSckt[ MAXTCPSCKTS ];     /* Array of TCP socket descriptors. */
   size_t      tScktSize = MAXTCPSCKTS;  /* Size of uSckt (# of elements).   */
   int         uSckt[ MAXUDPSCKTS ];     /* Array of UDP socket descriptors. */
   size_t      uScktSize = MAXUDPSCKTS;  /* Size of uSckt (# of elements).   */

   strcpy(service_name,DFLT_SERVICE);
   /*
   ** Set the program name (w/o directory prefix).
   */
   pgmName = strrchr( argv[ 0 ], '/' );
   pgmName = pgmName == NULL  ?  argv[ 0 ]  :  pgmName + 1;
   /*
   ** Process command options.
   */
   opterr = 0;   /* Turns off "invalid option" error messages. */
   while ( ( opt = getopt( argc, argv, VALIDOPTS ) ) >= 0 )
   {
      switch ( opt )
      {
         case 'v':   /* Verbose mode. */
         {
            verbose = true;
            break;
         }
         case 'p':   /* Get the port number */
         {
            strcpy(service_name,optarg);
        need++;
            break;
         }
         default:
         {
            USAGE;
         }
      }  /* End SWITCH on command option. */
   }  /* End WHILE processing options. */

   if(need < 1)
   {
    USAGE;
    exit;
   }
   /*
   ** Open both a TCP and UDP socket, for both IPv4 & IPv6, on which to receive
   ** service requests.
   */
   if ( ( openSckt( service_name, "tcp", tSckt, &tScktSize ) < 0 ) ||
        ( openSckt( service_name, "udp", uSckt, &uScktSize ) < 0 ) )
   {
      exit( 1 );
   }
   /*
   ** Run the Programmable Interdimensional Timer server.
   */
   if ( ( tScktSize > 0 ) || ( uScktSize > 0 ) )
   {
      pit( tSckt,         /* pit() never returns. */
           tScktSize,
           uSckt,
           uScktSize );
   }
   /*
   ** Since pit() never returns, execution only gets here if no sockets were
   ** created.
   */
   if ( verbose )
   {
      fprintf( stderr,
               "%s: No sockets opened... terminating.\n",
               pgmName );
   }
   return 0;
}  /* End main() */

Here is the call graph for this function:

static int openSckt ( const char *  service,
const char *  protocol,
int  desc[],
size_t descSize 
) [static]

Definition at line 232 of file pit_server.c.

{
   struct addrinfo *ai;
   int              aiErr;
   struct addrinfo *aiHead;
   struct addrinfo  hints    = { .ai_flags  = AI_PASSIVE,    /* Server mode.  */
                                 .ai_family = PF_UNSPEC };   /* IPv4 or IPv6. */
   size_t           maxDescs = *descSize;
   /*
   ** Initialize output parameters.  When the loop completes, *descSize is 0.
   */
   while ( *descSize > 0 )
   {
      desc[ --( *descSize ) ] = INVALID_DESC;
   }
   /*
   ** Check which protocol is selected (only TCP and UDP are valid).
   */
   if ( strcmp( protocol, "tcp" ) == 0 )        /* TCP protocol.     */
   {
      hints.ai_socktype = SOCK_STREAM;
      hints.ai_protocol = IPPROTO_TCP;
   }
   else if ( strcmp( protocol, "udp" ) == 0 )   /* UDP protocol.     */
   {
      hints.ai_socktype = SOCK_DGRAM;
      hints.ai_protocol = IPPROTO_UDP;
   }
   else                                         /* Invalid protocol. */
   {
      fprintf( stderr,
               "%s (line %d): ERROR - Unknown transport "
               "layer protocol \"%s\".\n",
               pgmName,
               __LINE__,
               protocol );
      return -1;
   }
   /*
   ** Look up the service's "well-known" port number.  Notice that NULL is being
   ** passed for the 'node' parameter, and that the AI_PASSIVE flag is set in
   ** 'hints'.  Thus, the program is requesting passive address information.
   ** The network address is initialized to :: (all zeros) for IPv6 records, or
   ** 0.0.0.0 for IPv4 records.
   */
   if ( ( aiErr = getaddrinfo( NULL,
                               service,
                               &hints,
                               &aiHead ) ) != 0 )
   {
      fprintf( stderr,
               "%s (line %d): ERROR - %s.\n",
               pgmName,
               __LINE__,
               gai_strerror( aiErr ) );
      return -1;
   }
   /*
   ** For each of the address records returned, attempt to set up a passive
   ** socket.
   */
   for ( ai = aiHead;
         ( ai != NULL ) && ( *descSize < maxDescs );
         ai = ai->ai_next )
   {
      if ( verbose )
      {
         /*
         ** Display the current address info.   Start with the protocol-
         ** independent fields first.
         */
         fprintf( stderr,
                  "Setting up a passive socket based on the "
                  "following address info:\n"
                  "   ai_flags     = 0x%02X\n"
                  "   ai_family    = %d (PF_INET = %d, PF_INET6 = %d)\n"
                  "   ai_socktype  = %d (SOCK_STREAM = %d, SOCK_DGRAM = %d)\n"
                  "   ai_protocol  = %d (IPPROTO_TCP = %d, IPPROTO_UDP = %d)\n"
                  "   ai_addrlen   = %d (sockaddr_in = %lu, "
                  "sockaddr_in6 = %lu)\n",
                  ai->ai_flags,
                  ai->ai_family,
                  PF_INET,
                  PF_INET6,
                  ai->ai_socktype,
                  SOCK_STREAM,
                  SOCK_DGRAM,
                  ai->ai_protocol,
                  IPPROTO_TCP,
                  IPPROTO_UDP,
                  ai->ai_addrlen,
                  sizeof( struct sockaddr_in ),
                  sizeof( struct sockaddr_in6 ) );
         /*
         ** Now display the protocol-specific formatted socket address.  Note
         ** that the program is requesting that getnameinfo(3) convert the
         ** host & service into numeric strings.
         */
         getnameinfo( ai->ai_addr,
                      ai->ai_addrlen,
                      hostBfr,
                      sizeof( hostBfr ),
                      servBfr,
                      sizeof( servBfr ),
                      NI_NUMERICHOST | NI_NUMERICSERV );
         switch ( ai->ai_family )
         {
            case PF_INET:   /* IPv4 address record. */
            {
               struct sockaddr_in *p = (struct sockaddr_in*) ai->ai_addr;
               fprintf( stderr,
                        "   ai_addr      = sin_family:   %d (AF_INET = %d, "
                        "AF_INET6 = %d)\n"
                        "                  sin_addr:     %s\n"
                        "                  sin_port:     %s\n",
                        p->sin_family,
                        AF_INET,
                        AF_INET6,
                        hostBfr,
                        servBfr );
               break;
            }  /* End CASE of IPv4. */
            case PF_INET6:   /* IPv6 address record. */
            {
               struct sockaddr_in6 *p = (struct sockaddr_in6*) ai->ai_addr;
               fprintf( stderr,
                        "   ai_addr      = sin6_family:   %d (AF_INET = %d, "
                        "AF_INET6 = %d)\n"
                        "                  sin6_addr:     %s\n"
                        "                  sin6_port:     %s\n"
                        "                  sin6_flowinfo: %d\n"
                        "                  sin6_scope_id: %d\n",
                        p->sin6_family,
                        AF_INET,
                        AF_INET6,
                        hostBfr,
                        servBfr,
                        p->sin6_flowinfo,
                        p->sin6_scope_id );
               break;
            }  /* End CASE of IPv6. */
            default:   /* Can never get here, but just for completeness. */
            {
               fprintf( stderr,
                        "%s (line %d): ERROR - Unknown protocol family (%d).\n",
                        pgmName,
                        __LINE__,
                        ai->ai_family );
               freeaddrinfo( aiHead );
               return -1;
            }  /* End DEFAULT case (unknown protocol family). */
         }  /* End SWITCH on protocol family. */
      }  /* End IF verbose mode. */
      /*
      ** Create a socket using the info in the addrinfo structure.
      */
      CHK( desc[ *descSize ] = socket( ai->ai_family,
                                       ai->ai_socktype,
                                       ai->ai_protocol ) );
      /*
      ** Here is the code that prevents "IPv4 mapped addresses", as discussed
      ** in Section 22.1.3.1.  If an IPv6 socket was just created, then set the
      ** IPV6_V6ONLY socket option.
      */
      if ( ai->ai_family == PF_INET6 )
      {
#if defined( IPV6_V6ONLY )
         /*
         ** Disable IPv4 mapped addresses.
         */
         int v6Only = 1;
         CHK( setsockopt( desc[ *descSize ],
                          IPPROTO_IPV6,
                          IPV6_V6ONLY,
                          &v6Only,
                          sizeof( v6Only ) ) );
#else
         /*
         ** IPV6_V6ONLY is not defined, so the socket option can't be set and
         ** thus IPv4 mapped addresses can't be disabled.  Print a warning
         ** message and close the socket.  Design note: If the
         ** #if...#else...#endif construct were removed, then this program
         ** would not compile (because IPV6_V6ONLY isn't defined).  That's an
         ** acceptable approach; IPv4 mapped addresses are certainly disabled
         ** if the program can't build!  However, since this program is also
         ** designed to work for IPv4 sockets as well as IPv6, I decided to
         ** allow the program to compile when IPV6_V6ONLY is not defined, and
         ** turn it into a run-time warning rather than a compile-time error.
         ** IPv4 mapped addresses are still disabled because _all_ IPv6 traffic
         ** is disabled (all IPv6 sockets are closed here), but at least this
         ** way the server can still service IPv4 network traffic.
         */
         fprintf( stderr,
                  "%s (line %d): WARNING - Cannot set IPV6_V6ONLY socket "
                  "option.  Closing IPv6 %s socket.\n",
                  pgmName,
                  __LINE__,
                  ai->ai_protocol == IPPROTO_TCP  ?  "TCP"  :  "UDP" );
         CHK( close( desc[ *descSize ] ) );
         continue;   /* Go to top of FOR loop w/o updating *descSize! */
#endif /* IPV6_V6ONLY */
      }  /* End IF this is an IPv6 socket. */
      /*
      ** Bind the socket.  Again, the info from the addrinfo structure is used.
      */
      CHK( bind( desc[ *descSize ],
                 ai->ai_addr,
                 ai->ai_addrlen ) );
      /*
      ** If this is a TCP socket, put the socket into passive listening mode
      ** (listen is only valid on connection-oriented sockets).
      */
      if ( ai->ai_socktype == SOCK_STREAM )
      {
         CHK( listen( desc[ *descSize ],
                      MAXCONNQLEN ) );
      }
      /*
      ** Socket set up okay.  Bump index to next descriptor array element.
      */
      *descSize += 1;
   }  /* End FOR each address info structure returned. */
   /*
   ** Dummy check for unused address records.
   */
   if ( verbose && ( ai != NULL ) )
   {
      fprintf( stderr,
               "%s (line %d): WARNING - Some address records were "
               "not processed due to insufficient array space.\n",
               pgmName,
               __LINE__ );
   }  /* End IF verbose and some address records remain unprocessed. */
   /*
   ** Clean up.
   */
   freeaddrinfo( aiHead );
   return 0;
}  /* End openSckt() */

Here is the call graph for this function:

Here is the caller graph for this function:

static void pit ( int  tSckt[],
size_t  tScktSize,
int  uSckt[],
size_t  uScktSize 
) [static]

Definition at line 490 of file pit_server.c.

{
   char                     bfr[ 256 ];
   ssize_t                  count;
   struct pollfd           *desc;
   size_t                   descSize = tScktSize + uScktSize;
   int                      idx;
   int                      newSckt;
   struct sockaddr         *sadr;
   socklen_t                sadrLen;
   struct sockaddr_storage  sockStor;
   int                      status;
   size_t                   timeLen;
   time_t                   timeVal;
   ssize_t                  wBytes;
   unsigned long long       secs;
   int                  ret;
   /*
   ** Allocate memory for the poll(2) array.
   */
   desc = malloc( descSize * sizeof( struct pollfd ) );
   if ( desc == NULL )
   {
      fprintf( stderr,
               "%s (line %d): ERROR - %s.\n",
               pgmName,
               __LINE__,
               strerror( ENOMEM ) );
      exit( 1 );
   }
   /*
   ** Initialize the poll(2) array.
   */
   for ( idx = 0;     idx < descSize;     idx++ )
   {
      desc[ idx ].fd      = idx < tScktSize  ?  tSckt[ idx ]
                                             :  uSckt[ idx - tScktSize ];
      desc[ idx ].events  = POLLIN;
      desc[ idx ].revents = 0;
   }
   /*
   ** Main PIT server loop.  Handles both TCP & UDP requests.  This is
   ** an interative server, and all requests are handled directly within the
   ** main loop.
   */
   while ( true )   /* Do forever. */
   {
      /*
      ** Wait for activity on one of the sockets.  The DO..WHILE construct is
      ** used to restart the system call in the event the process is
      ** interrupted by a signal.
      */
      do
      {
         status = poll( desc,
                        descSize,
                        -1 /* Wait indefinitely for input. */ );
      } while ( ( status < 0 ) && ( errno == EINTR ) );
      CHK( status );   /* Check for a bona fide system call error. */
      /*
      ** Get the current time.
      */
#if defined(Windows)
   LARGE_INTEGER freq,counter;
   double wintime,bigcounter;
   /* For Windows the time_of_day() is useless. It increments in 55 milli 
    * second increments. By using the Win32api one can get access to the 
    * high performance measurement interfaces. With this one can get back 
    * into the 8 to 9 microsecond resolution.
    */
      QueryPerformanceFrequency(&freq);
      QueryPerformanceCounter(&counter);
      bigcounter=(double)counter.HighPart *(double)0xffffffff +
              (double)counter.LowPart;
      wintime = (double)(bigcounter/(double)freq.LowPart);
      secs = (long long)(wintime * 1000000);
#else
      ret = gettimeofday( &tm,0 );
      secs = ((unsigned long long)tm.tv_sec * 1000000) 
        + (unsigned long long)tm.tv_usec;
#endif

      ret = sprintf(timeStr,"%llu",secs);
      timeLen = strlen( timeStr );
      /*
      ** Process sockets with input available.
      */
      for ( idx = 0;     idx < descSize;     idx++ )
      {
         switch ( desc[ idx ].revents )
         {
            case 0:        /* No activity on this socket; try the next. */
               continue;
            case POLLIN:   /* Network activity.  Go process it.         */
               break;
            default:       /* Invalid poll events.                      */
            {
               fprintf( stderr,
                        "%s (line %d): ERROR - Invalid poll event (0x%02X).\n",
                        pgmName,
                        __LINE__,
                        desc[ idx ].revents );
               exit( 1 );
            }
         }  /* End SWITCH on returned poll events. */
         /*
         ** Determine if this is a TCP request or UDP request.
         */
         if ( idx < tScktSize )
         {
            /*
            ** TCP connection requested.  Accept it.  Notice the use of
            ** the sockaddr_storage data type.
            */
            sadrLen = sizeof( sockStor );
            sadr    = (struct sockaddr*) &sockStor;
            CHK( newSckt = accept( desc[ idx ].fd,
                                   sadr,
                                   &sadrLen ) );
            CHK( shutdown( newSckt,       /* Server never recv's anything. */
                           SHUT_RD ) );
            if ( verbose )
            {
               /*
               ** Display the socket address of the remote client.  Begin with
               ** the address-independent fields.
               */
               fprintf( stderr,
                        "Sockaddr info for new TCP client:\n"
                        "   sa_family = %d (AF_INET = %d, AF_INET6 = %d)\n"
                        "   addr len  = %d (sockaddr_in = %lu, "
                        "sockaddr_in6 = %lu)\n",
                        sadr->sa_family,
                        AF_INET,
                        AF_INET6,
                        sadrLen,
                        sizeof( struct sockaddr_in ),
                        sizeof( struct sockaddr_in6 ) );
               /*
               ** Display the address-specific fields.
               */
               getnameinfo( sadr,
                            sadrLen,
                            hostBfr,
                            sizeof( hostBfr ),
                            servBfr,
                            sizeof( servBfr ),
                            NI_NUMERICHOST | NI_NUMERICSERV );
               /*
               ** Notice that we're switching on an address family now, not a
               ** protocol family.
               */
               switch ( sadr->sa_family )
               {
                  case AF_INET:   /* IPv4 address. */
                  {
                     struct sockaddr_in *p = (struct sockaddr_in*) sadr;
                     fprintf( stderr,
                              "   sin_addr  = sin_family: %d\n"
                              "               sin_addr:   %s\n"
                              "               sin_port:   %s\n",
                              p->sin_family,
                              hostBfr,
                              servBfr );
                     break;
                  }  /* End CASE of IPv4. */
                  case AF_INET6:   /* IPv6 address. */
                  {
                     struct sockaddr_in6 *p = (struct sockaddr_in6*) sadr;
                     fprintf( stderr,
                              "   sin6_addr = sin6_family:   %d\n"
                              "               sin6_addr:     %s\n"
                              "               sin6_port:     %s\n"
                              "               sin6_flowinfo: %d\n"
                              "               sin6_scope_id: %d\n",
                              p->sin6_family,
                              hostBfr,
                              servBfr,
                              p->sin6_flowinfo,
                              p->sin6_scope_id );
                     break;
                  }  /* End CASE of IPv6. */
                  default:   /* Can never get here, but for completeness. */
                  {
                     fprintf( stderr,
                              "%s (line %d): ERROR - Unknown address "
                              "family (%d).\n",
                              pgmName,
                              __LINE__,
                              sadr->sa_family );
                     break;
                  }  /* End DEFAULT case (unknown address family). */
               }  /* End SWITCH on address family. */
            }  /* End IF verbose mode. */
            /*
            ** Send the PIT to the client.
            */
            wBytes = timeLen;
            while ( wBytes > 0 )
            {
               do
               {
                  count = write( newSckt,
                                 timeStr,
                                 wBytes );
               } while ( ( count < 0 ) && ( errno == EINTR ) );
               CHK( count );   /* Check for an error. */
               wBytes -= count;
            }  /* End WHILE there is data to send. */
            CHK( close( newSckt ) );
         }  /* End IF this was a TCP connection request. */
         else
         {
            /*
            ** This is a UDP socket, and a datagram is available.  The funny
            ** thing about UDP requests is that this server doesn't require any
            ** client input; but it can't send the PIT unless it knows a client
            ** wants the data, and the only way that can occur with UDP is if
            ** the server receives a datagram from the client.  Thus, the
            ** server must receive _something_, but the content of the datagram
            ** is irrelevant.  Read in the datagram.  Again note the use of
            ** sockaddr_storage to receive the address.
            */
            sadrLen = sizeof( sockStor );
            sadr    = (struct sockaddr*) &sockStor;
            CHK( count = recvfrom( desc[ idx ].fd,
                                   bfr,
                                   sizeof( bfr ),
                                   0,
                                   sadr,
                                   &sadrLen ) );
            /*
            ** Display whatever was received on stdout.
            */
            if ( verbose )
            {
               ssize_t rBytes = count;
               fprintf( stderr,
                        "%s: UDP datagram received (%ld bytes).\n",
                        pgmName,
                        count );
               while ( count > 0 )
               {
                  fputc( bfr[ rBytes - count-- ],
                         stdout );
               }
               if ( bfr[ rBytes-1 ] != '\n' )
                  fputc( '\n', stdout );   /* Newline also flushes stdout. */
               /*
               ** Display the socket address of the remote client.  Address-
               ** independent fields first.
               */
               fprintf( stderr,
                        "Remote client's sockaddr info:\n"
                        "   sa_family = %d (AF_INET = %d, AF_INET6 = %d)\n"
                        "   addr len  = %d (sockaddr_in = %lu, "
                        "sockaddr_in6 = %lu)\n",
                        sadr->sa_family,
                        AF_INET,
                        AF_INET6,
                        sadrLen,
                        sizeof( struct sockaddr_in ),
                        sizeof( struct sockaddr_in6 ) );
               /*
               ** Display the address-specific information.
               */
               getnameinfo( sadr,
                            sadrLen,
                            hostBfr,
                            sizeof( hostBfr ),
                            servBfr,
                            sizeof( servBfr ),
                            NI_NUMERICHOST | NI_NUMERICSERV );
               switch ( sadr->sa_family )
               {
                  case AF_INET:   /* IPv4 address. */
                  {
                     struct sockaddr_in *p = (struct sockaddr_in*) sadr;
                     fprintf( stderr,
                              "   sin_addr  = sin_family: %d\n"
                              "               sin_addr:   %s\n"
                              "               sin_port:   %s\n",
                              p->sin_family,
                              hostBfr,
                              servBfr );
                     break;
                  }  /* End CASE of IPv4 address. */
                  case AF_INET6:   /* IPv6 address. */
                  {
                     struct sockaddr_in6 *p = (struct sockaddr_in6*) sadr;
                     fprintf( stderr,
                              "   sin6_addr = sin6_family:   %d\n"
                              "               sin6_addr:     %s\n"
                              "               sin6_port:     %s\n"
                              "               sin6_flowinfo: %d\n"
                              "               sin6_scope_id: %d\n",
                              p->sin6_family,
                              hostBfr,
                              servBfr,
                              p->sin6_flowinfo,
                              p->sin6_scope_id );
                     break;
                  }  /* End CASE of IPv6 address. */
                  default:   /* Can never get here, but for completeness. */
                  {
                     fprintf( stderr,
                              "%s (line %d): ERROR - Unknown address "
                              "family (%d).\n",
                              pgmName,
                              __LINE__,
                              sadr->sa_family );
                     break;
                  }  /* End DEFAULT case (unknown address family). */
               }  /* End SWITCH on address family. */
            }  /* End IF verbose mode. */
            /*
            ** Send the PIT to the client.
            */
            wBytes = timeLen;
            while ( wBytes > 0 )
            {
               do
               {
                  count = sendto( desc[ idx ].fd,
                                  timeStr,
                                  wBytes,
                                  0,
                                  sadr,        /* Address & address length   */
                                  sadrLen );   /*    received in recvfrom(). */
               } while ( ( count < 0 ) && ( errno == EINTR ) );
               CHK( count );   /* Check for a bona fide error. */
               wBytes -= count;
            }  /* End WHILE there is data to send. */
         }  /* End ELSE a UDP datagram is available. */
         desc[ idx ].revents = 0;   /* Clear the returned poll events. */
      }  /* End FOR each socket descriptor. */
   }  /* End WHILE forever. */
}  /* End pit() */

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int false = 0

Definition at line 64 of file pit_server.c.

char hostBfr[NI_MAXHOST] [static]

Definition at line 80 of file pit_server.c.

int need

Definition at line 87 of file pit_server.c.

const char* pgmName [static]

Definition at line 81 of file pit_server.c.

char servBfr[NI_MAXSERV] [static]

Definition at line 82 of file pit_server.c.

char service_name[20]

Definition at line 86 of file pit_server.c.

char timeStr[40]

Definition at line 85 of file pit_server.c.

struct timeval tm

Definition at line 84 of file pit_server.c.

int true = 1

Definition at line 65 of file pit_server.c.

int verbose = 0 [static]

Definition at line 83 of file pit_server.c.

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines