ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/host/c++/udp_util.c
Revision: 1.2
Committed: Wed Jan 24 19:45:22 2001 UTC (23 years, 8 months ago) by ab11
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
State: FILE REMOVED
Log Message:
deleted

File Contents

# User Rev Content
1 ab11 1.1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2     <!-- saved from url=(0068)http://www.interlog.com/~calex/software/source/lib/libgpl/udp_util.c -->
3     <HTML><HEAD>
4     <META content="text/html; charset=windows-1252" http-equiv=Content-Type>
5     <META content="MSHTML 5.00.3105.105" name=GENERATOR></HEAD>
6     <BODY><XMP>/************************************************************************
7     * Copyright (c) 1996 by Charles A. Measday *
8     * *
9     * Permission to use, copy, modify, and distribute this software *
10     * and its documentation for any purpose and without fee is hereby *
11     * granted, provided that the above copyright notice appear in all *
12     * copies. The author makes no representations about the suitability *
13     * of this software for any purpose. It is provided "as is" without *
14     * express or implied warranty. *
15     ************************************************************************/
16    
17     /*
18     @(#) FILE: udp_util.c RELEASE: 1.9 DATE: 09/10/96, 10:40:50
19     */
20     /*******************************************************************************
21    
22     File:
23    
24     udp_util.c
25    
26     UDP Networking Utilities.
27    
28    
29     Author: Alex Measday, ISI
30    
31    
32     Purpose:
33    
34     The UDP_UTIL package implements a high-level interface to UDP/IP
35     network communications. Under the UDP protocol, processes send
36     "datagrams" to each other. Unlike TCP, UDP has no concept of a
37     "connection"; messages are individually routed to one or more
38     destination endpoints through a single socket. Also unlike TCP,
39     UDP does not guarantee reliable transmission; messages may be
40     lost or sent out of order.
41    
42     In the UDP_UTIL package, the endpoints of a connection-less UDP
43     "connection" are called, well, "endpoints". A given program may
44     create an anonymous UDP endpoint bound to a system-assigned network
45     port:
46    
47     udpCreate (NULL, NULL, &endpoint) ;
48    
49     or it may create a UDP endpoint bound to a predetermined network
50     port (specified by name or port number):
51    
52     udpCreate ("<name>", NULL, &endpoint) ;
53    
54     Client processes generally create anonymous UDP endpoints for the
55     purpose of sending messages to a server process at a predetermined
56     network port. With an anonymous endpoint, a client must let the
57     server(s) know its port number before the client can receive messages
58     from the server(s). The act of sending a datagram to the server(s)
59     automatically supplies the server(s) with the client's port number
60     and IP address.
61    
62     By creating a UDP endpoint bound to a predetermined network port, a
63     server is immediately ready to receive datagrams sent by clients to
64     that port; the clients already know the port number, so there is no
65     need for the server to send messages first.
66    
67     To send a datagram from one endpoint to another, you must specify the
68     network address of the destination endpoint. Since the destination
69     endpoint probably belongs to another process, possibly on a remote host,
70     the UDP_UTIL package requires you to create a "proxy" endpoint for the
71     destination endpoint:
72    
73     udpCreate ("<name>[@<host>]", source, &destination) ;
74    
75     A proxy endpoint simply specifies the network address of the destination
76     endpoint; the proxy endpoint is not bound to a network port and it has
77     no operating system socket associated with it. The proxy endpoint is
78     internally linked with its source endpoint, so, when a datagram is sent
79     to the proxy, udpWrite() automatically sends the datagram through the
80     source endpoint to the destination. A source endpoint may have many
81     proxy endpoints, but a given proxy endpoint is only linked to a single
82     source. (If you have multiple source endpoints, you can create multiple
83     proxy endpoints for the same destination.)
84    
85     When a datagram is read from an anonymous or predetermined endpoint,
86     udpRead() returns the text of the datagram and a proxy endpoint for
87     the sender of the datagram. The proxy endpoint can be used to return
88     a response to the sender:
89    
90     char message[64], response[32] ;
91     UdpEndpoint me, you ;
92     ...
93     -- Read message.
94     udpRead (me, -1.0, sizeof message, message, NULL, &you) ;
95     -- Send response.
96     udpWrite (you, -1.0, sizeof response, response) ;
97    
98     Although there is no harm in doing so, there is no need to delete proxy
99     endpoints; they are automatically garbage-collected when their source
100     endpoint is deleted.
101    
102     The following is a very simple server process that creates a UDP
103     endpoint bound to a predetermined network port and then reads and
104     displays messages received from clients:
105    
106     #include <stdio.h> -- Standard I/O definitions.
107     #include "udp_util.h" -- UDP utilities.
108    
109     main (int argc, char *argv[])
110     {
111     char buffer[128] ;
112     UdpEndpoint client, server ;
113     -- Create UDP endpoint.
114     udpCreate ("<name>", NULL, &server) ;
115    
116     for ( ; ; ) { -- Read and display messages.
117     udpRead (server, -1.0, 128, buffer, NULL, &client) ;
118     printf ("From %s: %s\n", udpName (client), buffer) ;
119     }
120    
121     }
122    
123     The following client process creates an anonymous UDP endpoint and
124     sends 16 messages through that endpoint to the server:
125    
126     #include <stdio.h> -- Standard I/O definitions.
127     #include "udp_util.h" -- UDP utilities.
128    
129     main (int argc, char *argv[])
130     {
131     char buffer[128] ;
132     int i ;
133     UdpEndpoint client, server ;
134    
135     udpCreate (NULL, NULL, &client) ; -- Create client and target.
136     udpCreate ("<name>[@<host>]", client, &server) ;
137    
138     for (i = 0 ; i < 16 ; i++) { -- Send messages.
139     sprintf (buffer, "Hello for the %dth time!", i) ;
140     udpWrite (server, -1.0, strlen (buffer) + 1, buffer) ;
141     }
142    
143     udpDestroy (client) ; -- Deletes client and target.
144    
145     }
146    
147     Note that "client" is the anonymous endpoint and "server" is a proxy
148     for the destination endpoint.
149    
150    
151     Notes:
152    
153     These functions are reentrant under VxWorks (except for the global
154     debug flag).
155    
156    
157     Public Procedures (* defined as macros):
158    
159     udpCreate() - creates a UDP endpoint.
160     udpDestroy() - destroys a UDP endpoint.
161     udpFd() - returns the file descriptor for an endpoint's socket.
162     udpIsReadable() - checks if a datagram is waiting to be read.
163     udpIsUp() - checks if an endpoint is up.
164     udpIsWriteable() - checks if a datagram can be written.
165     udpName() - returns the name of an endpoint.
166     udpRead() - reads a datagram.
167     * udpSetBuf() - changes the sizes of an endpoint's receive and send buffers.
168     udpWrite() - sends a datagram.
169    
170     *******************************************************************************/
171    
172     #define _BSD_SOURCE 1
173    
174     #include <ctype.h> /* Standard character functions. */
175     #include <errno.h> /* System error definitions. */
176     #include <limits.h> /* Maximum/minimum value definitions. */
177     #ifndef PATH_MAX
178     # include <sys/param.h> /* System parameters. */
179     # define PATH_MAX MAXPATHLEN
180     #endif
181     #include <stdio.h> /* Standard I/O definitions. */
182     #include <stdlib.h> /* Standard C Library definitions. */
183     #include <string.h> /* C Library string functions. */
184    
185     #if defined(VMS)
186     # include <socket.h> /* Socket-related definitions. */
187     # include <ucx$inetdef.h> /* VMS/Ultrix network definitions. */
188     # include <unixio.h> /* VMS-emulation of UNIX I/O. */
189     # include "fd.h" /* File descriptor set definitions. */
190     # define MAXHOSTNAMELEN 64
191     #elif defined(VXWORKS)
192     # include <hostLib.h> /* Host library definitions. */
193     # include <ioLib.h> /* I/O library definitions. */
194     # include <selectLib.h> /* SELECT(2) definitions. */
195     # include <socket.h> /* Socket-related definitions. */
196     # include <sockLib.h> /* Socket library definitions. */
197     # include <types.h> /* System type definitions. */
198     # include <unistd.h> /* UNIX I/O definitions. */
199     # include <sys/times.h> /* System time definitions. */
200     #else
201     # include <netdb.h> /* Network database definitions. */
202     # include <unistd.h> /* UNIX I/O definitions. */
203     # include <sys/param.h> /* System parameters. */
204     # include <sys/socket.h> /* Socket-related definitions. */
205     # include <sys/time.h> /* System time definitions. */
206     # include <sys/types.h> /* System type definitions. */
207     #endif
208    
209     #include <netinet/in.h> /* Internet IPC domain definitions. */
210    
211     #include "meo_util.h" /* Memory operations. */
212     #include "net_util.h" /* Networking utilities. */
213     #include "skt_util.h" /* Socket support functions. */
214     #include "tv_util.h" /* "timeval" manipulation functions. */
215     #include "vperror.h" /* VPERROR() definitions. */
216     #include "udp_util.h" /* UDP networking utilities. */
217    
218    
219     /*******************************************************************************
220     UDP Endpoints - contain information about local and remote UDP sockets.
221     A "local" (to the application) endpoint represents a UDP socket on
222     which the application can receive UDP datagrams. A "remote" (to
223     the application) endpoint has no socket and simply specifies the
224     source address of a datagram received by the application or the
225     destination address of a datagram being sent by the application.
226     Socket-less remote endpoints are linked to their "parent" local
227     endpoint; when the parent is deleted, the children are automatically
228     deleted.
229     *******************************************************************************/
230    
231     typedef struct _UdpEndpoint {
232     char *name ; /* "<port>[@<host>]" */
233     struct sockaddr address ; /* Network address and port number. */
234     int addressLength ; /* Length (in bytes) of address. */
235     int fd ; /* UDP socket. */
236     struct _UdpEndpoint *parent ; /* Local parent of remote endpoint. */
237     struct _UdpEndpoint *next ; /* Link to first child or next sibling. */
238     } _UdpEndpoint ;
239    
240    
241     int udp_util_debug = 0 ; /* Global debug switch (1/0 = yes/no). */
242    
243     /*******************************************************************************
244    
245     Procedure:
246    
247     udpCreate ()
248    
249     Create a UDP Endpoint.
250    
251    
252     Purpose:
253    
254     The udpCreate() function creates any one of three types of UDP endpoints:
255    
256     (1) a UDP socket bound to a system-chosen network port,
257    
258     (2) a UDP socket bound to a predetermined network port
259     (identified by port name or number), and
260    
261     (3) a socket-less UDP endpoint used to specify the target
262     of a datagram being sent.
263    
264     The anonymous and predetermined endpoints (#'s 1 and 2 above) should
265     be closed by a call to udpDestroy() when they are no longer needed.
266     Proxy endpoints (#3 above) are linked upon creation to an existing
267     anonymous or predetermined endpoint (i.e., its "parent"). When a
268     parent endpoint is closed, all of its "children" (i.e., the associated
269     proxy endpoints) are automatically deleted.
270    
271    
272     Invocation (anonymous endpoint):
273    
274     status = udpCreate (NULL, NULL, &endpoint) ;
275    
276     Invocation (predetermined endpoint):
277    
278     status = udpCreate (serverName, NULL, &endpoint) ;
279    
280     Invocation (proxy endpoint):
281    
282     status = udpCreate (targetName, parent, &endpoint) ;
283    
284     where
285    
286     <serverName> - I
287     is the server's name. This is used for determining the port
288     associated with the server (via the system's name/port mappings).
289     You can side-step the system maps and explicitly specify a
290     particular port by passing in a decimal number encoded in ASCII
291     (e.g., "1234" for port 1234).
292     <targetName> - I
293     is the target's name: "<server>[@<host>]". The server can be
294     specified as a name or as a port number; see the "serverName"
295     argument description above. The host, if given, can be
296     specified as a name or as a dotted Internet address.
297     <endpoint> - O
298     returns a handle for the UDP endpoint.
299     <status> - O
300     returns the status of creating the UDP endpoint, zero if
301     there were no errors and ERRNO otherwise.
302    
303     *******************************************************************************/
304    
305    
306     int udpCreate (
307    
308     # if __STDC__
309     const char *name,
310     UdpEndpoint parent,
311     UdpEndpoint *endpoint)
312     # else
313     name, parent, endpoint)
314    
315     char *name ;
316     UdpEndpoint parent ;
317     UdpEndpoint *endpoint ;
318     # endif
319    
320     { /* Local variables. */
321     char *s, hostName[MAXHOSTNAMELEN+1], serverName[MAXHOSTNAMELEN+1] ;
322     int length, portNumber ;
323     struct sockaddr_in socketName ;
324    
325    
326    
327    
328    
329     /*******************************************************************************
330     Construct the endpoint's network address.
331     *******************************************************************************/
332    
333     /* Parse the host and server names. If the host name is not defined
334     explicitly, it defaults to the local host. */
335    
336     s = netHostOf (netAddrOf (NULL)) ;
337     if (s == NULL) {
338     vperror ("(udpCreate) Error getting local host name.\nnetHostOf: ") ;
339     return (errno) ;
340     }
341     strcpy (hostName, s) ;
342    
343     if (name == NULL) { /* Let system choose port #? */
344     strcpy (serverName, "0") ;
345     } else { /* User-specified port #. */
346     s = strchr (name, '@') ;
347     if (s == NULL) { /* "<server>" */
348     strcpy (serverName, name) ;
349     } else { /* "<server>@<host>" */
350     length = s - name ;
351     strncpy (serverName, name, length) ;
352     serverName[length] = '\0' ;
353     strcpy (hostName, ++s) ;
354     }
355     }
356    
357     /* Lookup the port number bound to the server name. */
358    
359     portNumber = netPortOf (serverName, "udp") ;
360     if (portNumber == -1) {
361     vperror ("(udpCreate) Error getting server entry for %s.\nnetPortOf: ",
362     serverName) ;
363     return (errno) ;
364     }
365    
366     /* Set up the network address for the endpoint. */
367    
368     memset (&socketName, '\0', sizeof socketName) ;
369     socketName.sin_family = AF_INET ;
370     socketName.sin_port = htons (portNumber) ;
371    
372     socketName.sin_addr.s_addr = netAddrOf (hostName) ;
373     if ((long) socketName.sin_addr.s_addr == -1) {
374     vperror ("(udpCreate) Error getting host entry for %s.\nnetAddrOf: ",
375     hostName) ;
376     return (errno) ;
377     }
378    
379    
380     /*******************************************************************************
381     Create a UDP endpoint structure.
382     *******************************************************************************/
383    
384     *endpoint = (UdpEndpoint) malloc (sizeof (_UdpEndpoint)) ;
385     if (*endpoint == NULL) {
386     vperror ("(udpCreate) Error allocating endpoint structure for %s.\nmalloc: ",
387     serverName) ;
388     return (errno) ;
389     }
390    
391     (*endpoint)->name = NULL ;
392     *((struct sockaddr_in *) &(*endpoint)->address) = socketName ;
393     (*endpoint)->addressLength = sizeof socketName ;
394     (*endpoint)->fd = -1 ;
395     (*endpoint)->parent = parent ;
396     (*endpoint)->next = NULL ;
397    
398    
399     /*******************************************************************************
400     If a UDP socket is to be created, then create the socket and bind it to
401     the specified port number.
402     *******************************************************************************/
403    
404     if (parent == NULL) {
405    
406     /* Create a socket for the endpoint. */
407    
408     (*endpoint)->fd = socket (AF_INET, SOCK_DGRAM, 0) ;
409     if ((*endpoint)->fd < 0) {
410     vperror ("(udpCreate) Error creating socket for %s.\nsocket: ",
411     serverName) ;
412     udpDestroy (*endpoint) ; *endpoint = NULL ;
413     return (errno) ;
414     }
415    
416     /* Bind the network address to the socket. */
417    
418     if (bind ((*endpoint)->fd,
419     &(*endpoint)->address, (*endpoint)->addressLength)) {
420     vperror ("(udpCreate) Error binding %s's socket name.\nbind: ",
421     serverName) ;
422     udpDestroy (*endpoint) ; *endpoint = NULL ;
423     return (errno) ;
424     }
425    
426     sprintf (serverName, "%d",
427     sktPort ((*endpoint)->name, (*endpoint)->fd)) ;
428    
429     }
430    
431    
432     /*******************************************************************************
433     Otherwise, if a socket-less, proxy endpoint is being created, then
434     simply link it to its parent endpoint.
435     *******************************************************************************/
436    
437     else {
438    
439     (*endpoint)->next = parent->next ;
440     parent->next = *endpoint ;
441    
442     }
443    
444    
445     /*******************************************************************************
446     Construct the endpoint's name.
447     *******************************************************************************/
448    
449     (*endpoint)->name = malloc (strlen (serverName) + 1 +
450     strlen (hostName) + 1) ;
451     if ((*endpoint)->name == NULL) {
452     vperror ("(udpCreate) Error duplicating server name: %s%c%s\nmalloc: ",
453     serverName, (parent == NULL) ? '#' : '@', hostName) ;
454     udpDestroy (*endpoint) ; *endpoint = NULL ;
455     return (errno) ;
456     }
457     sprintf ((*endpoint)->name, "%s%c%s",
458     serverName, (parent == NULL) ? '#' : '@', hostName) ;
459    
460    
461     if (udp_util_debug) printf ("(udpCreate) Created %s, socket %d.\n",
462     (*endpoint)->name, (*endpoint)->fd) ;
463    
464     return (0) ; /* Successful completion. */
465    
466     }
467    
468     /*******************************************************************************
469    
470     Procedure:
471    
472     udpDestroy ()
473    
474     Destroy a UDP Endpoint.
475    
476    
477     Purpose:
478    
479     The udpDestroy() function destroys a UDP endpoint. If the endpoint
480     is a socket bound to a network port, the socket is closed. If the
481     endpoint is a socket-less, proxy endpoint, the endpoint is simply
482     unlinked from the socket endpoint (i.e., its "parent") with which
483     it is associated.
484    
485    
486     Invocation:
487    
488     status = udpDestroy (endpoint) ;
489    
490     where
491    
492     <endpoint> - I
493     is the endpoint handle returned by udpCreate() or udpRead().
494     <status> - O
495     returns the status of destroying the endpoint, zero if there
496     were no errors and ERRNO otherwise.
497    
498     *******************************************************************************/
499    
500    
501     int udpDestroy (
502    
503     # if __STDC__
504     UdpEndpoint endpoint)
505     # else
506     endpoint)
507    
508     UdpEndpoint endpoint ;
509     # endif
510    
511     { /* Local variables. */
512     UdpEndpoint prev ;
513    
514    
515    
516    
517     if (endpoint == NULL) return (0) ;
518    
519     if (udp_util_debug) printf ("(udpDestroy) Destroying %s, socket %d ...\n",
520     endpoint->name, endpoint->fd) ;
521    
522     /* If this is a socket endpoint, then delete all of the socket-less proxy
523     endpoints associated with the endpoint. */
524    
525     if (endpoint->parent == NULL) {
526     while (endpoint->next != NULL)
527     udpDestroy (endpoint->next) ;
528     close (endpoint->fd) ;
529     endpoint->fd = -1 ;
530     }
531    
532     /* Otherwise, if this is a socket-less proxy, then unlink the proxy endpoint
533     from its socket endpoint (i.e., its "parent"). */
534    
535     else {
536     for (prev = endpoint->parent ; prev != NULL ; prev = prev->next)
537     if (prev->next == endpoint) break ;
538     if (prev != NULL) prev->next = endpoint->next ;
539     }
540    
541     /* Deallocate the endpoint structure. */
542    
543     if (endpoint->name != NULL) {
544     free (endpoint->name) ; endpoint->name = NULL ;
545     }
546     free (endpoint) ;
547    
548     return (0) ;
549    
550     }
551    
552     /*******************************************************************************
553    
554     Procedure:
555    
556     udpFd ()
557    
558     Get a UDP Endpoint's Socket.
559    
560    
561     Purpose:
562    
563     Function udpFd() returns a UDP endpoint's socket.
564    
565    
566     Invocation:
567    
568     fd = udpFd (endpoint) ;
569    
570     where
571    
572     <endpoint> - I
573     is the endpoint handle returned by udpCreate() or udpRead().
574     <fd> - O
575     returns the UNIX file descriptor for the endpoint's socket.
576    
577     *******************************************************************************/
578    
579    
580     int udpFd (
581    
582     # if __STDC__
583     UdpEndpoint endpoint)
584     # else
585     endpoint)
586    
587     UdpEndpoint endpoint ;
588     # endif
589    
590     {
591     return ((endpoint == NULL) ? -1 : endpoint->fd) ;
592     }
593    
594     /*******************************************************************************
595    
596     Procedure:
597    
598     udpIsReadable ()
599    
600     Check if Data is Waiting to be Read.
601    
602    
603     Purpose:
604    
605     The udpIsReadable() function checks to see if data is waiting to
606     be read from a UDP endpoint.
607    
608    
609     Invocation:
610    
611     isReadable = udpIsReadable (endpoint) ;
612    
613     where
614    
615     <endpoint> - I
616     is the endpoint handle returned by udpCreate().
617     <isReadable> - O
618     returns true (a non-zero value) if data is available for
619     reading and false (zero) otherwise.
620    
621     *******************************************************************************/
622    
623    
624     int udpIsReadable (
625    
626     # if __STDC__
627     UdpEndpoint endpoint)
628     # else
629     endpoint)
630    
631     UdpEndpoint endpoint ;
632     # endif
633    
634     {
635    
636     if (endpoint == NULL)
637     return (0) ;
638     else if (endpoint->parent == NULL)
639     return (sktIsReadable (endpoint->name, endpoint->fd)) ;
640     else
641     return (sktIsReadable (endpoint->name, (endpoint->parent)->fd)) ;
642    
643     }
644    
645     /*******************************************************************************
646    
647     Procedure:
648    
649     udpIsUp ()
650    
651     Check if a UDP Endpoint is Up.
652    
653    
654     Purpose:
655    
656     The udpIsUp() function checks to see if a UDP endpoint is still up.
657    
658    
659     Invocation:
660    
661     isUp = udpIsUp (endpoint) ;
662    
663     where
664    
665     <endpoint> - I
666     is the endpoint handle returned by udpCreate().
667     <isUp> - O
668     returns true (a non-zero value) if the endpoint is up and
669     false (zero) otherwise.
670    
671     *******************************************************************************/
672    
673    
674     int udpIsUp (
675    
676     # if __STDC__
677     UdpEndpoint endpoint)
678     # else
679     endpoint)
680    
681     UdpEndpoint endpoint ;
682     # endif
683    
684     {
685    
686     if (endpoint == NULL)
687     return (0) ;
688     else if (endpoint->parent == NULL)
689     return (sktIsUp (endpoint->name, endpoint->fd)) ;
690     else
691     return (sktIsUp (endpoint->name, (endpoint->parent)->fd)) ;
692    
693     }
694    
695     /*******************************************************************************
696    
697     Procedure:
698    
699     udpIsWriteable ()
700    
701     Check if Data can be Written.
702    
703    
704     Purpose:
705    
706     The udpIsWriteable() function checks to see if data can be written
707     to a UDP endpoint.
708    
709    
710     Invocation:
711    
712     isWriteable = udpIsWriteable (endpoint) ;
713    
714     where
715    
716     <endpoint> - I
717     is the endpoint handle returned by udpCreate().
718     <isWriteable> - O
719     returns true (a non-zero value) if the endpoint is ready
720     for writing and false (zero) otherwise.
721    
722     *******************************************************************************/
723    
724    
725     int udpIsWriteable (
726    
727     # if __STDC__
728     UdpEndpoint endpoint)
729     # else
730     endpoint)
731    
732     UdpEndpoint endpoint ;
733     # endif
734    
735     {
736    
737     if (endpoint == NULL)
738     return (0) ;
739     else if (endpoint->parent == NULL)
740     return (sktIsWriteable (endpoint->name, endpoint->fd)) ;
741     else
742     return (sktIsWriteable (endpoint->name, (endpoint->parent)->fd)) ;
743    
744     }
745    
746     /*******************************************************************************
747    
748     Procedure:
749    
750     udpName ()
751    
752     Get a UDP Endpoint's Name.
753    
754    
755     Purpose:
756    
757     Function udpName() returns a UDP endpoint's name.
758    
759    
760     Invocation:
761    
762     name = udpName (endpoint) ;
763    
764     where
765    
766     <endpoint> - I
767     is the endpoint handle returned by udpCreate() or udpRead().
768     <name> - O
769     returns the endpoint's name. The name is stored in memory
770     local to the UDP utilities and it should not be modified or
771     freed by the caller.
772    
773     *******************************************************************************/
774    
775    
776     char *udpName (
777    
778     # if __STDC__
779     UdpEndpoint endpoint)
780     # else
781     endpoint)
782    
783     UdpEndpoint endpoint ;
784     # endif
785    
786     {
787     if (endpoint == NULL) return ("") ;
788     if (endpoint->name == NULL) return ("") ;
789     return (endpoint->name) ;
790     }
791    
792     /*******************************************************************************
793    
794     Procedure:
795    
796     udpRead ()
797    
798     Read Data from a UDP Endpoint.
799    
800    
801     Purpose:
802    
803     Function udpRead() reads the next message on a UDP endpoint. A timeout
804     can be specified that limits how long udpRead() waits for the message
805     to be received.
806    
807    
808     Invocation:
809    
810     status = udpRead (endpoint, timeout, maxBytesToRead,
811     buffer, &numBytesRead, &source) ;
812    
813     where
814    
815     <endpoint> - I
816     is the endpoint handle returned by udpCreate().
817     <timeout> - I
818     specifies the maximum amount of time (in seconds) that the caller
819     wishes to wait for the next message to be received. A fractional
820     time can be specified; e.g., 2.5 seconds. A negative timeout
821     (e.g., -1.0) causes an infinite wait; a zero timeout (0.0) allows
822     a read only if message is immediately available.
823     <maxBytesToRead> - I
824     specifies the maximum number of bytes to read; i.e., the size of
825     the message buffer.
826     <buffer> - O
827     receives the input data. This buffer should be at least
828     maxBytesToRead in size.
829     <numBytesRead> - O
830     returns the actual number of bytes read.
831     <source> - O
832     returns an endpoint handle for the source of the message.
833     <status> - O
834     returns the status of reading from the endpoint: zero if no
835     errors occurred, EWOULDBLOCK if the timeout interval expired
836     before a message was received, and ERRNO otherwise.
837    
838     *******************************************************************************/
839    
840    
841     int udpRead (
842    
843     # if __STDC__
844     UdpEndpoint endpoint,
845     double timeout,
846     int maxBytesToRead,
847     char *buffer,
848     int *numBytesRead,
849     UdpEndpoint *source)
850     # else
851     endpoint, timeout, maxBytesToRead, buffer, numBytesRead, source)
852    
853     UdpEndpoint endpoint ;
854     double timeout ;
855     int maxBytesToRead ;
856     char *buffer ;
857     int *numBytesRead ;
858     UdpEndpoint *source ;
859     # endif
860    
861     { /* Local variables. */
862     char *hostName ;
863     char sourceName[PATH_MAX+1] ;
864     fd_set readMask ;
865     int addressLength, fd, length, numActive ;
866     struct sockaddr address ;
867     struct timeval deltaTime, expirationTime ;
868     UdpEndpoint ep, sourcePoint ;
869    
870    
871    
872    
873    
874     if (endpoint == NULL) {
875     errno = EINVAL ;
876     vperror ("(udpRead) NULL endpoint handle: ") ;
877     return (errno) ;
878     }
879    
880     fd = endpoint->fd ;
881     if (fd < 0) {
882     errno = EINVAL ;
883     vperror ("(udpRead) %d file descriptor: ", fd) ;
884     return (errno) ;
885     }
886    
887    
888     /*******************************************************************************
889     If a timeout interval was specified, then wait until the expiration of
890     the interval for a message to be received.
891     *******************************************************************************/
892    
893     if (timeout >= 0.0) {
894    
895     /* Compute the expiration time as the current time plus the interval. */
896    
897     expirationTime = tvAdd (tvTOD (), tvCreateF (timeout)) ;
898    
899     /* Wait for the next message to arrive. */
900    
901     for ( ; ; ) {
902     deltaTime = tvSubtract (expirationTime, tvTOD ()) ;
903     FD_ZERO (&readMask) ; FD_SET (fd, &readMask) ;
904     numActive = select (fd+1, &readMask, NULL, NULL, &deltaTime) ;
905     if (numActive >= 0) break ;
906     if (errno == EINTR) continue ;
907     vperror ("(udpRead) Error waiting for input on %s.\nselect: ",
908     endpoint->name) ;
909     return (errno) ;
910     }
911    
912     if (numActive == 0) {
913     errno = EWOULDBLOCK ;
914     vperror ("(udpRead) Timeout while waiting for input on %s.\n",
915     endpoint->name) ;
916     return (errno) ;
917     }
918    
919     }
920    
921    
922     /*******************************************************************************
923     Read the message.
924     *******************************************************************************/
925    
926     addressLength = sizeof address ;
927     length = recvfrom (fd, buffer, maxBytesToRead, 0, &address, &addressLength) ;
928     if (length < 0) {
929     vperror ("(udpRead) Error reading from %s.\nrecvfrom: ",
930     endpoint->name) ;
931     return (errno) ;
932     } else if (length == 0) {
933     errno = EPIPE ;
934     vperror ("(udpRead) Broken connection on %s.\nrecvfrom: ",
935     endpoint->name) ;
936     return (errno) ;
937     }
938    
939     if (numBytesRead != NULL) *numBytesRead = length ;
940    
941    
942     /*******************************************************************************
943     Create a UDP endpoint for the source of the message.
944     *******************************************************************************/
945    
946     /* Check to see if an endpoint already exists for this particular source. */
947    
948     for (ep = endpoint->next ; ep != NULL ; ep = ep->next) {
949     if ((addressLength == ep->addressLength) &&
950     (memcmp (&address, &ep->address, addressLength) == 0)) break ;
951     }
952    
953     /* If not, create a brand new endpoint. If so, then use the existing one. */
954    
955     if (ep == NULL) {
956     hostName = netHostOf (
957     ((struct sockaddr_in *) &address)->sin_addr.s_addr) ;
958     sprintf (sourceName, "%d@%s",
959     ntohs (((struct sockaddr_in *) &address)->sin_port),
960     hostName) ;
961     if (udpCreate (sourceName, endpoint, &sourcePoint)) {
962     vperror ("(udpRead) Error creating source endpoint: %s\nudpCreate: ",
963     sourceName) ;
964     return (errno) ;
965     }
966     } else {
967     sourcePoint = ep ;
968     }
969    
970     if (source != NULL) *source = sourcePoint ;
971    
972    
973     if (udp_util_debug) {
974     printf ("(udpRead) Read %d bytes from %s on %s, socket %d.\n",
975     length, sourcePoint->name, endpoint->name, endpoint->fd) ;
976     meoDumpX (stdout, " ", 0, buffer, length) ;
977     }
978    
979     return (0) ;
980    
981     }
982    
983     /*******************************************************************************
984    
985     Procedure:
986    
987     Write ()
988    
989     Write Data to a UDP Endpoint.
990    
991    
992     Purpose:
993    
994     Function udpWrite() writes a message to a destination UDP endpoint.
995     A timeout interval can be specified that limits how long udpWrite()
996     waits to output the message.
997    
998     Note that a message is written through a local source endpoint to the
999     remote destination endpoint. Only the destination endpoint is passed
1000     to udpWrite(); udpWrite() will use the destination's "parent" as the
1001     source endpoint.
1002    
1003    
1004     Invocation:
1005    
1006     status = udpWrite (destination, timeout, numBytesToWrite, buffer) ;
1007    
1008     where
1009    
1010     <destination> - I
1011     is the destination endpoint handle returned by udpCreate()
1012     or udpRead().
1013     <timeout> - I
1014     specifies the maximum amount of time (in seconds) that the
1015     caller wishes to wait for the data to be output. A fractional
1016     time can be specified; e.g., 2.5 seconds. A negative timeout
1017     (e.g., -1.0) causes an infinite wait; udpWrite() will wait as
1018     long as necessary to output all of the data. A zero timeout
1019     (0.0) specifies no wait: if the socket is not ready for writing,
1020     udpWrite() returns immediately.
1021     <numBytesToWrite> - I
1022     is the number of bytes to write.
1023     <buffer> - O
1024     is the data to be output.
1025     <status> - O
1026     returns the status of sending the message: zero if no errors
1027     occurred, EWOULDBLOCK if the timeout interval expired before
1028     the message could be sent, and ERRNO otherwise.
1029    
1030     *******************************************************************************/
1031    
1032    
1033     int udpWrite (
1034    
1035     # if __STDC__
1036     UdpEndpoint destination,
1037     double timeout,
1038     int numBytesToWrite,
1039     const char *buffer)
1040     # else
1041     destination, timeout, numBytesToWrite, buffer)
1042    
1043     UdpEndpoint destination ;
1044     double timeout ;
1045     int numBytesToWrite ;
1046     const char *buffer ;
1047     # endif
1048    
1049     { /* Local variables. */
1050     fd_set writeMask ;
1051     int fd, length, numActive ;
1052     struct timeval deltaTime, expirationTime ;
1053    
1054    
1055    
1056    
1057    
1058     if (destination == NULL) {
1059     errno = EINVAL ;
1060     vperror ("(udpWrite) NULL destination handle: ") ;
1061     return (errno) ;
1062     }
1063    
1064     fd = (destination->parent == NULL) ? destination->fd
1065     : (destination->parent)->fd ;
1066     if (fd < 0) {
1067     errno = EINVAL ;
1068     vperror ("(udpWrite) %d file descriptor: ", fd) ;
1069     return (errno) ;
1070     }
1071    
1072    
1073     /*******************************************************************************
1074     If a timeout interval was specified, then wait until the expiration
1075     of the interval for the endpoint's socket to be ready for writing.
1076     *******************************************************************************/
1077    
1078     if (timeout >= 0.0) {
1079    
1080     /* Compute the expiration time as the current time plus the interval. */
1081    
1082     expirationTime = tvAdd (tvTOD (), tvCreateF (timeout)) ;
1083    
1084     /* Wait for the endpoint to be ready for writing. */
1085    
1086     for ( ; ; ) {
1087     deltaTime = tvSubtract (expirationTime, tvTOD ()) ;
1088     FD_ZERO (&writeMask) ; FD_SET (fd, &writeMask) ;
1089     numActive = select (fd+1, NULL, &writeMask, NULL, &deltaTime) ;
1090     if (numActive >= 0) break ;
1091     if (errno == EINTR) continue ;
1092     vperror ("(udpWrite) Error waiting to write to %s.\nselect: ",
1093     destination->name) ;
1094     return (errno) ;
1095     }
1096    
1097     if (numActive == 0) {
1098     errno = EWOULDBLOCK ;
1099     vperror ("(udpWrite) Timeout while waiting to write data to %s.\n",
1100     destination->name) ;
1101     return (errno) ;
1102     }
1103    
1104     }
1105    
1106    
1107     /*******************************************************************************
1108     Send the message to the destination endpoint.
1109     *******************************************************************************/
1110    
1111     length = sendto (fd, (char *) buffer, numBytesToWrite, 0,
1112     &destination->address, destination->addressLength) ;
1113     if (length < 0) {
1114     vperror ("(udpWrite) Error sending %d-byte message to %s.\nsendto: ",
1115     numBytesToWrite, destination->name) ;
1116     return (errno) ;
1117     }
1118    
1119     if (udp_util_debug) {
1120     printf ("(udpWrite) Wrote %d bytes to %s, socket %d.\n",
1121     length, destination->name, fd) ;
1122     meoDumpX (stdout, " ", 0, buffer, length) ;
1123     }
1124    
1125    
1126     return (0) ;
1127    
1128     }
1129     </XMP></BODY></HTML>