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"
#define INVALID_DESC   -1
#define MAXCONNQLEN   3
#define MAXTCPSCKTS   2
#define MAXUDPSCKTS   2
#define VALIDOPTS   "vh:p:"
#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"

Definition at line 54 of file pit_server.c.

#define INVALID_DESC   -1

Definition at line 56 of file pit_server.c.

#define MAXCONNQLEN   3

Definition at line 57 of file pit_server.c.

#define MAXTCPSCKTS   2

Definition at line 58 of file pit_server.c.

#define MAXUDPSCKTS   2

Definition at line 59 of file pit_server.c.

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

Definition at line 91 of file pit_server.c.

#define VALIDOPTS   "vh:p:"

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.

00131 {
00132    int         opt;
00133    int         tSckt[ MAXTCPSCKTS ];     /* Array of TCP socket descriptors. */
00134    size_t      tScktSize = MAXTCPSCKTS;  /* Size of uSckt (# of elements).   */
00135    int         uSckt[ MAXUDPSCKTS ];     /* Array of UDP socket descriptors. */
00136    size_t      uScktSize = MAXUDPSCKTS;  /* Size of uSckt (# of elements).   */
00137 
00138    strcpy(service_name,DFLT_SERVICE);
00139    /*
00140    ** Set the program name (w/o directory prefix).
00141    */
00142    pgmName = strrchr( argv[ 0 ], '/' );
00143    pgmName = pgmName == NULL  ?  argv[ 0 ]  :  pgmName + 1;
00144    /*
00145    ** Process command options.
00146    */
00147    opterr = 0;   /* Turns off "invalid option" error messages. */
00148    while ( ( opt = getopt( argc, argv, VALIDOPTS ) ) >= 0 )
00149    {
00150       switch ( opt )
00151       {
00152          case 'v':   /* Verbose mode. */
00153          {
00154             verbose = true;
00155             break;
00156          }
00157          case 'p':   /* Get the port number */
00158          {
00159             strcpy(service_name,optarg);
00160         need++;
00161             break;
00162          }
00163          default:
00164          {
00165             USAGE;
00166          }
00167       }  /* End SWITCH on command option. */
00168    }  /* End WHILE processing options. */
00169 
00170    if(need < 1)
00171    {
00172     USAGE;
00173     exit;
00174    }
00175    /*
00176    ** Open both a TCP and UDP socket, for both IPv4 & IPv6, on which to receive
00177    ** service requests.
00178    */
00179    if ( ( openSckt( service_name, "tcp", tSckt, &tScktSize ) < 0 ) ||
00180         ( openSckt( service_name, "udp", uSckt, &uScktSize ) < 0 ) )
00181    {
00182       exit( 1 );
00183    }
00184    /*
00185    ** Run the Programmable Interdimensional Timer server.
00186    */
00187    if ( ( tScktSize > 0 ) || ( uScktSize > 0 ) )
00188    {
00189       pit( tSckt,         /* pit() never returns. */
00190            tScktSize,
00191            uSckt,
00192            uScktSize );
00193    }
00194    /*
00195    ** Since pit() never returns, execution only gets here if no sockets were
00196    ** created.
00197    */
00198    if ( verbose )
00199    {
00200       fprintf( stderr,
00201                "%s: No sockets opened... terminating.\n",
00202                pgmName );
00203    }
00204    return 0;
00205 }  /* 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.

00236 {
00237    struct addrinfo *ai;
00238    int              aiErr;
00239    struct addrinfo *aiHead;
00240    struct addrinfo  hints    = { .ai_flags  = AI_PASSIVE,    /* Server mode.  */
00241                                  .ai_family = PF_UNSPEC };   /* IPv4 or IPv6. */
00242    size_t           maxDescs = *descSize;
00243    /*
00244    ** Initialize output parameters.  When the loop completes, *descSize is 0.
00245    */
00246    while ( *descSize > 0 )
00247    {
00248       desc[ --( *descSize ) ] = INVALID_DESC;
00249    }
00250    /*
00251    ** Check which protocol is selected (only TCP and UDP are valid).
00252    */
00253    if ( strcmp( protocol, "tcp" ) == 0 )        /* TCP protocol.     */
00254    {
00255       hints.ai_socktype = SOCK_STREAM;
00256       hints.ai_protocol = IPPROTO_TCP;
00257    }
00258    else if ( strcmp( protocol, "udp" ) == 0 )   /* UDP protocol.     */
00259    {
00260       hints.ai_socktype = SOCK_DGRAM;
00261       hints.ai_protocol = IPPROTO_UDP;
00262    }
00263    else                                         /* Invalid protocol. */
00264    {
00265       fprintf( stderr,
00266                "%s (line %d): ERROR - Unknown transport "
00267                "layer protocol \"%s\".\n",
00268                pgmName,
00269                __LINE__,
00270                protocol );
00271       return -1;
00272    }
00273    /*
00274    ** Look up the service's "well-known" port number.  Notice that NULL is being
00275    ** passed for the 'node' parameter, and that the AI_PASSIVE flag is set in
00276    ** 'hints'.  Thus, the program is requesting passive address information.
00277    ** The network address is initialized to :: (all zeros) for IPv6 records, or
00278    ** 0.0.0.0 for IPv4 records.
00279    */
00280    if ( ( aiErr = getaddrinfo( NULL,
00281                                service,
00282                                &hints,
00283                                &aiHead ) ) != 0 )
00284    {
00285       fprintf( stderr,
00286                "%s (line %d): ERROR - %s.\n",
00287                pgmName,
00288                __LINE__,
00289                gai_strerror( aiErr ) );
00290       return -1;
00291    }
00292    /*
00293    ** For each of the address records returned, attempt to set up a passive
00294    ** socket.
00295    */
00296    for ( ai = aiHead;
00297          ( ai != NULL ) && ( *descSize < maxDescs );
00298          ai = ai->ai_next )
00299    {
00300       if ( verbose )
00301       {
00302          /*
00303          ** Display the current address info.   Start with the protocol-
00304          ** independent fields first.
00305          */
00306          fprintf( stderr,
00307                   "Setting up a passive socket based on the "
00308                   "following address info:\n"
00309                   "   ai_flags     = %#02X\n"
00310                   "   ai_family    = %d (PF_INET = %d, PF_INET6 = %d)\n"
00311                   "   ai_socktype  = %d (SOCK_STREAM = %d, SOCK_DGRAM = %d)\n"
00312                   "   ai_protocol  = %d (IPPROTO_TCP = %d, IPPROTO_UDP = %d)\n"
00313                   "   ai_addrlen   = %d (sockaddr_in = %lu, "
00314                   "sockaddr_in6 = %lu)\n",
00315                   ai->ai_flags,
00316                   ai->ai_family,
00317                   PF_INET,
00318                   PF_INET6,
00319                   ai->ai_socktype,
00320                   SOCK_STREAM,
00321                   SOCK_DGRAM,
00322                   ai->ai_protocol,
00323                   IPPROTO_TCP,
00324                   IPPROTO_UDP,
00325                   ai->ai_addrlen,
00326                   sizeof( struct sockaddr_in ),
00327                   sizeof( struct sockaddr_in6 ) );
00328          /*
00329          ** Now display the protocol-specific formatted socket address.  Note
00330          ** that the program is requesting that getnameinfo(3) convert the
00331          ** host & service into numeric strings.
00332          */
00333          getnameinfo( ai->ai_addr,
00334                       ai->ai_addrlen,
00335                       hostBfr,
00336                       sizeof( hostBfr ),
00337                       servBfr,
00338                       sizeof( servBfr ),
00339                       NI_NUMERICHOST | NI_NUMERICSERV );
00340          switch ( ai->ai_family )
00341          {
00342             case PF_INET:   /* IPv4 address record. */
00343             {
00344                struct sockaddr_in *p = (struct sockaddr_in*) ai->ai_addr;
00345                fprintf( stderr,
00346                         "   ai_addr      = sin_family:   %d (AF_INET = %d, "
00347                         "AF_INET6 = %d)\n"
00348                         "                  sin_addr:     %s\n"
00349                         "                  sin_port:     %s\n",
00350                         p->sin_family,
00351                         AF_INET,
00352                         AF_INET6,
00353                         hostBfr,
00354                         servBfr );
00355                break;
00356             }  /* End CASE of IPv4. */
00357             case PF_INET6:   /* IPv6 address record. */
00358             {
00359                struct sockaddr_in6 *p = (struct sockaddr_in6*) ai->ai_addr;
00360                fprintf( stderr,
00361                         "   ai_addr      = sin6_family:   %d (AF_INET = %d, "
00362                         "AF_INET6 = %d)\n"
00363                         "                  sin6_addr:     %s\n"
00364                         "                  sin6_port:     %s\n"
00365                         "                  sin6_flowinfo: %d\n"
00366                         "                  sin6_scope_id: %d\n",
00367                         p->sin6_family,
00368                         AF_INET,
00369                         AF_INET6,
00370                         hostBfr,
00371                         servBfr,
00372                         p->sin6_flowinfo,
00373                         p->sin6_scope_id );
00374                break;
00375             }  /* End CASE of IPv6. */
00376             default:   /* Can never get here, but just for completeness. */
00377             {
00378                fprintf( stderr,
00379                         "%s (line %d): ERROR - Unknown protocol family (%d).\n",
00380                         pgmName,
00381                         __LINE__,
00382                         ai->ai_family );
00383                freeaddrinfo( aiHead );
00384                return -1;
00385             }  /* End DEFAULT case (unknown protocol family). */
00386          }  /* End SWITCH on protocol family. */
00387       }  /* End IF verbose mode. */
00388       /*
00389       ** Create a socket using the info in the addrinfo structure.
00390       */
00391       CHK( desc[ *descSize ] = socket( ai->ai_family,
00392                                        ai->ai_socktype,
00393                                        ai->ai_protocol ) );
00394       /*
00395       ** Here is the code that prevents "IPv4 mapped addresses", as discussed
00396       ** in Section 22.1.3.1.  If an IPv6 socket was just created, then set the
00397       ** IPV6_V6ONLY socket option.
00398       */
00399       if ( ai->ai_family == PF_INET6 )
00400       {
00401 #if defined( IPV6_V6ONLY )
00402          /*
00403          ** Disable IPv4 mapped addresses.
00404          */
00405          int v6Only = 1;
00406          CHK( setsockopt( desc[ *descSize ],
00407                           IPPROTO_IPV6,
00408                           IPV6_V6ONLY,
00409                           &v6Only,
00410                           sizeof( v6Only ) ) );
00411 #else
00412          /*
00413          ** IPV6_V6ONLY is not defined, so the socket option can't be set and
00414          ** thus IPv4 mapped addresses can't be disabled.  Print a warning
00415          ** message and close the socket.  Design note: If the
00416          ** #if...#else...#endif construct were removed, then this program
00417          ** would not compile (because IPV6_V6ONLY isn't defined).  That's an
00418          ** acceptable approach; IPv4 mapped addresses are certainly disabled
00419          ** if the program can't build!  However, since this program is also
00420          ** designed to work for IPv4 sockets as well as IPv6, I decided to
00421          ** allow the program to compile when IPV6_V6ONLY is not defined, and
00422          ** turn it into a run-time warning rather than a compile-time error.
00423          ** IPv4 mapped addresses are still disabled because _all_ IPv6 traffic
00424          ** is disabled (all IPv6 sockets are closed here), but at least this
00425          ** way the server can still service IPv4 network traffic.
00426          */
00427          fprintf( stderr,
00428                   "%s (line %d): WARNING - Cannot set IPV6_V6ONLY socket "
00429                   "option.  Closing IPv6 %s socket.\n",
00430                   pgmName,
00431                   __LINE__,
00432                   ai->ai_protocol == IPPROTO_TCP  ?  "TCP"  :  "UDP" );
00433          CHK( close( desc[ *descSize ] ) );
00434          continue;   /* Go to top of FOR loop w/o updating *descSize! */
00435 #endif /* IPV6_V6ONLY */
00436       }  /* End IF this is an IPv6 socket. */
00437       /*
00438       ** Bind the socket.  Again, the info from the addrinfo structure is used.
00439       */
00440       CHK( bind( desc[ *descSize ],
00441                  ai->ai_addr,
00442                  ai->ai_addrlen ) );
00443       /*
00444       ** If this is a TCP socket, put the socket into passive listening mode
00445       ** (listen is only valid on connection-oriented sockets).
00446       */
00447       if ( ai->ai_socktype == SOCK_STREAM )
00448       {
00449          CHK( listen( desc[ *descSize ],
00450                       MAXCONNQLEN ) );
00451       }
00452       /*
00453       ** Socket set up okay.  Bump index to next descriptor array element.
00454       */
00455       *descSize += 1;
00456    }  /* End FOR each address info structure returned. */
00457    /*
00458    ** Dummy check for unused address records.
00459    */
00460    if ( verbose && ( ai != NULL ) )
00461    {
00462       fprintf( stderr,
00463                "%s (line %d): WARNING - Some address records were "
00464                "not processed due to insufficient array space.\n",
00465                pgmName,
00466                __LINE__ );
00467    }  /* End IF verbose and some address records remain unprocessed. */
00468    /*
00469    ** Clean up.
00470    */
00471    freeaddrinfo( aiHead );
00472    return 0;
00473 }  /* 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.

00494 {
00495    char                     bfr[ 256 ];
00496    ssize_t                  count;
00497    struct pollfd           *desc;
00498    size_t                   descSize = tScktSize + uScktSize;
00499    int                      idx;
00500    int                      newSckt;
00501    struct sockaddr         *sadr;
00502    socklen_t                sadrLen;
00503    struct sockaddr_storage  sockStor;
00504    int                      status;
00505    size_t                   timeLen;
00506    time_t                   timeVal;
00507    ssize_t                  wBytes;
00508    unsigned long long       secs;
00509    int                  ret;
00510    /*
00511    ** Allocate memory for the poll(2) array.
00512    */
00513    desc = malloc( descSize * sizeof( struct pollfd ) );
00514    if ( desc == NULL )
00515    {
00516       fprintf( stderr,
00517                "%s (line %d): ERROR - %s.\n",
00518                pgmName,
00519                __LINE__,
00520                strerror( ENOMEM ) );
00521       exit( 1 );
00522    }
00523    /*
00524    ** Initialize the poll(2) array.
00525    */
00526    for ( idx = 0;     idx < descSize;     idx++ )
00527    {
00528       desc[ idx ].fd      = idx < tScktSize  ?  tSckt[ idx ]
00529                                              :  uSckt[ idx - tScktSize ];
00530       desc[ idx ].events  = POLLIN;
00531       desc[ idx ].revents = 0;
00532    }
00533    /*
00534    ** Main PIT server loop.  Handles both TCP & UDP requests.  This is
00535    ** an interative server, and all requests are handled directly within the
00536    ** main loop.
00537    */
00538    while ( true )   /* Do forever. */
00539    {
00540       /*
00541       ** Wait for activity on one of the sockets.  The DO..WHILE construct is
00542       ** used to restart the system call in the event the process is
00543       ** interrupted by a signal.
00544       */
00545       do
00546       {
00547          status = poll( desc,
00548                         descSize,
00549                         -1 /* Wait indefinitely for input. */ );
00550       } while ( ( status < 0 ) && ( errno == EINTR ) );
00551       CHK( status );   /* Check for a bona fide system call error. */
00552       /*
00553       ** Get the current time.
00554       */
00555 #if defined(Windows)
00556    LARGE_INTEGER freq,counter;
00557    double wintime,bigcounter;
00558    /* For Windows the time_of_day() is useless. It increments in 55 milli 
00559     * second increments. By using the Win32api one can get access to the 
00560     * high performance measurement interfaces. With this one can get back 
00561     * into the 8 to 9 microsecond resolution.
00562     */
00563       QueryPerformanceFrequency(&freq);
00564       QueryPerformanceCounter(&counter);
00565       bigcounter=(double)counter.HighPart *(double)0xffffffff +
00566               (double)counter.LowPart;
00567       wintime = (double)(bigcounter/(double)freq.LowPart);
00568       secs = (long long)(wintime * 1000000);
00569 #else
00570       ret = gettimeofday( &tm,0 );
00571       secs = ((unsigned long long)tm.tv_sec * 1000000) 
00572         + (unsigned long long)tm.tv_usec;
00573 #endif
00574 
00575       ret = sprintf(timeStr,"%llu",secs);
00576       timeLen = strlen( timeStr );
00577       /*
00578       ** Process sockets with input available.
00579       */
00580       for ( idx = 0;     idx < descSize;     idx++ )
00581       {
00582          switch ( desc[ idx ].revents )
00583          {
00584             case 0:        /* No activity on this socket; try the next. */
00585                continue;
00586             case POLLIN:   /* Network activity.  Go process it.         */
00587                break;
00588             default:       /* Invalid poll events.                      */
00589             {
00590                fprintf( stderr,
00591                         "%s (line %d): ERROR - Invalid poll event (%#02X).\n",
00592                         pgmName,
00593                         __LINE__,
00594                         desc[ idx ].revents );
00595                exit( 1 );
00596             }
00597          }  /* End SWITCH on returned poll events. */
00598          /*
00599          ** Determine if this is a TCP request or UDP request.
00600          */
00601          if ( idx < tScktSize )
00602          {
00603             /*
00604             ** TCP connection requested.  Accept it.  Notice the use of
00605             ** the sockaddr_storage data type.
00606             */
00607             sadrLen = sizeof( sockStor );
00608             sadr    = (struct sockaddr*) &sockStor;
00609             CHK( newSckt = accept( desc[ idx ].fd,
00610                                    sadr,
00611                                    &sadrLen ) );
00612             CHK( shutdown( newSckt,       /* Server never recv's anything. */
00613                            SHUT_RD ) );
00614             if ( verbose )
00615             {
00616                /*
00617                ** Display the socket address of the remote client.  Begin with
00618                ** the address-independent fields.
00619                */
00620                fprintf( stderr,
00621                         "Sockaddr info for new TCP client:\n"
00622                         "   sa_family = %d (AF_INET = %d, AF_INET6 = %d)\n"
00623                         "   addr len  = %d (sockaddr_in = %lu, "
00624                         "sockaddr_in6 = %lu)\n",
00625                         sadr->sa_family,
00626                         AF_INET,
00627                         AF_INET6,
00628                         sadrLen,
00629                         sizeof( struct sockaddr_in ),
00630                         sizeof( struct sockaddr_in6 ) );
00631                /*
00632                ** Display the address-specific fields.
00633                */
00634                getnameinfo( sadr,
00635                             sadrLen,
00636                             hostBfr,
00637                             sizeof( hostBfr ),
00638                             servBfr,
00639                             sizeof( servBfr ),
00640                             NI_NUMERICHOST | NI_NUMERICSERV );
00641                /*
00642                ** Notice that we're switching on an address family now, not a
00643                ** protocol family.
00644                */
00645                switch ( sadr->sa_family )
00646                {
00647                   case AF_INET:   /* IPv4 address. */
00648                   {
00649                      struct sockaddr_in *p = (struct sockaddr_in*) sadr;
00650                      fprintf( stderr,
00651                               "   sin_addr  = sin_family: %d\n"
00652                               "               sin_addr:   %s\n"
00653                               "               sin_port:   %s\n",
00654                               p->sin_family,
00655                               hostBfr,
00656                               servBfr );
00657                      break;
00658                   }  /* End CASE of IPv4. */
00659                   case AF_INET6:   /* IPv6 address. */
00660                   {
00661                      struct sockaddr_in6 *p = (struct sockaddr_in6*) sadr;
00662                      fprintf( stderr,
00663                               "   sin6_addr = sin6_family:   %d\n"
00664                               "               sin6_addr:     %s\n"
00665                               "               sin6_port:     %s\n"
00666                               "               sin6_flowinfo: %d\n"
00667                               "               sin6_scope_id: %d\n",
00668                               p->sin6_family,
00669                               hostBfr,
00670                               servBfr,
00671                               p->sin6_flowinfo,
00672                               p->sin6_scope_id );
00673                      break;
00674                   }  /* End CASE of IPv6. */
00675                   default:   /* Can never get here, but for completeness. */
00676                   {
00677                      fprintf( stderr,
00678                               "%s (line %d): ERROR - Unknown address "
00679                               "family (%d).\n",
00680                               pgmName,
00681                               __LINE__,
00682                               sadr->sa_family );
00683                      break;
00684                   }  /* End DEFAULT case (unknown address family). */
00685                }  /* End SWITCH on address family. */
00686             }  /* End IF verbose mode. */
00687             /*
00688             ** Send the PIT to the client.
00689             */
00690             wBytes = timeLen;
00691             while ( wBytes > 0 )
00692             {
00693                do
00694                {
00695                   count = write( newSckt,
00696                                  timeStr,
00697                                  wBytes );
00698                } while ( ( count < 0 ) && ( errno == EINTR ) );
00699                CHK( count );   /* Check for an error. */
00700                wBytes -= count;
00701             }  /* End WHILE there is data to send. */
00702             CHK( close( newSckt ) );
00703          }  /* End IF this was a TCP connection request. */
00704          else
00705          {
00706             /*
00707             ** This is a UDP socket, and a datagram is available.  The funny
00708             ** thing about UDP requests is that this server doesn't require any
00709             ** client input; but it can't send the PIT unless it knows a client
00710             ** wants the data, and the only way that can occur with UDP is if
00711             ** the server receives a datagram from the client.  Thus, the
00712             ** server must receive _something_, but the content of the datagram
00713             ** is irrelevant.  Read in the datagram.  Again note the use of
00714             ** sockaddr_storage to receive the address.
00715             */
00716             sadrLen = sizeof( sockStor );
00717             sadr    = (struct sockaddr*) &sockStor;
00718             CHK( count = recvfrom( desc[ idx ].fd,
00719                                    bfr,
00720                                    sizeof( bfr ),
00721                                    0,
00722                                    sadr,
00723                                    &sadrLen ) );
00724             /*
00725             ** Display whatever was received on stdout.
00726             */
00727             if ( verbose )
00728             {
00729                ssize_t rBytes = count;
00730                fprintf( stderr,
00731                         "%s: UDP datagram received (%ld bytes).\n",
00732                         pgmName,
00733                         count );
00734                while ( count > 0 )
00735                {
00736                   fputc( bfr[ rBytes - count-- ],
00737                          stdout );
00738                }
00739                if ( bfr[ rBytes-1 ] != '\n' )
00740                   fputc( '\n', stdout );   /* Newline also flushes stdout. */
00741                /*
00742                ** Display the socket address of the remote client.  Address-
00743                ** independent fields first.
00744                */
00745                fprintf( stderr,
00746                         "Remote client's sockaddr info:\n"
00747                         "   sa_family = %d (AF_INET = %d, AF_INET6 = %d)\n"
00748                         "   addr len  = %d (sockaddr_in = %lu, "
00749                         "sockaddr_in6 = %lu)\n",
00750                         sadr->sa_family,
00751                         AF_INET,
00752                         AF_INET6,
00753                         sadrLen,
00754                         sizeof( struct sockaddr_in ),
00755                         sizeof( struct sockaddr_in6 ) );
00756                /*
00757                ** Display the address-specific information.
00758                */
00759                getnameinfo( sadr,
00760                             sadrLen,
00761                             hostBfr,
00762                             sizeof( hostBfr ),
00763                             servBfr,
00764                             sizeof( servBfr ),
00765                             NI_NUMERICHOST | NI_NUMERICSERV );
00766                switch ( sadr->sa_family )
00767                {
00768                   case AF_INET:   /* IPv4 address. */
00769                   {
00770                      struct sockaddr_in *p = (struct sockaddr_in*) sadr;
00771                      fprintf( stderr,
00772                               "   sin_addr  = sin_family: %d\n"
00773                               "               sin_addr:   %s\n"
00774                               "               sin_port:   %s\n",
00775                               p->sin_family,
00776                               hostBfr,
00777                               servBfr );
00778                      break;
00779                   }  /* End CASE of IPv4 address. */
00780                   case AF_INET6:   /* IPv6 address. */
00781                   {
00782                      struct sockaddr_in6 *p = (struct sockaddr_in6*) sadr;
00783                      fprintf( stderr,
00784                               "   sin6_addr = sin6_family:   %d\n"
00785                               "               sin6_addr:     %s\n"
00786                               "               sin6_port:     %s\n"
00787                               "               sin6_flowinfo: %d\n"
00788                               "               sin6_scope_id: %d\n",
00789                               p->sin6_family,
00790                               hostBfr,
00791                               servBfr,
00792                               p->sin6_flowinfo,
00793                               p->sin6_scope_id );
00794                      break;
00795                   }  /* End CASE of IPv6 address. */
00796                   default:   /* Can never get here, but for completeness. */
00797                   {
00798                      fprintf( stderr,
00799                               "%s (line %d): ERROR - Unknown address "
00800                               "family (%d).\n",
00801                               pgmName,
00802                               __LINE__,
00803                               sadr->sa_family );
00804                      break;
00805                   }  /* End DEFAULT case (unknown address family). */
00806                }  /* End SWITCH on address family. */
00807             }  /* End IF verbose mode. */
00808             /*
00809             ** Send the PIT to the client.
00810             */
00811             wBytes = timeLen;
00812             while ( wBytes > 0 )
00813             {
00814                do
00815                {
00816                   count = sendto( desc[ idx ].fd,
00817                                   timeStr,
00818                                   wBytes,
00819                                   0,
00820                                   sadr,        /* Address & address length   */
00821                                   sadrLen );   /*    received in recvfrom(). */
00822                } while ( ( count < 0 ) && ( errno == EINTR ) );
00823                CHK( count );   /* Check for a bona fide error. */
00824                wBytes -= count;
00825             }  /* End WHILE there is data to send. */
00826          }  /* End ELSE a UDP datagram is available. */
00827          desc[ idx ].revents = 0;   /* Clear the returned poll events. */
00828       }  /* End FOR each socket descriptor. */
00829    }  /* End WHILE forever. */
00830 }  /* 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.


Generated on 26 Jan 2016 for PAPI by  doxygen 1.6.1