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

# Content
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>